Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
John W. Linville [Wed, 5 Jan 2011 21:06:25 +0000 (16:06 -0500)]
Conflicts:
net/bluetooth/Makefile

1  2 
MAINTAINERS
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
net/mac80211/ieee80211_i.h
net/mac80211/main.c
net/mac80211/rx.c
net/mac80211/tx.c

diff --combined MAINTAINERS
@@@ -161,13 -161,14 +161,13 @@@ M:      Greg Kroah-Hartman <gregkh@suse.de
  L:    linux-serial@vger.kernel.org
  W:    http://serial.sourceforge.net
  S:    Maintained
 -T:    quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6.git
  F:    drivers/serial/8250*
  F:    include/linux/serial_8250.h
  
  8390 NETWORK DRIVERS [WD80x3/SMC-ELITE, SMC-ULTRA, NE2000, 3C503, etc.]
 -M:    Paul Gortmaker <p_gortmaker@yahoo.com>
  L:    netdev@vger.kernel.org
 -S:    Maintained
 +S:    Orphan / Obsolete
  F:    drivers/net/*8390*
  F:    drivers/net/ax88796.c
  
@@@ -404,7 -405,7 +404,7 @@@ S: Supporte
  F:    drivers/usb/gadget/amd5536udc.*
  
  AMD GEODE PROCESSOR/CHIPSET SUPPORT
 -P:    Jordan Crouse
 +P:    Andres Salomon <dilinger@queued.net>
  L:    linux-geode@lists.infradead.org (moderated for non-subscribers)
  W:    http://www.amd.com/us-en/ConnectivitySolutions/TechnicalResources/0,,50_2334_2452_11363,00.html
  S:    Supported
@@@ -558,14 -559,14 +558,14 @@@ W:      http://maxim.org.za/at91_26.htm
  S:    Maintained
  
  ARM/BCMRING ARM ARCHITECTURE
 -M:    Leo Chen <leochen@broadcom.com>
 +M:    Jiandong Zheng <jdzheng@broadcom.com>
  M:    Scott Branden <sbranden@broadcom.com>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  S:    Maintained
  F:    arch/arm/mach-bcmring
  
  ARM/BCMRING MTD NAND DRIVER
 -M:    Leo Chen <leochen@broadcom.com>
 +M:    Jiandong Zheng <jdzheng@broadcom.com>
  M:    Scott Branden <sbranden@broadcom.com>
  L:    linux-mtd@lists.infradead.org
  S:    Maintained
@@@ -814,7 -815,7 +814,7 @@@ F: drivers/mmc/host/msm_sdcc.
  F:    drivers/mmc/host/msm_sdcc.h
  F:    drivers/serial/msm_serial.h
  F:    drivers/serial/msm_serial.c
 -T:    git git://codeaurora.org/quic/kernel/dwalker/linux-msm.git
 +T:    git git://codeaurora.org/quic/kernel/davidb/linux-msm.git
  S:    Maintained
  
  ARM/TOSA MACHINE SUPPORT
@@@ -944,7 -945,7 +944,7 @@@ M: Magnus Damm <magnus.damm@gmail.com
  L:    linux-sh@vger.kernel.org
  W:    http://oss.renesas.com
  Q:    http://patchwork.kernel.org/project/linux-sh/list/
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/lethal/genesis-2.6.git
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6.git rmobile-latest
  S:    Supported
  F:    arch/arm/mach-shmobile/
  F:    drivers/sh/
@@@ -1263,15 -1264,6 +1263,15 @@@ S:    Maintaine
  F:    drivers/video/backlight/
  F:    include/linux/backlight.h
  
 +BATMAN ADVANCED
 +M:    Marek Lindner <lindner_marek@yahoo.de>
 +M:    Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
 +M:    Sven Eckelmann <sven@narfation.org>
 +L:    b.a.t.m.a.n@lists.open-mesh.org
 +W:    http://www.open-mesh.org/
 +S:    Maintained
 +F:    net/batman-adv/
 +
  BAYCOM/HDLCDRV DRIVERS FOR AX.25
  M:    Thomas Sailer <t.sailer@alumni.ethz.ch>
  L:    linux-hams@vger.kernel.org
@@@ -1373,7 -1365,7 +1373,7 @@@ F:      include/net/bluetooth
  
  BONDING DRIVER
  M:    Jay Vosburgh <fubar@us.ibm.com>
 -L:    bonding-devel@lists.sourceforge.net
 +L:    netdev@vger.kernel.org
  W:    http://sourceforge.net/projects/bonding/
  S:    Supported
  F:    drivers/net/bonding/
@@@ -1843,13 -1835,6 +1843,13 @@@ W:    http://www.chelsio.co
  S:    Supported
  F:    drivers/net/cxgb4vf/
  
 +STMMAC ETHERNET DRIVER
 +M:    Giuseppe Cavallaro <peppe.cavallaro@st.com>
 +L:    netdev@vger.kernel.org
 +W:    http://www.stlinux.com
 +S:    Supported
 +F:    drivers/net/stmmac/
 +
  CYBERPRO FB DRIVER
  M:    Russell King <linux@arm.linux.org.uk>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@@ -2029,7 -2014,6 +2029,7 @@@ F:      drivers/hwmon/dme1737.
  DOCBOOK FOR DOCUMENTATION
  M:    Randy Dunlap <rdunlap@xenotime.net>
  S:    Maintained
 +F:    scripts/kernel-doc
  
  DOCKING STATION DRIVER
  M:    Shaohua Li <shaohua.li@intel.com>
@@@ -2040,7 -2024,6 +2040,7 @@@ F:      drivers/acpi/dock.
  DOCUMENTATION
  M:    Randy Dunlap <rdunlap@xenotime.net>
  L:    linux-doc@vger.kernel.org
 +T:    quilt oss.oracle.com/~rdunlap/kernel-doc-patches/current/
  S:    Maintained
  F:    Documentation/
  
@@@ -2074,7 -2057,7 +2074,7 @@@ F:      Documentation/blockdev/drbd
  
  DRIVER CORE, KOBJECTS, DEBUGFS AND SYSFS
  M:    Greg Kroah-Hartman <gregkh@suse.de>
 -T:    quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6.git
  S:    Supported
  F:    Documentation/kobject.txt
  F:    drivers/base/
@@@ -2094,7 -2077,7 +2094,7 @@@ F:      include/drm
  
  INTEL DRM DRIVERS (excluding Poulsbo, Moorestown and derivative chipsets)
  M:    Chris Wilson <chris@chris-wilson.co.uk>
 -L:    intel-gfx@lists.freedesktop.org
 +L:    intel-gfx@lists.freedesktop.org (subscribers-only)
  L:    dri-devel@lists.freedesktop.org
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/ickle/drm-intel.git
  S:    Supported
@@@ -2458,12 -2441,9 +2458,12 @@@ F:    drivers/net/wan/sdla.
  FRAMEBUFFER LAYER
  L:    linux-fbdev@vger.kernel.org
  W:    http://linux-fbdev.sourceforge.net/
 +Q:    http://patchwork.kernel.org/project/linux-fbdev/list/
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/lethal/fbdev-2.6.git
  S:    Orphan
  F:    Documentation/fb/
 -F:    drivers/video/fb*
 +F:    drivers/video/
 +F:    include/video/
  F:    include/linux/fb.h
  
  FREESCALE DMA DRIVER
@@@ -3134,8 -3114,6 +3134,8 @@@ M:      Alex Duyck <alexander.h.duyck@intel.
  M:    John Ronciak <john.ronciak@intel.com>
  L:    e1000-devel@lists.sourceforge.net
  W:    http://e1000.sourceforge.net/
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-2.6.git
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-next-2.6.git
  S:    Supported
  F:    Documentation/networking/e100.txt
  F:    Documentation/networking/e1000.txt
@@@ -4080,8 -4058,9 +4080,8 @@@ F:      drivers/scsi/NCR_D700.
  
  NETEFFECT IWARP RNIC DRIVER (IW_NES)
  M:    Faisal Latif <faisal.latif@intel.com>
 -M:    Chien Tung <chien.tin.tung@intel.com>
  L:    linux-rdma@vger.kernel.org
 -W:    http://www.neteffect.com
 +W:    http://www.intel.com/Products/Server/Adapters/Server-Cluster/Server-Cluster-overview.htm
  S:    Supported
  F:    drivers/infiniband/hw/nes/
  
@@@ -4606,7 -4585,7 +4606,7 @@@ F:      drivers/pcmcia
  F:    include/pcmcia/
  
  PCNET32 NETWORK DRIVER
 -M:    Don Fry <pcnet32@verizon.net>
 +M:    Don Fry <pcnet32@frontier.com>
  L:    netdev@vger.kernel.org
  S:    Maintained
  F:    drivers/net/pcnet32.c
@@@ -5053,7 -5032,7 +5053,7 @@@ L:      linux-wireless@vger.kernel.or
  W:    http://linuxwireless.org/
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
  S:    Maintained
- F:    drivers/net/wireless/rtl818x/rtl8180*
+ F:    drivers/net/wireless/rtl818x/rtl8180/
  
  RTL8187 WIRELESS DRIVER
  M:    Herton Ronaldo Krzesinski <herton@mandriva.com.br>
@@@ -5063,7 -5042,7 +5063,7 @@@ L:      linux-wireless@vger.kernel.or
  W:    http://linuxwireless.org/
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
  S:    Maintained
- F:    drivers/net/wireless/rtl818x/rtl8187*
+ F:    drivers/net/wireless/rtl818x/rtl8187/
  
  RTL8192CE WIRELESS DRIVER
  M:    Larry Finger <Larry.Finger@lwfinger.net>
@@@ -5713,7 -5692,7 +5713,7 @@@ S:      Maintaine
  
  STAGING SUBSYSTEM
  M:    Greg Kroah-Hartman <gregkh@suse.de>
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-next-2.6.git
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6.git
  L:    devel@driverdev.osuosl.org
  S:    Maintained
  F:    drivers/staging/
@@@ -5742,7 -5721,7 +5742,7 @@@ M:      Paul Mundt <lethal@linux-sh.org
  L:    linux-sh@vger.kernel.org
  W:    http://www.linux-sh.org
  Q:    http://patchwork.kernel.org/project/linux-sh/list/
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6.git
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6.git sh-latest
  S:    Supported
  F:    Documentation/sh/
  F:    arch/sh/
@@@ -5864,8 -5843,6 +5864,8 @@@ M:      Chris Metcalf <cmetcalf@tilera.com
  W:    http://www.tilera.com/scm/
  S:    Supported
  F:    arch/tile/
 +F:    drivers/char/hvc_tile.c
 +F:    drivers/net/tile/
  
  TLAN NETWORK DRIVER
  M:    Samuel Chessman <chessman@tux.org>
@@@ -5949,7 -5926,7 +5949,7 @@@ S:      Maintaine
  TTY LAYER
  M:    Greg Kroah-Hartman <gregkh@suse.de>
  S:    Maintained
 -T:    quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6.git
  F:    drivers/char/tty_*
  F:    drivers/serial/serial_core.c
  F:    include/linux/serial_core.h
@@@ -5958,6 -5935,7 +5958,6 @@@ F:      include/linux/tty.
  
  TULIP NETWORK DRIVERS
  M:    Grant Grundler <grundler@parisc-linux.org>
 -M:    Kyle McMartin <kyle@mcmartin.ca>
  L:    netdev@vger.kernel.org
  S:    Maintained
  F:    drivers/net/tulip/
@@@ -6271,7 -6249,7 +6271,7 @@@ USB SUBSYSTE
  M:    Greg Kroah-Hartman <gregkh@suse.de>
  L:    linux-usb@vger.kernel.org
  W:    http://www.linux-usb.org
 -T:    quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6.git
  S:    Supported
  F:    Documentation/usb/
  F:    drivers/net/usb/
@@@ -6609,15 -6587,6 +6609,15 @@@ F:    include/linux/mfd/wm8400
  F:    include/sound/wm????.h
  F:    sound/soc/codecs/wm*
  
 +WORKQUEUE
 +M:    Tejun Heo <tj@kernel.org>
 +L:    linux-kernel@vger.kernel.org
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git
 +S:    Maintained
 +F:    include/linux/workqueue.h
 +F:    kernel/workqueue.c
 +F:    Documentation/workqueue.txt
 +
  X.25 NETWORK LAYER
  M:    Andrew Hendry <andrew.hendry@gmail.com>
  L:    linux-x25@vger.kernel.org
@@@ -6645,14 -6614,14 +6645,14 @@@ F:   drivers/platform/x8
  
  XEN PCI SUBSYSTEM
  M:    Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
 -L:    xen-devel@lists.xensource.com
 +L:    xen-devel@lists.xensource.com (moderated for non-subscribers)
  S:    Supported
  F:    arch/x86/pci/*xen*
  F:    drivers/pci/*xen*
  
  XEN SWIOTLB SUBSYSTEM
  M:    Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
 -L:    xen-devel@lists.xensource.com
 +L:    xen-devel@lists.xensource.com (moderated for non-subscribers)
  S:    Supported
  F:    arch/x86/xen/*swiotlb*
  F:    drivers/xen/*swiotlb*
  XEN HYPERVISOR INTERFACE
  M:    Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
  M:    Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
 -L:    xen-devel@lists.xen.org
 +L:    xen-devel@lists.xensource.com (moderated for non-subscribers)
  L:    virtualization@lists.osdl.org
  S:    Supported
  F:    arch/x86/xen/
  
  #define CTL(_tpower, _flag) ((_tpower) | ((_flag) << 6))
  
+ #define EEPROM_DATA_LEN_9485  1088
  static int ar9003_hw_power_interpolate(int32_t x,
                                       int32_t *px, int32_t *py, u_int16_t np);
  
 +
  static const struct ar9300_eeprom ar9300_default = {
        .eepromVersion = 2,
        .templateVersion = 2,
@@@ -3368,7 -3369,7 +3370,7 @@@ found
                        "Found block at %x: code=%d ref=%d length=%d major=%d minor=%d\n",
                        cptr, code, reference, length, major, minor);
                if ((!AR_SREV_9485(ah) && length >= 1024) ||
-                   (AR_SREV_9485(ah) && length >= (4 * 1024))) {
+                   (AR_SREV_9485(ah) && length > EEPROM_DATA_LEN_9485)) {
                        ath_dbg(common, ATH_DBG_EEPROM,
                                "Skipping bad header\n");
                        cptr -= COMP_HDR_LEN;
@@@ -23,7 -23,6 +23,7 @@@
  #include <linux/types.h>
  #include <linux/spinlock.h>
  #include <linux/etherdevice.h>
 +#include <linux/leds.h>
  #include <net/ieee80211_radiotap.h>
  #include <net/cfg80211.h>
  #include <net/mac80211.h>
@@@ -168,6 -167,7 +168,7 @@@ typedef unsigned __bitwise__ ieee80211_
   * @IEEE80211_RX_FRAGMENTED: fragmented frame
   * @IEEE80211_RX_AMSDU: a-MSDU packet
   * @IEEE80211_RX_MALFORMED_ACTION_FRM: action frame is malformed
+  * @IEEE80211_RX_DEFERRED_RELEASE: frame was subjected to receive reordering
   *
   * These are per-frame flags that are attached to a frame in the
   * @rx_flags field of &struct ieee80211_rx_status.
@@@ -178,6 -178,7 +179,7 @@@ enum ieee80211_packet_rx_flags 
        IEEE80211_RX_FRAGMENTED                 = BIT(2),
        IEEE80211_RX_AMSDU                      = BIT(3),
        IEEE80211_RX_MALFORMED_ACTION_FRM       = BIT(4),
+       IEEE80211_RX_DEFERRED_RELEASE           = BIT(5),
  };
  
  /**
@@@ -631,20 -632,6 +633,20 @@@ enum queue_stop_reason 
        IEEE80211_QUEUE_STOP_REASON_SKB_ADD,
  };
  
 +#ifdef CONFIG_MAC80211_LEDS
 +struct tpt_led_trigger {
 +      struct led_trigger trig;
 +      char name[32];
 +      const struct ieee80211_tpt_blink *blink_table;
 +      unsigned int blink_table_len;
 +      struct timer_list timer;
 +      unsigned long prev_traffic;
 +      unsigned long tx_bytes, rx_bytes;
 +      unsigned int active, want;
 +      bool running;
 +};
 +#endif
 +
  /**
   * mac80211 scan flags - currently active scan mode
   *
@@@ -774,6 -761,15 +776,15 @@@ struct ieee80211_local 
        struct sk_buff_head skb_queue;
        struct sk_buff_head skb_queue_unreliable;
  
+       /*
+        * Internal FIFO queue which is shared between multiple rx path
+        * stages. Its main task is to provide a serialization mechanism,
+        * so all rx handlers can enjoy having exclusive access to their
+        * private data structures.
+        */
+       struct sk_buff_head rx_skb_queue;
+       bool running_rx_handler;        /* protected by rx_skb_queue.lock */
        /* Station data */
        /*
         * The mutex only protects the list and counter,
  #ifdef CONFIG_MAC80211_LEDS
        int tx_led_counter, rx_led_counter;
        struct led_trigger *tx_led, *rx_led, *assoc_led, *radio_led;
 +      struct tpt_led_trigger *tpt_led_trigger;
        char tx_led_name[32], rx_led_name[32],
             assoc_led_name[32], radio_led_name[32];
  #endif
diff --combined net/mac80211/main.c
@@@ -569,6 -569,8 +569,8 @@@ struct ieee80211_hw *ieee80211_alloc_hw
        spin_lock_init(&local->filter_lock);
        spin_lock_init(&local->queue_stop_reason_lock);
  
+       skb_queue_head_init(&local->rx_skb_queue);
        INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work);
  
        ieee80211_work_init(local);
        /* init dummy netdev for use w/ NAPI */
        init_dummy_netdev(&local->napi_dev);
  
 +      ieee80211_led_names(local);
 +
        return local_to_hw(local);
  }
  EXPORT_SYMBOL(ieee80211_alloc_hw);
@@@ -914,6 -914,7 +916,7 @@@ void ieee80211_unregister_hw(struct iee
                wiphy_warn(local->hw.wiphy, "skb_queue not empty\n");
        skb_queue_purge(&local->skb_queue);
        skb_queue_purge(&local->skb_queue_unreliable);
+       skb_queue_purge(&local->rx_skb_queue);
  
        destroy_workqueue(local->workqueue);
        wiphy_unregister(local->hw.wiphy);
diff --combined net/mac80211/rx.c
@@@ -533,10 -533,11 +533,11 @@@ static inline u16 seq_sub(u16 sq1, u16 
  
  static void ieee80211_release_reorder_frame(struct ieee80211_hw *hw,
                                            struct tid_ampdu_rx *tid_agg_rx,
-                                           int index,
-                                           struct sk_buff_head *frames)
+                                           int index)
  {
+       struct ieee80211_local *local = hw_to_local(hw);
        struct sk_buff *skb = tid_agg_rx->reorder_buf[index];
+       struct ieee80211_rx_status *status;
  
        lockdep_assert_held(&tid_agg_rx->reorder_lock);
  
        /* release the frame from the reorder ring buffer */
        tid_agg_rx->stored_mpdu_num--;
        tid_agg_rx->reorder_buf[index] = NULL;
-       __skb_queue_tail(frames, skb);
+       status = IEEE80211_SKB_RXCB(skb);
+       status->rx_flags |= IEEE80211_RX_DEFERRED_RELEASE;
+       skb_queue_tail(&local->rx_skb_queue, skb);
  
  no_frame:
        tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num);
  
  static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw,
                                             struct tid_ampdu_rx *tid_agg_rx,
-                                            u16 head_seq_num,
-                                            struct sk_buff_head *frames)
+                                            u16 head_seq_num)
  {
        int index;
  
        while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) {
                index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
                                                        tid_agg_rx->buf_size;
-               ieee80211_release_reorder_frame(hw, tid_agg_rx, index, frames);
+               ieee80211_release_reorder_frame(hw, tid_agg_rx, index);
        }
  }
  
  #define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10)
  
  static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw,
-                                         struct tid_ampdu_rx *tid_agg_rx,
-                                         struct sk_buff_head *frames)
+                                         struct tid_ampdu_rx *tid_agg_rx)
  {
        int index, j;
  
                                wiphy_debug(hw->wiphy,
                                            "release an RX reorder frame due to timeout on earlier frames\n");
  #endif
-                       ieee80211_release_reorder_frame(hw, tid_agg_rx,
-                                                       j, frames);
+                       ieee80211_release_reorder_frame(hw, tid_agg_rx, j);
  
                        /*
                         * Increment the head seq# also for the skipped slots.
                        skipped = 0;
                }
        } else while (tid_agg_rx->reorder_buf[index]) {
-               ieee80211_release_reorder_frame(hw, tid_agg_rx, index, frames);
+               ieee80211_release_reorder_frame(hw, tid_agg_rx, index);
                index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
                                                        tid_agg_rx->buf_size;
        }
  
-       /*
-        * Disable the reorder release timer for now.
-        *
-        * The current implementation lacks a proper locking scheme
-        * which would protect vital statistic and debug counters
-        * from being updated by two different but concurrent BHs.
-        *
-        * More information about the topic is available from:
-        * - thread: http://marc.info/?t=128635927000001
-        *
-        * What was wrong:
-        * =>  http://marc.info/?l=linux-wireless&m=128636170811964
-        * "Basically the thing is that until your patch, the data
-        *  in the struct didn't actually need locking because it
-        *  was accessed by the RX path only which is not concurrent."
-        *
-        * List of what needs to be fixed:
-        * => http://marc.info/?l=linux-wireless&m=128656352920957
-        *
        if (tid_agg_rx->stored_mpdu_num) {
                j = index = seq_sub(tid_agg_rx->head_seq_num,
                                    tid_agg_rx->ssn) % tid_agg_rx->buf_size;
        } else {
                del_timer(&tid_agg_rx->reorder_timer);
        }
-       */
- set_release_timer:
-       return;
  }
  
  /*
   */
  static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
                                             struct tid_ampdu_rx *tid_agg_rx,
-                                            struct sk_buff *skb,
-                                            struct sk_buff_head *frames)
+                                            struct sk_buff *skb)
  {
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
        u16 sc = le16_to_cpu(hdr->seq_ctrl);
        if (!seq_less(mpdu_seq_num, head_seq_num + buf_size)) {
                head_seq_num = seq_inc(seq_sub(mpdu_seq_num, buf_size));
                /* release stored frames up to new head to stack */
-               ieee80211_release_reorder_frames(hw, tid_agg_rx, head_seq_num,
-                                                frames);
+               ieee80211_release_reorder_frames(hw, tid_agg_rx, head_seq_num);
        }
  
        /* Now the new frame is always in the range of the reordering buffer */
        tid_agg_rx->reorder_buf[index] = skb;
        tid_agg_rx->reorder_time[index] = jiffies;
        tid_agg_rx->stored_mpdu_num++;
-       ieee80211_sta_reorder_release(hw, tid_agg_rx, frames);
+       ieee80211_sta_reorder_release(hw, tid_agg_rx);
  
   out:
        spin_unlock(&tid_agg_rx->reorder_lock);
   * Reorder MPDUs from A-MPDUs, keeping them on a buffer. Returns
   * true if the MPDU was buffered, false if it should be processed.
   */
- static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx,
-                                      struct sk_buff_head *frames)
+ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx)
  {
        struct sk_buff *skb = rx->skb;
        struct ieee80211_local *local = rx->local;
         * sure that we cannot get to it any more before doing
         * anything with it.
         */
-       if (ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, frames))
+       if (ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb))
                return;
  
   dont_reorder:
-       __skb_queue_tail(frames, skb);
+       skb_queue_tail(&local->rx_skb_queue, skb);
  }
  
  static ieee80211_rx_result debug_noinline
@@@ -1189,6 -1162,7 +1162,7 @@@ ieee80211_rx_h_sta_process(struct ieee8
         * exchange sequence.
         */
        if (!ieee80211_has_morefrags(hdr->frame_control) &&
+           !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) &&
            (rx->sdata->vif.type == NL80211_IFTYPE_AP ||
             rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) {
                if (test_sta_flags(sta, WLAN_STA_PS_STA)) {
@@@ -1831,11 -1805,11 +1805,11 @@@ ieee80211_rx_h_mesh_fwding(struct ieee8
  
                        fwd_skb = skb_copy(skb, GFP_ATOMIC);
  
-                       if (!fwd_skb && net_ratelimit()) {
+                       if (!fwd_skb && net_ratelimit())
                                printk(KERN_DEBUG "%s: failed to clone mesh frame\n",
                                                   sdata->name);
+                       if (!fwd_skb)
                                goto out;
-                       }
  
                        fwd_hdr =  (struct ieee80211_hdr *) fwd_skb->data;
                        memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN);
@@@ -1930,7 -1904,7 +1904,7 @@@ ieee80211_rx_h_data(struct ieee80211_rx
  }
  
  static ieee80211_rx_result debug_noinline
- ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames)
+ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx)
  {
        struct ieee80211_local *local = rx->local;
        struct ieee80211_hw *hw = &local->hw;
  
                spin_lock(&tid_agg_rx->reorder_lock);
                /* release stored frames up to start of BAR */
-               ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num,
-                                                frames);
+               ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num);
                spin_unlock(&tid_agg_rx->reorder_lock);
  
                kfree_skb(skb);
@@@ -2488,8 -2461,7 +2461,7 @@@ static void ieee80211_rx_handlers_resul
        }
  }
  
- static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx,
-                                 struct sk_buff_head *frames)
+ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx)
  {
        ieee80211_rx_result res = RX_DROP_MONITOR;
        struct sk_buff *skb;
                        goto rxh_next;  \
        } while (0);
  
-       while ((skb = __skb_dequeue(frames))) {
+       spin_lock(&rx->local->rx_skb_queue.lock);
+       if (rx->local->running_rx_handler)
+               goto unlock;
+       rx->local->running_rx_handler = true;
+       while ((skb = __skb_dequeue(&rx->local->rx_skb_queue))) {
+               spin_unlock(&rx->local->rx_skb_queue.lock);
                /*
                 * all the other fields are valid across frames
                 * that belong to an aMPDU since they are on the
                        CALL_RXH(ieee80211_rx_h_mesh_fwding);
  #endif
                CALL_RXH(ieee80211_rx_h_data)
-               /* special treatment -- needs the queue */
-               res = ieee80211_rx_h_ctrl(rx, frames);
-               if (res != RX_CONTINUE)
-                       goto rxh_next;
+               CALL_RXH(ieee80211_rx_h_ctrl);
                CALL_RXH(ieee80211_rx_h_mgmt_check)
                CALL_RXH(ieee80211_rx_h_action)
                CALL_RXH(ieee80211_rx_h_userspace_mgmt)
  
   rxh_next:
                ieee80211_rx_handlers_result(rx, res);
+               spin_lock(&rx->local->rx_skb_queue.lock);
  #undef CALL_RXH
        }
+       rx->local->running_rx_handler = false;
+  unlock:
+       spin_unlock(&rx->local->rx_skb_queue.lock);
  }
  
  static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx)
  {
-       struct sk_buff_head reorder_release;
        ieee80211_rx_result res = RX_DROP_MONITOR;
  
-       __skb_queue_head_init(&reorder_release);
  #define CALL_RXH(rxh)                 \
        do {                            \
                res = rxh(rx);          \
        CALL_RXH(ieee80211_rx_h_passive_scan)
        CALL_RXH(ieee80211_rx_h_check)
  
-       ieee80211_rx_reorder_ampdu(rx, &reorder_release);
+       ieee80211_rx_reorder_ampdu(rx);
  
-       ieee80211_rx_handlers(rx, &reorder_release);
+       ieee80211_rx_handlers(rx);
        return;
  
   rxh_next:
   */
  void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
  {
-       struct sk_buff_head frames;
        struct ieee80211_rx_data rx = {
                .sta = sta,
                .sdata = sta->sdata,
        if (!tid_agg_rx)
                return;
  
-       __skb_queue_head_init(&frames);
        spin_lock(&tid_agg_rx->reorder_lock);
-       ieee80211_sta_reorder_release(&sta->local->hw, tid_agg_rx, &frames);
+       ieee80211_sta_reorder_release(&sta->local->hw, tid_agg_rx);
        spin_unlock(&tid_agg_rx->reorder_lock);
  
-       ieee80211_rx_handlers(&rx, &frames);
+       ieee80211_rx_handlers(&rx);
  }
  
  /* main receive path */
@@@ -2931,9 -2905,6 +2905,9 @@@ void ieee80211_rx(struct ieee80211_hw *
                return;
        }
  
 +      ieee80211_tpt_led_trig_rx(local,
 +                      ((struct ieee80211_hdr *)skb->data)->frame_control,
 +                      skb->len);
        __ieee80211_rx_handle_packet(hw, skb);
  
        rcu_read_unlock();
diff --combined net/mac80211/tx.c
@@@ -1297,7 -1297,6 +1297,7 @@@ static int __ieee80211_tx(struct ieee80
  
        while (skb) {
                int q = skb_get_queue_mapping(skb);
 +              __le16 fc;
  
                spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
                ret = IEEE80211_TX_OK;
                else
                        info->control.sta = NULL;
  
 +              fc = ((struct ieee80211_hdr *)skb->data)->frame_control;
                ret = drv_tx(local, skb);
                if (WARN_ON(ret != NETDEV_TX_OK && skb->len != len)) {
                        dev_kfree_skb(skb);
                        return IEEE80211_TX_AGAIN;
                }
  
 +              ieee80211_tpt_led_trig_tx(local, fc, len);
                *skbp = skb = next;
                ieee80211_led_tx(local, 1);
                fragm = true;
@@@ -1750,6 -1747,7 +1750,7 @@@ netdev_tx_t ieee80211_subif_start_xmit(
        __le16 fc;
        struct ieee80211_hdr hdr;
        struct ieee80211s_hdr mesh_hdr __maybe_unused;
+       struct mesh_path *mppath = NULL;
        const u8 *encaps_data;
        int encaps_len, skip_header_bytes;
        int nh_pos, h_pos;
                        ret = NETDEV_TX_OK;
                        goto fail;
                }
+               if (!is_multicast_ether_addr(skb->data))
+                       mppath = mpp_path_lookup(skb->data, sdata);
  
+               /*
+                * Do not use address extension, if it is a packet from
+                * the same interface and the destination is not being
+                * proxied by any other mest point.
+                */
                if (compare_ether_addr(sdata->vif.addr,
-                                      skb->data + ETH_ALEN) == 0) {
+                                      skb->data + ETH_ALEN) == 0 &&
+                   (!mppath || !compare_ether_addr(mppath->mpp, skb->data))) {
                        hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc,
                                        skb->data, skb->data + ETH_ALEN);
                        meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr,
                                        sdata, NULL, NULL);
                } else {
                        /* packet from other interface */
-                       struct mesh_path *mppath;
                        int is_mesh_mcast = 1;
                        const u8 *mesh_da;
  
                        else {
                                static const u8 bcast[ETH_ALEN] =
                                        { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-                               mppath = mpp_path_lookup(skb->data, sdata);
                                if (mppath) {
                                        /* RA TA mDA mSA AE:DA SA */
                                        mesh_da = mppath->mpp;