diff --git a/patches/openwrt/0018-Backport-mac80211-from-Barrier-Breaker-r40995.patch b/patches/openwrt/0018-Backport-mac80211-from-Barrier-Breaker-r41029.patch
similarity index 79%
rename from patches/openwrt/0018-Backport-mac80211-from-Barrier-Breaker-r40995.patch
rename to patches/openwrt/0018-Backport-mac80211-from-Barrier-Breaker-r41029.patch
index 0e3412e5d99c8ca866594c5feb43b68e1a4c4131..2030a4fd43b59805fb744e2bc766c7519009c4ab 100644
--- a/patches/openwrt/0018-Backport-mac80211-from-Barrier-Breaker-r40995.patch
+++ b/patches/openwrt/0018-Backport-mac80211-from-Barrier-Breaker-r41029.patch
@@ -1,6 +1,6 @@
 From: Matthias Schiffer <mschiffer@universe-factory.net>
 Date: Mon, 19 May 2014 15:59:37 +0200
-Subject: Backport mac80211 from Barrier Breaker (r40995)
+Subject: Backport mac80211 from Barrier Breaker (r41029)
 
 diff --git a/package/mac80211/Makefile b/package/mac80211/Makefile
 index 9a7093c..c286b0f 100644
@@ -2142,10 +2142,10 @@ index 7b50154..6a7f5c1 100644
   	pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY,
   			       &local->network_latency_notifier);
 diff --git a/package/mac80211/patches/300-pending_work.patch b/package/mac80211/patches/300-pending_work.patch
-index a1af6c2..c621ddb 100644
+index a1af6c2..3305388 100644
 --- a/package/mac80211/patches/300-pending_work.patch
 +++ b/package/mac80211/patches/300-pending_work.patch
-@@ -1,4153 +1,386 @@
+@@ -1,4153 +1,2752 @@
 -commit 93f310a38a1d81a4bc8fcd9bf29628bd721cf2ef
 -Author: Felix Fietkau <nbd@openwrt.org>
 -Date:   Sun Apr 6 23:35:28 2014 +0200
@@ -2198,66 +2198,122 @@ index a1af6c2..c621ddb 100644
 -commit 91d70d40400c569b49605b78fd7c43e9405694f4
 -Author: Felix Fietkau <nbd@openwrt.org>
 -Date:   Tue Mar 11 14:00:37 2014 +0100
--
++commit d3a58df87a2e4c2301ac843604202d290a48440b
++Author: Avraham Stern <avraham.stern@intel.com>
++Date:   Thu May 22 12:17:47 2014 +0300
+ 
 -    ath9k_hw: set ANI cycpwr_thr1 as absolute values instead of relative
 -    
 -    The table was copied from the ANI implementation of AR9300. It assumes
 -    that the INI values contain a baseline value that is usable as reference
 -    from which to increase/decrease based on the noise immunity value.
--    
++    mac80211: set new interfaces as idle upon init
+     
 -    On older chips, the differences are bigger and especially AR5008/AR9001
 -    are configured to much more sensitive values than what is useful.
--    
++    Mark new interfaces as idle to allow operations that require that
++    interfaces are idle to take place. Interface types that are always
++    not idle (like AP interfaces) will be set as not idle when they are
++    assigned a channel context.
+     
 -    Improve ANI behavior by reverting to the absolute values used in the
 -    previous implementation (expressed as a simple formula instead of the
 -    old table).
 -    
 -    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
--
++    Signed-off-by: Avraham Stern <avraham.stern@intel.com>
++    Signed-off-by: Emmanuel Grumbach<emmanuel.grumbach@intel.com>
++    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit c977493766310a825f406836636ffd66e1447783
 -Author: Felix Fietkau <nbd@openwrt.org>
 -Date:   Mon Mar 10 19:52:56 2014 +0100
--
++commit 923eaf367206e01f22c97aee22300e332d071916
++Author: Arik Nemtsov <arik@wizery.com>
++Date:   Mon May 26 14:40:51 2014 +0300
+ 
 -    ath9k_hw: remove ANI function restrictions for AP mode
--    
++    mac80211: don't check netdev state for debugfs read/write
+     
 -    The primary purpose of this piece of code was to selectively disable
 -    OFDM weak signal detection. The checks for this are elsewhere, and an
 -    earlier commit relaxed the restrictions for older chips, which are more
 -    sensitive to interference.
--    
++    Doing so will lead to an oops for a p2p-dev interface, since it has
++    no netdev.
+     
 -    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
 -
 -commit 8d804f1af11e4e058b1e8453327777d73a585cb8
 -Author: Felix Fietkau <nbd@openwrt.org>
 -Date:   Sun Mar 9 11:25:43 2014 +0100
--
++    Cc: stable@vger.kernel.org
++    Signed-off-by: Arik Nemtsov <arikx.nemtsov@intel.com>
++    Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
++    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -    ath9k: clean up and enhance ANI debugfs file
 -    
 -    Unify scnprintf calls and include the current OFDM/CCK immunity level.
 -    
 -    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
--
++commit a9fb54169b197f31aff24c8d6270dd1e56cde395
++Author: chaitanya.mgit@gmail.com <chaitanya.mgit@gmail.com>
++Date:   Mon May 26 18:01:44 2014 +0530
++
++    regdb: Generalize the mW to dBm power conversion
++    
++    Generalize the power conversion from mW to dBm
++    using log. This should fix the below compilation
++    error for country NO which adds a new power value
++    2000mW which is not handled earlier.
++    
++     CC [M]  net/wireless/wext-sme.o
++     CC [M]  net/wireless/regdb.o
++    net/wireless/regdb.c:1130:1: error: Unknown undeclared here (not in
++    a function)
++    net/wireless/regdb.c:1130:9: error: expected } before power
++    make[2]: *** [net/wireless/regdb.o] Error 1
++    make[1]: *** [net/wireless] Error 2
++    make: *** [net] Error 2
++    
++    Reported-By:  John Walker <john@x109.net>
++    Signed-off-by: Chaitanya T K <chaitanya.mgit@gmail.com>
++    Acked-by: John W. Linville <linville@tuxdriver.com>
++    [remove unneeded parentheses, fix rounding by using %.0f]
++    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit 22e298b5a3a8a49e33805d4e351965123dede35b
 -Author: Felix Fietkau <nbd@openwrt.org>
 -Date:   Sun Mar 9 10:58:47 2014 +0100
--
++commit c7d37a66e345df2fdf1aa7b2c9a6d3d53846ca5b
++Author: Krzysztof Hałasa <khalasa@piap.pl>
++Date:   Mon May 26 14:14:46 2014 +0200
+ 
 -    ath9k: fix ready time of the multicast buffer queue
 -    
 -    qi->tqi_readyTime is written directly to registers that expect
 -    microseconds as unit instead of TU.
 -    When setting the CABQ ready time, cur_conf->beacon_interval is in TU, so
 -    convert it to microseconds before passing it to ath9k_hw.
--    
++    mac80211: fix IBSS join by initializing last_scan_completed
+     
 -    This should hopefully fix some Tx DMA issues with buffered multicast
 -    frames in AP mode.
--    
--    Cc: stable@vger.kernel.org
++    Without this fix, freshly rebooted Linux creates a new IBSS
++    instead of joining an existing one. Only when jiffies counter
++    overflows after 5 minutes the IBSS can be successfully joined.
+     
++    Signed-off-by: Krzysztof Hałasa <khalasa@piap.pl>
++    [edit commit message slightly]
+     Cc: stable@vger.kernel.org
 -    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
 -
 -commit fcb064fdd5a27bec8d24099bc0172468f34c97cb
 -Author: Felix Fietkau <nbd@openwrt.org>
 -Date:   Sun Mar 9 09:43:09 2014 +0100
--
++    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -    ath9k_hw: fix unreachable code in baseband hang detection code
 -    
 -    The commit "ath9k: reduce baseband hang detection false positive rate"
@@ -2266,11 +2322,50 @@ index a1af6c2..c621ddb 100644
 -    
 -    Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
 -    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
--
++commit 34171dc0d623be2c1032416bf7d3819f388ed70d
++Author: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
++Date:   Sun May 25 15:35:41 2014 +0300
++
++    mac80211: fix virtual monitor interface addition
++    
++    Since the commit below, cfg80211_chandef_dfs_required()
++    will warn if it gets a an NL80211_IFTYPE_UNSPECIFIED iftype
++    as explicitely written in the commit log.
++    When an virtual monitor interface is added, its type is set
++    in ieee80211_sub_if_data.vif.type, but not in
++    ieee80211_sub_if_data.wdev.iftype which is passed to
++    cfg80211_chandef_dfs_required() hence resulting in the
++    following warning:
++    
++    WARNING: CPU: 1 PID: 21265 at net/wireless/chan.c:376 cfg80211_chandef_dfs_required+0xbc/0x130 [cfg80211]()
++    Modules linked in: [...]
++    CPU: 1 PID: 21265 Comm: ifconfig Tainted: G        W  O 3.13.11+ #12
++    Hardware name: Dell Inc. Latitude E6410/0667CC, BIOS A01 03/05/2010
++     0000000000000009 ffff88008f5fdb08 ffffffff817d4219 ffff88008f5fdb50
++     ffff88008f5fdb40 ffffffff8106f57d 0000000000000000 0000000000000000
++     ffff880081062fb8 ffff8800810604e0 0000000000000001 ffff88008f5fdba0
++    Call Trace:
++     [<ffffffff817d4219>] dump_stack+0x4d/0x66
++     [<ffffffff8106f57d>] warn_slowpath_common+0x7d/0xa0
++     [<ffffffff8106f5ec>] warn_slowpath_fmt+0x4c/0x50
++     [<ffffffffa04ea4ec>] cfg80211_chandef_dfs_required+0xbc/0x130 [cfg80211]
++     [<ffffffffa06b1024>] ieee80211_vif_use_channel+0x94/0x500 [mac80211]
++     [<ffffffffa0684e6b>] ieee80211_add_virtual_monitor+0x1ab/0x5c0 [mac80211]
++     [<ffffffffa0686ae5>] ieee80211_do_open+0xe75/0x1580 [mac80211]
++     [<ffffffffa0687259>] ieee80211_open+0x69/0x70 [mac80211]
++    [snip]
++    
++    Fixes: 00ec75fc5a64 ("cfg80211: pass the actual iftype when calling cfg80211_chandef_dfs_required()")
++    Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
++    Acked-by: Luciano Coelho <luciano.coelho@intel.com>
++    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit 31959d8df39319e32c6d5ba9c135727be90cfad7
--Author: Michal Kazior <michal.kazior@tieto.com>
++commit d93cc72b37b4e2c314e1c499e80e8801907c2fea
+ Author: Michal Kazior <michal.kazior@tieto.com>
 -Date:   Fri Mar 7 08:09:38 2014 +0100
--
++Date:   Thu Jun 5 14:21:37 2014 +0200
+ 
 -    mac80211: fix possible NULL dereference
 -    
 -    If chanctx is missing on a given vif then the band
@@ -2279,14 +2374,23 @@ index a1af6c2..c621ddb 100644
 -    NULL dereference.
 -    
 -    This fixes a splat:
--    
++    mac80211: use csa counter offsets instead of csa_active
+     
 -    [ 4605.207223] BUG: unable to handle kernel NULL pointer dereference at 0000000000000018
 -    [ 4605.210789] IP: [<ffffffffa07b5635>] ieee80211_parse_bitrates+0x65/0x110 [mac80211]
--    
++    vif->csa_active is protected by mutexes only. This
++    means it is unreliable to depend on it on codeflow
++    in non-sleepable beacon and CSA code. There was no
++    guarantee to have vif->csa_active update be
++    visible before beacons are updated on SMP systems.
+     
 -    The splat was preceeded by WARN_ON(!chanctx_conf)
 -    in ieee80211_get_sdata_band().
--    
--    Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
++    Using csa counter offsets which are embedded in
++    beacon struct (and thus are protected with single
++    RCU assignment) is much safer.
+     
+     Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
 -
 -commit 6c5a3ffa0a2d22c091a2717f427259bacf77ac5e
 -Author: Michael Braun <michael-dev@fami-braun.de>
@@ -2328,8 +2432,8 @@ index a1af6c2..c621ddb 100644
 -    race since the assignment isn't properly locked.
 -    
 -    Reported-by: Michal Kazior <michal.kazior@tieto.com>
--    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
--
+     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit 1abdeca3c6fb9cf1f84f85e78ed8d1c33bd69db0
 -Author: Felix Fietkau <nbd@openwrt.org>
 -Date:   Fri Feb 28 18:52:56 2014 +0100
@@ -2446,13 +2550,17 @@ index a1af6c2..c621ddb 100644
 -commit 0f1cb7be2551b30b02cd54c897e0e29e483cfda5
 -Author: Felix Fietkau <nbd@openwrt.org>
 -Date:   Sat Feb 22 13:43:29 2014 +0100
--
++commit d2746694fcdef24e0a7a1947d8c70082cde81a26
++Author: Michal Kazior <michal.kazior@tieto.com>
++Date:   Thu Jun 5 14:21:36 2014 +0200
+ 
 -    ath9k: fix ps-poll responses under a-mpdu sessions
 -    
 -    When passing tx frames to the U-APSD queue for powersave poll responses,
 -    the ath_atx_tid pointer needs to be passed to ath_tx_setup_buffer for
 -    proper sequence number accounting.
--    
++    mac80211: move csa counters from sdata to beacon/presp
+     
 -    This fixes high latency and connection stability issues with ath9k
 -    running as AP and a few kinds of mobile phones as client, when PS-Poll
 -    is heavily used
@@ -2465,15 +2573,27 @@ index a1af6c2..c621ddb 100644
 -Date:   Fri Feb 21 11:39:59 2014 +0100
 -
 -    ath9k: list more reset causes in debugfs
--    
++    Having csa counters part of beacon and probe_resp
++    structures makes it easier to get rid of possible
++    races between setting a beacon and updating
++    counters on SMP systems by guaranteeing counters
++    are always consistent against given beacon struct.
+     
 -    Number of MAC hangs and stuck beacons were missing
--    
++    While at it relax WARN_ON into WARN_ON_ONCE to
++    prevent spamming logs and racing.
+     
 -    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
--
++    Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
++    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit d84856012e0f10fe598a5ad3b7b869397a089e07
 -Author: Johannes Berg <johannes.berg@intel.com>
 -Date:   Thu Feb 20 11:19:58 2014 +0100
--
++commit 5dcb54f3a1a8cd7e0331e773487574f9743615db
++Author: Janusz Dziedzic <janusz.dziedzic@tieto.com>
++Date:   Thu Jun 5 08:12:57 2014 +0200
+ 
 -    mac80211: fix station wakeup powersave race
 -    
 -    Consider the following (relatively unlikely) scenario:
@@ -2481,13 +2601,17 @@ index a1af6c2..c621ddb 100644
 -     2) driver blocks wakeup (until no more frames are buffered)
 -     3) station wakes up again
 -     4) driver unblocks wakeup
--    
++    mac80211: allow tx via monitor iface when DFS
+     
 -    In this case, the current mac80211 code will do the following:
 -     1) WLAN_STA_PS_STA set
 -     2) WLAN_STA_PS_DRIVER set
 -     3) - nothing -
 -     4) WLAN_STA_PS_DRIVER cleared
--    
++    Allow send frames using monitor interface
++    when DFS chandef and we pass CAC (beaconing
++    allowed).
+     
 -    As a result, no frames will be delivered to the client, even
 -    though it is awake, until it sends another frame to us that
 -    triggers ieee80211_sta_ps_deliver_wakeup() in sta_ps_end().
@@ -2500,13 +2624,20 @@ index a1af6c2..c621ddb 100644
 -    
 -    While at it, fix a cleanup path issue when a station is
 -    removed while the driver is still blocking its wakeup.
--    
--    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
--
++    This fix problem when old kernel and new backports used,
++    in such case hostapd create/use also monitor interface.
++    Before this patch all frames hostapd send using monitor
++    iface were dropped when AP was configured on DFS channel.
+     
++    Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
+     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit 798f2786602cbe93e6b928299614aa36ebf50692
--Author: Johannes Berg <johannes.berg@intel.com>
++commit 6f09a1beb0d2007572248c986780562219bd206f
+ Author: Johannes Berg <johannes.berg@intel.com>
 -Date:   Mon Feb 17 20:49:03 2014 +0100
--
++Date:   Wed Jun 4 17:31:56 2014 +0200
+ 
 -    mac80211: insert stations before adding to driver
 -    
 -    There's a race condition in mac80211 because we add stations
@@ -2515,14 +2646,20 @@ index a1af6c2..c621ddb 100644
 -     1. a station connects and is added
 -     2. first, it is added to the driver
 -     3. then, it is added to the mac80211 lists
--    
++    cfg80211: make ethtool the driver's responsibility
+     
 -    If the station goes to sleep between steps 2 and 3, and the
 -    firmware/hardware records it as being asleep, mac80211 will
 -    never instruct the driver to wake it up again as it never
 -    realized it went to sleep since the RX path discarded the
 -    frame as a "spurious class 3 frame", no station entry was
 -    present yet.
--    
++    Currently, cfg80211 tries to implement ethtool, but that doesn't
++    really scale well, with all the different operations. Make the
++    lower-level driver responsible for it, which currently only has
++    an effect on mac80211. It will similarly not scale well at that
++    level though, since mac80211 also has many drivers.
+     
 -    Fix this by adding the station in software first, and only
 -    then adding it to the driver. That way, any state that the
 -    driver changes will be reflected properly in mac80211's
@@ -2530,13 +2667,18 @@ index a1af6c2..c621ddb 100644
 -    driver fails to add the station, in that case a bit more is
 -    needed. To not make that overly complex prevent starting BA
 -    sessions in the meantime.
--    
--    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
--
++    To cleanly implement this in mac80211, introduce a new file and
++    move some code to appropriate places.
+     
+     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit b9ba6a520cb07ab3aa7aaaf9ce4a0bc7a6bc06fe
 -Author: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
 -Date:   Thu Feb 20 09:22:11 2014 +0200
--
++commit 6b0c6f133de8f90caeb1c4a902e6140567c5bf96
++Author: Johannes Berg <johannes.berg@intel.com>
++Date:   Wed Jun 4 17:06:23 2014 +0200
+ 
 -    mac80211: fix AP powersave TX vs. wakeup race
 -    
 -    There is a race between the TX path and the STA wakeup: while
@@ -2549,11 +2691,14 @@ index a1af6c2..c621ddb 100644
 -    is emptied on the one side, while a frame is being added on
 -    the other side, as the station is still seen as sleeping in
 -    the TX path.
--    
++    mac80211: remove weak WEP IV accounting
+     
 -    As a result, the newly added frame will not be send anytime
 -    soon. It might be sent much later (and out of order) when the
 -    station goes to sleep and wakes up the next time.
--    
++    Since WEP is practically dead, there seems very little
++    point in keeping WEP weak IV accounting.
+     
 -    Additionally, it can lead to the crash below.
 -    
 -    Fix all this by synchronising both paths with a new lock.
@@ -2597,43 +2742,66 @@ index a1af6c2..c621ddb 100644
 -    Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
 -    Reviewed-by: Stanislaw Gruszka <sgruszka@redhat.com>
 -    [reword commit log, use a separate lock]
--    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
--
+     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit 80e419de0dff38436b30d363311c625766193f86
 -Author: Inbal Hacohen <Inbal.Hacohen@intel.com>
 -Date:   Wed Feb 12 09:32:27 2014 +0200
--
++commit aecdc89fb4664c76baa4bbd46008f220532309ff
++Author: Luciano Coelho <luciano.coelho@intel.com>
++Date:   Fri May 23 11:04:50 2014 +0300
+ 
 -    cfg80211: bugfix in regulatory user hint process
--    
++    ath9k/ath10k: remove unnecessary channel_switch_beacon callbacks
+     
 -    After processing hint_user, we would want to schedule the
 -    timeout work only if we are actually waiting to CRDA. This happens
 -    when the status is not "IGNORE" nor "ALREADY_SET".
--    
++    The channel_switch_beacon callback is optional, so it doesn't have to
++    be defined if it's not going to do anything useful with it.  Both
++    ath9k and ath10k define the callback and just returns.  This commit
++    removes them.
+     
 -    Signed-off-by: Inbal Hacohen <Inbal.Hacohen@intel.com>
 -    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
--
++    Cc: Michal Kazior <michal.kazior@tieto.com>
++    Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
++    Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
+ 
 -commit 6514c93afede55284e2cb63359aadedb85884c80
 -Author: Jouni Malinen <jouni@qca.qualcomm.com>
 -Date:   Tue Feb 18 20:41:08 2014 +0200
--
++commit 60ccc107c9b9fb732fdee1f76bb2dad44f0e1798
++Author: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
++Date:   Tue May 27 16:58:02 2014 +0530
+ 
 -    ath9k: Enable U-APSD AP mode support
--    
++    ath9k: Fix deadlock while updating p2p beacon timer
+     
 -    mac80211 handles the actual operations, so ath9k can just indicate
 -    support for this. Based on initial tests, this combination seems to
 -    work fine.
--    
++    pm_lock is taken twice while syncing HW TSF of p2p vif.
++    Fix this by taking the lock at caller side.
+     
 -    Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
--
++    Cc: Felix Fietkau <nbd@openwrt.org>
++    Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
++    Signed-off-by: John W. Linville <linville@tuxdriver.com>
+ 
 -commit a63caf0a357ad5c1f08d6b7827dc76c451445017
--Author: Stanislaw Gruszka <sgruszka@redhat.com>
++commit f3831a4e3903dbc1a57d5df56deb6a143fd001bc
+ Author: Stanislaw Gruszka <sgruszka@redhat.com>
 -Date:   Wed Feb 19 13:15:17 2014 +0100
--
++Date:   Thu Jun 5 13:52:27 2014 +0200
+ 
 -    ath9k: protect tid->sched check
 -    
 -    We check tid->sched without a lock taken on ath_tx_aggr_sleep(). That
 -    is race condition which can result of doing list_del(&tid->list) twice
 -    (second time with poisoned list node) and cause crash like shown below:
--    
++    rt2x00: do not initialize BCN_OFFSET registers
+     
 -    [424271.637220] BUG: unable to handle kernel paging request at 00100104
 -    [424271.637328] IP: [<f90fc072>] ath_tx_aggr_sleep+0x62/0xe0 [ath9k]
 -    ...
@@ -2656,14 +2824,16 @@ index a1af6c2..c621ddb 100644
 -    [424271.641266]  [<f90fa6ee>] ath_rx_tasklet+0x88e/0xf70 [ath9k]
 -    [424271.641358]  [<f80a0f2c>] ? ieee80211_rx+0x1dc/0x7c0 [mac80211]
 -    [424271.641445]  [<f90f82db>] ath9k_tasklet+0xcb/0x130 [ath9k]
--    
++    We setup BCN_OFFSET{0,1} registers dynamically, don't have to
++    initialize them.
+     
 -    Bug report:
 -    https://bugzilla.kernel.org/show_bug.cgi?id=70551
 -    
 -    Reported-and-tested-by: Max Sydorenko <maxim.stargazer@gmail.com>
 -    Cc: stable@vger.kernel.org
--    Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
--
+     Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
+ 
 -commit 82ed9e3ccc02797df2ffe4b78127c4cd5f799a41
 -Author: Felix Fietkau <nbd@openwrt.org>
 -Date:   Tue Feb 11 15:54:13 2014 +0100
@@ -2799,36 +2969,55 @@ index a1af6c2..c621ddb 100644
 -commit cb4969634b93c4643a32cc3fbd27d2b288b25771
 -Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
 -Date:   Fri Feb 7 10:29:49 2014 +0530
--
++commit e5c58ca7a48d4c82f282749a978052c47fd95998
++Author: Stanislaw Gruszka <sgruszka@redhat.com>
++Date:   Thu Jun 5 13:52:26 2014 +0200
+ 
 -    ath9k: Fix IQ cal post processing for SoC
--    
++    rt2x00: change order when stop beaconing
+     
 -    Calibration data is not reused for SoC chips, so
 -    call ar9003_hw_tx_iq_cal_post_proc() with the correct
 -    argument. The 'is_reusable' flag is currently used
 -    only for PC-OEM chips, but it makes things clearer to
 -    specify it explicity.
--    
++    When no beaconing is needed, first stop beacon queue (disable beaconing
++    globally) to avoid possible sending of not prepared beacon on short
++    period after clearing beacon and before stop of BCN queue.
+     
 -    Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
--
++    Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
+ 
 -commit e138e0ef9560c46ce93dbb22a728a57888e94d1c
 -Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
 -Date:   Mon Feb 3 13:31:37 2014 +0530
--
++commit 382c1b9e03f52d0cd741ef1d942cad0f649f0744
++Author: Stanislaw Gruszka <sgruszka@redhat.com>
++Date:   Thu Jun 5 13:52:25 2014 +0200
+ 
 -    ath9k: Fix TX power calculation
--    
++    rt2x00: change default MAC_BSSID_DW1_BSS_BCN_NUM
+     
 -    The commit, "ath9k_hw: Fix incorrect Tx control power in AR9003 template"
 -    fixed the incorrect values in the eeprom templates, but if
 -    boards have already been calibrated with incorrect values,
 -    they would still be using the wrong TX power. Fix this by assigning
 -    a default value in such cases.
--    
++    We setup MAC_BSSID_DW1_BSS_BCN_NUM dynamically when numbers of active
++    beacons increase. Change default to 0 to tell hardware that we want to
++    send only one beacon as default.
+     
 -    Cc: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
 -    Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
--
++    Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
+ 
 -commit b9f268b5b01331c3c82179abca551429450e9417
 -Author: Michal Kazior <michal.kazior@tieto.com>
 -Date:   Wed Jan 29 14:22:27 2014 +0100
--
++commit 3b400571dd033e46fa7e76c5bb92a3ce8198afa9
++Author: Stanislaw Gruszka <sgruszka@redhat.com>
++Date:   Thu Jun 5 13:52:24 2014 +0200
+ 
 -    cfg80211: consider existing DFS interfaces
 -    
 -    It was possible to break interface combinations in
@@ -2836,13 +3025,20 @@ index a1af6c2..c621ddb 100644
 -    
 -     combo 1: iftype = AP, num_ifaces = 2, num_chans = 2,
 -     combo 2: iftype = AP, num_ifaces = 1, num_chans = 1, radar = HT20
--    
++    rt2x00: change beaconing setup on RT2800
+     
 -    With the above interface combinations it was
 -    possible to:
--    
++    As reported by Matthias, on 5572 chip, even if we clear up TXWI
++    of corresponding beacon, hardware still try to send it or do other
++    action that increase power consumption peak up to 1A.
+     
 -     step 1. start AP on DFS channel by matching combo 2
 -     step 2. start AP on non-DFS channel by matching combo 1
--    
++    To avoid the issue, setup beaconing dynamically by configuring offsets
++    of currently active beacons and MAC_BSSID_DW1_BSS_BCN_NUM variable,
++    which limit number of beacons that hardware will try to send.
+     
 -    This was possible beacuse (step 2) did not consider
 -    if other interfaces require radar detection.
 -    
@@ -2852,11 +3048,16 @@ index a1af6c2..c621ddb 100644
 -    
 -    Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
 -    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
--
++    Reported-by: Matthias Fend <Matthias.Fend@wolfvision.net>
++    Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
+ 
 -commit bc9c62f5f511cc395c62dbf4cdd437f23db53b28
 -Author: Antonio Quartulli <antonio@open-mesh.com>
 -Date:   Wed Jan 29 17:53:43 2014 +0100
--
++commit 916e591b2cc41f7e572992175ca56d866d7bc958
++Author: Stanislaw Gruszka <sgruszka@redhat.com>
++Date:   Thu Jun 5 13:52:23 2014 +0200
+ 
 -    cfg80211: fix channel configuration in IBSS join
 -    
 -    When receiving an IBSS_JOINED event select the BSS object
@@ -2876,12 +3077,15 @@ index a1af6c2..c621ddb 100644
 -    this ambiguity and retrieve/create the correct BSS object.
 -    All the users of cfg80211_ibss_joined() have been changed
 -    accordingly.
--    
++    rt2x00: change beaconing locking
+     
 -    Moreover WARN when cfg80211_ibss_joined() gets a NULL
 -    channel as argument and remove a bogus call of the same
 -    function in ath6kl (it does not make sense to call
 -    cfg80211_ibss_joined() with a zero BSSID on ibss-leave).
--    
++    This patch is needed for further changes to keep global variables
++    consistent when changing beaconing on diffrent vif's.
+     
 -    Cc: Kalle Valo <kvalo@qca.qualcomm.com>
 -    Cc: Arend van Spriel <arend@broadcom.com>
 -    Cc: Bing Zhao <bzhao@marvell.com>
@@ -2891,9 +3095,11 @@ index a1af6c2..c621ddb 100644
 -    Signed-off-by: Antonio Quartulli <antonio@open-mesh.com>
 -    [minor code cleanup in ath6kl]
 -    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
--
++    Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
+ 
 -commit 7e0c41cb41f215aba2c39b1c237bb4d42ec49a85
--Author: Johannes Berg <johannes.berg@intel.com>
++commit 930b0dffd1731f3f418f9132faea720a23b7af61
+ Author: Johannes Berg <johannes.berg@intel.com>
 -Date:   Fri Jan 24 14:41:44 2014 +0100
 -
 -    mac80211: fix bufferable MMPDU RX handling
@@ -2933,21 +3139,57 @@ index a1af6c2..c621ddb 100644
 -    excessive retries, as it happens quite often that the scanning client
 -    already left the channel. Therefore do it like hostapd and send probe
 -    responses for wildcard SSID only once by using the noack flag.
--    
++Date:   Tue Jun 3 11:18:47 2014 +0200
++
++    mac80211: fix station/driver powersave race
++    
++    It is currently possible to have a race due to the station PS
++    unblock work like this:
++     * station goes to sleep with frames buffered in the driver
++     * driver blocks wakeup
++     * station wakes up again
++     * driver flushes/returns frames, and unblocks, which schedules
++       the unblock work
++     * unblock work starts to run, and checks that the station is
++       awake (i.e. that the WLAN_STA_PS_STA flag isn't set)
++     * we process a received frame with PM=1, setting the flag again
++     * ieee80211_sta_ps_deliver_wakeup() runs, delivering all frames
++       to the driver, and then clearing the WLAN_STA_PS_DRIVER and
++       WLAN_STA_PS_STA flags
++    
++    In this scenario, mac80211 will think that the station is awake,
++    while it really is asleep, and any TX'ed frames should be filtered
++    by the device (it will know that the station is sleeping) but then
++    passed to mac80211 again, which will not buffer it either as it
++    thinks the station is awake, and eventually the packets will be
++    dropped.
++    
++    Fix this by moving the clearing of the flags to exactly where we
++    learn about the situation. This creates a problem of reordering,
++    so introduce another flag indicating that delivery is being done,
++    this new flag also queues frames and is cleared only while the
++    spinlock is held (which the queuing code also holds) so that any
++    concurrent delivery/TX is handled correctly.
+     
 -    Signed-off-by: Simon Wunderlich <simon@open-mesh.com>
 -    [fix typo & 'wildcard SSID' in commit log]
--    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
--
++    Reported-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
+     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+ 
 -commit 0b865d1e6b9c05052adae9315df7cb195dc60c3b
 -Author: Luciano Coelho <luciano.coelho@intel.com>
 -Date:   Tue Jan 28 17:09:08 2014 +0200
--
++commit 6df35206bc6c1c6aad1d8077df5786b4a7f77873
++Author: Felix Fietkau <nbd@openwrt.org>
++Date:   Fri May 23 19:58:14 2014 +0200
+ 
 -    mac80211: ibss: remove unnecessary call to release channel
 -    
 -    The ieee80211_vif_use_channel() function calls
 -    ieee80211_vif_release_channel(), so there's no need to call it
 -    explicitly in __ieee80211_sta_join_ibss().
--    
++    mac80211: reduce packet loss notifications under load
+     
 -    Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
 -    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
 -
@@ -2956,38 +3198,59 @@ index a1af6c2..c621ddb 100644
 -Date:   Wed Jan 29 07:56:21 2014 +0100
 -
 -    mac80211: add missing CSA locking
--    
++    During strong signal fluctuations under high throughput, few consecutive
++    failed A-MPDU transmissions can easily trigger packet loss notification,
++    and thus (in AP mode) client disconnection.
+     
 -    The patch adds a missing sdata lock and adds a few
 -    lockdeps for easier maintenance.
--    
++    Reduce the number of false positives by checking the A-MPDU status flag
++    and treating a failed A-MPDU as a single packet.
+     
 -    Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
 -    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
--
++    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+ 
 -commit ad17ba7d14d225b109b73c177cd446afb8050598
 -Author: Michal Kazior <michal.kazior@tieto.com>
 -Date:   Wed Jan 29 07:56:20 2014 +0100
--
++commit 7b7843a36fbcc568834404c7430ff895d8502131
++Author: Felix Fietkau <nbd@openwrt.org>
++Date:   Fri May 23 19:26:32 2014 +0200
+ 
 -    mac80211: fix sdata->radar_required locking
--    
++    mac80211: fix a memory leak on sta rate selection table
+     
 -    radar_required setting wasn't protected by
 -    local->mtx in some places. This should prevent
 -    from scanning/radar detection/roc colliding.
 -    
 -    Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
 -    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
--
++    Cc: stable@vger.kernel.org
++    Reported-by: Christophe Prévotaux <cprevotaux@nltinc.com>
++    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+ 
 -commit 5fcd5f1808813a3d9e502fd756e01bee8a79c85d
 -Author: Michal Kazior <michal.kazior@tieto.com>
 -Date:   Wed Jan 29 07:56:19 2014 +0100
--
++commit 96892d6aa0a153423070addf3070bc79578b3897
++Author: Felix Fietkau <nbd@openwrt.org>
++Date:   Mon May 19 21:20:49 2014 +0200
+ 
 -    mac80211: move csa_active setting in STA CSA
--    
++    ath9k: avoid passing buffers to the hardware during flush
+     
 -    The sdata->vif.csa_active could be left set after,
 -    e.g. channel context constraints check fail in STA
 -    mode leaving the interface in a strange state for
 -    a brief period of time until it is disconnected.
 -    This was harmless but ugly.
--    
++    The commit "ath9k: fix possible hang on flush" changed the receive code
++    to always link rx descriptors of processed frames, even when flushing.
++    In some cases, this leads to flushed rx buffers being passed to the
++    hardware while rx is already stopped.
+     
 -    Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
 -    Reviewed-by: Luciano Coelho <luciano.coelho@intel.com>
 -    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
@@ -2995,7 +3258,8 @@ index a1af6c2..c621ddb 100644
 -commit e486da4b7eed71821c6b4c1bb9ac62ffd3ab13e9
 -Author: Michal Kazior <michal.kazior@tieto.com>
 -Date:   Wed Jan 29 07:56:18 2014 +0100
--
++    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+ 
 -    mac80211: fix possible memory leak on AP CSA failure
 -    
 -    If CSA for AP interface failed and the interface
@@ -3456,10 +3720,39 @@ index a1af6c2..c621ddb 100644
 -+		mdelay(10);
 - 	else
 - 		udelay(100);
-- 
++--- a/drivers/net/wireless/ath/ath9k/recv.c
+++++ b/drivers/net/wireless/ath/ath9k/recv.c
++@@ -34,7 +34,8 @@ static inline bool ath9k_check_auto_slee
++  * buffer (or rx fifo). This can incorrectly acknowledge packets
++  * to a sender if last desc is self-linked.
++  */
++-static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf)
+++static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf,
+++			    bool flush)
++ {
++ 	struct ath_hw *ah = sc->sc_ah;
++ 	struct ath_common *common = ath9k_hw_common(ah);
++@@ -59,18 +60,19 @@ static void ath_rx_buf_link(struct ath_s
++ 			     common->rx_bufsize,
++ 			     0);
++ 
++-	if (sc->rx.rxlink == NULL)
++-		ath9k_hw_putrxbuf(ah, bf->bf_daddr);
++-	else
+++	if (sc->rx.rxlink)
++ 		*sc->rx.rxlink = bf->bf_daddr;
+++	else if (!flush)
+++		ath9k_hw_putrxbuf(ah, bf->bf_daddr);
++ 
++ 	sc->rx.rxlink = &ds->ds_link;
++ }
+  
 -@@ -1534,7 +1534,7 @@ EXPORT_SYMBOL(ath9k_hw_check_nav);
 - bool ath9k_hw_check_alive(struct ath_hw *ah)
-- {
++-static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf)
+++static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf,
+++			      bool flush)
+  {
 - 	int count = 50;
 --	u32 reg;
 -+	u32 reg, last_val;
@@ -3491,7 +3784,10 @@ index a1af6c2..c621ddb 100644
 -+		mdelay(10);
 - 	else
 - 		udelay(50);
-- 
++ 	if (sc->rx.buf_hold)
++-		ath_rx_buf_link(sc, sc->rx.buf_hold);
+++		ath_rx_buf_link(sc, sc->rx.buf_hold, flush);
+  
 ---- a/drivers/net/wireless/ath/ath9k/main.c
 -+++ b/drivers/net/wireless/ath/ath9k/main.c
 -@@ -451,7 +451,7 @@ void ath9k_tasklet(unsigned long data)
@@ -3501,8 +3797,16 @@ index a1af6c2..c621ddb 100644
 --		ath_dbg(common, ANY, "FATAL: Skipping interrupts\n");
 -+		ath_dbg(common, RESET, "FATAL: Skipping interrupts\n");
 - 		goto out;
-- 	}
-- 
++ 	sc->rx.buf_hold = bf;
++ }
++@@ -442,7 +444,7 @@ int ath_startrecv(struct ath_softc *sc)
++ 	sc->rx.buf_hold = NULL;
++ 	sc->rx.rxlink = NULL;
++ 	list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) {
++-		ath_rx_buf_link(sc, bf);
+++		ath_rx_buf_link(sc, bf, false);
+  	}
+  
 -@@ -471,7 +471,7 @@ void ath9k_tasklet(unsigned long data)
 - 			 * interrupts are enabled in the reset routine.
 - 			 */
@@ -3520,9 +3824,24 @@ index a1af6c2..c621ddb 100644
 -+			ath_dbg(common, RESET,
 - 				"GTT: Skipping interrupts\n");
 - 			goto out;
-- 		}
--@@ -1866,7 +1866,7 @@ static void ath9k_set_coverage_class(str
-- 
++ 	/* We could have deleted elements so the list may be empty now */
++@@ -1118,12 +1120,12 @@ requeue_drop_frag:
++ requeue:
++ 		list_add_tail(&bf->list, &sc->rx.rxbuf);
++ 
++-		if (edma) {
++-			ath_rx_edma_buf_link(sc, qtype);
++-		} else {
++-			ath_rx_buf_relink(sc, bf);
+++		if (!edma) {
+++			ath_rx_buf_relink(sc, bf, flush);
++ 			if (!flush)
++ 				ath9k_hw_rxena(ah);
+++		} else if (!flush) {
+++			ath_rx_edma_buf_link(sc, qtype);
+  		}
+-@@ -1866,7 +1866,7 @@ static void ath9k_set_coverage_class(str
+  
 - static bool ath9k_has_tx_pending(struct ath_softc *sc)
 - {
 --	int i, npend;
@@ -3590,7 +3909,12 @@ index a1af6c2..c621ddb 100644
 -+++ b/include/linux/ieee80211.h
 -@@ -597,6 +597,20 @@ static inline int ieee80211_is_qos_nullf
 - }
-- 
++ 		if (!budget--)
++--- a/net/mac80211/sta_info.c
+++++ b/net/mac80211/sta_info.c
++@@ -100,7 +100,8 @@ static void __cleanup_single_sta(struct 
++ 	struct ps_data *ps;
+  
 - /**
 -+ * ieee80211_is_bufferable_mmpdu - check if frame is bufferable MMPDU
 -+ * @fc: frame control field in little-endian byteorder
@@ -3611,7 +3935,15 @@ index a1af6c2..c621ddb 100644
 -  */
 -@@ -2192,10 +2206,10 @@ static inline u8 *ieee80211_get_DA(struc
 - }
-- 
++ 	if (test_sta_flag(sta, WLAN_STA_PS_STA) ||
++-	    test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
+++	    test_sta_flag(sta, WLAN_STA_PS_DRIVER) ||
+++	    test_sta_flag(sta, WLAN_STA_PS_DELIVER)) {
++ 		if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
++ 		    sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
++ 			ps = &sdata->bss->ps;
++@@ -111,6 +112,7 @@ static void __cleanup_single_sta(struct 
+  
 - /**
 -- * ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame
 -+ * _ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame
@@ -3624,7 +3956,10 @@ index a1af6c2..c621ddb 100644
 - 	    ieee80211_is_deauth(hdr->frame_control))
 -@@ -2224,6 +2238,17 @@ static inline bool ieee80211_is_robust_m
 - }
-- 
++ 		clear_sta_flag(sta, WLAN_STA_PS_STA);
++ 		clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
+++		clear_sta_flag(sta, WLAN_STA_PS_DELIVER);
+  
 - /**
 -+ * ieee80211_is_robust_mgmt_frame - check if skb contains a robust mgmt frame
 -+ * @skb: the skb containing the frame, length will be checked
@@ -3652,7 +3987,12 @@ index a1af6c2..c621ddb 100644
 - 	struct cfg80211_ssid ssid;
 -+	s32 rssi_thold;
 - };
-- 
++ 		atomic_dec(&ps->num_sta_ps);
++ 		sta_info_recalc_tim(sta);
++@@ -125,7 +127,7 @@ static void __cleanup_single_sta(struct 
++ 	if (ieee80211_vif_is_mesh(&sdata->vif))
++ 		mesh_sta_cleanup(sta);
+  
 - /**
 -@@ -1420,7 +1422,8 @@ struct cfg80211_match_set {
 -  * @dev: the interface
@@ -3692,7 +4032,9 @@ index a1af6c2..c621ddb 100644
 --	/* for AP and mesh channel tracking */
 --	struct ieee80211_channel *channel;
 -+	struct cfg80211_chan_def chandef;
-- 
++-	cancel_work_sync(&sta->drv_unblock_wk);
+++	cancel_work_sync(&sta->drv_deliver_wk);
+  
 - 	bool ibss_fixed;
 - 	bool ibss_dfs_possible;
 -@@ -3879,6 +3880,7 @@ void cfg80211_michael_mic_failure(struct
@@ -3706,7 +4048,10 @@ index a1af6c2..c621ddb 100644
 -@@ -3888,7 +3890,8 @@ void cfg80211_michael_mic_failure(struct
 -  * with the locally generated beacon -- this guarantees that there is
 -  * always a scan result for this IBSS. cfg80211 will handle the rest.
--  */
++ 	/*
++ 	 * Destroy aggregation state here. It would be nice to wait for the
++@@ -227,6 +229,7 @@ struct sta_info *sta_info_get_by_idx(str
+   */
 --void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp);
 -+void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
 -+			  struct ieee80211_channel *channel, gfp_t gfp);
@@ -3759,7 +4104,11 @@ index a1af6c2..c621ddb 100644
 - 	mutex_unlock(&local->mtx);
 -@@ -1021,8 +1021,10 @@ static int ieee80211_start_ap(struct wip
 - 					IEEE80211_P2P_OPPPS_ENABLE_BIT;
-- 
++ void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
++ {
+++	struct ieee80211_sta_rates *rates;
++ 	int i;
+  
 - 	err = ieee80211_assign_beacon(sdata, &params->beacon);
 --	if (err < 0)
 -+	if (err < 0) {
@@ -3775,8 +4124,11 @@ index a1af6c2..c621ddb 100644
 - 		RCU_INIT_POINTER(sdata->u.ap.beacon, NULL);
 -+		ieee80211_vif_release_channel(sdata);
 - 		return err;
-- 	}
-- 
++ 	if (sta->rate_ctrl)
++@@ -238,6 +241,10 @@ void sta_info_free(struct ieee80211_loca
++ 		kfree(sta->tx_lat);
+  	}
+  
 -@@ -1053,6 +1056,7 @@ static int ieee80211_change_beacon(struc
 - 	int err;
 - 
@@ -3790,14 +4142,18 @@ index a1af6c2..c621ddb 100644
 - 	struct cfg80211_chan_def chandef;
 - 
 -+	sdata_assert_lock(sdata);
--+
+++	rates = rcu_dereference_protected(sta->sta.rates, true);
+++	if (rates)
+++		kfree(rates);
+ +
 - 	old_beacon = sdata_dereference(sdata->u.ap.beacon, sdata);
 - 	if (!old_beacon)
 - 		return -ENOENT;
 -@@ -1090,8 +1096,6 @@ static int ieee80211_stop_ap(struct wiph
 - 	kfree(sdata->u.ap.next_beacon);
 - 	sdata->u.ap.next_beacon = NULL;
-- 
++ 	sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr);
+  
 --	cancel_work_sync(&sdata->u.ap.request_smps_work);
 --
 - 	/* turn off carrier for this interface and dependent VLANs */
@@ -3869,8 +4225,11 @@ index a1af6c2..c621ddb 100644
 --	}
 --
 - 	return 0;
-- }
-- 
++ 	kfree(sta);
++@@ -252,33 +259,23 @@ static void sta_info_hash_add(struct iee
++ 	rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], sta);
+  }
+  
 -@@ -3004,8 +3012,10 @@ void ieee80211_csa_finalize_work(struct 
 - 	if (!ieee80211_sdata_running(sdata))
 - 		goto unlock;
@@ -3930,23 +4289,45 @@ index a1af6c2..c621ddb 100644
 -+					    sdata->u.ap.driver_smps_mode);
 - 	sdata_unlock(sdata);
 - }
-- 
++-static void sta_unblock(struct work_struct *wk)
+++static void sta_deliver_ps_frames(struct work_struct *wk)
++ {
++ 	struct sta_info *sta;
+  
 ---- a/net/mac80211/iface.c
 -+++ b/net/mac80211/iface.c
 -@@ -770,12 +770,19 @@ static void ieee80211_do_stop(struct iee
-- 
++-	sta = container_of(wk, struct sta_info, drv_unblock_wk);
+++	sta = container_of(wk, struct sta_info, drv_deliver_wk);
+  
 - 	ieee80211_roc_purge(local, sdata);
-- 
++ 	if (sta->dead)
++ 		return;
+  
 --	if (sdata->vif.type == NL80211_IFTYPE_STATION)
 -+	switch (sdata->vif.type) {
 -+	case NL80211_IFTYPE_STATION:
 - 		ieee80211_mgd_stop(sdata);
---
++-	if (!test_sta_flag(sta, WLAN_STA_PS_STA)) {
++-		local_bh_disable();
+++	local_bh_disable();
+++	if (!test_sta_flag(sta, WLAN_STA_PS_STA))
++ 		ieee80211_sta_ps_deliver_wakeup(sta);
++-		local_bh_enable();
++-	} else if (test_and_clear_sta_flag(sta, WLAN_STA_PSPOLL)) {
++-		clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
+ -
 --	if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
 -+		break;
 -+	case NL80211_IFTYPE_ADHOC:
 - 		ieee80211_ibss_stop(sdata);
---
++-		local_bh_disable();
+++	else if (test_and_clear_sta_flag(sta, WLAN_STA_PSPOLL))
++ 		ieee80211_sta_ps_deliver_poll_response(sta);
++-		local_bh_enable();
++-	} else if (test_and_clear_sta_flag(sta, WLAN_STA_UAPSD)) {
++-		clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
+ -
 -+		break;
 -+	case NL80211_IFTYPE_AP:
 -+		cancel_work_sync(&sdata->u.ap.request_smps_work);
@@ -3979,9 +4360,18 @@ index a1af6c2..c621ddb 100644
 - 
 --	return ieee80211_is_robust_mgmt_frame(hdr);
 -+	return ieee80211_is_robust_mgmt_frame(skb);
-- }
-- 
-- 
++-		local_bh_disable();
+++	else if (test_and_clear_sta_flag(sta, WLAN_STA_UAPSD))
++ 		ieee80211_sta_ps_deliver_uapsd(sta);
++-		local_bh_enable();
++-	} else
++-		clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
+++	local_bh_enable();
+  }
+  
++ static int sta_prepare_rate_control(struct ieee80211_local *local,
++@@ -340,7 +337,7 @@ struct sta_info *sta_info_alloc(struct i
+  
 -@@ -610,10 +610,10 @@ static int ieee80211_is_multicast_robust
 - {
 - 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
@@ -4053,8 +4443,16 @@ index a1af6c2..c621ddb 100644
 --				     (struct ieee80211_hdr *) rx->skb->data)))
 -+			     ieee80211_is_robust_mgmt_frame(rx->skb)))
 - 			return -EACCES;
-- 	}
-- 
++ 	spin_lock_init(&sta->lock);
++ 	spin_lock_init(&sta->ps_lock);
++-	INIT_WORK(&sta->drv_unblock_wk, sta_unblock);
+++	INIT_WORK(&sta->drv_deliver_wk, sta_deliver_ps_frames);
++ 	INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work);
++ 	mutex_init(&sta->ampdu_mlme.mtx);
++ #ifdef CPTCFG_MAC80211_MESH
++@@ -1140,8 +1137,15 @@ void ieee80211_sta_ps_deliver_wakeup(str
+  	}
+  
 ---- a/net/mac80211/tx.c
 -+++ b/net/mac80211/tx.c
 -@@ -452,8 +452,7 @@ static int ieee80211_use_mfp(__le16 fc, 
@@ -4071,7 +4469,10 @@ index a1af6c2..c621ddb 100644
 - 		       sta->sta.addr, sta->sta.aid, ac);
 - 		if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
 - 			purge_old_ps_buffers(tx->local);
--+
++ 	ieee80211_add_pending_skbs(local, &pending);
++-	clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
++-	clear_sta_flag(sta, WLAN_STA_PS_STA);
+ +
 -+		/* sync with ieee80211_sta_ps_deliver_wakeup */
 -+		spin_lock(&sta->ps_lock);
 -+		/*
@@ -4084,7 +4485,9 @@ index a1af6c2..c621ddb 100644
 -+			spin_unlock(&sta->ps_lock);
 -+			return TX_CONTINUE;
 -+		}
--+
+++	/* now we're no longer in the deliver code */
+++	clear_sta_flag(sta, WLAN_STA_PS_DELIVER);
+ +
 - 		if (skb_queue_len(&sta->ps_tx_buf[ac]) >= STA_MAX_TX_BUFFER) {
 - 			struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf[ac]);
 - 			ps_dbg(tx->sdata,
@@ -4172,23 +4575,55 @@ index a1af6c2..c621ddb 100644
 - 		rdev_set_qos_map(rdev, dev, NULL);
 -+		nl80211_send_ap_stopped(wdev);
 - 	}
-- 
+++	/* The station might have polled and then woken up before we responded,
+++	 * so clear these flags now to avoid them sticking around.
+++	 */
+++	clear_sta_flag(sta, WLAN_STA_PSPOLL);
+++	clear_sta_flag(sta, WLAN_STA_UAPSD);
++ 	spin_unlock(&sta->ps_lock);
+  
 - 	return err;
 ---- a/net/wireless/core.c
 -+++ b/net/wireless/core.c
 -@@ -203,8 +203,11 @@ void cfg80211_stop_p2p_device(struct cfg
-- 
++ 	atomic_dec(&ps->num_sta_ps);
++@@ -1542,10 +1546,26 @@ void ieee80211_sta_block_awake(struct ie
+  
 - 	rdev->opencount--;
-- 
++ 	trace_api_sta_block_awake(sta->local, pubsta, block);
+  
 --	WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev &&
 --		!rdev->scan_req->notified);
 -+	if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
 -+		if (WARN_ON(!rdev->scan_req->notified))
 -+			rdev->scan_req->aborted = true;
 -+		___cfg80211_scan_done(rdev, false);
--+	}
-- }
-- 
++-	if (block)
+++	if (block) {
++ 		set_sta_flag(sta, WLAN_STA_PS_DRIVER);
++-	else if (test_sta_flag(sta, WLAN_STA_PS_DRIVER))
++-		ieee80211_queue_work(hw, &sta->drv_unblock_wk);
+++		return;
+++	}
+++
+++	if (!test_sta_flag(sta, WLAN_STA_PS_DRIVER))
+++		return;
+++
+++	if (!test_sta_flag(sta, WLAN_STA_PS_STA)) {
+++		set_sta_flag(sta, WLAN_STA_PS_DELIVER);
+++		clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
+++		ieee80211_queue_work(hw, &sta->drv_deliver_wk);
+++	} else if (test_sta_flag(sta, WLAN_STA_PSPOLL) ||
+++		   test_sta_flag(sta, WLAN_STA_UAPSD)) {
+++		/* must be asleep in this case */
+++		clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
+++		ieee80211_queue_work(hw, &sta->drv_deliver_wk);
+++	} else {
+++		clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
+ +	}
+  }
++ EXPORT_SYMBOL(ieee80211_sta_block_awake);
+  
 - static int cfg80211_rfkill_set_block(void *data, bool blocked)
 -@@ -447,9 +450,6 @@ int wiphy_register(struct wiphy *wiphy)
 - 	int i;
@@ -4206,7 +4641,10 @@ index a1af6c2..c621ddb 100644
 - 	}
 --
 --	wdev->beacon_interval = 0;
-- }
++@@ -1703,3 +1723,137 @@ u8 sta_info_tx_streams(struct sta_info *
++ 	return ((ht_cap->mcs.tx_params & IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
++ 			>> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT) + 1;
+  }
 - 
 - static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
 -@@ -875,8 +873,11 @@ static int cfg80211_netdev_notifier_call
@@ -4364,7 +4802,7 @@ index a1af6c2..c621ddb 100644
 --			n_match_sets++;
 -+				    tmp) {
 -+			struct nlattr *rssi;
--+
+ +
 -+			err = nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
 -+					nla_data(attr), nla_len(attr),
 -+					nl80211_match_policy);
@@ -4378,9 +4816,70 @@ index a1af6c2..c621ddb 100644
 -+			rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
 -+			if (rssi)
 -+				default_match_rssi = nla_get_s32(rssi);
--+		}
--+	}
--+
+++void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
+++{
+++	struct ieee80211_sub_if_data *sdata = sta->sdata;
+++	struct ieee80211_local *local = sdata->local;
+++	struct rate_control_ref *ref = local->rate_ctrl;
+++	struct timespec uptime;
+++	u64 packets = 0;
+++	u32 thr = 0;
+++	int i, ac;
+++
+++	sinfo->generation = sdata->local->sta_generation;
+++
+++	sinfo->filled = STATION_INFO_INACTIVE_TIME |
+++			STATION_INFO_RX_BYTES64 |
+++			STATION_INFO_TX_BYTES64 |
+++			STATION_INFO_RX_PACKETS |
+++			STATION_INFO_TX_PACKETS |
+++			STATION_INFO_TX_RETRIES |
+++			STATION_INFO_TX_FAILED |
+++			STATION_INFO_TX_BITRATE |
+++			STATION_INFO_RX_BITRATE |
+++			STATION_INFO_RX_DROP_MISC |
+++			STATION_INFO_BSS_PARAM |
+++			STATION_INFO_CONNECTED_TIME |
+++			STATION_INFO_STA_FLAGS |
+++			STATION_INFO_BEACON_LOSS_COUNT;
+++
+++	do_posix_clock_monotonic_gettime(&uptime);
+++	sinfo->connected_time = uptime.tv_sec - sta->last_connected;
+++
+++	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
+++	sinfo->tx_bytes = 0;
+++	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
+++		sinfo->tx_bytes += sta->tx_bytes[ac];
+++		packets += sta->tx_packets[ac];
+++	}
+++	sinfo->tx_packets = packets;
+++	sinfo->rx_bytes = sta->rx_bytes;
+++	sinfo->rx_packets = sta->rx_packets;
+++	sinfo->tx_retries = sta->tx_retry_count;
+++	sinfo->tx_failed = sta->tx_retry_failed;
+++	sinfo->rx_dropped_misc = sta->rx_dropped;
+++	sinfo->beacon_loss_count = sta->beacon_loss_count;
+++
+++	if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) ||
+++	    (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) {
+++		sinfo->filled |= STATION_INFO_SIGNAL | STATION_INFO_SIGNAL_AVG;
+++		if (!local->ops->get_rssi ||
+++		    drv_get_rssi(local, sdata, &sta->sta, &sinfo->signal))
+++			sinfo->signal = (s8)sta->last_signal;
+++		sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal);
+++	}
+++	if (sta->chains) {
+++		sinfo->filled |= STATION_INFO_CHAIN_SIGNAL |
+++				 STATION_INFO_CHAIN_SIGNAL_AVG;
+++
+++		sinfo->chains = sta->chains;
+++		for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) {
+++			sinfo->chain_signal[i] = sta->chain_signal_last[i];
+++			sinfo->chain_signal_avg[i] =
+++				(s8) -ewma_read(&sta->chain_signal_avg[i]);
+ +		}
+ +	}
+ +
 -+	/* However, if there's no other matchset, add the RSSI one */
 -+	if (!n_match_sets && default_match_rssi != NL80211_SCAN_RSSI_THOLD_OFF)
 -+		n_match_sets = 1;
@@ -4437,7 +4936,31 @@ index a1af6c2..c621ddb 100644
 -+		/* there was no other matchset, so the RSSI one is alone */
 -+		if (i == 0)
 -+			request->match_sets[0].rssi_thold = default_match_rssi;
--+
+++	sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate);
+++	sta_set_rate_info_rx(sta, &sinfo->rxrate);
+++
+++	if (ieee80211_vif_is_mesh(&sdata->vif)) {
+++#ifdef CPTCFG_MAC80211_MESH
+++		sinfo->filled |= STATION_INFO_LLID |
+++				 STATION_INFO_PLID |
+++				 STATION_INFO_PLINK_STATE |
+++				 STATION_INFO_LOCAL_PM |
+++				 STATION_INFO_PEER_PM |
+++				 STATION_INFO_NONPEER_PM;
+++
+++		sinfo->llid = sta->llid;
+++		sinfo->plid = sta->plid;
+++		sinfo->plink_state = sta->plink_state;
+++		if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) {
+++			sinfo->filled |= STATION_INFO_T_OFFSET;
+++			sinfo->t_offset = sta->t_offset;
+++		}
+++		sinfo->local_pm = sta->local_pm;
+++		sinfo->peer_pm = sta->peer_pm;
+++		sinfo->nonpeer_pm = sta->nonpeer_pm;
+++#endif
+++	}
+ +
 -+		request->min_rssi_thold = INT_MAX;
 -+		for (i = 0; i < n_match_sets; i++)
 -+			request->min_rssi_thold =
@@ -4466,7 +4989,45 @@ index a1af6c2..c621ddb 100644
 -+	nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem) {
 - 		enum ieee80211_band band = nla_type(tx_rates);
 -+		int err;
--+
+++	sinfo->bss_param.flags = 0;
+++	if (sdata->vif.bss_conf.use_cts_prot)
+++		sinfo->bss_param.flags |= BSS_PARAM_FLAGS_CTS_PROT;
+++	if (sdata->vif.bss_conf.use_short_preamble)
+++		sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE;
+++	if (sdata->vif.bss_conf.use_short_slot)
+++		sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME;
+++	sinfo->bss_param.dtim_period = sdata->local->hw.conf.ps_dtim_period;
+++	sinfo->bss_param.beacon_interval = sdata->vif.bss_conf.beacon_int;
+++
+++	sinfo->sta_flags.set = 0;
+++	sinfo->sta_flags.mask = BIT(NL80211_STA_FLAG_AUTHORIZED) |
+++				BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
+++				BIT(NL80211_STA_FLAG_WME) |
+++				BIT(NL80211_STA_FLAG_MFP) |
+++				BIT(NL80211_STA_FLAG_AUTHENTICATED) |
+++				BIT(NL80211_STA_FLAG_ASSOCIATED) |
+++				BIT(NL80211_STA_FLAG_TDLS_PEER);
+++	if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
+++		sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHORIZED);
+++	if (test_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE))
+++		sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);
+++	if (test_sta_flag(sta, WLAN_STA_WME))
+++		sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_WME);
+++	if (test_sta_flag(sta, WLAN_STA_MFP))
+++		sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_MFP);
+++	if (test_sta_flag(sta, WLAN_STA_AUTH))
+++		sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
+++	if (test_sta_flag(sta, WLAN_STA_ASSOC))
+++		sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_ASSOCIATED);
+++	if (test_sta_flag(sta, WLAN_STA_TDLS_PEER))
+++		sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
+++
+++	/* check if the driver has a SW RC implementation */
+++	if (ref && ref->ops->get_expected_throughput)
+++		thr = ref->ops->get_expected_throughput(sta->rate_ctrl_priv);
+++	else
+++		thr = drv_get_expected_throughput(local, &sta->sta);
+ +
 - 		if (band < 0 || band >= IEEE80211_NUM_BANDS)
 - 			return -EINVAL;
 - 		sband = rdev->wiphy.bands[band];
@@ -4544,18 +5105,33 @@ index a1af6c2..c621ddb 100644
 -@@ -11673,6 +11727,35 @@ void cfg80211_crit_proto_stopped(struct 
 - }
 - EXPORT_SYMBOL(cfg80211_crit_proto_stopped);
-- 
+++	if (thr != 0) {
+++		sinfo->filled |= STATION_INFO_EXPECTED_THROUGHPUT;
+++		sinfo->expected_throughput = thr;
+++	}
+++}
++--- a/net/mac80211/status.c
+++++ b/net/mac80211/status.c
++@@ -541,6 +541,23 @@ static void ieee80211_tx_latency_end_msr
++  */
++ #define STA_LOST_PKT_THRESHOLD	50
+  
 -+void nl80211_send_ap_stopped(struct wireless_dev *wdev)
--+{
+++static void ieee80211_lost_packet(struct sta_info *sta, struct sk_buff *skb)
+ +{
 -+	struct wiphy *wiphy = wdev->wiphy;
 -+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 -+	struct sk_buff *msg;
 -+	void *hdr;
--+
+++	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ +
 -+	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
 -+	if (!msg)
--+		return;
--+
+++	/* This packet was aggregated but doesn't carry status info */
+++	if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
+++	    !(info->flags & IEEE80211_TX_STAT_AMPDU))
+ +		return;
+ +
 -+	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_STOP_AP);
 -+	if (!hdr)
 -+		goto out;
@@ -4566,14 +5142,19 @@ index a1af6c2..c621ddb 100644
 -+		goto out;
 -+
 -+	genlmsg_end(msg, hdr);
--+
+++	if (++sta->lost_packets < STA_LOST_PKT_THRESHOLD)
+++		return;
+ +
 -+	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(wiphy), msg, 0,
 -+				NL80211_MCGRP_MLME, GFP_KERNEL);
 -+	return;
 -+ out:
 -+	nlmsg_free(msg);
--+}
--+
+++	cfg80211_cqm_pktloss_notify(sta->sdata->dev, sta->sta.addr,
+++				    sta->lost_packets, GFP_ATOMIC);
+++	sta->lost_packets = 0;
+ +}
+ +
 - /* initialisation/exit functions */
 - 
 - int nl80211_init(void)
@@ -4612,7 +5193,8 @@ index a1af6c2..c621ddb 100644
 --void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev)
 -+void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
 -+			   bool send_message)
-- {
++ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
+  {
 - 	struct cfg80211_scan_request *request;
 - 	struct wireless_dev *wdev;
 -+	struct sk_buff *msg;
@@ -4628,19 +5210,37 @@ index a1af6c2..c621ddb 100644
 -+		rdev->scan_msg = NULL;
 -+		return;
 -+	}
-- 
--+	request = rdev->scan_req;
-- 	if (!request)
-- 		return;
-- 
--@@ -186,18 +193,16 @@ void ___cfg80211_scan_done(struct cfg802
-- 	if (wdev->netdev)
-- 		cfg80211_sme_scan_done(wdev->netdev);
-- 
---	if (request->aborted) {
---		nl80211_send_scan_aborted(rdev, wdev);
---	} else {
---		if (request->flags & NL80211_SCAN_FLAG_FLUSH) {
++ 	struct sk_buff *skb2;
++@@ -680,12 +697,8 @@ void ieee80211_tx_status(struct ieee8021
++ 			if (info->flags & IEEE80211_TX_STAT_ACK) {
++ 				if (sta->lost_packets)
++ 					sta->lost_packets = 0;
++-			} else if (++sta->lost_packets >= STA_LOST_PKT_THRESHOLD) {
++-				cfg80211_cqm_pktloss_notify(sta->sdata->dev,
++-							    sta->sta.addr,
++-							    sta->lost_packets,
++-							    GFP_ATOMIC);
++-				sta->lost_packets = 0;
+++			} else {
+++				ieee80211_lost_packet(sta, skb);
++ 			}
++ 		}
+  
+-+	request = rdev->scan_req;
+- 	if (!request)
++--- a/net/mac80211/rx.c
+++++ b/net/mac80211/rx.c
++@@ -1107,6 +1107,8 @@ static void sta_ps_end(struct sta_info *
+  		return;
+- 
+-@@ -186,18 +193,16 @@ void ___cfg80211_scan_done(struct cfg802
+- 	if (wdev->netdev)
+- 		cfg80211_sme_scan_done(wdev->netdev);
+- 
+--	if (request->aborted) {
+--		nl80211_send_scan_aborted(rdev, wdev);
+--	} else {
+--		if (request->flags & NL80211_SCAN_FLAG_FLUSH) {
 --			/* flush entries from previous scans */
 --			spin_lock_bh(&rdev->bss_lock);
 --			__cfg80211_bss_expire(rdev, request->scan_start);
@@ -4653,8 +5253,8 @@ index a1af6c2..c621ddb 100644
 -+		spin_lock_bh(&rdev->bss_lock);
 -+		__cfg80211_bss_expire(rdev, request->scan_start);
 -+		spin_unlock_bh(&rdev->bss_lock);
-- 	}
-- 
+  	}
+  
 -+	msg = nl80211_build_scan_msg(rdev, wdev, request->aborted);
 -+
 - #ifdef CPTCFG_CFG80211_WEXT
@@ -4669,22 +5269,87 @@ index a1af6c2..c621ddb 100644
 -+		rdev->scan_msg = msg;
 -+	else
 -+		nl80211_send_scan_result(rdev, msg);
-- }
-- 
+++	set_sta_flag(sta, WLAN_STA_PS_DELIVER);
+++	clear_sta_flag(sta, WLAN_STA_PS_STA);
++ 	ieee80211_sta_ps_deliver_wakeup(sta);
+  }
+  
 - void __cfg80211_scan_done(struct work_struct *wk)
 -@@ -221,7 +231,7 @@ void __cfg80211_scan_done(struct work_st
 - 			    scan_done_wk);
-- 
++--- a/net/mac80211/sta_info.h
+++++ b/net/mac80211/sta_info.h
++@@ -82,6 +82,7 @@ enum ieee80211_sta_info_flags {
++ 	WLAN_STA_TOFFSET_KNOWN,
++ 	WLAN_STA_MPSP_OWNER,
++ 	WLAN_STA_MPSP_RECIPIENT,
+++	WLAN_STA_PS_DELIVER,
++ };
+  
 - 	rtnl_lock();
 --	___cfg80211_scan_done(rdev);
 -+	___cfg80211_scan_done(rdev, true);
 - 	rtnl_unlock();
 - }
-- 
++ #define ADDBA_RESP_INTERVAL HZ
++@@ -265,7 +266,7 @@ struct ieee80211_tx_latency_stat {
++  * @last_rx_rate_vht_nss: rx status nss of last data packet
++  * @lock: used for locking all fields that require locking, see comments
++  *	in the header file.
++- * @drv_unblock_wk: used for driver PS unblocking
+++ * @drv_deliver_wk: used for delivering frames after driver PS unblocking
++  * @listen_interval: listen interval of this station, when we're acting as AP
++  * @_flags: STA flags, see &enum ieee80211_sta_info_flags, do not use directly
++  * @ps_lock: used for powersave (when mac80211 is the AP) related locking
++@@ -278,7 +279,6 @@ struct ieee80211_tx_latency_stat {
++  * @driver_buffered_tids: bitmap of TIDs the driver has data buffered on
++  * @rx_packets: Number of MSDUs received from this STA
++  * @rx_bytes: Number of bytes received from this STA
++- * @wep_weak_iv_count: number of weak WEP IVs received from this station
++  * @last_rx: time (in jiffies) when last frame was received from this STA
++  * @last_connected: time (in seconds) when a station got connected
++  * @num_duplicates: number of duplicate frames received from this STA
++@@ -345,7 +345,7 @@ struct sta_info {
++ 	void *rate_ctrl_priv;
++ 	spinlock_t lock;
++ 
++-	struct work_struct drv_unblock_wk;
+++	struct work_struct drv_deliver_wk;
++ 
++ 	u16 listen_interval;
++ 
++@@ -367,7 +367,6 @@ struct sta_info {
++ 	/* Updated from RX path only, no locking requirements */
++ 	unsigned long rx_packets;
++ 	u64 rx_bytes;
++-	unsigned long wep_weak_iv_count;
++ 	unsigned long last_rx;
++ 	long last_connected;
++ 	unsigned long num_duplicates;
++@@ -628,6 +627,8 @@ void sta_set_rate_info_tx(struct sta_inf
++ 			  struct rate_info *rinfo);
++ void sta_set_rate_info_rx(struct sta_info *sta,
++ 			  struct rate_info *rinfo);
+++void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo);
+++
++ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
++ 			  unsigned long exp_time);
++ u8 sta_info_tx_streams(struct sta_info *sta);
++--- a/net/mac80211/tx.c
+++++ b/net/mac80211/tx.c
++@@ -469,7 +469,8 @@ ieee80211_tx_h_unicast_ps_buf(struct iee
++ 		return TX_CONTINUE;
+  
 -@@ -1079,7 +1089,7 @@ int cfg80211_wext_siwscan(struct net_dev
 - 	if (IS_ERR(rdev))
 - 		return PTR_ERR(rdev);
-- 
++ 	if (unlikely((test_sta_flag(sta, WLAN_STA_PS_STA) ||
++-		      test_sta_flag(sta, WLAN_STA_PS_DRIVER)) &&
+++		      test_sta_flag(sta, WLAN_STA_PS_DRIVER) ||
+++		      test_sta_flag(sta, WLAN_STA_PS_DELIVER)) &&
++ 		     !(info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER))) {
++ 		int ac = skb_get_queue_mapping(tx->skb);
+  
 --	if (rdev->scan_req) {
 -+	if (rdev->scan_req || rdev->scan_msg) {
 - 		err = -EBUSY;
@@ -4714,18 +5379,59 @@ index a1af6c2..c621ddb 100644
 -+++ b/net/mac80211/mlme.c
 -@@ -1001,7 +1001,6 @@ ieee80211_sta_process_chanswitch(struct 
 - 	}
-- 
++@@ -486,7 +487,8 @@ ieee80211_tx_h_unicast_ps_buf(struct iee
++ 		 * ahead and Tx the packet.
++ 		 */
++ 		if (!test_sta_flag(sta, WLAN_STA_PS_STA) &&
++-		    !test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
+++		    !test_sta_flag(sta, WLAN_STA_PS_DRIVER) &&
+++		    !test_sta_flag(sta, WLAN_STA_PS_DELIVER)) {
++ 			spin_unlock(&sta->ps_lock);
++ 			return TX_CONTINUE;
++ 		}
++@@ -1618,12 +1620,12 @@ netdev_tx_t ieee80211_monitor_start_xmit
++ {
++ 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
++ 	struct ieee80211_chanctx_conf *chanctx_conf;
++-	struct ieee80211_channel *chan;
++ 	struct ieee80211_radiotap_header *prthdr =
++ 		(struct ieee80211_radiotap_header *)skb->data;
++ 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
++ 	struct ieee80211_hdr *hdr;
++ 	struct ieee80211_sub_if_data *tmp_sdata, *sdata;
+++	struct cfg80211_chan_def *chandef;
++ 	u16 len_rthdr;
++ 	int hdrlen;
+  
 - 	ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED;
 --	sdata->vif.csa_active = true;
-- 
++@@ -1721,9 +1723,9 @@ netdev_tx_t ieee80211_monitor_start_xmit
++ 	}
+  
 - 	mutex_lock(&local->chanctx_mtx);
 - 	if (local->use_chanctx) {
 -@@ -1039,6 +1038,7 @@ ieee80211_sta_process_chanswitch(struct 
 - 	mutex_unlock(&local->chanctx_mtx);
-- 
++ 	if (chanctx_conf)
++-		chan = chanctx_conf->def.chan;
+++		chandef = &chanctx_conf->def;
++ 	else if (!local->use_chanctx)
++-		chan = local->_oper_chandef.chan;
+++		chandef = &local->_oper_chandef;
++ 	else
++ 		goto fail_rcu;
+  
 - 	sdata->csa_chandef = csa_ie.chandef;
 -+	sdata->vif.csa_active = true;
-- 
++@@ -1743,10 +1745,11 @@ netdev_tx_t ieee80211_monitor_start_xmit
++ 	 * radar detection by itself. We can do that later by adding a
++ 	 * monitor flag interfaces used for AP support.
++ 	 */
++-	if ((chan->flags & (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_RADAR)))
+++	if (!cfg80211_reg_can_beacon(local->hw.wiphy, chandef,
+++				     sdata->vif.type))
++ 		goto fail_rcu;
+  
 - 	if (csa_ie.mode)
 - 		ieee80211_stop_queues_by_reason(&local->hw,
 ---- a/net/mac80211/chan.c
@@ -4733,7 +5439,10 @@ index a1af6c2..c621ddb 100644
 -@@ -196,6 +196,8 @@ static bool ieee80211_is_radar_required(
 - {
 - 	struct ieee80211_sub_if_data *sdata;
-- 
++-	ieee80211_xmit(sdata, skb, chan->band);
+++	ieee80211_xmit(sdata, skb, chandef->chan->band);
++ 	rcu_read_unlock();
+  
 -+	lockdep_assert_held(&local->mtx);
 -+
 - 	rcu_read_lock();
@@ -4743,7 +5452,14 @@ index a1af6c2..c621ddb 100644
 -+++ b/net/mac80211/ibss.c
 -@@ -294,7 +294,6 @@ static void __ieee80211_sta_join_ibss(st
 - 	}
-- 
++ 	return NETDEV_TX_OK;
++@@ -2425,7 +2428,7 @@ static void ieee80211_set_csa(struct iee
++ 	u8 *beacon_data;
++ 	size_t beacon_data_len;
++ 	int i;
++-	u8 count = sdata->csa_current_counter;
+++	u8 count = beacon->csa_current_counter;
+  
 - 	mutex_lock(&local->mtx);
 --	ieee80211_vif_release_channel(sdata);
 - 	if (ieee80211_vif_use_channel(sdata, &chandef,
@@ -4751,8 +5467,11 @@ index a1af6c2..c621ddb 100644
 - 					IEEE80211_CHANCTX_SHARED :
 -@@ -303,6 +302,7 @@ static void __ieee80211_sta_join_ibss(st
 - 		mutex_unlock(&local->mtx);
-- 		return;
-- 	}
++ 	switch (sdata->vif.type) {
++ 	case NL80211_IFTYPE_AP:
++@@ -2444,46 +2447,54 @@ static void ieee80211_set_csa(struct iee
+  		return;
+  	}
 -+	sdata->radar_required = radar_required;
 - 	mutex_unlock(&local->mtx);
 - 
@@ -4777,7 +5496,7 @@ index a1af6c2..c621ddb 100644
 -@@ -802,6 +801,8 @@ ieee80211_ibss_process_chanswitch(struct
 - 	int err;
 - 	u32 sta_flags;
-- 
+  
 -+	sdata_assert_lock(sdata);
 -+
 - 	sta_flags = IEEE80211_STA_DISABLE_VHT;
@@ -4787,20 +5506,90 @@ index a1af6c2..c621ddb 100644
 - 	memcpy(((struct ieee80211_mgmt *) skb->data)->da, mgmt->sa, ETH_ALEN);
 - 	ibss_dbg(sdata, "Sending ProbeResp to %pM\n", mgmt->sa);
 - 	IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
--+
+++	rcu_read_lock();
++ 	for (i = 0; i < IEEE80211_MAX_CSA_COUNTERS_NUM; ++i) {
++-		u16 counter_offset_beacon =
++-			sdata->csa_counter_offset_beacon[i];
++-		u16 counter_offset_presp = sdata->csa_counter_offset_presp[i];
++-
++-		if (counter_offset_beacon) {
++-			if (WARN_ON(counter_offset_beacon >= beacon_data_len))
++-				return;
++-
++-			beacon_data[counter_offset_beacon] = count;
++-		}
++-
++-		if (sdata->vif.type == NL80211_IFTYPE_AP &&
++-		    counter_offset_presp) {
++-			rcu_read_lock();
++-			resp = rcu_dereference(sdata->u.ap.probe_resp);
+++		resp = rcu_dereference(sdata->u.ap.probe_resp);
++ 
++-			/* If nl80211 accepted the offset, this should
++-			 * not happen.
++-			 */
++-			if (WARN_ON(!resp)) {
+++		if (beacon->csa_counter_offsets[i]) {
+++			if (WARN_ON_ONCE(beacon->csa_counter_offsets[i] >=
+++					 beacon_data_len)) {
++ 				rcu_read_unlock();
++ 				return;
++ 			}
++-			resp->data[counter_offset_presp] = count;
++-			rcu_read_unlock();
+ +
 -+	/* avoid excessive retries for probe request to wildcard SSIDs */
 -+	if (pos[1] == 0)
 -+		IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_NO_ACK;
--+
+++			beacon_data[beacon->csa_counter_offsets[i]] = count;
++ 		}
+ +
 - 	ieee80211_tx_skb(sdata, skb);
-- }
-- 
+++		if (sdata->vif.type == NL80211_IFTYPE_AP && resp &&
+++		    resp->csa_counter_offsets)
+++			resp->data[resp->csa_counter_offsets[i]] = count;
++ 	}
+++	rcu_read_unlock();
+  }
+  
 ---- a/net/mac80211/mesh.c
 -+++ b/net/mac80211/mesh.c
 -@@ -872,6 +872,8 @@ ieee80211_mesh_process_chnswitch(struct 
 - 	if (!ifmsh->mesh_id)
 - 		return false;
-- 
++ u8 ieee80211_csa_update_counter(struct ieee80211_vif *vif)
++ {
++ 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+++	struct beacon_data *beacon = NULL;
+++	u8 count = 0;
+++
+++	rcu_read_lock();
+++
+++	if (sdata->vif.type == NL80211_IFTYPE_AP)
+++		beacon = rcu_dereference(sdata->u.ap.beacon);
+++	else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
+++		beacon = rcu_dereference(sdata->u.ibss.presp);
+++	else if (ieee80211_vif_is_mesh(&sdata->vif))
+++		beacon = rcu_dereference(sdata->u.mesh.beacon);
+++
+++	if (!beacon)
+++		goto unlock;
++ 
++-	sdata->csa_current_counter--;
+++	beacon->csa_current_counter--;
++ 
++ 	/* the counter should never reach 0 */
++-	WARN_ON(!sdata->csa_current_counter);
+++	WARN_ON_ONCE(!beacon->csa_current_counter);
+++	count = beacon->csa_current_counter;
++ 
++-	return sdata->csa_current_counter;
+++unlock:
+++	rcu_read_unlock();
+++	return count;
++ }
++ EXPORT_SYMBOL(ieee80211_csa_update_counter);
+  
 -+	sdata_assert_lock(sdata);
 -+
 - 	sta_flags = IEEE80211_STA_DISABLE_VHT;
@@ -4869,8 +5658,18 @@ index a1af6c2..c621ddb 100644
 -+++ b/net/wireless/ibss.c
 -@@ -14,7 +14,8 @@
 - #include "rdev-ops.h"
-- 
-- 
++@@ -2493,7 +2504,6 @@ bool ieee80211_csa_is_complete(struct ie
++ 	struct beacon_data *beacon = NULL;
++ 	u8 *beacon_data;
++ 	size_t beacon_data_len;
++-	int counter_beacon = sdata->csa_counter_offset_beacon[0];
++ 	int ret = false;
+  
++ 	if (!ieee80211_sdata_running(sdata))
++@@ -2531,10 +2541,13 @@ bool ieee80211_csa_is_complete(struct ie
++ 		goto out;
++ 	}
+  
 --void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid)
 -+void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
 -+			    struct ieee80211_channel *channel)
@@ -4880,17 +5679,63 @@ index a1af6c2..c621ddb 100644
 -@@ -28,8 +29,7 @@ void __cfg80211_ibss_joined(struct net_d
 - 	if (!wdev->ssid_len)
 - 		return;
-- 
++-	if (WARN_ON(counter_beacon > beacon_data_len))
+++	if (!beacon->csa_counter_offsets[0])
+++		goto out;
+++
+++	if (WARN_ON_ONCE(beacon->csa_counter_offsets[0] > beacon_data_len))
++ 		goto out;
+  
 --	bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
 --			       wdev->ssid, wdev->ssid_len,
 -+	bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, NULL, 0,
 - 			       WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS);
-- 
++-	if (beacon_data[counter_beacon] == 1)
+++	if (beacon_data[beacon->csa_counter_offsets[0]] == 1)
++ 		ret = true;
++  out:
++ 	rcu_read_unlock();
++@@ -2550,6 +2563,7 @@ __ieee80211_beacon_get(struct ieee80211_
++ 		       bool is_template)
++ {
++ 	struct ieee80211_local *local = hw_to_local(hw);
+++	struct beacon_data *beacon = NULL;
++ 	struct sk_buff *skb = NULL;
++ 	struct ieee80211_tx_info *info;
++ 	struct ieee80211_sub_if_data *sdata = NULL;
++@@ -2571,10 +2585,10 @@ __ieee80211_beacon_get(struct ieee80211_
++ 
++ 	if (sdata->vif.type == NL80211_IFTYPE_AP) {
++ 		struct ieee80211_if_ap *ap = &sdata->u.ap;
++-		struct beacon_data *beacon = rcu_dereference(ap->beacon);
++ 
+++		beacon = rcu_dereference(ap->beacon);
++ 		if (beacon) {
++-			if (sdata->vif.csa_active) {
+++			if (beacon->csa_counter_offsets[0]) {
++ 				if (!is_template)
++ 					ieee80211_csa_update_counter(vif);
++ 
++@@ -2615,37 +2629,37 @@ __ieee80211_beacon_get(struct ieee80211_
++ 	} else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
++ 		struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
++ 		struct ieee80211_hdr *hdr;
++-		struct beacon_data *presp = rcu_dereference(ifibss->presp);
++ 
++-		if (!presp)
+++		beacon = rcu_dereference(ifibss->presp);
+++		if (!beacon)
++ 			goto out;
+  
 - 	if (WARN_ON(!bss))
 -@@ -54,21 +54,26 @@ void __cfg80211_ibss_joined(struct net_d
 - #endif
 - }
-- 
++-		if (sdata->vif.csa_active) {
+++		if (beacon->csa_counter_offsets[0]) {
++ 			if (!is_template)
++ 				ieee80211_csa_update_counter(vif);
+  
 --void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp)
 -+void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
 -+			  struct ieee80211_channel *channel, gfp_t gfp)
@@ -4899,26 +5744,87 @@ index a1af6c2..c621ddb 100644
 - 	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
 - 	struct cfg80211_event *ev;
 - 	unsigned long flags;
-- 
++-			ieee80211_set_csa(sdata, presp);
+++			ieee80211_set_csa(sdata, beacon);
++ 		}
+  
 --	trace_cfg80211_ibss_joined(dev, bssid);
 -+	trace_cfg80211_ibss_joined(dev, bssid, channel);
 -+
 -+	if (WARN_ON(!channel))
 -+		return;
-- 
++-		skb = dev_alloc_skb(local->tx_headroom + presp->head_len +
+++		skb = dev_alloc_skb(local->tx_headroom + beacon->head_len +
++ 				    local->hw.extra_beacon_tailroom);
++ 		if (!skb)
++ 			goto out;
++ 		skb_reserve(skb, local->tx_headroom);
++-		memcpy(skb_put(skb, presp->head_len), presp->head,
++-		       presp->head_len);
+++		memcpy(skb_put(skb, beacon->head_len), beacon->head,
+++		       beacon->head_len);
++ 
++ 		hdr = (struct ieee80211_hdr *) skb->data;
++ 		hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
++ 						 IEEE80211_STYPE_BEACON);
++ 	} else if (ieee80211_vif_is_mesh(&sdata->vif)) {
++ 		struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
++-		struct beacon_data *bcn = rcu_dereference(ifmsh->beacon);
++ 
++-		if (!bcn)
+++		beacon = rcu_dereference(ifmsh->beacon);
+++		if (!beacon)
++ 			goto out;
+  
 - 	ev = kzalloc(sizeof(*ev), gfp);
 - 	if (!ev)
 - 		return;
-- 
++-		if (sdata->vif.csa_active) {
+++		if (beacon->csa_counter_offsets[0]) {
++ 			if (!is_template)
++ 				/* TODO: For mesh csa_counter is in TU, so
++ 				 * decrementing it by one isn't correct, but
++@@ -2654,40 +2668,42 @@ __ieee80211_beacon_get(struct ieee80211_
++ 				 */
++ 				ieee80211_csa_update_counter(vif);
+  
 - 	ev->type = EVENT_IBSS_JOINED;
 --	memcpy(ev->cr.bssid, bssid, ETH_ALEN);
 -+	memcpy(ev->ij.bssid, bssid, ETH_ALEN);
 -+	ev->ij.channel = channel;
-- 
++-			ieee80211_set_csa(sdata, bcn);
+++			ieee80211_set_csa(sdata, beacon);
++ 		}
+  
 - 	spin_lock_irqsave(&wdev->event_lock, flags);
 - 	list_add_tail(&ev->list, &wdev->event_list);
 -@@ -117,6 +122,7 @@ int __cfg80211_join_ibss(struct cfg80211
-- 
++ 		if (ifmsh->sync_ops)
++-			ifmsh->sync_ops->adjust_tbtt(sdata, bcn);
+++			ifmsh->sync_ops->adjust_tbtt(sdata, beacon);
++ 
++ 		skb = dev_alloc_skb(local->tx_headroom +
++-				    bcn->head_len +
+++				    beacon->head_len +
++ 				    256 + /* TIM IE */
++-				    bcn->tail_len +
+++				    beacon->tail_len +
++ 				    local->hw.extra_beacon_tailroom);
++ 		if (!skb)
++ 			goto out;
++ 		skb_reserve(skb, local->tx_headroom);
++-		memcpy(skb_put(skb, bcn->head_len), bcn->head, bcn->head_len);
+++		memcpy(skb_put(skb, beacon->head_len), beacon->head,
+++		       beacon->head_len);
++ 		ieee80211_beacon_add_tim(sdata, &ifmsh->ps, skb, is_template);
++ 
++ 		if (offs) {
++-			offs->tim_offset = bcn->head_len;
++-			offs->tim_length = skb->len - bcn->head_len;
+++			offs->tim_offset = beacon->head_len;
+++			offs->tim_length = skb->len - beacon->head_len;
++ 		}
+  
 - 	wdev->ibss_fixed = params->channel_fixed;
 - 	wdev->ibss_dfs_possible = params->userspace_handles_dfs;
 -+	wdev->chandef = params->chandef;
@@ -4938,7 +5844,14 @@ index a1af6c2..c621ddb 100644
 -@@ -2278,11 +2278,6 @@ DECLARE_EVENT_CLASS(cfg80211_rx_evt,
 - 	TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT, NETDEV_PR_ARG, MAC_PR_ARG(addr))
 - );
-- 
++-		memcpy(skb_put(skb, bcn->tail_len), bcn->tail, bcn->tail_len);
+++		memcpy(skb_put(skb, beacon->tail_len), beacon->tail,
+++		       beacon->tail_len);
++ 	} else {
++ 		WARN_ON(1);
++ 		goto out;
++ 	}
+  
 --DEFINE_EVENT(cfg80211_rx_evt, cfg80211_ibss_joined,
 --	TP_PROTO(struct net_device *netdev, const u8 *addr),
 --	TP_ARGS(netdev, addr)
@@ -4950,7 +5863,23 @@ index a1af6c2..c621ddb 100644
 -@@ -2293,6 +2288,24 @@ DEFINE_EVENT(cfg80211_rx_evt, cfg80211_r
 - 	TP_ARGS(netdev, addr)
 - );
-- 
++ 	/* CSA offsets */
++-	if (offs) {
+++	if (offs && beacon) {
++ 		int i;
++ 
++ 		for (i = 0; i < IEEE80211_MAX_CSA_COUNTERS_NUM; i++) {
++-			u16 csa_off = sdata->csa_counter_offset_beacon[i];
+++			u16 csa_off = beacon->csa_counter_offsets[i];
++ 
++ 			if (!csa_off)
++ 				continue;
++--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
++@@ -947,6 +947,40 @@ static inline u8 rt2800_get_beacon_offse
++ 	return BEACON_BASE_TO_OFFSET(rt2800_hw_beacon_base(rt2x00dev, index));
++ }
+  
 -+TRACE_EVENT(cfg80211_ibss_joined,
 -+	TP_PROTO(struct net_device *netdev, const u8 *bssid,
 -+		 struct ieee80211_channel *channel),
@@ -4968,7 +5897,14 @@ index a1af6c2..c621ddb 100644
 -+	TP_printk(NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", " CHAN_PR_FMT,
 -+		  NETDEV_PR_ARG, MAC_PR_ARG(bssid), CHAN_PR_ARG)
 -+);
--+
+++static void rt2800_update_beacons_setup(struct rt2x00_dev *rt2x00dev)
+++{
+++	struct data_queue *queue = rt2x00dev->bcn;
+++	struct queue_entry *entry;
+++	int i, bcn_num = 0;
+++	u64 off, reg = 0;
+++	u32 bssid_dw1;
+ +
 - TRACE_EVENT(cfg80211_probe_status,
 - 	TP_PROTO(struct net_device *netdev, const u8 *addr, u64 cookie,
 - 		 bool acked),
@@ -5009,7 +5945,18 @@ index a1af6c2..c621ddb 100644
 - 				     !wdev->ibss_dfs_possible)
 - 				  ? CHAN_MODE_SHARED
 - 				  : CHAN_MODE_EXCLUSIVE;
--+
+++	/*
+++	 * Setup offsets of all active beacons in BCN_OFFSET{0,1} registers.
+++	 */
+++	for (i = 0; i < queue->limit; i++) {
+++		entry = &queue->entries[i];
+++		if (!test_bit(ENTRY_BCN_ENABLED, &entry->flags))
+++			continue;
+++		off = rt2800_get_beacon_offset(rt2x00dev, entry->entry_idx);
+++		reg |= off << (8 * bcn_num);
+++		bcn_num++;
+++	}
+ +
 -+			/* consider worst-case - IBSS can try to return to the
 -+			 * original user-specified channel as creator */
 -+			if (wdev->ibss_dfs_possible)
@@ -5029,7 +5976,8 @@ index a1af6c2..c621ddb 100644
 --			*chan = wdev->channel;
 -+			*chan = wdev->chandef.chan;
 - 			*chanmode = CHAN_MODE_SHARED;
--+
+++	WARN_ON_ONCE(bcn_num != rt2x00dev->intf_beaconing);
+ +
 -+			if (cfg80211_chandef_dfs_required(wdev->wiphy,
 -+							  &wdev->chandef))
 -+				*radar_detect |= BIT(wdev->chandef.width);
@@ -5040,7 +5988,27 @@ index a1af6c2..c621ddb 100644
 --			*chan = wdev->channel;
 -+			*chan = wdev->chandef.chan;
 - 			*chanmode = CHAN_MODE_SHARED;
--+
+++	rt2800_register_write(rt2x00dev, BCN_OFFSET0, (u32) reg);
+++	rt2800_register_write(rt2x00dev, BCN_OFFSET1, (u32) (reg >> 32));
+++
+++	/*
+++	 * H/W sends up to MAC_BSSID_DW1_BSS_BCN_NUM + 1 consecutive beacons.
+++	 */
+++	rt2800_register_read(rt2x00dev, MAC_BSSID_DW1, &bssid_dw1);
+++	rt2x00_set_field32(&bssid_dw1, MAC_BSSID_DW1_BSS_BCN_NUM,
+++			   bcn_num > 0 ? bcn_num - 1 : 0);
+++	rt2800_register_write(rt2x00dev, MAC_BSSID_DW1, bssid_dw1);
+++}
+++
++ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
++ {
++ 	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
++@@ -1003,6 +1037,12 @@ void rt2800_write_beacon(struct queue_en
++ 
++ 	rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,
++ 				   entry->skb->len + padding_len);
+++	__set_bit(ENTRY_BCN_ENABLED, &entry->flags);
+ +
 -+			if (cfg80211_chandef_dfs_required(wdev->wiphy,
 -+							  &wdev->chandef))
 -+				*radar_detect |= BIT(wdev->chandef.width);
@@ -5056,7 +6024,11 @@ index a1af6c2..c621ddb 100644
 --		wdev->channel = setup->chandef.chan;
 -+		wdev->chandef = setup->chandef;
 - 	}
-- 
+++	/*
+++	 * Change global beacons settings.
+++	 */
+++	rt2800_update_beacons_setup(rt2x00dev);
+  
 - 	return err;
 -@@ -244,7 +244,7 @@ int cfg80211_set_mesh_channel(struct cfg
 - 		err = rdev_libertas_set_mesh_channel(rdev, wdev->netdev,
@@ -5064,7 +6036,14 @@ index a1af6c2..c621ddb 100644
 - 		if (!err)
 --			wdev->channel = chandef->chan;
 -+			wdev->chandef = *chandef;
-- 
++ 	/*
++ 	 * Restore beaconing state.
++@@ -1053,8 +1093,13 @@ void rt2800_clear_beacon(struct queue_en
++ 	 * Clear beacon.
++ 	 */
++ 	rt2800_clear_beacon_register(rt2x00dev, entry->entry_idx);
+++	__clear_bit(ENTRY_BCN_ENABLED, &entry->flags);
+  
 - 		return err;
 - 	}
 -@@ -276,7 +276,7 @@ static int __cfg80211_leave_mesh(struct 
@@ -5075,17 +6054,65 @@ index a1af6c2..c621ddb 100644
 -+		memset(&wdev->chandef, 0, sizeof(wdev->chandef));
 - 		rdev_set_qos_map(rdev, dev, NULL);
 - 	}
-- 
++ 	/*
+++	 * Change global beacons settings.
+++	 */
+++	rt2800_update_beacons_setup(rt2x00dev);
+++	/*
++ 	 * Restore beaconing state.
++ 	 */
++ 	rt2800_register_write(rt2x00dev, BCN_TIME_CFG, orig_reg);
++@@ -1556,7 +1601,7 @@ void rt2800_config_intf(struct rt2x00_de
++ 		if (!is_zero_ether_addr((const u8 *)conf->bssid)) {
++ 			reg = le32_to_cpu(conf->bssid[1]);
++ 			rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_ID_MASK, 3);
++-			rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_BCN_NUM, 7);
+++			rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_BCN_NUM, 0);
++ 			conf->bssid[1] = cpu_to_le32(reg);
++ 		}
+  
 ---- a/net/wireless/mlme.c
 -+++ b/net/wireless/mlme.c
 -@@ -772,7 +772,7 @@ void cfg80211_cac_event(struct net_devic
 - 	if (WARN_ON(!wdev->cac_started))
 - 		return;
-- 
++@@ -4517,28 +4562,6 @@ static int rt2800_init_registers(struct 
++ 	if (ret)
++ 		return ret;
++ 
++-	rt2800_register_read(rt2x00dev, BCN_OFFSET0, &reg);
++-	rt2x00_set_field32(&reg, BCN_OFFSET0_BCN0,
++-			   rt2800_get_beacon_offset(rt2x00dev, 0));
++-	rt2x00_set_field32(&reg, BCN_OFFSET0_BCN1,
++-			   rt2800_get_beacon_offset(rt2x00dev, 1));
++-	rt2x00_set_field32(&reg, BCN_OFFSET0_BCN2,
++-			   rt2800_get_beacon_offset(rt2x00dev, 2));
++-	rt2x00_set_field32(&reg, BCN_OFFSET0_BCN3,
++-			   rt2800_get_beacon_offset(rt2x00dev, 3));
++-	rt2800_register_write(rt2x00dev, BCN_OFFSET0, reg);
++-
++-	rt2800_register_read(rt2x00dev, BCN_OFFSET1, &reg);
++-	rt2x00_set_field32(&reg, BCN_OFFSET1_BCN4,
++-			   rt2800_get_beacon_offset(rt2x00dev, 4));
++-	rt2x00_set_field32(&reg, BCN_OFFSET1_BCN5,
++-			   rt2800_get_beacon_offset(rt2x00dev, 5));
++-	rt2x00_set_field32(&reg, BCN_OFFSET1_BCN6,
++-			   rt2800_get_beacon_offset(rt2x00dev, 6));
++-	rt2x00_set_field32(&reg, BCN_OFFSET1_BCN7,
++-			   rt2800_get_beacon_offset(rt2x00dev, 7));
++-	rt2800_register_write(rt2x00dev, BCN_OFFSET1, reg);
++-
++ 	rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f);
++ 	rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003);
+  
 --	if (WARN_ON(!wdev->channel))
 -+	if (WARN_ON(!wdev->chandef.chan))
-- 		return;
-- 
++--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
++@@ -141,8 +141,11 @@ static void rt2x00lib_intf_scheduled_ite
++ 	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+  		return;
+  
 - 	switch (event) {
 ---- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
 -+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -5098,8 +6125,14 @@ index a1af6c2..c621ddb 100644
 -+		twiceMaxEdgePower = 60;
 -+
 - 	return twiceMaxEdgePower;
-- }
-- 
++-	if (test_and_clear_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags))
+++	if (test_and_clear_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags)) {
+++		mutex_lock(&intf->beacon_skb_mutex);
++ 		rt2x00queue_update_beacon(rt2x00dev, vif);
+++		mutex_unlock(&intf->beacon_skb_mutex);
+++	}
+  }
+  
 ---- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
 -+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
 -@@ -23,10 +23,11 @@
@@ -5115,34 +6148,109 @@ index a1af6c2..c621ddb 100644
 -+	int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MAXIQCAL];
 - 	int iqc_coeff[2];
 - };
-- 
++ static void rt2x00lib_intf_scheduled(struct work_struct *work)
++@@ -216,7 +219,7 @@ static void rt2x00lib_beaconupdate_iter(
++ 	 * never be called for USB devices.
++ 	 */
++ 	WARN_ON(rt2x00_is_usb(rt2x00dev));
++-	rt2x00queue_update_beacon_locked(rt2x00dev, vif);
+++	rt2x00queue_update_beacon(rt2x00dev, vif);
++ }
+  
 -@@ -800,7 +801,7 @@ static bool ar9003_hw_calc_iq_corr(struc
 - 	if (q_q_coff > 63)
 - 		q_q_coff = 63;
-- 
++ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
++--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
++@@ -624,25 +624,24 @@ void rt2x00mac_bss_info_changed(struct i
++ 	 * Start/stop beaconing.
++ 	 */
++ 	if (changes & BSS_CHANGED_BEACON_ENABLED) {
+++		mutex_lock(&intf->beacon_skb_mutex);
++ 		if (!bss_conf->enable_beacon && intf->enable_beacon) {
++ 			rt2x00dev->intf_beaconing--;
++ 			intf->enable_beacon = false;
++-			/*
++-			 * Clear beacon in the H/W for this vif. This is needed
++-			 * to disable beaconing on this particular interface
++-			 * and keep it running on other interfaces.
++-			 */
++-			rt2x00queue_clear_beacon(rt2x00dev, vif);
+  
 --	iqc_coeff[0] = (q_q_coff * 128) + q_i_coff;
 -+	iqc_coeff[0] = (q_q_coff * 128) + (0x7f & q_i_coff);
-- 
++ 			if (rt2x00dev->intf_beaconing == 0) {
++ 				/*
++ 				 * Last beaconing interface disabled
++ 				 * -> stop beacon queue.
++ 				 */
++-				mutex_lock(&intf->beacon_skb_mutex);
++ 				rt2x00queue_stop_queue(rt2x00dev->bcn);
++-				mutex_unlock(&intf->beacon_skb_mutex);
++ 			}
+++			/*
+++			 * Clear beacon in the H/W for this vif. This is needed
+++			 * to disable beaconing on this particular interface
+++			 * and keep it running on other interfaces.
+++			 */
+++			rt2x00queue_clear_beacon(rt2x00dev, vif);
++ 		} else if (bss_conf->enable_beacon && !intf->enable_beacon) {
++ 			rt2x00dev->intf_beaconing++;
++ 			intf->enable_beacon = true;
++@@ -658,11 +657,10 @@ void rt2x00mac_bss_info_changed(struct i
++ 				 * First beaconing interface enabled
++ 				 * -> start beacon queue.
++ 				 */
++-				mutex_lock(&intf->beacon_skb_mutex);
++ 				rt2x00queue_start_queue(rt2x00dev->bcn);
++-				mutex_unlock(&intf->beacon_skb_mutex);
++ 			}
++ 		}
+++		mutex_unlock(&intf->beacon_skb_mutex);
++ 	}
+  
 - 	ath_dbg(common, CALIBRATE, "tx chain %d: iq corr coeff=%x\n",
 - 		chain_idx, iqc_coeff[0]);
 -@@ -831,7 +832,7 @@ static bool ar9003_hw_calc_iq_corr(struc
 - 	if (q_q_coff > 63)
 - 		q_q_coff = 63;
-- 
++ 	/*
++--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
++@@ -754,8 +754,6 @@ int rt2x00queue_clear_beacon(struct rt2x
++ 	if (unlikely(!intf->beacon))
++ 		return -ENOBUFS;
+  
 --	iqc_coeff[1] = (q_q_coff * 128) + q_i_coff;
 -+	iqc_coeff[1] = (q_q_coff * 128) + (0x7f & q_i_coff);
-- 
++-	mutex_lock(&intf->beacon_skb_mutex);
++-
++ 	/*
++ 	 * Clean up the beacon skb.
++ 	 */
++@@ -768,13 +766,11 @@ int rt2x00queue_clear_beacon(struct rt2x
++ 	if (rt2x00dev->ops->lib->clear_beacon)
++ 		rt2x00dev->ops->lib->clear_beacon(intf->beacon);
+  
 - 	ath_dbg(common, CALIBRATE, "rx chain %d: iq corr coeff=%x\n",
 - 		chain_idx, iqc_coeff[1]);
 -@@ -839,7 +840,8 @@ static bool ar9003_hw_calc_iq_corr(struc
 - 	return true;
-- }
-- 
++-	mutex_unlock(&intf->beacon_skb_mutex);
++-
++ 	return 0;
+  }
+  
 --static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
 -+static void ar9003_hw_detect_outlier(int mp_coeff[][MAXIQCAL],
 -+				     int nmeasurement,
 - 				     int max_delta)
-- {
++-int rt2x00queue_update_beacon_locked(struct rt2x00_dev *rt2x00dev,
++-				     struct ieee80211_vif *vif)
+++int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
+++			      struct ieee80211_vif *vif)
+  {
 - 	int mp_max = -64, max_idx = 0;
 -@@ -848,20 +850,20 @@ static void ar9003_hw_detect_outlier(int
 - 
@@ -5160,7 +6268,10 @@ index a1af6c2..c621ddb 100644
 - 			min_idx = i;
 - 		}
 - 	}
-- 
++ 	struct rt2x00_intf *intf = vif_to_intf(vif);
++ 	struct skb_frame_desc *skbdesc;
++@@ -815,19 +811,6 @@ int rt2x00queue_update_beacon_locked(str
+  
 - 	/* find average (exclude max abs value) */
 - 	for (i = 0; i < nmeasurement; i++) {
 --		if ((abs(mp_coeff[i]) < abs(mp_max)) ||
@@ -5188,8 +6299,8 @@ index a1af6c2..c621ddb 100644
 --		mp_coeff[outlier_idx] = mp_avg;
 -+		mp_coeff[outlier_idx][0] = mp_avg;
 - 	}
-- }
-- 
+  }
+  
 --static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
 --						 struct coeff *coeff,
 --						 bool is_reusable)
@@ -5211,7 +6322,12 @@ index a1af6c2..c621ddb 100644
 --			/* Detect magnitude outlier */
 --			ar9003_hw_detect_outlier(coeff->mag_coeff[i],
 --					nmeasurement, MAX_MAG_DELTA);
---
++-int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
++-			      struct ieee80211_vif *vif)
++-{
++-	struct rt2x00_intf *intf = vif_to_intf(vif);
++-	int ret;
+ -
 --			/* Detect phase outlier */
 --			ar9003_hw_detect_outlier(coeff->phs_coeff[i],
 --					nmeasurement, MAX_PHS_DELTA);
@@ -5236,18 +6352,61 @@ index a1af6c2..c621ddb 100644
 - 		for (im = 0; im < nmeasurement; im++) {
 -+			magnitude = coeff->mag_coeff[i][im][0];
 -+			phase = coeff->phs_coeff[i][im][0];
-- 
++-	mutex_lock(&intf->beacon_skb_mutex);
++-	ret = rt2x00queue_update_beacon_locked(rt2x00dev, vif);
++-	mutex_unlock(&intf->beacon_skb_mutex);
++-
++-	return ret;
++-}
++-
++ bool rt2x00queue_for_each_entry(struct data_queue *queue,
++ 				enum queue_index start,
++ 				enum queue_index end,
++--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
++@@ -353,6 +353,7 @@ struct txentry_desc {
++  */
++ enum queue_entry_flags {
++ 	ENTRY_BCN_ASSIGNED,
+++	ENTRY_BCN_ENABLED,
++ 	ENTRY_OWNER_DEVICE_DATA,
++ 	ENTRY_DATA_PENDING,
++ 	ENTRY_DATA_IO_FAILED,
++--- a/drivers/net/wireless/ath/ath9k/main.c
+++++ b/drivers/net/wireless/ath/ath9k/main.c
++@@ -1757,7 +1757,6 @@ out:
++ void ath9k_update_p2p_ps(struct ath_softc *sc, struct ieee80211_vif *vif)
++ {
++ 	struct ath_vif *avp = (void *)vif->drv_priv;
++-	unsigned long flags;
++ 	u32 tsf;
+  
 --			coeff->iqc_coeff[0] = (coeff->mag_coeff[i][im] & 0x7f) |
 --				((coeff->phs_coeff[i][im] & 0x7f) << 7);
 -+			coeff->iqc_coeff[0] =
 -+				(phase & 0x7f) | ((magnitude & 0x7f) << 7);
-- 
++ 	if (!sc->p2p_ps_timer)
++@@ -1767,14 +1766,9 @@ void ath9k_update_p2p_ps(struct ath_soft
++ 		return;
+  
 - 			if ((im % 2) == 0)
 - 				REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
 -@@ -991,7 +1003,63 @@ static bool ar9003_hw_tx_iq_cal_run(stru
 - 	return true;
-- }
-- 
++ 	sc->p2p_ps_vif = avp;
++-
++-	spin_lock_irqsave(&sc->sc_pm_lock, flags);
++-	if (!(sc->ps_flags & PS_BEACON_SYNC)) {
++-		tsf = ath9k_hw_gettsf32(sc->sc_ah);
++-		ieee80211_parse_p2p_noa(&vif->bss_conf.p2p_noa_attr, &avp->noa, tsf);
++-		ath9k_update_p2p_ps_timer(sc, avp);
++-	}
++-	spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+++	tsf = ath9k_hw_gettsf32(sc->sc_ah);
+++	ieee80211_parse_p2p_noa(&vif->bss_conf.p2p_noa_attr, &avp->noa, tsf);
+++	ath9k_update_p2p_ps_timer(sc, avp);
+  }
+  
 --static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, bool is_reusable)
 -+static void __ar955x_tx_iq_cal_sort(struct ath_hw *ah,
 -+				    struct coeff *coeff,
@@ -5306,91 +6465,9 @@ index a1af6c2..c621ddb 100644
 -+static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah,
 -+					  int iqcal_idx,
 -+					  bool is_reusable)
-+commit 930b0dffd1731f3f418f9132faea720a23b7af61
-+Author: Johannes Berg <johannes.berg@intel.com>
-+Date:   Tue Jun 3 11:18:47 2014 +0200
-+
-+    mac80211: fix station/driver powersave race
-+    
-+    It is currently possible to have a race due to the station PS
-+    unblock work like this:
-+     * station goes to sleep with frames buffered in the driver
-+     * driver blocks wakeup
-+     * station wakes up again
-+     * driver flushes/returns frames, and unblocks, which schedules
-+       the unblock work
-+     * unblock work starts to run, and checks that the station is
-+       awake (i.e. that the WLAN_STA_PS_STA flag isn't set)
-+     * we process a received frame with PM=1, setting the flag again
-+     * ieee80211_sta_ps_deliver_wakeup() runs, delivering all frames
-+       to the driver, and then clearing the WLAN_STA_PS_DRIVER and
-+       WLAN_STA_PS_STA flags
-+    
-+    In this scenario, mac80211 will think that the station is awake,
-+    while it really is asleep, and any TX'ed frames should be filtered
-+    by the device (it will know that the station is sleeping) but then
-+    passed to mac80211 again, which will not buffer it either as it
-+    thinks the station is awake, and eventually the packets will be
-+    dropped.
-+    
-+    Fix this by moving the clearing of the flags to exactly where we
-+    learn about the situation. This creates a problem of reordering,
-+    so introduce another flag indicating that delivery is being done,
-+    this new flag also queues frames and is cleared only while the
-+    spinlock is held (which the queuing code also holds) so that any
-+    concurrent delivery/TX is handled correctly.
-+    
-+    Reported-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
-+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-+
-+commit 6df35206bc6c1c6aad1d8077df5786b4a7f77873
-+Author: Felix Fietkau <nbd@openwrt.org>
-+Date:   Fri May 23 19:58:14 2014 +0200
-+
-+    mac80211: reduce packet loss notifications under load
-+    
-+    During strong signal fluctuations under high throughput, few consecutive
-+    failed A-MPDU transmissions can easily trigger packet loss notification,
-+    and thus (in AP mode) client disconnection.
-+    
-+    Reduce the number of false positives by checking the A-MPDU status flag
-+    and treating a failed A-MPDU as a single packet.
-+    
-+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-+
-+commit 7b7843a36fbcc568834404c7430ff895d8502131
-+Author: Felix Fietkau <nbd@openwrt.org>
-+Date:   Fri May 23 19:26:32 2014 +0200
-+
-+    mac80211: fix a memory leak on sta rate selection table
-+    
-+    Cc: stable@vger.kernel.org
-+    Reported-by: Christophe Prévotaux <cprevotaux@nltinc.com>
-+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-+
-+commit 96892d6aa0a153423070addf3070bc79578b3897
-+Author: Felix Fietkau <nbd@openwrt.org>
-+Date:   Mon May 19 21:20:49 2014 +0200
-+
-+    ath9k: avoid passing buffers to the hardware during flush
-+    
-+    The commit "ath9k: fix possible hang on flush" changed the receive code
-+    to always link rx descriptors of processed frames, even when flushing.
-+    In some cases, this leads to flushed rx buffers being passed to the
-+    hardware while rx is already stopped.
-+    
-+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-+
-+--- a/drivers/net/wireless/ath/ath9k/recv.c
-++++ b/drivers/net/wireless/ath/ath9k/recv.c
-+@@ -34,7 +34,8 @@ static inline bool ath9k_check_auto_slee
-+  * buffer (or rx fifo). This can incorrectly acknowledge packets
-+  * to a sender if last desc is self-linked.
-+  */
-+-static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf)
-++static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf,
-++			    bool flush)
-  {
+- {
++ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
++@@ -1791,6 +1785,7 @@ static void ath9k_bss_info_changed(struc
 + 	struct ath_hw *ah = sc->sc_ah;
   	struct ath_common *common = ath9k_hw_common(ah);
 - 	const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
@@ -5428,7 +6505,22 @@ index a1af6c2..c621ddb 100644
 -+			if (coeff.phs_coeff[i][im][iqcal_idx] > 63)
 -+				coeff.phs_coeff[i][im][iqcal_idx] -= 128;
 - 		}
-- 	}
++ 	struct ath_vif *avp = (void *)vif->drv_priv;
+++	unsigned long flags;
++ 	int slottime;
++ 
++ 	ath9k_ps_wakeup(sc);
++@@ -1853,7 +1848,10 @@ static void ath9k_bss_info_changed(struc
++ 
++ 	if (changed & BSS_CHANGED_P2P_PS) {
++ 		spin_lock_bh(&sc->sc_pcu_lock);
++-		ath9k_update_p2p_ps(sc, vif);
+++		spin_lock_irqsave(&sc->sc_pm_lock, flags);
+++		if (!(sc->ps_flags & PS_BEACON_SYNC))
+++			ath9k_update_p2p_ps(sc, vif);
+++		spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
++ 		spin_unlock_bh(&sc->sc_pcu_lock);
+  	}
 --	ar9003_hw_tx_iqcal_load_avg_2_passes(ah, &coeff, is_reusable);
 -+
 -+	if (AR_SREV_9550(ah))
@@ -5436,31 +6528,68 @@ index a1af6c2..c621ddb 100644
 -+							 iqcal_idx, nmeasurement);
 -+	if (outlier_detect)
 -+		ar9003_hw_tx_iq_cal_outlier_detection(ah, &coeff, is_reusable);
-+@@ -59,18 +60,19 @@ static void ath_rx_buf_link(struct ath_s
-+ 			     common->rx_bufsize,
-+ 			     0);
-  
+- 
 - 	return;
-+-	if (sc->rx.rxlink == NULL)
-+-		ath9k_hw_putrxbuf(ah, bf->bf_daddr);
-+-	else
-++	if (sc->rx.rxlink)
-+ 		*sc->rx.rxlink = bf->bf_daddr;
-++	else if (!flush)
-++		ath9k_hw_putrxbuf(ah, bf->bf_daddr);
   
 -@@ -1409,7 +1484,7 @@ skip_tx_iqcal:
 - 	}
-- 
++@@ -2232,14 +2230,6 @@ static void ath9k_sw_scan_complete(struc
++ 	clear_bit(ATH_OP_SCANNING, &common->op_flags);
++ }
+  
 - 	if (txiqcal_done)
 --		ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable);
 -+		ar9003_hw_tx_iq_cal_post_proc(ah, 0, is_reusable);
 - 	else if (caldata && test_bit(TXIQCAL_DONE, &caldata->cal_flags))
 - 		ar9003_hw_tx_iq_cal_reload(ah);
-- 
++-static void ath9k_channel_switch_beacon(struct ieee80211_hw *hw,
++-					struct ieee80211_vif *vif,
++-					struct cfg80211_chan_def *chandef)
++-{
++-	/* depend on vif->csa_active only */
++-	return;
++-}
++-
++ struct ieee80211_ops ath9k_ops = {
++ 	.tx 		    = ath9k_tx,
++ 	.start 		    = ath9k_start,
++@@ -2287,5 +2277,4 @@ struct ieee80211_ops ath9k_ops = {
++ #endif
++ 	.sw_scan_start	    = ath9k_sw_scan_start,
++ 	.sw_scan_complete   = ath9k_sw_scan_complete,
++-	.channel_switch_beacon     = ath9k_channel_switch_beacon,
++ };
++--- a/drivers/net/wireless/ath/ath10k/mac.c
+++++ b/drivers/net/wireless/ath/ath10k/mac.c
++@@ -4142,14 +4142,6 @@ static int ath10k_set_bitrate_mask(struc
++ 					   fixed_nss, force_sgi);
++ }
+  
 -@@ -1455,14 +1530,38 @@ skip_tx_iqcal:
 - 	return true;
-+ 	sc->rx.rxlink = &ds->ds_link;
++-static void ath10k_channel_switch_beacon(struct ieee80211_hw *hw,
++-					 struct ieee80211_vif *vif,
++-					 struct cfg80211_chan_def *chandef)
++-{
++-	/* there's no need to do anything here. vif->csa_active is enough */
++-	return;
++-}
++-
++ static void ath10k_sta_rc_update(struct ieee80211_hw *hw,
++ 				 struct ieee80211_vif *vif,
++ 				 struct ieee80211_sta *sta,
++@@ -4256,7 +4248,6 @@ static const struct ieee80211_ops ath10k
++ 	.restart_complete		= ath10k_restart_complete,
++ 	.get_survey			= ath10k_get_survey,
++ 	.set_bitrate_mask		= ath10k_set_bitrate_mask,
++-	.channel_switch_beacon		= ath10k_channel_switch_beacon,
++ 	.sta_rc_update			= ath10k_sta_rc_update,
++ 	.get_tsf			= ath10k_get_tsf,
++ #ifdef CONFIG_PM
++--- a/net/mac80211/cfg.c
+++++ b/net/mac80211/cfg.c
++@@ -468,327 +468,6 @@ void sta_set_rate_info_rx(struct sta_inf
++ 		rinfo->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH;
   }
   
 -+static bool do_ar9003_agc_cal(struct ath_hw *ah)
@@ -5488,10 +6617,7 @@ index a1af6c2..c621ddb 100644
 -+
 - static bool ar9003_hw_init_cal_soc(struct ath_hw *ah,
 - 				   struct ath9k_channel *chan)
-+-static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf)
-++static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf,
-++			      bool flush)
-  {
+- {
 - 	struct ath_common *common = ath9k_hw_common(ah);
 - 	struct ath9k_hw_cal_data *caldata = ah->caldata;
 - 	bool txiqcal_done = false;
@@ -5524,12 +6650,46 @@ index a1af6c2..c621ddb 100644
 --		REG_WRITE(ah, AR_PHY_AGC_CONTROL,
 --			  REG_READ(ah, AR_PHY_AGC_CONTROL) |
 --			  AR_PHY_AGC_CONTROL_CAL);
---
++-static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
++-{
++-	struct ieee80211_sub_if_data *sdata = sta->sdata;
++-	struct ieee80211_local *local = sdata->local;
++-	struct rate_control_ref *ref = local->rate_ctrl;
++-	struct timespec uptime;
++-	u64 packets = 0;
++-	u32 thr = 0;
++-	int i, ac;
++-
++-	sinfo->generation = sdata->local->sta_generation;
++-
++-	sinfo->filled = STATION_INFO_INACTIVE_TIME |
++-			STATION_INFO_RX_BYTES64 |
++-			STATION_INFO_TX_BYTES64 |
++-			STATION_INFO_RX_PACKETS |
++-			STATION_INFO_TX_PACKETS |
++-			STATION_INFO_TX_RETRIES |
++-			STATION_INFO_TX_FAILED |
++-			STATION_INFO_TX_BITRATE |
++-			STATION_INFO_RX_BITRATE |
++-			STATION_INFO_RX_DROP_MISC |
++-			STATION_INFO_BSS_PARAM |
++-			STATION_INFO_CONNECTED_TIME |
++-			STATION_INFO_STA_FLAGS |
++-			STATION_INFO_BEACON_LOSS_COUNT;
+ -
 --		/* Poll for offset calibration complete */
 --		status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
 --				       AR_PHY_AGC_CONTROL_CAL,
 --				       0, AH_WAIT_TIMEOUT);
---	}
++-	do_posix_clock_monotonic_gettime(&uptime);
++-	sinfo->connected_time = uptime.tv_sec - sta->last_connected;
++-
++-	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
++-	sinfo->tx_bytes = 0;
++-	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
++-		sinfo->tx_bytes += sta->tx_bytes[ac];
++-		packets += sta->tx_packets[ac];
+ -	}
 -+		/*
 -+		 * For non-AR9550 chips, we just trigger AGC calibration
 -+		 * in the HW, poll for completion and then process
@@ -5568,18 +6728,321 @@ index a1af6c2..c621ddb 100644
 - 
 --	if (txiqcal_done)
 --		ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable);
---
++-	sinfo->tx_packets = packets;
++-	sinfo->rx_bytes = sta->rx_bytes;
++-	sinfo->rx_packets = sta->rx_packets;
++-	sinfo->tx_retries = sta->tx_retry_count;
++-	sinfo->tx_failed = sta->tx_retry_failed;
++-	sinfo->rx_dropped_misc = sta->rx_dropped;
++-	sinfo->beacon_loss_count = sta->beacon_loss_count;
++-
++-	if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) ||
++-	    (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) {
++-		sinfo->filled |= STATION_INFO_SIGNAL | STATION_INFO_SIGNAL_AVG;
++-		if (!local->ops->get_rssi ||
++-		    drv_get_rssi(local, sdata, &sta->sta, &sinfo->signal))
++-			sinfo->signal = (s8)sta->last_signal;
++-		sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal);
++-	}
++-	if (sta->chains) {
++-		sinfo->filled |= STATION_INFO_CHAIN_SIGNAL |
++-				 STATION_INFO_CHAIN_SIGNAL_AVG;
++-
++-		sinfo->chains = sta->chains;
++-		for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) {
++-			sinfo->chain_signal[i] = sta->chain_signal_last[i];
++-			sinfo->chain_signal_avg[i] =
++-				(s8) -ewma_read(&sta->chain_signal_avg[i]);
++-		}
++-	}
++-
++-	sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate);
++-	sta_set_rate_info_rx(sta, &sinfo->rxrate);
++-
++-	if (ieee80211_vif_is_mesh(&sdata->vif)) {
++-#ifdef CPTCFG_MAC80211_MESH
++-		sinfo->filled |= STATION_INFO_LLID |
++-				 STATION_INFO_PLID |
++-				 STATION_INFO_PLINK_STATE |
++-				 STATION_INFO_LOCAL_PM |
++-				 STATION_INFO_PEER_PM |
++-				 STATION_INFO_NONPEER_PM;
++-
++-		sinfo->llid = sta->llid;
++-		sinfo->plid = sta->plid;
++-		sinfo->plink_state = sta->plink_state;
++-		if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) {
++-			sinfo->filled |= STATION_INFO_T_OFFSET;
++-			sinfo->t_offset = sta->t_offset;
++-		}
++-		sinfo->local_pm = sta->local_pm;
++-		sinfo->peer_pm = sta->peer_pm;
++-		sinfo->nonpeer_pm = sta->nonpeer_pm;
++-#endif
++-	}
++-
++-	sinfo->bss_param.flags = 0;
++-	if (sdata->vif.bss_conf.use_cts_prot)
++-		sinfo->bss_param.flags |= BSS_PARAM_FLAGS_CTS_PROT;
++-	if (sdata->vif.bss_conf.use_short_preamble)
++-		sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE;
++-	if (sdata->vif.bss_conf.use_short_slot)
++-		sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME;
++-	sinfo->bss_param.dtim_period = sdata->local->hw.conf.ps_dtim_period;
++-	sinfo->bss_param.beacon_interval = sdata->vif.bss_conf.beacon_int;
++-
++-	sinfo->sta_flags.set = 0;
++-	sinfo->sta_flags.mask = BIT(NL80211_STA_FLAG_AUTHORIZED) |
++-				BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
++-				BIT(NL80211_STA_FLAG_WME) |
++-				BIT(NL80211_STA_FLAG_MFP) |
++-				BIT(NL80211_STA_FLAG_AUTHENTICATED) |
++-				BIT(NL80211_STA_FLAG_ASSOCIATED) |
++-				BIT(NL80211_STA_FLAG_TDLS_PEER);
++-	if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
++-		sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHORIZED);
++-	if (test_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE))
++-		sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);
++-	if (test_sta_flag(sta, WLAN_STA_WME))
++-		sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_WME);
++-	if (test_sta_flag(sta, WLAN_STA_MFP))
++-		sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_MFP);
++-	if (test_sta_flag(sta, WLAN_STA_AUTH))
++-		sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
++-	if (test_sta_flag(sta, WLAN_STA_ASSOC))
++-		sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_ASSOCIATED);
++-	if (test_sta_flag(sta, WLAN_STA_TDLS_PEER))
++-		sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
++-
++-	/* check if the driver has a SW RC implementation */
++-	if (ref && ref->ops->get_expected_throughput)
++-		thr = ref->ops->get_expected_throughput(sta->rate_ctrl_priv);
++-	else
++-		thr = drv_get_expected_throughput(local, &sta->sta);
++-
++-	if (thr != 0) {
++-		sinfo->filled |= STATION_INFO_EXPECTED_THROUGHPUT;
++-		sinfo->expected_throughput = thr;
++-	}
++-}
++-
++-static const char ieee80211_gstrings_sta_stats[][ETH_GSTRING_LEN] = {
++-	"rx_packets", "rx_bytes", "wep_weak_iv_count",
++-	"rx_duplicates", "rx_fragments", "rx_dropped",
++-	"tx_packets", "tx_bytes", "tx_fragments",
++-	"tx_filtered", "tx_retry_failed", "tx_retries",
++-	"beacon_loss", "sta_state", "txrate", "rxrate", "signal",
++-	"channel", "noise", "ch_time", "ch_time_busy",
++-	"ch_time_ext_busy", "ch_time_rx", "ch_time_tx"
++-};
++-#define STA_STATS_LEN	ARRAY_SIZE(ieee80211_gstrings_sta_stats)
++-
++-static int ieee80211_get_et_sset_count(struct wiphy *wiphy,
++-				       struct net_device *dev,
++-				       int sset)
++-{
++-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++-	int rv = 0;
++-
++-	if (sset == ETH_SS_STATS)
++-		rv += STA_STATS_LEN;
++-
++-	rv += drv_get_et_sset_count(sdata, sset);
++-
++-	if (rv == 0)
++-		return -EOPNOTSUPP;
++-	return rv;
++-}
++-
++-static void ieee80211_get_et_stats(struct wiphy *wiphy,
++-				   struct net_device *dev,
++-				   struct ethtool_stats *stats,
++-				   u64 *data)
++-{
++-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++-	struct ieee80211_chanctx_conf *chanctx_conf;
++-	struct ieee80211_channel *channel;
++-	struct sta_info *sta;
++-	struct ieee80211_local *local = sdata->local;
++-	struct station_info sinfo;
++-	struct survey_info survey;
++-	int i, q;
++-#define STA_STATS_SURVEY_LEN 7
++-
++-	memset(data, 0, sizeof(u64) * STA_STATS_LEN);
++-
++-#define ADD_STA_STATS(sta)				\
++-	do {						\
++-		data[i++] += sta->rx_packets;		\
++-		data[i++] += sta->rx_bytes;		\
++-		data[i++] += sta->wep_weak_iv_count;	\
++-		data[i++] += sta->num_duplicates;	\
++-		data[i++] += sta->rx_fragments;		\
++-		data[i++] += sta->rx_dropped;		\
++-							\
++-		data[i++] += sinfo.tx_packets;		\
++-		data[i++] += sinfo.tx_bytes;		\
++-		data[i++] += sta->tx_fragments;		\
++-		data[i++] += sta->tx_filtered_count;	\
++-		data[i++] += sta->tx_retry_failed;	\
++-		data[i++] += sta->tx_retry_count;	\
++-		data[i++] += sta->beacon_loss_count;	\
++-	} while (0)
++-
++-	/* For Managed stations, find the single station based on BSSID
++-	 * and use that.  For interface types, iterate through all available
++-	 * stations and add stats for any station that is assigned to this
++-	 * network device.
++-	 */
++-
++-	mutex_lock(&local->sta_mtx);
++-
++-	if (sdata->vif.type == NL80211_IFTYPE_STATION) {
++-		sta = sta_info_get_bss(sdata, sdata->u.mgd.bssid);
++-
++-		if (!(sta && !WARN_ON(sta->sdata->dev != dev)))
++-			goto do_survey;
++-
++-		sinfo.filled = 0;
++-		sta_set_sinfo(sta, &sinfo);
++-
++-		i = 0;
++-		ADD_STA_STATS(sta);
++-
++-		data[i++] = sta->sta_state;
++-
++-
++-		if (sinfo.filled & STATION_INFO_TX_BITRATE)
++-			data[i] = 100000 *
++-				cfg80211_calculate_bitrate(&sinfo.txrate);
++-		i++;
++-		if (sinfo.filled & STATION_INFO_RX_BITRATE)
++-			data[i] = 100000 *
++-				cfg80211_calculate_bitrate(&sinfo.rxrate);
++-		i++;
++-
++-		if (sinfo.filled & STATION_INFO_SIGNAL_AVG)
++-			data[i] = (u8)sinfo.signal_avg;
++-		i++;
++-	} else {
++-		list_for_each_entry(sta, &local->sta_list, list) {
++-			/* Make sure this station belongs to the proper dev */
++-			if (sta->sdata->dev != dev)
++-				continue;
++-
++-			sinfo.filled = 0;
++-			sta_set_sinfo(sta, &sinfo);
++-			i = 0;
++-			ADD_STA_STATS(sta);
++-		}
++-	}
++-
++-do_survey:
++-	i = STA_STATS_LEN - STA_STATS_SURVEY_LEN;
++-	/* Get survey stats for current channel */
++-	survey.filled = 0;
++-
++-	rcu_read_lock();
++-	chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
++-	if (chanctx_conf)
++-		channel = chanctx_conf->def.chan;
++-	else
++-		channel = NULL;
++-	rcu_read_unlock();
+ -
 - 	/* Revert chainmask to runtime parameters */
 - 	ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
-- 
++-	if (channel) {
++-		q = 0;
++-		do {
++-			survey.filled = 0;
++-			if (drv_get_survey(local, q, &survey) != 0) {
++-				survey.filled = 0;
++-				break;
++-			}
++-			q++;
++-		} while (channel != survey.channel);
++-	}
++-
++-	if (survey.filled)
++-		data[i++] = survey.channel->center_freq;
++-	else
++-		data[i++] = 0;
++-	if (survey.filled & SURVEY_INFO_NOISE_DBM)
++-		data[i++] = (u8)survey.noise;
++-	else
++-		data[i++] = -1LL;
++-	if (survey.filled & SURVEY_INFO_CHANNEL_TIME)
++-		data[i++] = survey.channel_time;
++-	else
++-		data[i++] = -1LL;
++-	if (survey.filled & SURVEY_INFO_CHANNEL_TIME_BUSY)
++-		data[i++] = survey.channel_time_busy;
++-	else
++-		data[i++] = -1LL;
++-	if (survey.filled & SURVEY_INFO_CHANNEL_TIME_EXT_BUSY)
++-		data[i++] = survey.channel_time_ext_busy;
++-	else
++-		data[i++] = -1LL;
++-	if (survey.filled & SURVEY_INFO_CHANNEL_TIME_RX)
++-		data[i++] = survey.channel_time_rx;
++-	else
++-		data[i++] = -1LL;
++-	if (survey.filled & SURVEY_INFO_CHANNEL_TIME_TX)
++-		data[i++] = survey.channel_time_tx;
++-	else
++-		data[i++] = -1LL;
++-
++-	mutex_unlock(&local->sta_mtx);
++-
++-	if (WARN_ON(i != STA_STATS_LEN))
++-		return;
++-
++-	drv_get_et_stats(sdata, stats, &(data[STA_STATS_LEN]));
++-}
++-
++-static void ieee80211_get_et_strings(struct wiphy *wiphy,
++-				     struct net_device *dev,
++-				     u32 sset, u8 *data)
++-{
++-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++-	int sz_sta_stats = 0;
++-
++-	if (sset == ETH_SS_STATS) {
++-		sz_sta_stats = sizeof(ieee80211_gstrings_sta_stats);
++-		memcpy(data, ieee80211_gstrings_sta_stats, sz_sta_stats);
++-	}
++-	drv_get_et_strings(sdata, sset, &(data[sz_sta_stats]));
++-}
++-
++ static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
++ 				  int idx, u8 *mac, struct station_info *sinfo)
++ {
++@@ -875,7 +554,8 @@ static int ieee80211_set_monitor_channel
++ }
++ 
++ static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
++-				    const u8 *resp, size_t resp_len)
+++				    const u8 *resp, size_t resp_len,
+++				    const struct ieee80211_csa_settings *csa)
++ {
++ 	struct probe_resp *new, *old;
+  
 ---- a/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h
 -+++ b/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h
 -@@ -15,6 +15,8 @@
 - #ifndef RTL8187_H
 - #define RTL8187_H
-- 
++@@ -891,6 +571,11 @@ static int ieee80211_set_probe_resp(stru
++ 	new->len = resp_len;
++ 	memcpy(new->data, resp, resp_len);
+  
 -+#include <linux/cache.h>
--+
+++	if (csa)
+++		memcpy(new->csa_counter_offsets, csa->counter_offsets_presp,
+++		       csa->n_counter_offsets_presp *
+++		       sizeof(new->csa_counter_offsets[0]));
+ +
 - #include "rtl818x.h"
 - #include "leds.h"
 - 
@@ -5610,12 +7073,33 @@ index a1af6c2..c621ddb 100644
 -@@ -154,6 +154,11 @@ u16 ieee80211_select_queue(struct ieee80
 - 		return IEEE80211_AC_BE;
 - 	}
-- 
++ 	rcu_assign_pointer(sdata->u.ap.probe_resp, new);
++ 	if (old)
++ 		kfree_rcu(old, rcu_head);
++@@ -899,7 +584,8 @@ static int ieee80211_set_probe_resp(stru
++ }
+  
 -+	if (skb->protocol == sdata->control_port_protocol) {
 -+		skb->priority = 7;
 -+		return ieee80211_downgrade_queue(sdata, skb);
--+	}
--+
++ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
++-				   struct cfg80211_beacon_data *params)
+++				   struct cfg80211_beacon_data *params,
+++				   const struct ieee80211_csa_settings *csa)
++ {
++ 	struct beacon_data *new, *old;
++ 	int new_head_len, new_tail_len;
++@@ -943,6 +629,13 @@ static int ieee80211_assign_beacon(struc
++ 	new->head_len = new_head_len;
++ 	new->tail_len = new_tail_len;
++ 
+++	if (csa) {
+++		new->csa_current_counter = csa->count;
+++		memcpy(new->csa_counter_offsets, csa->counter_offsets_beacon,
+++		       csa->n_counter_offsets_beacon *
+++		       sizeof(new->csa_counter_offsets[0]));
+ +	}
+ +
 - 	/* use the data classifier to determine what 802.1d tag the
 - 	 * data frame has */
 - 	rcu_read_lock();
@@ -5630,30 +7114,136 @@ index a1af6c2..c621ddb 100644
 --
 - 		ac = tid->ac;
 - 		txq = ac->txq;
-- 
++ 	/* copy in head */
++ 	if (params->head)
++ 		memcpy(new->head, params->head, new_head_len);
++@@ -957,7 +650,7 @@ static int ieee80211_assign_beacon(struc
++ 			memcpy(new->tail, old->tail, new_tail_len);
+  
 - 		ath_txq_lock(sc, txq);
-- 
++ 	err = ieee80211_set_probe_resp(sdata, params->probe_resp,
++-				       params->probe_resp_len);
+++				       params->probe_resp_len, csa);
++ 	if (err < 0)
++ 		return err;
++ 	if (err == 0)
++@@ -1042,7 +735,7 @@ static int ieee80211_start_ap(struct wip
++ 		sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |=
++ 					IEEE80211_P2P_OPPPS_ENABLE_BIT;
+  
 -+		if (!tid->sched) {
 -+			ath_txq_unlock(sc, txq);
 -+			continue;
 -+		}
 -+
 - 		buffered = ath_tid_has_buffered(tid);
-- 
++-	err = ieee80211_assign_beacon(sdata, &params->beacon);
+++	err = ieee80211_assign_beacon(sdata, &params->beacon, NULL);
++ 	if (err < 0) {
++ 		ieee80211_vif_release_channel(sdata);
++ 		return err;
++@@ -1090,7 +783,7 @@ static int ieee80211_change_beacon(struc
++ 	if (!old)
++ 		return -ENOENT;
+  
 - 		tid->sched = false;
 -@@ -1696,7 +1698,7 @@ int ath_cabq_update(struct ath_softc *sc
-- 
++-	err = ieee80211_assign_beacon(sdata, params);
+++	err = ieee80211_assign_beacon(sdata, params, NULL);
++ 	if (err < 0)
++ 		return err;
++ 	ieee80211_bss_info_change_notify(sdata, err);
++@@ -3073,7 +2766,8 @@ static int ieee80211_set_after_csa_beaco
+  
 - 	ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi);
-- 
++ 	switch (sdata->vif.type) {
++ 	case NL80211_IFTYPE_AP:
++-		err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon);
+++		err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon,
+++					      NULL);
++ 		kfree(sdata->u.ap.next_beacon);
++ 		sdata->u.ap.next_beacon = NULL;
++ 
++@@ -3176,6 +2870,7 @@ static int ieee80211_set_csa_beacon(stru
++ 				    struct cfg80211_csa_settings *params,
++ 				    u32 *changed)
++ {
+++	struct ieee80211_csa_settings csa = {};
++ 	int err;
+  
 --	qi.tqi_readyTime = (cur_conf->beacon_interval *
 -+	qi.tqi_readyTime = (TU_TO_USEC(cur_conf->beacon_interval) *
 - 			    ATH_CABQ_READY_TIME) / 100;
 - 	ath_txq_update(sc, qnum, &qi);
-- 
++ 	switch (sdata->vif.type) {
++@@ -3210,20 +2905,13 @@ static int ieee80211_set_csa_beacon(stru
++ 		     IEEE80211_MAX_CSA_COUNTERS_NUM))
++ 			return -EINVAL;
+  
 -@@ -2061,7 +2063,7 @@ static struct ath_buf *ath_tx_setup_buff
-- 
++-		/* make sure we don't have garbage in other counters */
++-		memset(sdata->csa_counter_offset_beacon, 0,
++-		       sizeof(sdata->csa_counter_offset_beacon));
++-		memset(sdata->csa_counter_offset_presp, 0,
++-		       sizeof(sdata->csa_counter_offset_presp));
++-
++-		memcpy(sdata->csa_counter_offset_beacon,
++-		       params->counter_offsets_beacon,
++-		       params->n_counter_offsets_beacon * sizeof(u16));
++-		memcpy(sdata->csa_counter_offset_presp,
++-		       params->counter_offsets_presp,
++-		       params->n_counter_offsets_presp * sizeof(u16));
+++		csa.counter_offsets_beacon = params->counter_offsets_beacon;
+++		csa.counter_offsets_presp = params->counter_offsets_presp;
+++		csa.n_counter_offsets_beacon = params->n_counter_offsets_beacon;
+++		csa.n_counter_offsets_presp = params->n_counter_offsets_presp;
+++		csa.count = params->count;
++ 
++-		err = ieee80211_assign_beacon(sdata, &params->beacon_csa);
+++		err = ieee80211_assign_beacon(sdata, &params->beacon_csa, &csa);
++ 		if (err < 0) {
++ 			kfree(sdata->u.ap.next_beacon);
++ 			return err;
++@@ -3367,7 +3055,6 @@ __ieee80211_channel_switch(struct wiphy 
++ 	sdata->csa_radar_required = params->radar_required;
++ 	sdata->csa_chandef = params->chandef;
++ 	sdata->csa_block_tx = params->block_tx;
++-	sdata->csa_current_counter = params->count;
++ 	sdata->vif.csa_active = true;
++ 
++ 	if (sdata->csa_block_tx)
++@@ -3515,10 +3202,23 @@ static int ieee80211_mgmt_tx(struct wiph
++ 	     sdata->vif.type == NL80211_IFTYPE_ADHOC) &&
++ 	    params->n_csa_offsets) {
++ 		int i;
++-		u8 c = sdata->csa_current_counter;
+++		struct beacon_data *beacon = NULL;
+++
+++		rcu_read_lock();
++ 
++-		for (i = 0; i < params->n_csa_offsets; i++)
++-			data[params->csa_offsets[i]] = c;
+++		if (sdata->vif.type == NL80211_IFTYPE_AP)
+++			beacon = rcu_dereference(sdata->u.ap.beacon);
+++		else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
+++			beacon = rcu_dereference(sdata->u.ibss.presp);
+++		else if (ieee80211_vif_is_mesh(&sdata->vif))
+++			beacon = rcu_dereference(sdata->u.mesh.beacon);
+++
+++		if (beacon)
+++			for (i = 0; i < params->n_csa_offsets; i++)
+++				data[params->csa_offsets[i]] =
+++					beacon->csa_current_counter;
+++
+++		rcu_read_unlock();
++ 	}
+  
 - 	ATH_TXBUF_RESET(bf);
-- 
++ 	IEEE80211_SKB_CB(skb)->flags = flags;
++@@ -3598,21 +3298,6 @@ static int ieee80211_get_antenna(struct 
++ 	return drv_get_antenna(local, tx_ant, rx_ant);
++ }
+  
 --	if (tid) {
 -+	if (tid && ieee80211_is_data_present(hdr->frame_control)) {
 - 		fragno = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG;
@@ -5662,7 +7252,59 @@ index a1af6c2..c621ddb 100644
 -@@ -2184,14 +2186,15 @@ int ath_tx_start(struct ieee80211_hw *hw
 - 		txq->stopped = true;
 - 	}
-- 
++-static int ieee80211_set_ringparam(struct wiphy *wiphy, u32 tx, u32 rx)
++-{
++-	struct ieee80211_local *local = wiphy_priv(wiphy);
++-
++-	return drv_set_ringparam(local, tx, rx);
++-}
++-
++-static void ieee80211_get_ringparam(struct wiphy *wiphy,
++-				    u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max)
++-{
++-	struct ieee80211_local *local = wiphy_priv(wiphy);
++-
++-	drv_get_ringparam(local, tx, tx_max, rx, rx_max);
++-}
++-
++ static int ieee80211_set_rekey_data(struct wiphy *wiphy,
++ 				    struct net_device *dev,
++ 				    struct cfg80211_gtk_rekey_data *data)
++@@ -3844,8 +3529,6 @@ const struct cfg80211_ops mac80211_confi
++ 	.mgmt_frame_register = ieee80211_mgmt_frame_register,
++ 	.set_antenna = ieee80211_set_antenna,
++ 	.get_antenna = ieee80211_get_antenna,
++-	.set_ringparam = ieee80211_set_ringparam,
++-	.get_ringparam = ieee80211_get_ringparam,
++ 	.set_rekey_data = ieee80211_set_rekey_data,
++ 	.tdls_oper = ieee80211_tdls_oper,
++ 	.tdls_mgmt = ieee80211_tdls_mgmt,
++@@ -3854,9 +3537,6 @@ const struct cfg80211_ops mac80211_confi
++ #ifdef CONFIG_PM
++ 	.set_wakeup = ieee80211_set_wakeup,
++ #endif
++-	.get_et_sset_count = ieee80211_get_et_sset_count,
++-	.get_et_stats = ieee80211_get_et_stats,
++-	.get_et_strings = ieee80211_get_et_strings,
++ 	.get_channel = ieee80211_cfg_get_channel,
++ 	.start_radar_detection = ieee80211_start_radar_detection,
++ 	.channel_switch = ieee80211_channel_switch,
++--- a/net/mac80211/debugfs_sta.c
+++++ b/net/mac80211/debugfs_sta.c
++@@ -587,7 +587,6 @@ void ieee80211_sta_debugfs_add(struct st
++ 	DEBUGFS_ADD_COUNTER(tx_filtered, tx_filtered_count);
++ 	DEBUGFS_ADD_COUNTER(tx_retry_failed, tx_retry_failed);
++ 	DEBUGFS_ADD_COUNTER(tx_retry_count, tx_retry_count);
++-	DEBUGFS_ADD_COUNTER(wep_weak_iv_count, wep_weak_iv_count);
++ 
++ 	if (sizeof(sta->driver_buffered_tids) == sizeof(u32))
++ 		debugfs_create_x32("driver_buffered_tids", 0400,
++--- a/net/mac80211/wep.c
+++++ b/net/mac80211/wep.c
++@@ -271,22 +271,6 @@ static int ieee80211_wep_decrypt(struct 
++ 	return ret;
++ }
+  
 -+	if (txctl->an && ieee80211_is_data_present(hdr->frame_control))
 -+		tid = ath_get_skb_tid(sc, txctl->an, skb);
 -+
@@ -5673,7 +7315,7 @@ index a1af6c2..c621ddb 100644
 - 	} else if (txctl->an &&
 - 		   ieee80211_is_data_present(hdr->frame_control)) {
 --		tid = ath_get_skb_tid(sc, txctl->an, skb);
---
+ -
 - 		WARN_ON(tid->ac->txq != txctl->txq);
 - 
 - 		if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
@@ -5698,51 +7340,137 @@ index a1af6c2..c621ddb 100644
 --				   void (*fn)(void *data), void *data);
 --static inline void ieee80211_add_pending_skbs(struct ieee80211_local *local,
 --					      struct sk_buff_head *skbs)
---{
++-static bool ieee80211_wep_is_weak_iv(struct sk_buff *skb,
++-				     struct ieee80211_key *key)
+ -{
 --	ieee80211_add_pending_skbs_fn(local, skbs, NULL, NULL);
---}
++-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
++-	unsigned int hdrlen;
++-	u8 *ivpos;
++-	u32 iv;
++-
++-	hdrlen = ieee80211_hdrlen(hdr->frame_control);
++-	ivpos = skb->data + hdrlen;
++-	iv = (ivpos[0] << 16) | (ivpos[1] << 8) | ivpos[2];
++-
++-	return ieee80211_wep_weak_iv(iv, key->conf.keylen);
+ -}
 -+void ieee80211_add_pending_skbs(struct ieee80211_local *local,
 -+				struct sk_buff_head *skbs);
 - void ieee80211_flush_queues(struct ieee80211_local *local,
 - 			    struct ieee80211_sub_if_data *sdata);
-+ 	if (sc->rx.buf_hold)
-+-		ath_rx_buf_link(sc, sc->rx.buf_hold);
-++		ath_rx_buf_link(sc, sc->rx.buf_hold, flush);
-+ 
-+ 	sc->rx.buf_hold = bf;
-+ }
-+@@ -442,7 +444,7 @@ int ath_startrecv(struct ath_softc *sc)
-+ 	sc->rx.buf_hold = NULL;
-+ 	sc->rx.rxlink = NULL;
-+ 	list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) {
-+-		ath_rx_buf_link(sc, bf);
-++		ath_rx_buf_link(sc, bf, false);
-+ 	}
-+ 
-+ 	/* We could have deleted elements so the list may be empty now */
-+@@ -1118,12 +1120,12 @@ requeue_drop_frag:
-+ requeue:
-+ 		list_add_tail(&bf->list, &sc->rx.rxbuf);
-+ 
-+-		if (edma) {
-+-			ath_rx_edma_buf_link(sc, qtype);
-+-		} else {
-+-			ath_rx_buf_relink(sc, bf);
-++		if (!edma) {
-++			ath_rx_buf_relink(sc, bf, flush);
-+ 			if (!flush)
-+ 				ath9k_hw_rxena(ah);
-++		} else if (!flush) {
-++			ath_rx_edma_buf_link(sc, qtype);
-+ 		}
++-
++ ieee80211_rx_result
++ ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx)
++ {
++@@ -301,16 +285,12 @@ ieee80211_crypto_wep_decrypt(struct ieee
++ 	if (!(status->flag & RX_FLAG_DECRYPTED)) {
++ 		if (skb_linearize(rx->skb))
++ 			return RX_DROP_UNUSABLE;
++-		if (rx->sta && ieee80211_wep_is_weak_iv(rx->skb, rx->key))
++-			rx->sta->wep_weak_iv_count++;
++ 		if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key))
++ 			return RX_DROP_UNUSABLE;
++ 	} else if (!(status->flag & RX_FLAG_IV_STRIPPED)) {
++ 		if (!pskb_may_pull(rx->skb, ieee80211_hdrlen(fc) +
++ 					    IEEE80211_WEP_IV_LEN))
++ 			return RX_DROP_UNUSABLE;
++-		if (rx->sta && ieee80211_wep_is_weak_iv(rx->skb, rx->key))
++-			rx->sta->wep_weak_iv_count++;
++ 		ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key);
++ 		/* remove ICV */
++ 		if (pskb_trim(rx->skb, rx->skb->len - IEEE80211_WEP_ICV_LEN))
++--- a/include/net/cfg80211.h
+++++ b/include/net/cfg80211.h
++@@ -2278,16 +2278,6 @@ struct cfg80211_qos_map {
++  *
++  * @set_noack_map: Set the NoAck Map for the TIDs.
++  *
++- * @get_et_sset_count:  Ethtool API to get string-set count.
++- *	See @ethtool_ops.get_sset_count
++- *
++- * @get_et_stats:  Ethtool API to get a set of u64 stats.
++- *	See @ethtool_ops.get_ethtool_stats
++- *
++- * @get_et_strings:  Ethtool API to get a set of strings to describe stats
++- *	and perhaps other supported types of ethtool data-sets.
++- *	See @ethtool_ops.get_strings
++- *
++  * @get_channel: Get the current operating channel for the virtual interface.
++  *	For monitor interfaces, it should return %NULL unless there's a single
++  *	current monitoring channel.
++@@ -2529,13 +2519,6 @@ struct cfg80211_ops {
++ 				  struct net_device *dev,
++ 				  u16 noack_map);
++ 
++-	int	(*get_et_sset_count)(struct wiphy *wiphy,
++-				     struct net_device *dev, int sset);
++-	void	(*get_et_stats)(struct wiphy *wiphy, struct net_device *dev,
++-				struct ethtool_stats *stats, u64 *data);
++-	void	(*get_et_strings)(struct wiphy *wiphy, struct net_device *dev,
++-				  u32 sset, u8 *data);
++-
++ 	int	(*get_channel)(struct wiphy *wiphy,
++ 			       struct wireless_dev *wdev,
++ 			       struct cfg80211_chan_def *chandef);
++@@ -4846,6 +4829,10 @@ void cfg80211_stop_iface(struct wiphy *w
++  */
++ void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy);
   
-+ 		if (!budget--)
- --- a/net/mac80211/sta_info.c
- +++ b/net/mac80211/sta_info.c
+---- a/net/mac80211/sta_info.c
+-+++ b/net/mac80211/sta_info.c
 -@@ -91,7 +91,7 @@ static int sta_info_hash_del(struct ieee
 - 	return -ENOENT;
 - }
-- 
+++
+++/* ethtool helper */
+++void cfg80211_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info);
+++
++ /* Logging, debugging and troubleshooting/diagnostic helpers. */
++ 
++ /* wiphy_printk helpers, similar to dev_printk */
++--- a/net/mac80211/Makefile
+++++ b/net/mac80211/Makefile
++@@ -17,6 +17,7 @@ mac80211-y := \
++ 	aes_ccm.o \
++ 	aes_cmac.o \
++ 	cfg.o \
+++	ethtool.o \
++ 	rx.o \
++ 	spectmgmt.o \
++ 	tx.o \
++--- a/net/mac80211/ieee80211_i.h
+++++ b/net/mac80211/ieee80211_i.h
++@@ -229,16 +229,29 @@ struct ieee80211_rx_data {
++ 	u16 tkip_iv16;
++ };
++ 
+++struct ieee80211_csa_settings {
+++	const u16 *counter_offsets_beacon;
+++	const u16 *counter_offsets_presp;
+++
+++	int n_counter_offsets_beacon;
+++	int n_counter_offsets_presp;
+++
+++	u8 count;
+++};
+++
++ struct beacon_data {
++ 	u8 *head, *tail;
++ 	int head_len, tail_len;
++ 	struct ieee80211_meshconf_ie *meshconf;
+++	u16 csa_counter_offsets[IEEE80211_MAX_CSA_COUNTERS_NUM];
+++	u8 csa_current_counter;
++ 	struct rcu_head rcu_head;
++ };
++ 
++ struct probe_resp {
++ 	struct rcu_head rcu_head;
++ 	int len;
+++	u16 csa_counter_offsets[IEEE80211_MAX_CSA_COUNTERS_NUM];
++ 	u8 data[0];
++ };
+  
 --static void cleanup_single_sta(struct sta_info *sta)
 -+static void __cleanup_single_sta(struct sta_info *sta)
 - {
@@ -5750,60 +7478,68 @@ index a1af6c2..c621ddb 100644
 - 	struct tid_ampdu_tx *tid_tx;
 -@@ -99,7 +99,8 @@ static void cleanup_single_sta(struct st
 - 	struct ieee80211_local *local = sdata->local;
-+@@ -100,7 +100,8 @@ static void __cleanup_single_sta(struct 
-  	struct ps_data *ps;
+- 	struct ps_data *ps;
++@@ -754,8 +767,6 @@ struct ieee80211_sub_if_data {
++ 	struct mac80211_qos_map __rcu *qos_map;
   
 --	if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
 -+	if (test_sta_flag(sta, WLAN_STA_PS_STA) ||
 -+	    test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
-+ 	if (test_sta_flag(sta, WLAN_STA_PS_STA) ||
-+-	    test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
-++	    test_sta_flag(sta, WLAN_STA_PS_DRIVER) ||
-++	    test_sta_flag(sta, WLAN_STA_PS_DELIVER)) {
-  		if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
-  		    sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
-  			ps = &sdata->bss->ps;
+- 		if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
+- 		    sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+- 			ps = &sdata->bss->ps;
 -@@ -109,6 +110,7 @@ static void cleanup_single_sta(struct st
 - 			return;
-+@@ -111,6 +112,7 @@ static void __cleanup_single_sta(struct 
-  
-  		clear_sta_flag(sta, WLAN_STA_PS_STA);
++ 	struct work_struct csa_finalize_work;
++-	u16 csa_counter_offset_beacon[IEEE80211_MAX_CSA_COUNTERS_NUM];
++-	u16 csa_counter_offset_presp[IEEE80211_MAX_CSA_COUNTERS_NUM];
++ 	bool csa_radar_required;
++ 	bool csa_block_tx; /* write-protected by sdata_lock and local->mtx */
++ 	struct cfg80211_chan_def csa_chandef;
++@@ -767,7 +778,6 @@ struct ieee80211_sub_if_data {
++ 	struct ieee80211_chanctx *reserved_chanctx;
++ 	struct cfg80211_chan_def reserved_chandef;
++ 	bool reserved_radar_required;
++-	u8 csa_current_counter;
+  
+- 		clear_sta_flag(sta, WLAN_STA_PS_STA);
 -+		clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
-+ 		clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
-++		clear_sta_flag(sta, WLAN_STA_PS_DELIVER);
++ 	/* used to reconfigure hardware SM PS */
++ 	struct work_struct recalc_smps;
++@@ -1850,6 +1860,8 @@ int ieee80211_tdls_oper(struct wiphy *wi
++ 			const u8 *peer, enum nl80211_tdls_operation oper);
   
-  		atomic_dec(&ps->num_sta_ps);
-  		sta_info_recalc_tim(sta);
+- 		atomic_dec(&ps->num_sta_ps);
+- 		sta_info_recalc_tim(sta);
 -@@ -139,7 +141,14 @@ static void cleanup_single_sta(struct st
 - 		ieee80211_purge_tx_queue(&local->hw, &tid_tx->pending);
 - 		kfree(tid_tx);
 - 	}
 -+}
-+@@ -125,7 +127,7 @@ static void __cleanup_single_sta(struct 
-+ 	if (ieee80211_vif_is_mesh(&sdata->vif))
-+ 		mesh_sta_cleanup(sta);
   
 -+static void cleanup_single_sta(struct sta_info *sta)
 -+{
 -+	struct ieee80211_sub_if_data *sdata = sta->sdata;
 -+	struct ieee80211_local *local = sdata->local;
--+
+++extern const struct ethtool_ops ieee80211_ethtool_ops;
+ +
 -+	__cleanup_single_sta(sta);
 - 	sta_info_free(local, sta);
 - }
-+-	cancel_work_sync(&sta->drv_unblock_wk);
-++	cancel_work_sync(&sta->drv_deliver_wk);
++ #ifdef CPTCFG_MAC80211_NOINLINE
++ #define debug_noinline noinline
++ #else
++--- a/net/mac80211/iface.c
+++++ b/net/mac80211/iface.c
++@@ -399,6 +399,7 @@ int ieee80211_add_virtual_monitor(struct
++ 	sdata->vif.type = NL80211_IFTYPE_MONITOR;
++ 	snprintf(sdata->name, IFNAMSIZ, "%s-monitor",
++ 		 wiphy_name(local->hw.wiphy));
+++	sdata->wdev.iftype = NL80211_IFTYPE_MONITOR;
   
 -@@ -330,6 +339,7 @@ struct sta_info *sta_info_alloc(struct i
 - 	rcu_read_unlock();
-+ 	/*
-+ 	 * Destroy aggregation state here. It would be nice to wait for the
-+@@ -227,6 +229,7 @@ struct sta_info *sta_info_get_by_idx(str
-+  */
-+ void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
-+ {
-++	struct ieee80211_sta_rates *rates;
-+ 	int i;
++ 	sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
   
 - 	spin_lock_init(&sta->lock);
 -+	spin_lock_init(&sta->ps_lock);
@@ -5812,10 +7548,12 @@ index a1af6c2..c621ddb 100644
 - 	mutex_init(&sta->ampdu_mlme.mtx);
 -@@ -487,21 +497,26 @@ static int sta_info_insert_finish(struct
 - 		goto out_err;
-+ 	if (sta->rate_ctrl)
-+@@ -238,6 +241,10 @@ void sta_info_free(struct ieee80211_loca
-+ 		kfree(sta->tx_lat);
-  	}
+- 	}
++@@ -1303,6 +1304,7 @@ static void ieee80211_setup_sdata(struct
++ 	sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE);
++ 	sdata->control_port_no_encrypt = false;
++ 	sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
+++	sdata->vif.bss_conf.idle = true;
   
 --	/* notify driver */
 --	err = sta_info_insert_drv_state(local, sdata, sta);
@@ -5825,33 +7563,48 @@ index a1af6c2..c621ddb 100644
 - 	local->num_sta++;
 - 	local->sta_generation++;
 - 	smp_mb();
-- 
++ 	sdata->noack_map = 0;
+  
 -+	/* simplify things and don't accept BA sessions yet */
 -+	set_sta_flag(sta, WLAN_STA_BLOCK_BA);
-++	rates = rcu_dereference_protected(sta->sta.rates, true);
-++	if (rates)
-++		kfree(rates);
- +
+-+
 - 	/* make the station visible */
 - 	sta_info_hash_add(local, sta);
-+ 	sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr);
++@@ -1721,6 +1723,8 @@ int ieee80211_if_add(struct ieee80211_lo
   
 - 	list_add_rcu(&sta->list, &local->sta_list);
-- 
++ 		ndev->features |= local->hw.netdev_features;
+  
 -+	/* notify driver */
 -+	err = sta_info_insert_drv_state(local, sdata, sta);
 -+	if (err)
 -+		goto out_remove;
--+
+++		netdev_set_default_ethtool_ops(ndev, &ieee80211_ethtool_ops);
+ +
 - 	set_sta_flag(sta, WLAN_STA_INSERTED);
 -+	/* accept BA sessions now */
 -+	clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
-- 
++ 		ret = register_netdevice(ndev);
++ 		if (ret) {
++ 			free_netdev(ndev);
++--- a/net/wireless/core.c
+++++ b/net/wireless/core.c
++@@ -25,7 +25,6 @@
++ #include "sysfs.h"
++ #include "debugfs.h"
++ #include "wext-compat.h"
++-#include "ethtool.h"
++ #include "rdev-ops.h"
+  
 - 	ieee80211_recalc_min_chandef(sdata);
 - 	ieee80211_sta_debugfs_add(sta);
 -@@ -522,6 +537,12 @@ static int sta_info_insert_finish(struct
 - 		mesh_accept_plinks_update(sdata);
-- 
++ /* name for sysfs, %d is appended */
++@@ -940,8 +939,6 @@ static int cfg80211_netdev_notifier_call
++ 		/* allow mac80211 to determine the timeout */
++ 		wdev->ps_timeout = -1;
+  
 - 	return 0;
 -+ out_remove:
 -+	sta_info_hash_del(local, sta);
@@ -5863,17 +7616,28 @@ index a1af6c2..c621ddb 100644
 - 	mutex_unlock(&local->sta_mtx);
 - 	rcu_read_lock();
 -@@ -1071,10 +1092,14 @@ struct ieee80211_sta *ieee80211_find_sta
-+ 	kfree(sta);
-+@@ -252,33 +259,23 @@ static void sta_info_hash_add(struct iee
-+ 	rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], sta);
-  }
+- }
 - EXPORT_SYMBOL(ieee80211_find_sta);
++-		netdev_set_default_ethtool_ops(dev, &cfg80211_ethtool_ops);
++-
++ 		if ((wdev->iftype == NL80211_IFTYPE_STATION ||
++ 		     wdev->iftype == NL80211_IFTYPE_P2P_CLIENT ||
++ 		     wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr)
++--- a/net/wireless/ethtool.c
+++++ b/net/wireless/ethtool.c
++@@ -1,11 +1,9 @@
++ #include <linux/utsname.h>
++ #include <net/cfg80211.h>
++ #include "core.h"
++-#include "ethtool.h"
++ #include "rdev-ops.h"
   
 --static void clear_sta_ps_flags(void *_sta)
 -+/* powersave support code */
 -+void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
-+-static void sta_unblock(struct work_struct *wk)
-++static void sta_deliver_ps_frames(struct work_struct *wk)
++-static void cfg80211_get_drvinfo(struct net_device *dev,
++-					struct ethtool_drvinfo *info)
+++void cfg80211_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
   {
 --	struct sta_info *sta = _sta;
 - 	struct ieee80211_sub_if_data *sdata = sta->sdata;
@@ -5882,52 +7646,154 @@ index a1af6c2..c621ddb 100644
 -+	int filtered = 0, buffered = 0, ac;
 -+	unsigned long flags;
 - 	struct ps_data *ps;
-+ 	struct sta_info *sta;
-+ 
-+-	sta = container_of(wk, struct sta_info, drv_unblock_wk);
-++	sta = container_of(wk, struct sta_info, drv_deliver_wk);
-  
+- 
 - 	if (sdata->vif.type == NL80211_IFTYPE_AP ||
 -@@ -1085,20 +1110,6 @@ static void clear_sta_ps_flags(void *_st
 - 	else
-+ 	if (sta->dead)
-  		return;
+- 		return;
++ 	struct wireless_dev *wdev = dev->ieee80211_ptr;
   
 --	clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
 --	if (test_and_clear_sta_flag(sta, WLAN_STA_PS_STA))
 --		atomic_dec(&ps->num_sta_ps);
---}
-+-	if (!test_sta_flag(sta, WLAN_STA_PS_STA)) {
-+-		local_bh_disable();
-++	local_bh_disable();
-++	if (!test_sta_flag(sta, WLAN_STA_PS_STA))
-+ 		ieee80211_sta_ps_deliver_wakeup(sta);
-+-		local_bh_enable();
-+-	} else if (test_and_clear_sta_flag(sta, WLAN_STA_PSPOLL)) {
-+-		clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
++@@ -23,84 +21,4 @@ static void cfg80211_get_drvinfo(struct 
++ 	strlcpy(info->bus_info, dev_name(wiphy_dev(wdev->wiphy)),
++ 		sizeof(info->bus_info));
++ }
++-
++-static int cfg80211_get_regs_len(struct net_device *dev)
++-{
++-	/* For now, return 0... */
++-	return 0;
+ -}
  -
 --/* powersave support code */
 --void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
---{
++-static void cfg80211_get_regs(struct net_device *dev, struct ethtool_regs *regs,
++-			void *data)
+ -{
 --	struct ieee80211_sub_if_data *sdata = sta->sdata;
 --	struct ieee80211_local *local = sdata->local;
 --	struct sk_buff_head pending;
 --	int filtered = 0, buffered = 0, ac;
 --	unsigned long flags;
-+-		local_bh_disable();
-++	else if (test_and_clear_sta_flag(sta, WLAN_STA_PSPOLL))
-+ 		ieee80211_sta_ps_deliver_poll_response(sta);
-+-		local_bh_enable();
-+-	} else if (test_and_clear_sta_flag(sta, WLAN_STA_UAPSD)) {
-+-		clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
++-	struct wireless_dev *wdev = dev->ieee80211_ptr;
  -
 - 	clear_sta_flag(sta, WLAN_STA_SP);
 - 
 - 	BUILD_BUG_ON(BITS_TO_LONGS(IEEE80211_NUM_TIDS) > 1);
 -@@ -1109,6 +1120,8 @@ void ieee80211_sta_ps_deliver_wakeup(str
-- 
++-	regs->version = wdev->wiphy->hw_version;
++-	regs->len = 0;
++-}
++-
++-static void cfg80211_get_ringparam(struct net_device *dev,
++-				   struct ethtool_ringparam *rp)
++-{
++-	struct wireless_dev *wdev = dev->ieee80211_ptr;
++-	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
++-
++-	memset(rp, 0, sizeof(*rp));
++-
++-	if (rdev->ops->get_ringparam)
++-		rdev_get_ringparam(rdev, &rp->tx_pending, &rp->tx_max_pending,
++-				   &rp->rx_pending, &rp->rx_max_pending);
++-}
++-
++-static int cfg80211_set_ringparam(struct net_device *dev,
++-				  struct ethtool_ringparam *rp)
++-{
++-	struct wireless_dev *wdev = dev->ieee80211_ptr;
++-	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
++-
++-	if (rp->rx_mini_pending != 0 || rp->rx_jumbo_pending != 0)
++-		return -EINVAL;
++-
++-	if (rdev->ops->set_ringparam)
++-		return rdev_set_ringparam(rdev, rp->tx_pending, rp->rx_pending);
++-
++-	return -ENOTSUPP;
++-}
++-
++-static int cfg80211_get_sset_count(struct net_device *dev, int sset)
++-{
++-	struct wireless_dev *wdev = dev->ieee80211_ptr;
++-	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
++-	if (rdev->ops->get_et_sset_count)
++-		return rdev_get_et_sset_count(rdev, dev, sset);
++-	return -EOPNOTSUPP;
++-}
++-
++-static void cfg80211_get_stats(struct net_device *dev,
++-			       struct ethtool_stats *stats, u64 *data)
++-{
++-	struct wireless_dev *wdev = dev->ieee80211_ptr;
++-	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
++-	if (rdev->ops->get_et_stats)
++-		rdev_get_et_stats(rdev, dev, stats, data);
++-}
++-
++-static void cfg80211_get_strings(struct net_device *dev, u32 sset, u8 *data)
++-{
++-	struct wireless_dev *wdev = dev->ieee80211_ptr;
++-	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
++-	if (rdev->ops->get_et_strings)
++-		rdev_get_et_strings(rdev, dev, sset, data);
++-}
++-
++-const struct ethtool_ops cfg80211_ethtool_ops = {
++-	.get_drvinfo = cfg80211_get_drvinfo,
++-	.get_regs_len = cfg80211_get_regs_len,
++-	.get_regs = cfg80211_get_regs,
++-	.get_link = ethtool_op_get_link,
++-	.get_ringparam = cfg80211_get_ringparam,
++-	.set_ringparam = cfg80211_set_ringparam,
++-	.get_strings = cfg80211_get_strings,
++-	.get_ethtool_stats = cfg80211_get_stats,
++-	.get_sset_count = cfg80211_get_sset_count,
++-};
+++EXPORT_SYMBOL(cfg80211_get_drvinfo);
++--- a/net/wireless/ethtool.h
+++++ /dev/null
++@@ -1,6 +0,0 @@
++-#ifndef __CFG80211_ETHTOOL__
++-#define __CFG80211_ETHTOOL__
++-
++-extern const struct ethtool_ops cfg80211_ethtool_ops;
++-
++-#endif /* __CFG80211_ETHTOOL__ */
++--- a/net/wireless/rdev-ops.h
+++++ b/net/wireless/rdev-ops.h
++@@ -714,25 +714,6 @@ static inline int rdev_get_antenna(struc
++ 	return ret;
++ }
+  
 - 	skb_queue_head_init(&pending);
-- 
++-static inline int rdev_set_ringparam(struct cfg80211_registered_device *rdev,
++-				     u32 tx, u32 rx)
++-{
++-	int ret;
++-	trace_rdev_set_ringparam(&rdev->wiphy, tx, rx);
++-	ret = rdev->ops->set_ringparam(&rdev->wiphy, tx, rx);
++-	trace_rdev_return_int(&rdev->wiphy, ret);
++-	return ret;
++-}
++-
++-static inline void rdev_get_ringparam(struct cfg80211_registered_device *rdev,
++-				      u32 *tx, u32 *tx_max, u32 *rx,
++-				      u32 *rx_max)
++-{
++-	trace_rdev_get_ringparam(&rdev->wiphy);
++-	rdev->ops->get_ringparam(&rdev->wiphy, tx, tx_max, rx, rx_max);
++-	trace_rdev_return_void_tx_rx(&rdev->wiphy, *tx, *tx_max, *rx, *rx_max);
++-}
++-
++ static inline int
++ rdev_sched_scan_start(struct cfg80211_registered_device *rdev,
++ 		      struct net_device *dev,
++@@ -816,35 +797,6 @@ static inline int rdev_set_noack_map(str
++ }
+  
 -+	/* sync with ieee80211_tx_h_unicast_ps_buf */
 -+	spin_lock(&sta->ps_lock);
 - 	/* Send all buffered frames to the station */
@@ -5936,7 +7802,45 @@ index a1af6c2..c621ddb 100644
 -@@ -1127,7 +1140,12 @@ void ieee80211_sta_ps_deliver_wakeup(str
 - 		buffered += tmp - count;
 - 	}
-- 
++ static inline int
++-rdev_get_et_sset_count(struct cfg80211_registered_device *rdev,
++-		       struct net_device *dev, int sset)
++-{
++-	int ret;
++-	trace_rdev_get_et_sset_count(&rdev->wiphy, dev, sset);
++-	ret = rdev->ops->get_et_sset_count(&rdev->wiphy, dev, sset);
++-	trace_rdev_return_int(&rdev->wiphy, ret);
++-	return ret;
++-}
++-
++-static inline void rdev_get_et_stats(struct cfg80211_registered_device *rdev,
++-				     struct net_device *dev,
++-				     struct ethtool_stats *stats, u64 *data)
++-{
++-	trace_rdev_get_et_stats(&rdev->wiphy, dev);
++-	rdev->ops->get_et_stats(&rdev->wiphy, dev, stats, data);
++-	trace_rdev_return_void(&rdev->wiphy);
++-}
++-
++-static inline void rdev_get_et_strings(struct cfg80211_registered_device *rdev,
++-				       struct net_device *dev, u32 sset,
++-				       u8 *data)
++-{
++-	trace_rdev_get_et_strings(&rdev->wiphy, dev, sset);
++-	rdev->ops->get_et_strings(&rdev->wiphy, dev, sset, data);
++-	trace_rdev_return_void(&rdev->wiphy);
++-}
++-
++-static inline int
++ rdev_get_channel(struct cfg80211_registered_device *rdev,
++ 		 struct wireless_dev *wdev,
++ 		 struct cfg80211_chan_def *chandef)
++--- a/net/wireless/trace.h
+++++ b/net/wireless/trace.h
++@@ -298,11 +298,6 @@ DEFINE_EVENT(wiphy_only_evt, rdev_return
++ 	TP_ARGS(wiphy)
++ );
+  
 --	ieee80211_add_pending_skbs_fn(local, &pending, clear_sta_ps_flags, sta);
 -+	ieee80211_add_pending_skbs(local, &pending);
 -+	clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
@@ -5944,7 +7848,18 @@ index a1af6c2..c621ddb 100644
 -+	spin_unlock(&sta->ps_lock);
 -+
 -+	atomic_dec(&ps->num_sta_ps);
-- 
++-DEFINE_EVENT(wiphy_only_evt, rdev_get_ringparam,
++-	TP_PROTO(struct wiphy *wiphy),
++-	TP_ARGS(wiphy)
++-);
++-
++ DEFINE_EVENT(wiphy_only_evt, rdev_get_antenna,
++ 	TP_PROTO(struct wiphy *wiphy),
++ 	TP_ARGS(wiphy)
++@@ -580,11 +575,6 @@ DEFINE_EVENT(wiphy_netdev_evt, rdev_stop
++ 	TP_ARGS(wiphy, netdev)
++ );
+  
 - 	/* This station just woke up and isn't aware of our SMPS state */
 - 	if (!ieee80211_smps_is_restrictive(sta->known_smps_mode,
 ---- a/net/mac80211/sta_info.h
@@ -5974,14 +7889,18 @@ index a1af6c2..c621ddb 100644
 -+++ b/net/mac80211/util.c
 -@@ -435,9 +435,8 @@ void ieee80211_add_pending_skb(struct ie
 - 	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
-+-		local_bh_disable();
-++	else if (test_and_clear_sta_flag(sta, WLAN_STA_UAPSD))
-+ 		ieee80211_sta_ps_deliver_uapsd(sta);
-+-		local_bh_enable();
-+-	} else
-+-		clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
-++	local_bh_enable();
-  }
+- }
++-DEFINE_EVENT(wiphy_netdev_evt, rdev_get_et_stats,
++-	TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
++-	TP_ARGS(wiphy, netdev)
++-);
++-
++ DEFINE_EVENT(wiphy_netdev_evt, rdev_sched_scan_stop,
++ 	TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
++ 	TP_ARGS(wiphy, netdev)
++@@ -1439,11 +1429,6 @@ DECLARE_EVENT_CLASS(tx_rx_evt,
++ 		  WIPHY_PR_ARG, __entry->tx, __entry->rx)
++ );
   
 --void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local,
 --				   struct sk_buff_head *skbs,
@@ -5994,10 +7913,37 @@ index a1af6c2..c621ddb 100644
 -@@ -461,9 +460,6 @@ void ieee80211_add_pending_skbs_fn(struc
 - 		__skb_queue_tail(&local->pending[queue], skb);
 - 	}
-- 
++-DEFINE_EVENT(tx_rx_evt, rdev_set_ringparam,
++-	TP_PROTO(struct wiphy *wiphy, u32 tx, u32 rx),
++-	TP_ARGS(wiphy, rx, tx)
++-);
++-
++ DEFINE_EVENT(tx_rx_evt, rdev_set_antenna,
++ 	TP_PROTO(struct wiphy *wiphy, u32 tx, u32 rx),
++ 	TP_ARGS(wiphy, rx, tx)
++@@ -1725,40 +1710,6 @@ TRACE_EVENT(rdev_set_noack_map,
++ 		  WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->noack_map)
++ );
+  
 --	if (fn)
 --		fn(data);
---
++-TRACE_EVENT(rdev_get_et_sset_count,
++-	TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, int sset),
++-	TP_ARGS(wiphy, netdev, sset),
++-	TP_STRUCT__entry(
++-		WIPHY_ENTRY
++-		NETDEV_ENTRY
++-		__field(int, sset)
++-	),
++-	TP_fast_assign(
++-		WIPHY_ASSIGN;
++-		NETDEV_ASSIGN;
++-		__entry->sset = sset;
++-	),
++-	TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", sset: %d",
++-		  WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->sset)
++-);
+ -
 - 	for (i = 0; i < hw->queues; i++)
 - 		__ieee80211_wake_queue(hw, i,
 - 			IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
@@ -6048,7 +7994,49 @@ index a1af6c2..c621ddb 100644
 --				 "ANI", "DISABLED");
 -+	len += scnprintf(buf + len, size - len, "%15s: %s\n", "ANI",
 -+			 common->disable_ani ? "DISABLED" : "ENABLED");
--+
++-TRACE_EVENT(rdev_get_et_strings,
++-	TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u32 sset),
++-	TP_ARGS(wiphy, netdev, sset),
++-	TP_STRUCT__entry(
++-		WIPHY_ENTRY
++-		NETDEV_ENTRY
++-		__field(u32, sset)
++-	),
++-	TP_fast_assign(
++-		WIPHY_ASSIGN;
++-		NETDEV_ASSIGN;
++-		__entry->sset = sset;
++-	),
++-	TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", sset: %u",
++-		  WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->sset)
++-);
++-
++ DEFINE_EVENT(wiphy_wdev_evt, rdev_get_channel,
++ 	TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
++ 	TP_ARGS(wiphy, wdev)
++--- /dev/null
+++++ b/net/mac80211/ethtool.c
++@@ -0,0 +1,244 @@
+++/*
+++ * mac80211 ethtool hooks for cfg80211
+++ *
+++ * Copied from cfg.c - originally
+++ * Copyright 2006-2010	Johannes Berg <johannes@sipsolutions.net>
+++ * Copyright 2014	Intel Corporation (Author: Johannes Berg)
+++ *
+++ * This file is GPLv2 as found in COPYING.
+++ */
+++#include <linux/types.h>
+++#include <net/cfg80211.h>
+++#include "ieee80211_i.h"
+++#include "sta_info.h"
+++#include "driver-ops.h"
+++
+++static int ieee80211_set_ringparam(struct net_device *dev,
+++				   struct ethtool_ringparam *rp)
+++{
+++	struct ieee80211_local *local = wiphy_priv(dev->ieee80211_ptr->wiphy);
+ +
 -+	if (common->disable_ani)
 - 		goto exit;
 --	}
@@ -6082,7 +8070,9 @@ index a1af6c2..c621ddb 100644
 -+	for (i = 0; i < ARRAY_SIZE(ani_info); i++)
 -+		len += scnprintf(buf + len, size - len, "%15s: %u\n",
 -+				 ani_info[i].name, ani_info[i].val);
--+
+++	if (rp->rx_mini_pending != 0 || rp->rx_jumbo_pending != 0)
+++		return -EINVAL;
+ +
 - exit:
 - 	if (len > size)
 - 		len = size;
@@ -6109,9 +8099,7 @@ index a1af6c2..c621ddb 100644
 --		rfMode |= AR_PHY_MODE_QUARTER;
 --	if (IS_CHAN_HALF_RATE(chan))
 --		rfMode |= AR_PHY_MODE_HALF;
-+ static int sta_prepare_rate_control(struct ieee80211_local *local,
-+@@ -340,7 +337,7 @@ struct sta_info *sta_info_alloc(struct i
-  
+- 
 - 	if (rfMode & (AR_PHY_MODE_QUARTER | AR_PHY_MODE_HALF))
 - 		REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL,
 ---- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
@@ -6146,16 +8134,8 @@ index a1af6c2..c621ddb 100644
 -+			rs->rs_datalen = 0;
 -+			rs->rs_more = true;
 -+		}
-+ 	spin_lock_init(&sta->lock);
-+ 	spin_lock_init(&sta->ps_lock);
-+-	INIT_WORK(&sta->drv_unblock_wk, sta_unblock);
-++	INIT_WORK(&sta->drv_deliver_wk, sta_deliver_ps_frames);
-+ 	INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work);
-+ 	mutex_init(&sta->ampdu_mlme.mtx);
-+ #ifdef CPTCFG_MAC80211_MESH
-+@@ -1140,8 +1137,15 @@ void ieee80211_sta_ps_deliver_wakeup(str
-  	}
-  
+- 	}
+- 
 - 	list_del(&bf->list);
 -@@ -985,32 +992,32 @@ static int ath9k_rx_skb_preprocess(struc
 - 	struct ath_common *common = ath9k_hw_common(ah);
@@ -6171,9 +8151,8 @@ index a1af6c2..c621ddb 100644
 - 	if (discard_current)
 --		return -EINVAL;
 -+		goto corrupt;
-+ 	ieee80211_add_pending_skbs(local, &pending);
-+-	clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
-+-	clear_sta_flag(sta, WLAN_STA_PS_STA);
+++	return drv_set_ringparam(local, rp->tx_pending, rp->rx_pending);
+++}
  +
 -+	sc->rx.discard_next = false;
 - 
@@ -6195,18 +8174,239 @@ index a1af6c2..c621ddb 100644
 -+	 * rs_status follows rs_datalen so if rs_datalen is too large
 -+	 * we can take a hint that hardware corrupted it, so ignore
 -+	 * those frames.
-++	/* now we're no longer in the deliver code */
-++	clear_sta_flag(sta, WLAN_STA_PS_DELIVER);
+++static void ieee80211_get_ringparam(struct net_device *dev,
+++				    struct ethtool_ringparam *rp)
+++{
+++	struct ieee80211_local *local = wiphy_priv(dev->ieee80211_ptr->wiphy);
 ++
-++	/* The station might have polled and then woken up before we responded,
-++	 * so clear these flags now to avoid them sticking around.
+++	memset(rp, 0, sizeof(*rp));
+++
+++	drv_get_ringparam(local, &rp->tx_pending, &rp->tx_max_pending,
+++			  &rp->rx_pending, &rp->rx_max_pending);
+++}
+++
+++static const char ieee80211_gstrings_sta_stats[][ETH_GSTRING_LEN] = {
+++	"rx_packets", "rx_bytes",
+++	"rx_duplicates", "rx_fragments", "rx_dropped",
+++	"tx_packets", "tx_bytes", "tx_fragments",
+++	"tx_filtered", "tx_retry_failed", "tx_retries",
+++	"beacon_loss", "sta_state", "txrate", "rxrate", "signal",
+++	"channel", "noise", "ch_time", "ch_time_busy",
+++	"ch_time_ext_busy", "ch_time_rx", "ch_time_tx"
+++};
+++#define STA_STATS_LEN	ARRAY_SIZE(ieee80211_gstrings_sta_stats)
+++
+++static int ieee80211_get_sset_count(struct net_device *dev, int sset)
+++{
+++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+++	int rv = 0;
+++
+++	if (sset == ETH_SS_STATS)
+++		rv += STA_STATS_LEN;
+++
+++	rv += drv_get_et_sset_count(sdata, sset);
+++
+++	if (rv == 0)
+++		return -EOPNOTSUPP;
+++	return rv;
+++}
+++
+++static void ieee80211_get_stats(struct net_device *dev,
+++				struct ethtool_stats *stats,
+++				u64 *data)
+++{
+++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+++	struct ieee80211_chanctx_conf *chanctx_conf;
+++	struct ieee80211_channel *channel;
+++	struct sta_info *sta;
+++	struct ieee80211_local *local = sdata->local;
+++	struct station_info sinfo;
+++	struct survey_info survey;
+++	int i, q;
+++#define STA_STATS_SURVEY_LEN 7
+++
+++	memset(data, 0, sizeof(u64) * STA_STATS_LEN);
+++
+++#define ADD_STA_STATS(sta)				\
+++	do {						\
+++		data[i++] += sta->rx_packets;		\
+++		data[i++] += sta->rx_bytes;		\
+++		data[i++] += sta->num_duplicates;	\
+++		data[i++] += sta->rx_fragments;		\
+++		data[i++] += sta->rx_dropped;		\
+++							\
+++		data[i++] += sinfo.tx_packets;		\
+++		data[i++] += sinfo.tx_bytes;		\
+++		data[i++] += sta->tx_fragments;		\
+++		data[i++] += sta->tx_filtered_count;	\
+++		data[i++] += sta->tx_retry_failed;	\
+++		data[i++] += sta->tx_retry_count;	\
+++		data[i++] += sta->beacon_loss_count;	\
+++	} while (0)
+++
+++	/* For Managed stations, find the single station based on BSSID
+++	 * and use that.  For interface types, iterate through all available
+++	 * stations and add stats for any station that is assigned to this
+++	 * network device.
  +	 */
 - 	if (rx_stats->rs_datalen > (common->rx_bufsize - ah->caps.rx_status_len)) {
 - 		RX_STAT_INC(rx_len_err);
 --		return -EINVAL;
 -+		goto corrupt;
-- 	}
-- 
+++
+++	mutex_lock(&local->sta_mtx);
+++
+++	if (sdata->vif.type == NL80211_IFTYPE_STATION) {
+++		sta = sta_info_get_bss(sdata, sdata->u.mgd.bssid);
+++
+++		if (!(sta && !WARN_ON(sta->sdata->dev != dev)))
+++			goto do_survey;
+++
+++		sinfo.filled = 0;
+++		sta_set_sinfo(sta, &sinfo);
+++
+++		i = 0;
+++		ADD_STA_STATS(sta);
+++
+++		data[i++] = sta->sta_state;
+++
+++
+++		if (sinfo.filled & STATION_INFO_TX_BITRATE)
+++			data[i] = 100000 *
+++				cfg80211_calculate_bitrate(&sinfo.txrate);
+++		i++;
+++		if (sinfo.filled & STATION_INFO_RX_BITRATE)
+++			data[i] = 100000 *
+++				cfg80211_calculate_bitrate(&sinfo.rxrate);
+++		i++;
+++
+++		if (sinfo.filled & STATION_INFO_SIGNAL_AVG)
+++			data[i] = (u8)sinfo.signal_avg;
+++		i++;
+++	} else {
+++		list_for_each_entry(sta, &local->sta_list, list) {
+++			/* Make sure this station belongs to the proper dev */
+++			if (sta->sdata->dev != dev)
+++				continue;
+++
+++			sinfo.filled = 0;
+++			sta_set_sinfo(sta, &sinfo);
+++			i = 0;
+++			ADD_STA_STATS(sta);
+++		}
+++	}
+++
+++do_survey:
+++	i = STA_STATS_LEN - STA_STATS_SURVEY_LEN;
+++	/* Get survey stats for current channel */
+++	survey.filled = 0;
+++
+++	rcu_read_lock();
+++	chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+++	if (chanctx_conf)
+++		channel = chanctx_conf->def.chan;
+++	else
+++		channel = NULL;
+++	rcu_read_unlock();
+++
+++	if (channel) {
+++		q = 0;
+++		do {
+++			survey.filled = 0;
+++			if (drv_get_survey(local, q, &survey) != 0) {
+++				survey.filled = 0;
+++				break;
+++			}
+++			q++;
+++		} while (channel != survey.channel);
+++	}
+++
+++	if (survey.filled)
+++		data[i++] = survey.channel->center_freq;
+++	else
+++		data[i++] = 0;
+++	if (survey.filled & SURVEY_INFO_NOISE_DBM)
+++		data[i++] = (u8)survey.noise;
+++	else
+++		data[i++] = -1LL;
+++	if (survey.filled & SURVEY_INFO_CHANNEL_TIME)
+++		data[i++] = survey.channel_time;
+++	else
+++		data[i++] = -1LL;
+++	if (survey.filled & SURVEY_INFO_CHANNEL_TIME_BUSY)
+++		data[i++] = survey.channel_time_busy;
+++	else
+++		data[i++] = -1LL;
+++	if (survey.filled & SURVEY_INFO_CHANNEL_TIME_EXT_BUSY)
+++		data[i++] = survey.channel_time_ext_busy;
+++	else
+++		data[i++] = -1LL;
+++	if (survey.filled & SURVEY_INFO_CHANNEL_TIME_RX)
+++		data[i++] = survey.channel_time_rx;
+++	else
+++		data[i++] = -1LL;
+++	if (survey.filled & SURVEY_INFO_CHANNEL_TIME_TX)
+++		data[i++] = survey.channel_time_tx;
+++	else
+++		data[i++] = -1LL;
+++
+++	mutex_unlock(&local->sta_mtx);
+++
+++	if (WARN_ON(i != STA_STATS_LEN))
+++		return;
+++
+++	drv_get_et_stats(sdata, stats, &(data[STA_STATS_LEN]));
+++}
+++
+++static void ieee80211_get_strings(struct net_device *dev, u32 sset, u8 *data)
+++{
+++	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+++	int sz_sta_stats = 0;
+++
+++	if (sset == ETH_SS_STATS) {
+++		sz_sta_stats = sizeof(ieee80211_gstrings_sta_stats);
+++		memcpy(data, ieee80211_gstrings_sta_stats, sz_sta_stats);
+++	}
+++	drv_get_et_strings(sdata, sset, &(data[sz_sta_stats]));
+++}
+++
+++static int ieee80211_get_regs_len(struct net_device *dev)
+++{
+++	return 0;
+++}
+++
+++static void ieee80211_get_regs(struct net_device *dev,
+++			       struct ethtool_regs *regs,
+++			       void *data)
+++{
+++	struct wireless_dev *wdev = dev->ieee80211_ptr;
+++
+++	regs->version = wdev->wiphy->hw_version;
+++	regs->len = 0;
+++}
+++
+++const struct ethtool_ops ieee80211_ethtool_ops = {
+++	.get_drvinfo = cfg80211_get_drvinfo,
+++	.get_regs_len = ieee80211_get_regs_len,
+++	.get_regs = ieee80211_get_regs,
+++	.get_link = ethtool_op_get_link,
+++	.get_ringparam = ieee80211_get_ringparam,
+++	.set_ringparam = ieee80211_set_ringparam,
+++	.get_strings = ieee80211_get_strings,
+++	.get_ethtool_stats = ieee80211_get_stats,
+++	.get_sset_count = ieee80211_get_sset_count,
+++};
++--- a/net/mac80211/ibss.c
+++++ b/net/mac80211/ibss.c
++@@ -143,7 +143,7 @@ ieee80211_ibss_build_presp(struct ieee80
++ 		*pos++ = csa_settings->block_tx ? 1 : 0;
++ 		*pos++ = ieee80211_frequency_to_channel(
++ 				csa_settings->chandef.chan->center_freq);
++-		sdata->csa_counter_offset_beacon[0] = (pos - presp->head);
+++		presp->csa_counter_offsets[0] = (pos - presp->head);
++ 		*pos++ = csa_settings->count;
+  	}
+  
 - 	/* Only use status info from the last fragment */
 -@@ -1024,10 +1031,8 @@ static int ath9k_rx_skb_preprocess(struc
 - 	 * This is different from the other corrupt descriptor
@@ -6224,12 +8424,51 @@ index a1af6c2..c621ddb 100644
 -@@ -1043,18 +1048,15 @@ static int ath9k_rx_skb_preprocess(struc
 - 		if (ath_process_fft(sc, hdr, rx_stats, rx_status->mactime))
 - 			RX_STAT_INC(rx_spectral);
-- 
++@@ -1677,6 +1677,7 @@ int ieee80211_ibss_join(struct ieee80211
++ 	sdata->u.ibss.control_port = params->control_port;
++ 	sdata->u.ibss.userspace_handles_dfs = params->userspace_handles_dfs;
++ 	sdata->u.ibss.basic_rates = params->basic_rates;
+++	sdata->u.ibss.last_scan_completed = jiffies;
+  
 --		ret = -EINVAL;
 --		goto exit;
 -+		return -EINVAL;
-- 	}
-- 
++ 	/* fix basic_rates if channel does not support these rates */
++ 	rate_flags = ieee80211_chandef_rate_flags(&params->chandef);
++--- a/net/mac80211/mesh.c
+++++ b/net/mac80211/mesh.c
++@@ -679,7 +679,7 @@ ieee80211_mesh_build_beacon(struct ieee8
++ 		*pos++ = 0x0;
++ 		*pos++ = ieee80211_frequency_to_channel(
++ 				csa->settings.chandef.chan->center_freq);
++-		sdata->csa_counter_offset_beacon[0] = hdr_len + 6;
+++		bcn->csa_counter_offsets[0] = hdr_len + 6;
++ 		*pos++ = csa->settings.count;
++ 		*pos++ = WLAN_EID_CHAN_SWITCH_PARAM;
++ 		*pos++ = 6;
++--- a/net/wireless/genregdb.awk
+++++ b/net/wireless/genregdb.awk
++@@ -65,17 +65,7 @@ function parse_reg_rule()
++ 	sub(/,/, "", units)
++ 	dfs_cac = $9
++ 	if (units == "mW") {
++-		if (power == 100) {
++-			power = 20
++-		} else if (power == 200) {
++-			power = 23
++-		} else if (power == 500) {
++-			power = 27
++-		} else if (power == 1000) {
++-			power = 30
++-		} else {
++-			print "Unknown power value in database!"
++-		}
+++		power = 10 * log(power)/log(10)
++ 	} else {
++ 		dfs_cac = $8
+  	}
++@@ -114,7 +104,7 @@ function parse_reg_rule()
+  
 - 	/*
 - 	 * everything but the rate is checked here, the rate check is done
 - 	 * separately to avoid doing two lookups for a rate for each frame.
@@ -6240,10 +8479,7 @@ index a1af6c2..c621ddb 100644
 --	}
 -+	if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error))
 -+		return -EINVAL;
-++	clear_sta_flag(sta, WLAN_STA_PSPOLL);
-++	clear_sta_flag(sta, WLAN_STA_UAPSD);
-+ 	spin_unlock(&sta->ps_lock);
-  
+- 
 - 	if (ath_is_mybeacon(common, hdr)) {
 - 		RX_STAT_INC(rx_beacons);
 -@@ -1064,15 +1066,11 @@ static int ath9k_rx_skb_preprocess(struc
@@ -6265,12 +8501,20 @@ index a1af6c2..c621ddb 100644
 -+		return -EINVAL;
 - 
 - 	ath9k_process_rssi(common, hw, rx_stats, rx_status);
-- 
++ 	}
++ 	flags = flags "0"
++-	printf "\t\tREG_RULE_EXT(%d, %d, %d, %d, %d, %d, %s),\n", start, end, bw, gain, power, dfs_cac, flags
+++	printf "\t\tREG_RULE_EXT(%d, %d, %d, %d, %.0f, %d, %s),\n", start, end, bw, gain, power, dfs_cac, flags
++ 	rules++
++ }
+  
 -@@ -1087,9 +1085,11 @@ static int ath9k_rx_skb_preprocess(struc
 - 		sc->rx.num_pkts++;
 - #endif
-+ 	atomic_dec(&ps->num_sta_ps);
-+@@ -1542,10 +1546,26 @@ void ieee80211_sta_block_awake(struct ie
++--- a/net/mac80211/debugfs_netdev.c
+++++ b/net/mac80211/debugfs_netdev.c
++@@ -34,8 +34,7 @@ static ssize_t ieee80211_if_read(
++ 	ssize_t ret = -EINVAL;
   
 --exit:
 --	sc->rx.discard_next = false;
@@ -6281,7 +8525,11 @@ index a1af6c2..c621ddb 100644
 -+	sc->rx.discard_next = rx_stats->rs_more;
 -+	return -EINVAL;
 - }
-+ 	trace_api_sta_block_awake(sta->local, pubsta, block);
++ 	read_lock(&dev_base_lock);
++-	if (sdata->dev->reg_state == NETREG_REGISTERED)
++-		ret = (*format)(sdata, buf, sizeof(buf));
+++	ret = (*format)(sdata, buf, sizeof(buf));
++ 	read_unlock(&dev_base_lock);
   
 - static void ath9k_rx_skb_postprocess(struct ath_common *common,
 ---- a/drivers/net/wireless/ath/ath9k/ani.c
@@ -6315,18 +8563,12 @@ index a1af6c2..c621ddb 100644
 -+	if (aniState->ofdmWeakSigDetect != weak_sig)
 -+		ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
 -+				     weak_sig);
-+-	if (block)
-++	if (block) {
-+ 		set_sta_flag(sta, WLAN_STA_PS_DRIVER);
-+-	else if (test_sta_flag(sta, WLAN_STA_PS_DRIVER))
-+-		ieee80211_queue_work(hw, &sta->drv_unblock_wk);
-++		return;
-++	}
- +
+-+
 -+	if (!AR_SREV_9300_20_OR_LATER(ah))
-++	if (!test_sta_flag(sta, WLAN_STA_PS_DRIVER))
- +		return;
-- 
+-+		return;
++ 	if (ret >= 0)
++@@ -62,8 +61,7 @@ static ssize_t ieee80211_if_write(
+  
 - 	if (aniState->ofdmNoiseImmunityLevel >= ATH9K_ANI_OFDM_DEF_LEVEL) {
 - 		ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH;
 -@@ -308,17 +318,6 @@ void ath9k_ani_reset(struct ath_hw *ah, 
@@ -6360,25 +8602,18 @@ index a1af6c2..c621ddb 100644
 -+		ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW;
 -+		ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH;
 -+		ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW;
-++
-++	if (!test_sta_flag(sta, WLAN_STA_PS_STA)) {
-++		set_sta_flag(sta, WLAN_STA_PS_DELIVER);
-++		clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
-++		ieee80211_queue_work(hw, &sta->drv_deliver_wk);
-++	} else if (test_sta_flag(sta, WLAN_STA_PSPOLL) ||
-++		   test_sta_flag(sta, WLAN_STA_UAPSD)) {
-++		/* must be asleep in this case */
-++		clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
-++		ieee80211_queue_work(hw, &sta->drv_deliver_wk);
- +	} else {
+-+	} else {
 -+		ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_OLD;
 -+		ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_OLD;
 -+		ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_OLD;
 -+		ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_OLD;
-++		clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
- +	}
-+ }
-+ EXPORT_SYMBOL(ieee80211_sta_block_awake);
+-+	}
++ 	ret = -ENODEV;
++ 	rtnl_lock();
++-	if (sdata->dev->reg_state == NETREG_REGISTERED)
++-		ret = (*write)(sdata, buf, count);
+++	ret = (*write)(sdata, buf, count);
++ 	rtnl_unlock();
   
 - 	ani->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
 - 	ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
@@ -6389,60 +8624,16 @@ index a1af6c2..c621ddb 100644
 - #define ATH9K_ANI_OFDM_TRIG_HIGH           3500
 - #define ATH9K_ANI_OFDM_TRIG_HIGH_BELOW_INI 1000
 -+#define ATH9K_ANI_OFDM_TRIG_HIGH_OLD       500
-+--- a/net/mac80211/status.c
-++++ b/net/mac80211/status.c
-+@@ -541,6 +541,23 @@ static void ieee80211_tx_latency_end_msr
-+  */
-+ #define STA_LOST_PKT_THRESHOLD	50
-  
+- 
 - #define ATH9K_ANI_OFDM_TRIG_LOW           400
 - #define ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI 900
 -+#define ATH9K_ANI_OFDM_TRIG_LOW_OLD       200
-++static void ieee80211_lost_packet(struct sta_info *sta, struct sk_buff *skb)
-++{
-++	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-++
-++	/* This packet was aggregated but doesn't carry status info */
-++	if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
-++	    !(info->flags & IEEE80211_TX_STAT_AMPDU))
-++		return;
-++
-++	if (++sta->lost_packets < STA_LOST_PKT_THRESHOLD)
-++		return;
-++
-++	cfg80211_cqm_pktloss_notify(sta->sdata->dev, sta->sta.addr,
-++				    sta->lost_packets, GFP_ATOMIC);
-++	sta->lost_packets = 0;
-++}
-++
-+ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
-+ {
-+ 	struct sk_buff *skb2;
-+@@ -680,12 +697,8 @@ void ieee80211_tx_status(struct ieee8021
-+ 			if (info->flags & IEEE80211_TX_STAT_ACK) {
-+ 				if (sta->lost_packets)
-+ 					sta->lost_packets = 0;
-+-			} else if (++sta->lost_packets >= STA_LOST_PKT_THRESHOLD) {
-+-				cfg80211_cqm_pktloss_notify(sta->sdata->dev,
-+-							    sta->sta.addr,
-+-							    sta->lost_packets,
-+-							    GFP_ATOMIC);
-+-				sta->lost_packets = 0;
-++			} else {
-++				ieee80211_lost_packet(sta, skb);
-+ 			}
-+ 		}
-  
+- 
 - #define ATH9K_ANI_CCK_TRIG_HIGH           600
 -+#define ATH9K_ANI_CCK_TRIG_HIGH_OLD       200
 - #define ATH9K_ANI_CCK_TRIG_LOW            300
 -+#define ATH9K_ANI_CCK_TRIG_LOW_OLD        100
-+--- a/net/mac80211/rx.c
-++++ b/net/mac80211/rx.c
-+@@ -1107,6 +1107,8 @@ static void sta_ps_end(struct sta_info *
-+ 		return;
-+ 	}
-  
+- 
 - #define ATH9K_ANI_SPUR_IMMUNE_LVL         3
 - #define ATH9K_ANI_FIRSTEP_LVL             2
 ---- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
@@ -6450,11 +8641,7 @@ index a1af6c2..c621ddb 100644
 -@@ -26,10 +26,6 @@ static const int firstep_table[] =
 - /* level:  0   1   2   3   4   5   6   7   8  */
 - 	{ -4, -2,  0,  2,  4,  6,  8, 10, 12 }; /* lvl 0-8, default 2 */
-++	set_sta_flag(sta, WLAN_STA_PS_DELIVER);
-++	clear_sta_flag(sta, WLAN_STA_PS_STA);
-+ 	ieee80211_sta_ps_deliver_wakeup(sta);
-+ }
-  
+- 
 --static const int cycpwrThr1_table[] =
 --/* level:  0   1   2   3   4   5   6   7   8  */
 --	{ -6, -4, -2,  0,  2,  4,  6,  8 };     /* lvl 0-7, default 3 */
@@ -6468,34 +8655,13 @@ index a1af6c2..c621ddb 100644
 - 	struct ar5416AniState *aniState = &ah->ani;
 --	s32 value, value2;
 -+	s32 value;
-+--- a/net/mac80211/sta_info.h
-++++ b/net/mac80211/sta_info.h
-+@@ -82,6 +82,7 @@ enum ieee80211_sta_info_flags {
-+ 	WLAN_STA_TOFFSET_KNOWN,
-+ 	WLAN_STA_MPSP_OWNER,
-+ 	WLAN_STA_MPSP_RECIPIENT,
-++	WLAN_STA_PS_DELIVER,
-+ };
-  
+- 
 - 	switch (cmd & ah->ani_function) {
 - 	case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
 -@@ -1008,42 +1004,9 @@ static bool ar5008_hw_ani_control_new(st
 - 	case ATH9K_ANI_FIRSTEP_LEVEL:{
 - 		u32 level = param;
-+ #define ADDBA_RESP_INTERVAL HZ
-+@@ -265,7 +266,7 @@ struct ieee80211_tx_latency_stat {
-+  * @last_rx_rate_vht_nss: rx status nss of last data packet
-+  * @lock: used for locking all fields that require locking, see comments
-+  *	in the header file.
-+- * @drv_unblock_wk: used for driver PS unblocking
-++ * @drv_deliver_wk: used for delivering frames after driver PS unblocking
-+  * @listen_interval: listen interval of this station, when we're acting as AP
-+  * @_flags: STA flags, see &enum ieee80211_sta_info_flags, do not use directly
-+  * @ps_lock: used for powersave (when mac80211 is the AP) related locking
-+@@ -345,7 +346,7 @@ struct sta_info {
-+ 	void *rate_ctrl_priv;
-+ 	spinlock_t lock;
-  
+- 
 --		if (level >= ARRAY_SIZE(firstep_table)) {
 --			ath_dbg(common, ANI,
 --				"ATH9K_ANI_FIRSTEP_LEVEL: level out of range (%u > %zu)\n",
@@ -6534,9 +8700,7 @@ index a1af6c2..c621ddb 100644
 --		REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW,
 --			      AR_PHY_FIND_SIG_FIRSTEP_LOW, value2);
 -+			      AR_PHY_FIND_SIG_FIRSTEP, value);
-+-	struct work_struct drv_unblock_wk;
-++	struct work_struct drv_deliver_wk;
-  
+- 
 - 		if (level != aniState->firstepLevel) {
 - 			ath_dbg(common, ANI,
 -@@ -1060,7 +1023,7 @@ static bool ar5008_hw_ani_control_new(st
@@ -6551,8 +8715,7 @@ index a1af6c2..c621ddb 100644
 -@@ -1073,41 +1036,13 @@ static bool ar5008_hw_ani_control_new(st
 - 	case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
 - 		u32 level = param;
-+ 	u16 listen_interval;
-  
+- 
 --		if (level >= ARRAY_SIZE(cycpwrThr1_table)) {
 --			ath_dbg(common, ANI,
 --				"ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level out of range (%u > %zu)\n",
@@ -6575,11 +8738,7 @@ index a1af6c2..c621ddb 100644
 --			      AR_PHY_TIMING5_CYCPWR_THR1,
 --			      value);
 -+			      AR_PHY_TIMING5_CYCPWR_THR1, value);
-+--- a/net/mac80211/tx.c
-++++ b/net/mac80211/tx.c
-+@@ -469,7 +469,8 @@ ieee80211_tx_h_unicast_ps_buf(struct iee
-+ 		return TX_CONTINUE;
-  
+- 
 --		/*
 --		 * set AR_PHY_EXT_CCA for extension channel
 --		 * make register setting relative to default
@@ -6597,13 +8756,7 @@ index a1af6c2..c621ddb 100644
 -+		if (IS_CHAN_HT40(ah->curchan))
 -+			REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
 -+				      AR_PHY_EXT_TIMING5_CYCPWR_THR1, value);
-+ 	if (unlikely((test_sta_flag(sta, WLAN_STA_PS_STA) ||
-+-		      test_sta_flag(sta, WLAN_STA_PS_DRIVER)) &&
-++		      test_sta_flag(sta, WLAN_STA_PS_DRIVER) ||
-++		      test_sta_flag(sta, WLAN_STA_PS_DELIVER)) &&
-+ 		     !(info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER))) {
-+ 		int ac = skb_get_queue_mapping(tx->skb);
-  
+- 
 - 		if (level != aniState->spurImmunityLevel) {
 - 			ath_dbg(common, ANI,
 -@@ -1124,7 +1059,7 @@ static bool ar5008_hw_ani_control_new(st
@@ -6615,25 +8768,16 @@ index a1af6c2..c621ddb 100644
 - 				aniState->iniDef.cycpwrThr1Ext);
 - 			if (level > aniState->spurImmunityLevel)
 - 				ah->stats.ast_ani_spurup++;
-+@@ -486,7 +487,8 @@ ieee80211_tx_h_unicast_ps_buf(struct iee
-+ 		 * ahead and Tx the packet.
-+ 		 */
-+ 		if (!test_sta_flag(sta, WLAN_STA_PS_STA) &&
-+-		    !test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
-++		    !test_sta_flag(sta, WLAN_STA_PS_DRIVER) &&
-++		    !test_sta_flag(sta, WLAN_STA_PS_DELIVER)) {
-+ 			spin_unlock(&sta->ps_lock);
-+ 			return TX_CONTINUE;
-+ 		}
++ 	return ret;
 diff --git a/package/mac80211/patches/310-ap_scan.patch b/package/mac80211/patches/310-ap_scan.patch
-index 389a003..9334e4d 100644
+index 389a003..23ecd37 100644
 --- a/package/mac80211/patches/310-ap_scan.patch
 +++ b/package/mac80211/patches/310-ap_scan.patch
 @@ -1,6 +1,6 @@
  --- a/net/mac80211/cfg.c
  +++ b/net/mac80211/cfg.c
 -@@ -2148,7 +2148,7 @@ static int ieee80211_scan(struct wiphy *
-+@@ -2210,7 +2210,7 @@ static int ieee80211_scan(struct wiphy *
++@@ -1903,7 +1903,7 @@ static int ieee80211_scan(struct wiphy *
   		 * the  frames sent while scanning on other channel will be
   		 * lost)
   		 */
@@ -6903,7 +9047,7 @@ index 8f3cc03..c0e173f 100644
   {
   	struct ieee80211_channel *curchan = chandef->chan;
 diff --git a/package/mac80211/patches/520-mac80211_cur_txpower.patch b/package/mac80211/patches/520-mac80211_cur_txpower.patch
-index 6df95bc..68320a0 100644
+index 6df95bc..ef7906e 100644
 --- a/package/mac80211/patches/520-mac80211_cur_txpower.patch
 +++ b/package/mac80211/patches/520-mac80211_cur_txpower.patch
 @@ -1,6 +1,6 @@
@@ -6919,7 +9063,7 @@ index 6df95bc..68320a0 100644
  --- a/net/mac80211/cfg.c
  +++ b/net/mac80211/cfg.c
 -@@ -2329,7 +2329,9 @@ static int ieee80211_get_tx_power(struct
-+@@ -2391,7 +2391,9 @@ static int ieee80211_get_tx_power(struct
++@@ -2084,7 +2084,9 @@ static int ieee80211_get_tx_power(struct
   	struct ieee80211_local *local = wiphy_priv(wiphy);
   	struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
   
@@ -6954,7 +9098,7 @@ index 0d6c360..83ff465 100644
   		ath9k_cmn_update_txpow(ah, sc->curtxpow,
   				       sc->config.txpowlimit, &sc->curtxpow);
 diff --git a/package/mac80211/patches/522-mac80211_configure_antenna_gain.patch b/package/mac80211/patches/522-mac80211_configure_antenna_gain.patch
-index 308ee6e..284d134 100644
+index 308ee6e..2109d2e 100644
 --- a/package/mac80211/patches/522-mac80211_configure_antenna_gain.patch
 +++ b/package/mac80211/patches/522-mac80211_configure_antenna_gain.patch
 @@ -1,6 +1,6 @@
@@ -6970,7 +9114,7 @@ index 308ee6e..284d134 100644
    * @set_wds_peer: set the WDS peer for a WDS interface
    *
 -@@ -2380,6 +2381,7 @@ struct cfg80211_ops {
-+@@ -2441,6 +2442,7 @@ struct cfg80211_ops {
++@@ -2431,6 +2432,7 @@ struct cfg80211_ops {
   				enum nl80211_tx_power_setting type, int mbm);
   	int	(*get_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev,
   				int *dbm);
@@ -7023,7 +9167,7 @@ index 308ee6e..284d134 100644
  --- a/net/mac80211/cfg.c
  +++ b/net/mac80211/cfg.c
 -@@ -2339,6 +2339,19 @@ static int ieee80211_get_tx_power(struct
-+@@ -2401,6 +2401,19 @@ static int ieee80211_get_tx_power(struct
++@@ -2094,6 +2094,19 @@ static int ieee80211_get_tx_power(struct
   	return 0;
   }
   
@@ -7032,7 +9176,7 @@ index 308ee6e..284d134 100644
   				  const u8 *addr)
   {
 -@@ -3924,6 +3937,7 @@ struct cfg80211_ops mac80211_config_ops 
-+@@ -3832,6 +3845,7 @@ const struct cfg80211_ops mac80211_confi
++@@ -3517,6 +3530,7 @@ const struct cfg80211_ops mac80211_confi
   	.set_wiphy_params = ieee80211_set_wiphy_params,
   	.set_tx_power = ieee80211_set_tx_power,
   	.get_tx_power = ieee80211_get_tx_power,
@@ -7041,7 +9185,7 @@ index 308ee6e..284d134 100644
  --- a/net/mac80211/ieee80211_i.h
  +++ b/net/mac80211/ieee80211_i.h
 -@@ -1221,6 +1221,7 @@ struct ieee80211_local {
-+@@ -1233,6 +1233,7 @@ struct ieee80211_local {
++@@ -1243,6 +1243,7 @@ struct ieee80211_local {
   	int dynamic_ps_forced_timeout;
   
   	int user_power_level; /* in dBm, for all interfaces */
@@ -7692,6 +9836,458 @@ index 4a61db3..0000000
 - 	}
 - 
 - 	if (ath_beacon_dtim_pending_cab(skb)) {
+diff --git a/package/mac80211/patches/560-ath9k_pcoem_optional.patch b/package/mac80211/patches/560-ath9k_pcoem_optional.patch
+new file mode 100644
+index 0000000..4d4ea3b
+--- /dev/null
++++ b/package/mac80211/patches/560-ath9k_pcoem_optional.patch
+@@ -0,0 +1,249 @@
++--- a/drivers/net/wireless/ath/ath9k/Kconfig
+++++ b/drivers/net/wireless/ath/ath9k/Kconfig
++@@ -133,6 +133,11 @@ config ATH9K_RFKILL
++ 	  seconds. Turn off to save power, but enable it if you have
++ 	  a platform that can toggle the RF-Kill GPIO.
++ 
+++config ATH9K_PCOEM
+++	bool "Atheros ath9k support for PC OEM cards" if EXPERT
+++	depends on ATH9K
+++	default y
+++
++ config ATH9K_HTC
++        tristate "Atheros HTC based wireless cards support"
++        depends on m
++--- a/drivers/net/wireless/ath/ath9k/Makefile
+++++ b/drivers/net/wireless/ath/ath9k/Makefile
++@@ -31,7 +31,6 @@ ath9k_hw-y:=	\
++ 		ar5008_phy.o \
++ 		ar9002_calib.o \
++ 		ar9003_calib.o \
++-		ar9003_rtt.o \
++ 		calib.o \
++ 		eeprom.o \
++ 		eeprom_def.o \
++@@ -48,6 +47,8 @@ ath9k_hw-$(CPTCFG_ATH9K_WOW) += ar9003_w
++ 
++ ath9k_hw-$(CPTCFG_ATH9K_BTCOEX_SUPPORT) += btcoex.o \
++ 					   ar9003_mci.o
+++ath9k_hw-$(CPTCFG_ATH9K_PCOEM) += ar9003_rtt.o
+++
++ obj-$(CPTCFG_ATH9K_HW) += ath9k_hw.o
++ 
++ obj-$(CPTCFG_ATH9K_COMMON) += ath9k_common.o
++--- a/drivers/net/wireless/ath/ath9k/ar9003_rtt.h
+++++ b/drivers/net/wireless/ath/ath9k/ar9003_rtt.h
++@@ -17,6 +17,7 @@
++ #ifndef AR9003_RTT_H
++ #define AR9003_RTT_H
++ 
+++#ifdef CPTCFG_ATH9K_PCOEM
++ void ar9003_hw_rtt_enable(struct ath_hw *ah);
++ void ar9003_hw_rtt_disable(struct ath_hw *ah);
++ void ar9003_hw_rtt_set_mask(struct ath_hw *ah, u32 rtt_mask);
++@@ -25,5 +26,40 @@ void ar9003_hw_rtt_load_hist(struct ath_
++ void ar9003_hw_rtt_fill_hist(struct ath_hw *ah);
++ void ar9003_hw_rtt_clear_hist(struct ath_hw *ah);
++ bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan);
+++#else
+++static inline void ar9003_hw_rtt_enable(struct ath_hw *ah)
+++{
+++}
+++
+++static inline void ar9003_hw_rtt_disable(struct ath_hw *ah)
+++{
+++}
+++
+++static inline void ar9003_hw_rtt_set_mask(struct ath_hw *ah, u32 rtt_mask)
+++{
+++}
+++
+++static inline bool ar9003_hw_rtt_force_restore(struct ath_hw *ah)
+++{
+++	return false;
+++}
+++
+++static inline void ar9003_hw_rtt_load_hist(struct ath_hw *ah)
+++{
+++}
+++
+++static inline void ar9003_hw_rtt_fill_hist(struct ath_hw *ah)
+++{
+++}
+++
+++static inline void ar9003_hw_rtt_clear_hist(struct ath_hw *ah)
+++{
+++}
+++
+++static inline bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan)
+++{
+++	return false;
+++}
+++#endif
++ 
++ #endif
++--- a/drivers/net/wireless/ath/ath9k/hw.h
+++++ b/drivers/net/wireless/ath/ath9k/hw.h
++@@ -244,13 +244,20 @@ enum ath9k_hw_caps {
++ 	ATH9K_HW_CAP_2GHZ			= BIT(11),
++ 	ATH9K_HW_CAP_5GHZ			= BIT(12),
++ 	ATH9K_HW_CAP_APM			= BIT(13),
+++#ifdef CPTCFG_ATH9K_PCOEM
++ 	ATH9K_HW_CAP_RTT			= BIT(14),
++ 	ATH9K_HW_CAP_MCI			= BIT(15),
++-	ATH9K_HW_CAP_DFS			= BIT(16),
++-	ATH9K_HW_WOW_DEVICE_CAPABLE		= BIT(17),
++-	ATH9K_HW_CAP_PAPRD			= BIT(18),
++-	ATH9K_HW_CAP_FCC_BAND_SWITCH		= BIT(19),
++-	ATH9K_HW_CAP_BT_ANT_DIV			= BIT(20),
+++	ATH9K_HW_WOW_DEVICE_CAPABLE		= BIT(16),
+++	ATH9K_HW_CAP_BT_ANT_DIV			= BIT(17),
+++#else
+++	ATH9K_HW_CAP_RTT			= 0,
+++	ATH9K_HW_CAP_MCI			= 0,
+++	ATH9K_HW_WOW_DEVICE_CAPABLE		= 0,
+++	ATH9K_HW_CAP_BT_ANT_DIV			= 0,
+++#endif
+++	ATH9K_HW_CAP_DFS			= BIT(18),
+++	ATH9K_HW_CAP_PAPRD			= BIT(19),
+++	ATH9K_HW_CAP_FCC_BAND_SWITCH		= BIT(20),
++ };
++ 
++ /*
++--- a/drivers/net/wireless/ath/ath9k/init.c
+++++ b/drivers/net/wireless/ath/ath9k/init.c
++@@ -355,6 +355,9 @@ static void ath9k_init_pcoem_platform(st
++ 	struct ath9k_hw_capabilities *pCap = &ah->caps;
++ 	struct ath_common *common = ath9k_hw_common(ah);
++ 
+++	if (!IS_ENABLED(CPTCFG_ATH9K_PCOEM))
+++		return;
+++
++ 	if (common->bus_ops->ath_bus_type != ATH_PCI)
++ 		return;
++ 
++--- a/drivers/net/wireless/ath/ath9k/pci.c
+++++ b/drivers/net/wireless/ath/ath9k/pci.c
++@@ -30,6 +30,7 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_i
++ 	{ PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI   */
++ 	{ PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */
++ 
+++#ifdef CPTCFG_ATH9K_PCOEM
++ 	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
++ 			 0x002A,
++ 			 PCI_VENDOR_ID_AZWAVE,
++@@ -82,6 +83,7 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_i
++ 			 PCI_VENDOR_ID_AZWAVE,
++ 			 0x2C37),
++ 	  .driver_data = ATH9K_PCI_BT_ANT_DIV },
+++#endif
++ 
++ 	{ PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */
++ 	{ PCI_VDEVICE(ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */
++@@ -102,6 +104,7 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_i
++ 
++ 	{ PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E  AR9300 */
++ 
+++#ifdef CPTCFG_ATH9K_PCOEM
++ 	/* PCI-E CUS198 */
++ 	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
++ 			 0x0032,
++@@ -294,10 +297,12 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_i
++ 			 PCI_VENDOR_ID_ASUSTEK,
++ 			 0x850D),
++ 	  .driver_data = ATH9K_PCI_NO_PLL_PWRSAVE },
+++#endif
++ 
++ 	{ PCI_VDEVICE(ATHEROS, 0x0032) }, /* PCI-E  AR9485 */
++ 	{ PCI_VDEVICE(ATHEROS, 0x0033) }, /* PCI-E  AR9580 */
++ 
+++#ifdef CPTCFG_ATH9K_PCOEM
++ 	/* PCI-E CUS217 */
++ 	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
++ 			 0x0034,
++@@ -657,6 +662,7 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_i
++ 	/* PCI-E AR9565 (WB335) */
++ 	{ PCI_VDEVICE(ATHEROS, 0x0036),
++ 	  .driver_data = ATH9K_PCI_BT_ANT_DIV },
+++#endif
++ 
++ 	{ PCI_VDEVICE(ATHEROS, 0xabcd) }, /* PCI-E  internal chip default ID */
++ 	{ 0 }
++--- a/drivers/net/wireless/ath/ath9k/reg.h
+++++ b/drivers/net/wireless/ath/ath9k/reg.h
++@@ -891,10 +891,21 @@
++ 	(AR_SREV_9330((_ah)) && \
++ 	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_12))
++ 
+++#ifdef CPTCFG_ATH9K_PCOEM
+++#define AR_SREV_9462(_ah) \
+++	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462))
++ #define AR_SREV_9485(_ah) \
++ 	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485))
+++#define AR_SREV_9565(_ah) \
+++	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565))
+++#else
+++#define AR_SREV_9462(_ah) 0
+++#define AR_SREV_9485(_ah) 0
+++#define AR_SREV_9565(_ah) 0
+++#endif
+++
++ #define AR_SREV_9485_11_OR_LATER(_ah) \
++-	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485) && \
+++	(AR_SREV_9485(_ah) && \
++ 	 ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9485_11))
++ #define AR_SREV_9485_OR_LATER(_ah) \
++ 	(((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9485))
++@@ -910,34 +921,30 @@
++     (AR_SREV_9285_12_OR_LATER(_ah) && \
++      ((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1))
++ 
++-#define AR_SREV_9462(_ah) \
++-	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462))
++ #define AR_SREV_9462_20(_ah) \
++-	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
+++	(AR_SREV_9462(_ah) && \
++ 	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9462_20))
++ #define AR_SREV_9462_21(_ah) \
++-	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
+++	(AR_SREV_9462(_ah) && \
++ 	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9462_21))
++ #define AR_SREV_9462_20_OR_LATER(_ah) \
++-	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
+++	(AR_SREV_9462(_ah) && \
++ 	 ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9462_20))
++ #define AR_SREV_9462_21_OR_LATER(_ah) \
++-	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
+++	(AR_SREV_9462(_ah) && \
++ 	 ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9462_21))
++ 
++-#define AR_SREV_9565(_ah) \
++-	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565))
++ #define AR_SREV_9565_10(_ah) \
++-	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \
+++	(AR_SREV_9565(_ah) && \
++ 	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9565_10))
++ #define AR_SREV_9565_101(_ah) \
++-	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \
+++	(AR_SREV_9565(_ah) && \
++ 	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9565_101))
++ #define AR_SREV_9565_11(_ah) \
++-	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \
+++	(AR_SREV_9565(_ah) && \
++ 	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9565_11))
++ #define AR_SREV_9565_11_OR_LATER(_ah) \
++-	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \
+++	(AR_SREV_9565(_ah) && \
++ 	 ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9565_11))
++ 
++ #define AR_SREV_9550(_ah) \
++--- a/.local-symbols
+++++ b/.local-symbols
++@@ -129,6 +129,7 @@ ATH9K_HW=
++ ATH9K_COMMON=
++ ATH9K_DFS_DEBUGFS=
++ ATH9K_BTCOEX_SUPPORT=
+++ATH9K_PCOEM=
++ ATH9K=
++ ATH9K_PCI=
++ ATH9K_AHB=
+diff --git a/package/mac80211/patches/561-ath9k_remove_gain_tables.patch b/package/mac80211/patches/561-ath9k_remove_gain_tables.patch
+new file mode 100644
+index 0000000..852eae3
+--- /dev/null
++++ b/package/mac80211/patches/561-ath9k_remove_gain_tables.patch
+@@ -0,0 +1,12 @@
++--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
+++++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
++@@ -663,9 +663,6 @@ static void ar9003_tx_gain_table_mode5(s
++ 	if (AR_SREV_9485_11_OR_LATER(ah))
++ 		INIT_INI_ARRAY(&ah->iniModesTxGain,
++ 			ar9485Modes_green_ob_db_tx_gain_1_1);
++-	else if (AR_SREV_9340(ah))
++-		INIT_INI_ARRAY(&ah->iniModesTxGain,
++-			ar9340Modes_ub124_tx_gain_table_1p0);
++ 	else if (AR_SREV_9580(ah))
++ 		INIT_INI_ARRAY(&ah->iniModesTxGain,
++ 			ar9580_1p0_type5_tx_gain_table);
+diff --git a/package/mac80211/patches/562-ath9k_ani_ws_detect.patch b/package/mac80211/patches/562-ath9k_ani_ws_detect.patch
+new file mode 100644
+index 0000000..1e4f451
+--- /dev/null
++++ b/package/mac80211/patches/562-ath9k_ani_ws_detect.patch
+@@ -0,0 +1,155 @@
++--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+++++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
++@@ -929,55 +929,6 @@ static bool ar5008_hw_ani_control_new(st
++ 		 * on == 0 means more noise imm
++ 		 */
++ 		u32 on = param ? 1 : 0;
++-		/*
++-		 * make register setting for default
++-		 * (weak sig detect ON) come from INI file
++-		 */
++-		int m1ThreshLow = on ?
++-			aniState->iniDef.m1ThreshLow : m1ThreshLow_off;
++-		int m2ThreshLow = on ?
++-			aniState->iniDef.m2ThreshLow : m2ThreshLow_off;
++-		int m1Thresh = on ?
++-			aniState->iniDef.m1Thresh : m1Thresh_off;
++-		int m2Thresh = on ?
++-			aniState->iniDef.m2Thresh : m2Thresh_off;
++-		int m2CountThr = on ?
++-			aniState->iniDef.m2CountThr : m2CountThr_off;
++-		int m2CountThrLow = on ?
++-			aniState->iniDef.m2CountThrLow : m2CountThrLow_off;
++-		int m1ThreshLowExt = on ?
++-			aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off;
++-		int m2ThreshLowExt = on ?
++-			aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off;
++-		int m1ThreshExt = on ?
++-			aniState->iniDef.m1ThreshExt : m1ThreshExt_off;
++-		int m2ThreshExt = on ?
++-			aniState->iniDef.m2ThreshExt : m2ThreshExt_off;
++-
++-		REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
++-			      AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
++-			      m1ThreshLow);
++-		REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
++-			      AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
++-			      m2ThreshLow);
++-		REG_RMW_FIELD(ah, AR_PHY_SFCORR,
++-			      AR_PHY_SFCORR_M1_THRESH, m1Thresh);
++-		REG_RMW_FIELD(ah, AR_PHY_SFCORR,
++-			      AR_PHY_SFCORR_M2_THRESH, m2Thresh);
++-		REG_RMW_FIELD(ah, AR_PHY_SFCORR,
++-			      AR_PHY_SFCORR_M2COUNT_THR, m2CountThr);
++-		REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
++-			      AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
++-			      m2CountThrLow);
++-
++-		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
++-			      AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLowExt);
++-		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
++-			      AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLowExt);
++-		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
++-			      AR_PHY_SFCORR_EXT_M1_THRESH, m1ThreshExt);
++-		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
++-			      AR_PHY_SFCORR_EXT_M2_THRESH, m2ThreshExt);
++ 
++ 		if (on)
++ 			REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
++--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
++@@ -26,20 +26,6 @@ static const int cycpwrThr1_table[] =
++ /* level:  0   1   2   3   4   5   6   7   8  */
++ 	{ -6, -4, -2,  0,  2,  4,  6,  8 };     /* lvl 0-7, default 3 */
++ 
++-/*
++- * register values to turn OFDM weak signal detection OFF
++- */
++-static const int m1ThreshLow_off = 127;
++-static const int m2ThreshLow_off = 127;
++-static const int m1Thresh_off = 127;
++-static const int m2Thresh_off = 127;
++-static const int m2CountThr_off =  31;
++-static const int m2CountThrLow_off =  63;
++-static const int m1ThreshLowExt_off = 127;
++-static const int m2ThreshLowExt_off = 127;
++-static const int m1ThreshExt_off = 127;
++-static const int m2ThreshExt_off = 127;
++-
++ /**
++  * ar9003_hw_set_channel - set channel on single-chip device
++  * @ah: atheros hardware structure
++@@ -954,11 +940,6 @@ static bool ar9003_hw_ani_control(struct
++ 	struct ath_common *common = ath9k_hw_common(ah);
++ 	struct ath9k_channel *chan = ah->curchan;
++ 	struct ar5416AniState *aniState = &ah->ani;
++-	int m1ThreshLow, m2ThreshLow;
++-	int m1Thresh, m2Thresh;
++-	int m2CountThr, m2CountThrLow;
++-	int m1ThreshLowExt, m2ThreshLowExt;
++-	int m1ThreshExt, m2ThreshExt;
++ 	s32 value, value2;
++ 
++ 	switch (cmd & ah->ani_function) {
++@@ -972,61 +953,6 @@ static bool ar9003_hw_ani_control(struct
++ 		 */
++ 		u32 on = param ? 1 : 0;
++ 
++-		if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
++-			goto skip_ws_det;
++-
++-		m1ThreshLow = on ?
++-			aniState->iniDef.m1ThreshLow : m1ThreshLow_off;
++-		m2ThreshLow = on ?
++-			aniState->iniDef.m2ThreshLow : m2ThreshLow_off;
++-		m1Thresh = on ?
++-			aniState->iniDef.m1Thresh : m1Thresh_off;
++-		m2Thresh = on ?
++-			aniState->iniDef.m2Thresh : m2Thresh_off;
++-		m2CountThr = on ?
++-			aniState->iniDef.m2CountThr : m2CountThr_off;
++-		m2CountThrLow = on ?
++-			aniState->iniDef.m2CountThrLow : m2CountThrLow_off;
++-		m1ThreshLowExt = on ?
++-			aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off;
++-		m2ThreshLowExt = on ?
++-			aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off;
++-		m1ThreshExt = on ?
++-			aniState->iniDef.m1ThreshExt : m1ThreshExt_off;
++-		m2ThreshExt = on ?
++-			aniState->iniDef.m2ThreshExt : m2ThreshExt_off;
++-
++-		REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
++-			      AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
++-			      m1ThreshLow);
++-		REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
++-			      AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
++-			      m2ThreshLow);
++-		REG_RMW_FIELD(ah, AR_PHY_SFCORR,
++-			      AR_PHY_SFCORR_M1_THRESH,
++-			      m1Thresh);
++-		REG_RMW_FIELD(ah, AR_PHY_SFCORR,
++-			      AR_PHY_SFCORR_M2_THRESH,
++-			      m2Thresh);
++-		REG_RMW_FIELD(ah, AR_PHY_SFCORR,
++-			      AR_PHY_SFCORR_M2COUNT_THR,
++-			      m2CountThr);
++-		REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
++-			      AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
++-			      m2CountThrLow);
++-		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
++-			      AR_PHY_SFCORR_EXT_M1_THRESH_LOW,
++-			      m1ThreshLowExt);
++-		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
++-			      AR_PHY_SFCORR_EXT_M2_THRESH_LOW,
++-			      m2ThreshLowExt);
++-		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
++-			      AR_PHY_SFCORR_EXT_M1_THRESH,
++-			      m1ThreshExt);
++-		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
++-			      AR_PHY_SFCORR_EXT_M2_THRESH,
++-			      m2ThreshExt);
++-skip_ws_det:
++ 		if (on)
++ 			REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
++ 				    AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+diff --git a/package/mac80211/patches/563-ath9k_rxorn_intr_fix.patch b/package/mac80211/patches/563-ath9k_rxorn_intr_fix.patch
+new file mode 100644
+index 0000000..47a7d82
+--- /dev/null
++++ b/package/mac80211/patches/563-ath9k_rxorn_intr_fix.patch
+@@ -0,0 +1,12 @@
++--- a/drivers/net/wireless/ath/ath9k/main.c
+++++ b/drivers/net/wireless/ath/ath9k/main.c
++@@ -628,8 +628,7 @@ irqreturn_t ath_isr(int irq, void *dev)
++ 	 * If a FATAL or RXORN interrupt is received, we have to reset the
++ 	 * chip immediately.
++ 	 */
++-	if ((status & ATH9K_INT_FATAL) || ((status & ATH9K_INT_RXORN) &&
++-	    !(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)))
+++	if (status & ATH9K_INT_FATAL)
++ 		goto chip_reset;
++ 
++ 	if ((ah->config.hw_hang_checks & HW_BB_WATCHDOG) &&
 diff --git a/package/mac80211/patches/566-ath9k-ar933x-usb-hang-workaround.patch b/package/mac80211/patches/566-ath9k-ar933x-usb-hang-workaround.patch
 deleted file mode 100644
 index af94c9e..0000000
@@ -7847,7 +10443,7 @@ index 0000000..d344957
 + 			      const unsigned int offset, u32 *value);
 diff --git a/package/mac80211/patches/600-0002-rt2x00-rt2800lib-introduce-RT2800_HAS_HIGH_SHARED_ME.patch b/package/mac80211/patches/600-0002-rt2x00-rt2800lib-introduce-RT2800_HAS_HIGH_SHARED_ME.patch
 new file mode 100644
-index 0000000..98c9203
+index 0000000..60d4c55
 --- /dev/null
 +++ b/package/mac80211/patches/600-0002-rt2x00-rt2800lib-introduce-RT2800_HAS_HIGH_SHARED_ME.patch
 @@ -0,0 +1,80 @@
@@ -7877,7 +10473,7 @@ index 0000000..98c9203
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -7711,6 +7711,7 @@ static int rt2800_probe_rt(struct rt2x00
++@@ -7734,6 +7734,7 @@ static int rt2800_probe_rt(struct rt2x00
 + 
 + int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev)
 + {
@@ -7885,7 +10481,7 @@ index 0000000..98c9203
 + 	int retval;
 + 	u32 reg;
 + 
-+@@ -7718,6 +7719,9 @@ int rt2800_probe_hw(struct rt2x00_dev *r
++@@ -7741,6 +7742,9 @@ int rt2800_probe_hw(struct rt2x00_dev *r
 + 	if (retval)
 + 		return retval;
 + 
@@ -7933,7 +10529,7 @@ index 0000000..98c9203
 + 					u32 *value)
 diff --git a/package/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch b/package/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch
 new file mode 100644
-index 0000000..97e213f
+index 0000000..2accf73
 --- /dev/null
 +++ b/package/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch
 @@ -0,0 +1,531 @@
@@ -8008,7 +10604,7 @@ index 0000000..97e213f
 + 		rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0);
 + 	}
 + 	msleep(1);
-+@@ -1001,8 +1011,10 @@ void rt2800_write_beacon(struct queue_en
++@@ -1035,8 +1045,10 @@ void rt2800_write_beacon(struct queue_en
 + 
 + 	beacon_base = rt2800_hw_beacon_base(rt2x00dev, entry->entry_idx);
 + 
@@ -8016,10 +10612,10 @@ index 0000000..97e213f
 + 	rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,
 + 				   entry->skb->len + padding_len);
 ++	rt2800_shared_mem_unlock(rt2x00dev);
++ 	__set_bit(ENTRY_BCN_ENABLED, &entry->flags);
 + 
 + 	/*
-+ 	 * Restore beaconing state.
-+@@ -1026,6 +1038,8 @@ static inline void rt2800_clear_beacon_r
++@@ -1066,6 +1078,8 @@ static inline void rt2800_clear_beacon_r
 + 
 + 	beacon_base = rt2800_hw_beacon_base(rt2x00dev, index);
 + 
@@ -8028,7 +10624,7 @@ index 0000000..97e213f
 + 	/*
 + 	 * For the Beacon base registers we only need to clear
 + 	 * the whole TXWI which (when set to 0) will invalidate
-+@@ -1033,6 +1047,8 @@ static inline void rt2800_clear_beacon_r
++@@ -1073,6 +1087,8 @@ static inline void rt2800_clear_beacon_r
 + 	 */
 + 	for (i = 0; i < txwi_desc_size; i += sizeof(__le32))
 + 		rt2800_register_write(rt2x00dev, beacon_base + i, 0);
@@ -8037,7 +10633,7 @@ index 0000000..97e213f
 + }
 + 
 + void rt2800_clear_beacon(struct queue_entry *entry)
-+@@ -1216,7 +1232,9 @@ static void rt2800_delete_wcid_attr(stru
++@@ -1261,7 +1277,9 @@ static void rt2800_delete_wcid_attr(stru
 + {
 + 	u32 offset;
 + 	offset = MAC_WCID_ATTR_ENTRY(wcid);
@@ -8047,7 +10643,7 @@ index 0000000..97e213f
 + }
 + 
 + static void rt2800_config_wcid_attr_bssidx(struct rt2x00_dev *rt2x00dev,
-+@@ -1229,11 +1247,13 @@ static void rt2800_config_wcid_attr_bssi
++@@ -1274,11 +1292,13 @@ static void rt2800_config_wcid_attr_bssi
 + 	 * The BSS Idx numbers is split in a main value of 3 bits,
 + 	 * and a extended field for adding one additional bit to the value.
 + 	 */
@@ -8061,7 +10657,7 @@ index 0000000..97e213f
 + }
 + 
 + static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev,
-+@@ -1246,6 +1266,7 @@ static void rt2800_config_wcid_attr_ciph
++@@ -1291,6 +1311,7 @@ static void rt2800_config_wcid_attr_ciph
 + 
 + 	offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx);
 + 
@@ -8069,7 +10665,7 @@ index 0000000..97e213f
 + 	if (crypto->cmd == SET_KEY) {
 + 		rt2800_register_read(rt2x00dev, offset, &reg);
 + 		rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_KEYTAB,
-+@@ -1270,6 +1291,7 @@ static void rt2800_config_wcid_attr_ciph
++@@ -1315,6 +1336,7 @@ static void rt2800_config_wcid_attr_ciph
 + 		rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_RX_WIUDF, 0);
 + 		rt2800_register_write(rt2x00dev, offset, reg);
 + 	}
@@ -8077,7 +10673,7 @@ index 0000000..97e213f
 + 
 + 	offset = MAC_IVEIV_ENTRY(key->hw_key_idx);
 + 
-+@@ -1279,8 +1301,11 @@ static void rt2800_config_wcid_attr_ciph
++@@ -1324,8 +1346,11 @@ static void rt2800_config_wcid_attr_ciph
 + 	    (crypto->cipher == CIPHER_AES))
 + 		iveiv_entry.iv[3] |= 0x20;
 + 	iveiv_entry.iv[3] |= key->keyidx << 6;
@@ -8089,7 +10685,7 @@ index 0000000..97e213f
 + }
 + 
 + int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
-+@@ -1303,8 +1328,11 @@ int rt2800_config_shared_key(struct rt2x
++@@ -1348,8 +1373,11 @@ int rt2800_config_shared_key(struct rt2x
 + 		       sizeof(key_entry.rx_mic));
 + 
 + 		offset = SHARED_KEY_ENTRY(key->hw_key_idx);
@@ -8101,7 +10697,7 @@ index 0000000..97e213f
 + 	}
 + 
 + 	/*
-+@@ -1319,10 +1347,12 @@ int rt2800_config_shared_key(struct rt2x
++@@ -1364,10 +1392,12 @@ int rt2800_config_shared_key(struct rt2x
 + 
 + 	offset = SHARED_KEY_MODE_ENTRY(key->hw_key_idx / 8);
 + 
@@ -8114,7 +10710,7 @@ index 0000000..97e213f
 + 
 + 	/*
 + 	 * Update WCID information
-+@@ -1392,8 +1422,11 @@ int rt2800_config_pairwise_key(struct rt
++@@ -1437,8 +1467,11 @@ int rt2800_config_pairwise_key(struct rt
 + 		       sizeof(key_entry.rx_mic));
 + 
 + 		offset = PAIRWISE_KEY_ENTRY(key->hw_key_idx);
@@ -8126,7 +10722,7 @@ index 0000000..97e213f
 + 	}
 + 
 + 	/*
-+@@ -4875,14 +4908,19 @@ static int rt2800_init_registers(struct 
++@@ -4898,14 +4931,19 @@ static int rt2800_init_registers(struct 
 + 	/*
 + 	 * ASIC will keep garbage value after boot, clear encryption keys.
 + 	 */
@@ -8146,7 +10742,7 @@ index 0000000..97e213f
 + 	}
 + 
 + 	/*
-+@@ -5008,8 +5046,10 @@ static int rt2800_wait_bbp_ready(struct 
++@@ -5031,8 +5069,10 @@ static int rt2800_wait_bbp_ready(struct 
 + 	 * BBP was enabled after firmware was loaded,
 + 	 * but we need to reactivate it now.
 + 	 */
@@ -8157,7 +10753,7 @@ index 0000000..97e213f
 + 	msleep(1);
 + 
 + 	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-+@@ -6705,11 +6745,19 @@ int rt2800_enable_radio(struct rt2x00_de
++@@ -6728,11 +6768,19 @@ int rt2800_enable_radio(struct rt2x00_de
 + 	/*
 + 	 * Send signal during boot time to initialize firmware.
 + 	 */
@@ -8178,7 +10774,7 @@ index 0000000..97e213f
 + 	msleep(1);
 + 
 + 	/*
-+@@ -7715,6 +7763,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r
++@@ -7738,6 +7786,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r
 + 	int retval;
 + 	u32 reg;
 + 
@@ -8187,7 +10783,7 @@ index 0000000..97e213f
 + 	retval = rt2800_probe_rt(rt2x00dev);
 + 	if (retval)
 + 		return retval;
-+@@ -7794,8 +7844,11 @@ void rt2800_get_tkip_seq(struct ieee8021
++@@ -7817,8 +7867,11 @@ void rt2800_get_tkip_seq(struct ieee8021
 + 	u32 offset;
 + 
 + 	offset = MAC_IVEIV_ENTRY(hw_key_idx);
@@ -8470,7 +11066,7 @@ index 0000000..97e213f
 + static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
 diff --git a/package/mac80211/patches/600-0004-rt2x00-rt2800lib-fix-beacon-generation-on-RT3593.patch b/package/mac80211/patches/600-0004-rt2x00-rt2800lib-fix-beacon-generation-on-RT3593.patch
 new file mode 100644
-index 0000000..5cb6eae
+index 0000000..7167f28
 --- /dev/null
 +++ b/package/mac80211/patches/600-0004-rt2x00-rt2800lib-fix-beacon-generation-on-RT3593.patch
 @@ -0,0 +1,131 @@
@@ -8574,7 +11170,7 @@ index 0000000..5cb6eae
 + 	return HW_BEACON_BASE(index);
 + }
 + 
-+@@ -1012,8 +1048,12 @@ void rt2800_write_beacon(struct queue_en
++@@ -1046,8 +1082,12 @@ void rt2800_write_beacon(struct queue_en
 + 	beacon_base = rt2800_hw_beacon_base(rt2x00dev, entry->entry_idx);
 + 
 + 	rt2800_shared_mem_lock(rt2x00dev);
@@ -8585,9 +11181,9 @@ index 0000000..5cb6eae
 ++	rt2800_deselect_beacon_mem(rt2x00dev);
 ++
 + 	rt2800_shared_mem_unlock(rt2x00dev);
++ 	__set_bit(ENTRY_BCN_ENABLED, &entry->flags);
 + 
-+ 	/*
-+@@ -1040,6 +1080,8 @@ static inline void rt2800_clear_beacon_r
++@@ -1080,6 +1120,8 @@ static inline void rt2800_clear_beacon_r
 + 
 + 	rt2800_shared_mem_lock(rt2x00dev);
 + 
@@ -8596,7 +11192,7 @@ index 0000000..5cb6eae
 + 	/*
 + 	 * For the Beacon base registers we only need to clear
 + 	 * the whole TXWI which (when set to 0) will invalidate
-+@@ -1048,6 +1090,8 @@ static inline void rt2800_clear_beacon_r
++@@ -1088,6 +1130,8 @@ static inline void rt2800_clear_beacon_r
 + 	for (i = 0; i < txwi_desc_size; i += sizeof(__le32))
 + 		rt2800_register_write(rt2x00dev, beacon_base + i, 0);
 + 
@@ -8607,7 +11203,7 @@ index 0000000..5cb6eae
 + 
 diff --git a/package/mac80211/patches/600-0005-rt2x00-rt2800lib-add-hw_beacon_count-field-to-struct.patch b/package/mac80211/patches/600-0005-rt2x00-rt2800lib-add-hw_beacon_count-field-to-struct.patch
 new file mode 100644
-index 0000000..d832f99
+index 0000000..0b509df
 --- /dev/null
 +++ b/package/mac80211/patches/600-0005-rt2x00-rt2800lib-add-hw_beacon_count-field-to-struct.patch
 @@ -0,0 +1,62 @@
@@ -8637,7 +11233,7 @@ index 0000000..d832f99
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -4583,6 +4583,7 @@ EXPORT_SYMBOL_GPL(rt2800_link_tuner);
++@@ -4628,6 +4628,7 @@ EXPORT_SYMBOL_GPL(rt2800_link_tuner);
 +  */
 + static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 + {
@@ -8645,7 +11241,7 @@ index 0000000..d832f99
 + 	u32 reg;
 + 	u16 eeprom;
 + 	unsigned int i;
-+@@ -4970,7 +4971,7 @@ static int rt2800_init_registers(struct 
++@@ -4993,7 +4994,7 @@ static int rt2800_init_registers(struct 
 + 	/*
 + 	 * Clear all beacons
 + 	 */
@@ -8654,7 +11250,7 @@ index 0000000..d832f99
 + 		rt2800_clear_beacon_register(rt2x00dev, i);
 + 
 + 	if (rt2x00_is_usb(rt2x00dev)) {
-+@@ -7816,6 +7817,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r
++@@ -7839,6 +7840,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r
 + 	if (rt2x00_rt(rt2x00dev, RT3593))
 + 		__set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags);
 + 
@@ -8675,7 +11271,7 @@ index 0000000..d832f99
 + 
 diff --git a/package/mac80211/patches/600-0006-rt2x00-rt2800lib-init-additional-beacon-offset-regis.patch b/package/mac80211/patches/600-0006-rt2x00-rt2800lib-init-additional-beacon-offset-regis.patch
 new file mode 100644
-index 0000000..040c69c
+index 0000000..95f44b5
 --- /dev/null
 +++ b/package/mac80211/patches/600-0006-rt2x00-rt2800lib-init-additional-beacon-offset-regis.patch
 @@ -0,0 +1,67 @@
@@ -8715,9 +11311,9 @@ index 0000000..040c69c
 +  */
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -4617,6 +4617,30 @@ static int rt2800_init_registers(struct 
-+ 			   rt2800_get_beacon_offset(rt2x00dev, 7));
-+ 	rt2800_register_write(rt2x00dev, BCN_OFFSET1, reg);
++@@ -4640,6 +4640,30 @@ static int rt2800_init_registers(struct 
++ 	if (ret)
++ 		return ret;
 + 
 ++	if (drv_data->hw_beacon_count == 16) {
 ++		rt2800_register_read(rt2x00dev, BCN_OFFSET2, &reg);
@@ -8748,7 +11344,7 @@ index 0000000..040c69c
 + 
 diff --git a/package/mac80211/patches/600-0007-rt2x00-rt2800lib-fix-max-supported-beacon-count-for-.patch b/package/mac80211/patches/600-0007-rt2x00-rt2800lib-fix-max-supported-beacon-count-for-.patch
 new file mode 100644
-index 0000000..752cd89
+index 0000000..303d2be
 --- /dev/null
 +++ b/package/mac80211/patches/600-0007-rt2x00-rt2800lib-fix-max-supported-beacon-count-for-.patch
 @@ -0,0 +1,24 @@
@@ -8764,7 +11360,7 @@ index 0000000..752cd89
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -7841,7 +7841,10 @@ int rt2800_probe_hw(struct rt2x00_dev *r
++@@ -7864,7 +7864,10 @@ int rt2800_probe_hw(struct rt2x00_dev *r
 + 	if (rt2x00_rt(rt2x00dev, RT3593))
 + 		__set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags);
 + 
@@ -8814,7 +11410,7 @@ index 0000000..8a10c6e
 + 
 diff --git a/package/mac80211/patches/600-0009-rt2x00-rt2800lib-enable-support-for-RT3883.patch b/package/mac80211/patches/600-0009-rt2x00-rt2800lib-enable-support-for-RT3883.patch
 new file mode 100644
-index 0000000..8cb93ec
+index 0000000..848d95f
 --- /dev/null
 +++ b/package/mac80211/patches/600-0009-rt2x00-rt2800lib-enable-support-for-RT3883.patch
 @@ -0,0 +1,20 @@
@@ -8830,7 +11426,7 @@ index 0000000..8cb93ec
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -7811,6 +7811,7 @@ static int rt2800_probe_rt(struct rt2x00
++@@ -7834,6 +7834,7 @@ static int rt2800_probe_rt(struct rt2x00
 + 	case RT3390:
 + 	case RT3572:
 + 	case RT3593:
@@ -8840,7 +11436,7 @@ index 0000000..8cb93ec
 + 	case RT5592:
 diff --git a/package/mac80211/patches/600-0010-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch b/package/mac80211/patches/600-0010-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch
 new file mode 100644
-index 0000000..e85ae97
+index 0000000..4ccd47f
 --- /dev/null
 +++ b/package/mac80211/patches/600-0010-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch
 @@ -0,0 +1,112 @@
@@ -8877,7 +11473,7 @@ index 0000000..e85ae97
 + #define RF5372				0x5372
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -7431,6 +7431,66 @@ static const struct rf_channel rf_vals_3
++@@ -7454,6 +7454,66 @@ static const struct rf_channel rf_vals_3
 + 	{173, 0x61, 0, 9},
 + };
 + 
@@ -8944,7 +11540,7 @@ index 0000000..e85ae97
 + static const struct rf_channel rf_vals_5592_xtal20[] = {
 + 	/* Channel, N, K, mod, R */
 + 	{1, 482, 4, 10, 3},
-+@@ -7659,6 +7719,11 @@ static int rt2800_probe_hw_mode(struct r
++@@ -7682,6 +7742,11 @@ static int rt2800_probe_hw_mode(struct r
 + 		spec->channels = rf_vals_3x;
 + 		break;
 + 
@@ -8958,7 +11554,7 @@ index 0000000..e85ae97
 + 		if (rt2x00_get_field32(reg, MAC_DEBUG_INDEX_XTAL)) {
 diff --git a/package/mac80211/patches/600-0011-rt2x00-rt2800lib-enable-VCO-calibration-for-RF3853.patch b/package/mac80211/patches/600-0011-rt2x00-rt2800lib-enable-VCO-calibration-for-RF3853.patch
 new file mode 100644
-index 0000000..898e385
+index 0000000..7dbfd7f
 --- /dev/null
 +++ b/package/mac80211/patches/600-0011-rt2x00-rt2800lib-enable-VCO-calibration-for-RF3853.patch
 @@ -0,0 +1,28 @@
@@ -8974,7 +11570,7 @@ index 0000000..898e385
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -4348,6 +4348,7 @@ void rt2800_vco_calibration(struct rt2x0
++@@ -4393,6 +4393,7 @@ void rt2800_vco_calibration(struct rt2x0
 + 	case RF3053:
 + 	case RF3070:
 + 	case RF3290:
@@ -8982,7 +11578,7 @@ index 0000000..898e385
 + 	case RF5360:
 + 	case RF5370:
 + 	case RF5372:
-+@@ -7838,6 +7839,7 @@ static int rt2800_probe_hw_mode(struct r
++@@ -7861,6 +7862,7 @@ static int rt2800_probe_hw_mode(struct r
 + 	case RF3053:
 + 	case RF3070:
 + 	case RF3290:
@@ -8992,7 +11588,7 @@ index 0000000..898e385
 + 	case RF5372:
 diff --git a/package/mac80211/patches/600-0012-rt2x00-rt2800lib-add-channel-configuration-function-.patch b/package/mac80211/patches/600-0012-rt2x00-rt2800lib-add-channel-configuration-function-.patch
 new file mode 100644
-index 0000000..1de99ea
+index 0000000..4c28f9b
 --- /dev/null
 +++ b/package/mac80211/patches/600-0012-rt2x00-rt2800lib-add-channel-configuration-function-.patch
 @@ -0,0 +1,235 @@
@@ -9009,7 +11605,7 @@ index 0000000..1de99ea
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -2604,6 +2604,211 @@ static void rt2800_config_channel_rf3053
++@@ -2649,6 +2649,211 @@ static void rt2800_config_channel_rf3053
 + 	}
 + }
 + 
@@ -9221,7 +11817,7 @@ index 0000000..1de99ea
 + #define POWER_BOUND		0x27
 + #define POWER_BOUND_5G		0x2b
 + 
-+@@ -3216,6 +3421,9 @@ static void rt2800_config_channel(struct
++@@ -3261,6 +3466,9 @@ static void rt2800_config_channel(struct
 + 	case RF3322:
 + 		rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info);
 + 		break;
@@ -9233,7 +11829,7 @@ index 0000000..1de99ea
 + 	case RF5370:
 diff --git a/package/mac80211/patches/600-0013-rt2x00-rt2800lib-enable-RF3853-support.patch b/package/mac80211/patches/600-0013-rt2x00-rt2800lib-enable-RF3853-support.patch
 new file mode 100644
-index 0000000..e7e17a9
+index 0000000..9419e62
 --- /dev/null
 +++ b/package/mac80211/patches/600-0013-rt2x00-rt2800lib-enable-RF3853-support.patch
 @@ -0,0 +1,20 @@
@@ -9249,7 +11845,7 @@ index 0000000..e7e17a9
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -7397,6 +7397,7 @@ static int rt2800_init_eeprom(struct rt2
++@@ -7420,6 +7420,7 @@ static int rt2800_init_eeprom(struct rt2
 + 	case RF3290:
 + 	case RF3320:
 + 	case RF3322:
@@ -9259,7 +11855,7 @@ index 0000000..e7e17a9
 + 	case RF5372:
 diff --git a/package/mac80211/patches/600-0014-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch b/package/mac80211/patches/600-0014-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch
 new file mode 100644
-index 0000000..95423d1
+index 0000000..65c6720
 --- /dev/null
 +++ b/package/mac80211/patches/600-0014-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch
 @@ -0,0 +1,77 @@
@@ -9300,7 +11896,7 @@ index 0000000..95423d1
 + #define RX_FILTER_CFG			0x1400
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -4972,6 +4972,12 @@ static int rt2800_init_registers(struct 
++@@ -4995,6 +4995,12 @@ static int rt2800_init_registers(struct 
 + 			rt2800_register_write(rt2x00dev, TX_SW_CFG2,
 + 					      0x00000000);
 + 		}
@@ -9313,7 +11909,7 @@ index 0000000..95423d1
 + 	} else if (rt2x00_rt(rt2x00dev, RT5390) ||
 + 		   rt2x00_rt(rt2x00dev, RT5392) ||
 + 		   rt2x00_rt(rt2x00dev, RT5592)) {
-+@@ -5002,9 +5008,11 @@ static int rt2800_init_registers(struct 
++@@ -5025,9 +5031,11 @@ static int rt2800_init_registers(struct 
 + 
 + 	rt2800_register_read(rt2x00dev, MAX_LEN_CFG, &reg);
 + 	rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE);
@@ -9328,7 +11924,7 @@ index 0000000..95423d1
 + 		rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 2);
 + 	else
 + 		rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 1);
-+@@ -5157,6 +5165,11 @@ static int rt2800_init_registers(struct 
++@@ -5180,6 +5188,11 @@ static int rt2800_init_registers(struct 
 + 	reg = rt2x00_rt(rt2x00dev, RT5592) ? 0x00000082 : 0x00000002;
 + 	rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, reg);
 + 
@@ -9378,7 +11974,7 @@ index 0000000..837c025
 + static int rt2800soc_set_device_state(struct rt2x00_dev *rt2x00dev,
 diff --git a/package/mac80211/patches/600-0016-rt2x00-rt2800lib-add-BBP-register-initialization-for.patch b/package/mac80211/patches/600-0016-rt2x00-rt2800lib-add-BBP-register-initialization-for.patch
 new file mode 100644
-index 0000000..d9694da
+index 0000000..bba96db
 --- /dev/null
 +++ b/package/mac80211/patches/600-0016-rt2x00-rt2800lib-add-BBP-register-initialization-for.patch
 @@ -0,0 +1,71 @@
@@ -9395,7 +11991,7 @@ index 0000000..d9694da
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -5775,6 +5775,47 @@ static void rt2800_init_bbp_3593(struct 
++@@ -5798,6 +5798,47 @@ static void rt2800_init_bbp_3593(struct 
 + 		rt2800_bbp_write(rt2x00dev, 103, 0xc0);
 + }
 + 
@@ -9443,7 +12039,7 @@ index 0000000..d9694da
 + static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev)
 + {
 + 	int ant, div_mode;
-+@@ -5993,6 +6034,9 @@ static void rt2800_init_bbp(struct rt2x0
++@@ -6016,6 +6057,9 @@ static void rt2800_init_bbp(struct rt2x0
 + 	case RT3593:
 + 		rt2800_init_bbp_3593(rt2x00dev);
 + 		return;
@@ -9455,7 +12051,7 @@ index 0000000..d9694da
 + 		rt2800_init_bbp_53xx(rt2x00dev);
 diff --git a/package/mac80211/patches/600-0017-rt2x00-rt2800lib-add-RFCSR-initialization-for-RT3883.patch b/package/mac80211/patches/600-0017-rt2x00-rt2800lib-add-RFCSR-initialization-for-RT3883.patch
 new file mode 100644
-index 0000000..dc45109
+index 0000000..568e60e
 --- /dev/null
 +++ b/package/mac80211/patches/600-0017-rt2x00-rt2800lib-add-RFCSR-initialization-for-RT3883.patch
 @@ -0,0 +1,178 @@
@@ -9482,7 +12078,7 @@ index 0000000..dc45109
 + /*
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -6810,6 +6810,144 @@ static void rt2800_init_rfcsr_3593(struc
++@@ -6833,6 +6833,144 @@ static void rt2800_init_rfcsr_3593(struc
 + 	/* TODO: enable stream mode support */
 + }
 + 
@@ -9627,7 +12223,7 @@ index 0000000..dc45109
 + static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev)
 + {
 + 	rt2800_rf_init_calibration(rt2x00dev, 2);
-+@@ -7041,6 +7179,9 @@ static void rt2800_init_rfcsr(struct rt2
++@@ -7064,6 +7202,9 @@ static void rt2800_init_rfcsr(struct rt2
 + 	case RT3390:
 + 		rt2800_init_rfcsr_3390(rt2x00dev);
 + 		break;
@@ -9667,7 +12263,7 @@ index 0000000..57af961
 + 		map = rt2800_eeprom_map;
 diff --git a/package/mac80211/patches/600-0019-rt2x00-rt2800lib-force-rf-type-to-RF3853-on-RT3883.patch b/package/mac80211/patches/600-0019-rt2x00-rt2800lib-force-rf-type-to-RF3853-on-RT3883.patch
 new file mode 100644
-index 0000000..4bfe8e1
+index 0000000..50fa94f
 --- /dev/null
 +++ b/package/mac80211/patches/600-0019-rt2x00-rt2800lib-force-rf-type-to-RF3853-on-RT3883.patch
 @@ -0,0 +1,21 @@
@@ -9683,7 +12279,7 @@ index 0000000..4bfe8e1
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -7578,6 +7578,8 @@ static int rt2800_init_eeprom(struct rt2
++@@ -7601,6 +7601,8 @@ static int rt2800_init_eeprom(struct rt2
 + 	    rt2x00_rt(rt2x00dev, RT5390) ||
 + 	    rt2x00_rt(rt2x00dev, RT5392))
 + 		rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf);
@@ -9694,7 +12290,7 @@ index 0000000..4bfe8e1
 + 
 diff --git a/package/mac80211/patches/600-0020-rt2x00-rt2800lib-add-channel-configuration-code-for-.patch b/package/mac80211/patches/600-0020-rt2x00-rt2800lib-add-channel-configuration-code-for-.patch
 new file mode 100644
-index 0000000..59b74ad
+index 0000000..e717baa
 --- /dev/null
 +++ b/package/mac80211/patches/600-0020-rt2x00-rt2800lib-add-channel-configuration-code-for-.patch
 @@ -0,0 +1,136 @@
@@ -9710,7 +12306,7 @@ index 0000000..59b74ad
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -3384,6 +3384,36 @@ static char rt2800_txpower_to_dev(struct
++@@ -3429,6 +3429,36 @@ static char rt2800_txpower_to_dev(struct
 + 		return clamp_t(char, txpower, MIN_A_TXPOWER, MAX_A_TXPOWER);
 + }
 + 
@@ -9747,7 +12343,7 @@ index 0000000..59b74ad
 + static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 + 				  struct ieee80211_conf *conf,
 + 				  struct rf_channel *rf,
-+@@ -3402,6 +3432,12 @@ static void rt2800_config_channel(struct
++@@ -3447,6 +3477,12 @@ static void rt2800_config_channel(struct
 + 			rt2800_txpower_to_dev(rt2x00dev, rf->channel,
 + 					      info->default_power3);
 + 
@@ -9760,7 +12356,7 @@ index 0000000..59b74ad
 + 	switch (rt2x00dev->chip.rf) {
 + 	case RF2020:
 + 	case RF3020:
-+@@ -3483,6 +3519,15 @@ static void rt2800_config_channel(struct
++@@ -3528,6 +3564,15 @@ static void rt2800_config_channel(struct
 + 		rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
 + 		rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain);
 + 		rt2800_bbp_write(rt2x00dev, 77, 0x98);
@@ -9776,7 +12372,7 @@ index 0000000..59b74ad
 + 	} else {
 + 		rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
 + 		rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
-+@@ -3495,6 +3540,7 @@ static void rt2800_config_channel(struct
++@@ -3540,6 +3585,7 @@ static void rt2800_config_channel(struct
 + 		    !rt2x00_rt(rt2x00dev, RT5392)) {
 + 			if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
 + 				rt2800_bbp_write(rt2x00dev, 82, 0x62);
@@ -9784,7 +12380,7 @@ index 0000000..59b74ad
 + 				rt2800_bbp_write(rt2x00dev, 75, 0x46);
 + 			} else {
 + 				if (rt2x00_rt(rt2x00dev, RT3593))
-+@@ -3503,19 +3549,22 @@ static void rt2800_config_channel(struct
++@@ -3548,19 +3594,22 @@ static void rt2800_config_channel(struct
 + 					rt2800_bbp_write(rt2x00dev, 82, 0x84);
 + 				rt2800_bbp_write(rt2x00dev, 75, 0x50);
 + 			}
@@ -9810,7 +12406,7 @@ index 0000000..59b74ad
 + 			rt2800_bbp_write(rt2x00dev, 83, 0x9a);
 + 
 + 		if (rt2x00_has_cap_external_lna_a(rt2x00dev))
-+@@ -3640,6 +3689,23 @@ static void rt2800_config_channel(struct
++@@ -3685,6 +3734,23 @@ static void rt2800_config_channel(struct
 + 		usleep_range(1000, 1500);
 + 	}
 + 
@@ -9836,7 +12432,7 @@ index 0000000..59b74ad
 + 		rt2800_bbp_write(rt2x00dev, 196, conf_is_ht40(conf) ? 0x10 : 0x1a);
 diff --git a/package/mac80211/patches/600-0021-rt2x00-rt2800lib-fix-txpower_to_dev-function-for-RT3.patch b/package/mac80211/patches/600-0021-rt2x00-rt2800lib-fix-txpower_to_dev-function-for-RT3.patch
 new file mode 100644
-index 0000000..e88a7c6
+index 0000000..1773128
 --- /dev/null
 +++ b/package/mac80211/patches/600-0021-rt2x00-rt2800lib-fix-txpower_to_dev-function-for-RT3.patch
 @@ -0,0 +1,30 @@
@@ -9852,7 +12448,7 @@ index 0000000..e88a7c6
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -3371,13 +3371,15 @@ static char rt2800_txpower_to_dev(struct
++@@ -3416,13 +3416,15 @@ static char rt2800_txpower_to_dev(struct
 + 				  unsigned int channel,
 + 				  char txpower)
 + {
@@ -9872,7 +12468,7 @@ index 0000000..e88a7c6
 + 	else
 diff --git a/package/mac80211/patches/600-0022-rt2x00-rt2800lib-use-correct-txpower-calculation-fun.patch b/package/mac80211/patches/600-0022-rt2x00-rt2800lib-use-correct-txpower-calculation-fun.patch
 new file mode 100644
-index 0000000..95484a0
+index 0000000..4956373
 --- /dev/null
 +++ b/package/mac80211/patches/600-0022-rt2x00-rt2800lib-use-correct-txpower-calculation-fun.patch
 @@ -0,0 +1,23 @@
@@ -9889,7 +12485,7 @@ index 0000000..95484a0
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -4581,7 +4581,8 @@ static void rt2800_config_txpower(struct
++@@ -4626,7 +4626,8 @@ static void rt2800_config_txpower(struct
 + 				  struct ieee80211_channel *chan,
 + 				  int power_level)
 + {
@@ -9901,7 +12497,7 @@ index 0000000..95484a0
 + 		rt2800_config_txpower_rt28xx(rt2x00dev, chan, power_level);
 diff --git a/package/mac80211/patches/600-0023-rt2x00-rt2800lib-hardcode-txmixer-gain-values-to-zer.patch b/package/mac80211/patches/600-0023-rt2x00-rt2800lib-hardcode-txmixer-gain-values-to-zer.patch
 new file mode 100644
-index 0000000..c57af60
+index 0000000..a692fd8
 --- /dev/null
 +++ b/package/mac80211/patches/600-0023-rt2x00-rt2800lib-hardcode-txmixer-gain-values-to-zer.patch
 @@ -0,0 +1,33 @@
@@ -9918,7 +12514,7 @@ index 0000000..c57af60
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -7460,7 +7460,8 @@ static u8 rt2800_get_txmixer_gain_24g(st
++@@ -7483,7 +7483,8 @@ static u8 rt2800_get_txmixer_gain_24g(st
 + {
 + 	u16 word;
 + 
@@ -9928,7 +12524,7 @@ index 0000000..c57af60
 + 		return 0;
 + 
 + 	rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &word);
-+@@ -7474,7 +7475,8 @@ static u8 rt2800_get_txmixer_gain_5g(str
++@@ -7497,7 +7498,8 @@ static u8 rt2800_get_txmixer_gain_5g(str
 + {
 + 	u16 word;
 + 
@@ -9994,7 +12590,7 @@ index 0000000..08f3f88
 + 	return HW_BEACON_BASE(index);
 diff --git a/package/mac80211/patches/600-0026-rt2x00-rt2800lib-use-correct-beacon-count-for-RT3883.patch b/package/mac80211/patches/600-0026-rt2x00-rt2800lib-use-correct-beacon-count-for-RT3883.patch
 new file mode 100644
-index 0000000..f606ed4
+index 0000000..f8fe496
 --- /dev/null
 +++ b/package/mac80211/patches/600-0026-rt2x00-rt2800lib-use-correct-beacon-count-for-RT3883.patch
 @@ -0,0 +1,22 @@
@@ -10010,7 +12606,7 @@ index 0000000..f606ed4
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -8392,7 +8392,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r
++@@ -8415,7 +8415,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r
 + 	if (rt2x00_rt(rt2x00dev, RT3593))
 + 		__set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags);
 + 
@@ -10022,7 +12618,7 @@ index 0000000..f606ed4
 + 		drv_data->hw_beacon_count = 8;
 diff --git a/package/mac80211/patches/600-0027-rt2x00-rt2800lib-fix-antenna-configuration-for-RT388.patch b/package/mac80211/patches/600-0027-rt2x00-rt2800lib-fix-antenna-configuration-for-RT388.patch
 new file mode 100644
-index 0000000..4096493
+index 0000000..22f7110
 --- /dev/null
 +++ b/package/mac80211/patches/600-0027-rt2x00-rt2800lib-fix-antenna-configuration-for-RT388.patch
 @@ -0,0 +1,22 @@
@@ -10038,7 +12634,7 @@ index 0000000..4096493
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -1916,7 +1916,8 @@ void rt2800_config_ant(struct rt2x00_dev
++@@ -1961,7 +1961,8 @@ void rt2800_config_ant(struct rt2x00_dev
 + 	rt2800_bbp_write(rt2x00dev, 3, r3);
 + 	rt2800_bbp_write(rt2x00dev, 1, r1);
 + 
@@ -10050,7 +12646,7 @@ index 0000000..4096493
 + 		else
 diff --git a/package/mac80211/patches/600-0028-rt2x00-rt2800lib-fix-LNA-gain-configuration-for-RT38.patch b/package/mac80211/patches/600-0028-rt2x00-rt2800lib-fix-LNA-gain-configuration-for-RT38.patch
 new file mode 100644
-index 0000000..2fc9d9d
+index 0000000..9945f38
 --- /dev/null
 +++ b/package/mac80211/patches/600-0028-rt2x00-rt2800lib-fix-LNA-gain-configuration-for-RT38.patch
 @@ -0,0 +1,32 @@
@@ -10066,7 +12662,7 @@ index 0000000..2fc9d9d
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -1939,7 +1939,8 @@ static void rt2800_config_lna_gain(struc
++@@ -1984,7 +1984,8 @@ static void rt2800_config_lna_gain(struc
 + 		rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom);
 + 		lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0);
 + 	} else if (libconf->rf.channel <= 128) {
@@ -10076,7 +12672,7 @@ index 0000000..2fc9d9d
 + 			rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &eeprom);
 + 			lna_gain = rt2x00_get_field16(eeprom,
 + 						      EEPROM_EXT_LNA2_A1);
-+@@ -1949,7 +1950,8 @@ static void rt2800_config_lna_gain(struc
++@@ -1994,7 +1995,8 @@ static void rt2800_config_lna_gain(struc
 + 						      EEPROM_RSSI_BG2_LNA_A1);
 + 		}
 + 	} else {
@@ -10088,7 +12684,7 @@ index 0000000..2fc9d9d
 + 						      EEPROM_EXT_LNA2_A2);
 diff --git a/package/mac80211/patches/600-0029-rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch b/package/mac80211/patches/600-0029-rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch
 new file mode 100644
-index 0000000..060d4c6
+index 0000000..80b3668
 --- /dev/null
 +++ b/package/mac80211/patches/600-0029-rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch
 @@ -0,0 +1,44 @@
@@ -10104,7 +12700,7 @@ index 0000000..060d4c6
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -4780,7 +4780,8 @@ static u8 rt2800_get_default_vgc(struct 
++@@ -4825,7 +4825,8 @@ static u8 rt2800_get_default_vgc(struct 
 + 		else
 + 			vgc = 0x2e + rt2x00dev->lna_gain;
 + 	} else { /* 5GHZ band */
@@ -10114,7 +12710,7 @@ index 0000000..060d4c6
 + 			vgc = 0x20 + (rt2x00dev->lna_gain * 5) / 3;
 + 		else if (rt2x00_rt(rt2x00dev, RT5592))
 + 			vgc = 0x24 + (2 * rt2x00dev->lna_gain);
-+@@ -4800,7 +4801,8 @@ static inline void rt2800_set_vgc(struct
++@@ -4845,7 +4846,8 @@ static inline void rt2800_set_vgc(struct
 + {
 + 	if (qual->vgc_level != vgc_level) {
 + 		if (rt2x00_rt(rt2x00dev, RT3572) ||
@@ -10124,7 +12720,7 @@ index 0000000..060d4c6
 + 			rt2800_bbp_write_with_rx_chain(rt2x00dev, 66,
 + 						       vgc_level);
 + 		} else if (rt2x00_rt(rt2x00dev, RT5592)) {
-+@@ -4847,6 +4849,11 @@ void rt2800_link_tuner(struct rt2x00_dev
++@@ -4892,6 +4894,11 @@ void rt2800_link_tuner(struct rt2x00_dev
 + 		}
 + 		break;
 + 
@@ -10138,7 +12734,7 @@ index 0000000..060d4c6
 + 			vgc += 0x20;
 diff --git a/package/mac80211/patches/600-0030-rt2x00-rt2800lib-fix-EEPROM-LNA-validation-for-RT388.patch b/package/mac80211/patches/600-0030-rt2x00-rt2800lib-fix-EEPROM-LNA-validation-for-RT388.patch
 new file mode 100644
-index 0000000..3e9a7d9
+index 0000000..424acff
 --- /dev/null
 +++ b/package/mac80211/patches/600-0030-rt2x00-rt2800lib-fix-EEPROM-LNA-validation-for-RT388.patch
 @@ -0,0 +1,42 @@
@@ -10154,7 +12750,7 @@ index 0000000..3e9a7d9
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -7597,7 +7597,8 @@ static int rt2800_validate_eeprom(struct
++@@ -7620,7 +7620,8 @@ static int rt2800_validate_eeprom(struct
 + 	rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word);
 + 	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10)
 + 		rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0);
@@ -10164,7 +12760,7 @@ index 0000000..3e9a7d9
 + 		if (rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0x00 ||
 + 		    rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0xff)
 + 			rt2x00_set_field16(&word, EEPROM_RSSI_BG2_LNA_A1,
-+@@ -7617,7 +7618,8 @@ static int rt2800_validate_eeprom(struct
++@@ -7640,7 +7641,8 @@ static int rt2800_validate_eeprom(struct
 + 	rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &word);
 + 	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A2_OFFSET2)) > 10)
 + 		rt2x00_set_field16(&word, EEPROM_RSSI_A2_OFFSET2, 0);
@@ -10174,7 +12770,7 @@ index 0000000..3e9a7d9
 + 		if (rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0x00 ||
 + 		    rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0xff)
 + 			rt2x00_set_field16(&word, EEPROM_RSSI_A2_LNA_A2,
-+@@ -7625,7 +7627,8 @@ static int rt2800_validate_eeprom(struct
++@@ -7648,7 +7650,8 @@ static int rt2800_validate_eeprom(struct
 + 	}
 + 	rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word);
 + 
@@ -10186,7 +12782,7 @@ index 0000000..3e9a7d9
 + 		    rt2x00_get_field16(word, EEPROM_EXT_LNA2_A1) == 0xff)
 diff --git a/package/mac80211/patches/600-0031-rt2x00-rt2800lib-fix-txpower-compensation-for-RT3883.patch b/package/mac80211/patches/600-0031-rt2x00-rt2800lib-fix-txpower-compensation-for-RT3883.patch
 new file mode 100644
-index 0000000..b87f36a
+index 0000000..00be526
 --- /dev/null
 +++ b/package/mac80211/patches/600-0031-rt2x00-rt2800lib-fix-txpower-compensation-for-RT3883.patch
 @@ -0,0 +1,22 @@
@@ -10202,7 +12798,7 @@ index 0000000..b87f36a
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -3958,6 +3958,9 @@ static u8 rt2800_compensate_txpower(stru
++@@ -4003,6 +4003,9 @@ static u8 rt2800_compensate_txpower(stru
 + 	if (rt2x00_rt(rt2x00dev, RT3593))
 + 		return min_t(u8, txpower, 0xc);
 + 
@@ -10214,7 +12810,7 @@ index 0000000..b87f36a
 + 		 * Check if eirp txpower exceed txpower_limit.
 diff --git a/package/mac80211/patches/600-0032-rt2x00-rt2800lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch b/package/mac80211/patches/600-0032-rt2x00-rt2800lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch
 new file mode 100644
-index 0000000..18d65e0
+index 0000000..7c4c1ab
 --- /dev/null
 +++ b/package/mac80211/patches/600-0032-rt2x00-rt2800lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch
 @@ -0,0 +1,23 @@
@@ -10231,7 +12827,7 @@ index 0000000..18d65e0
 +
 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c
 ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-+@@ -8405,7 +8405,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r
++@@ -8428,7 +8428,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r
 + 	if (retval)
 + 		return retval;
 + 
@@ -10412,7 +13008,7 @@ index 0000000..79334dd
 + 	 */
 + 	spinlock_t irqmask_lock;
 diff --git a/package/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch b/package/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch
-index 2bbc6f1..b7ba2af 100644
+index 2bbc6f1..e5ba10e 100644
 --- a/package/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch
 +++ b/package/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch
 @@ -1,6 +1,6 @@
@@ -10462,10 +13058,50 @@ index 2bbc6f1..b7ba2af 100644
   	.register_multiread	= rt2x00mmio_register_multiread,
   	.register_multiwrite	= rt2x00mmio_register_multiwrite,
   	.regbusy_read		= rt2x00mmio_regbusy_read,
+@@ -127,7 +127,7 @@
+  	DECLARE_KFIFO_PTR(txstatus_fifo, u32);
+ --- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+ +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
+-@@ -1324,6 +1324,10 @@ int rt2x00lib_probe_dev(struct rt2x00_de
++@@ -1327,6 +1327,10 @@ int rt2x00lib_probe_dev(struct rt2x00_de
+  	INIT_DELAYED_WORK(&rt2x00dev->autowakeup_work, rt2x00lib_autowakeup);
+  	INIT_WORK(&rt2x00dev->sleep_work, rt2x00lib_sleep);
+  
+@@ -138,7 +138,7 @@
+  	/*
+  	 * Let the driver probe the device to detect the capabilities.
+  	 */
+-@@ -1454,6 +1458,11 @@ void rt2x00lib_remove_dev(struct rt2x00_
++@@ -1457,6 +1461,11 @@ void rt2x00lib_remove_dev(struct rt2x00_
+  	 */
+  	if (rt2x00dev->drv_data)
+  		kfree(rt2x00dev->drv_data);
+diff --git a/package/mac80211/patches/607-rt2x00-allow_disabling_bands_through_platform_data.patch b/package/mac80211/patches/607-rt2x00-allow_disabling_bands_through_platform_data.patch
+index 4116735..70f7b78 100644
+--- a/package/mac80211/patches/607-rt2x00-allow_disabling_bands_through_platform_data.patch
++++ b/package/mac80211/patches/607-rt2x00-allow_disabling_bands_through_platform_data.patch
+@@ -12,7 +12,7 @@
+  #endif /* _RT2X00_PLATFORM_H */
+ --- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+ +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
+-@@ -937,6 +937,22 @@ static int rt2x00lib_probe_hw_modes(stru
++@@ -940,6 +940,22 @@ static int rt2x00lib_probe_hw_modes(stru
+  	unsigned int num_rates;
+  	unsigned int i;
+  
 diff --git a/package/mac80211/patches/608-add_platform_data_mac_addr.patch b/package/mac80211/patches/608-add_platform_data_mac_addr.patch
-index a910cc3..1db09a3 100644
+index a910cc3..4c2a8b8 100644
 --- a/package/mac80211/patches/608-add_platform_data_mac_addr.patch
 +++ b/package/mac80211/patches/608-add_platform_data_mac_addr.patch
+@@ -10,7 +10,7 @@
+  	int disable_5ghz;
+ --- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+ +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
+-@@ -928,6 +928,18 @@ static void rt2x00lib_rate(struct ieee80
++@@ -931,6 +931,18 @@ static void rt2x00lib_rate(struct ieee80
+  		entry->flags |= IEEE80211_RATE_SHORT_PREAMBLE;
+  }
+  
 @@ -31,7 +31,7 @@
   {
  --- a/drivers/net/wireless/rt2x00/rt2x00.h
@@ -10476,14 +13112,14 @@ index a910cc3..1db09a3 100644
   u32 rt2x00lib_get_bssidx(struct rt2x00_dev *rt2x00dev,
   			 struct ieee80211_vif *vif);
 diff --git a/package/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch b/package/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch
-index 83fbcd0..725f81f 100644
+index 83fbcd0..010a9e2 100644
 --- a/package/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch
 +++ b/package/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch
 @@ -1,14 +1,15 @@
  --- a/drivers/net/wireless/rt2x00/rt2800lib.c
  +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
 -@@ -3176,11 +3176,17 @@ static void rt2800_config_channel(struct
-+@@ -3505,11 +3505,18 @@ static void rt2800_config_channel(struct
++@@ -3550,11 +3550,18 @@ static void rt2800_config_channel(struct
   	/*
   	 * Change BBP settings
   	 */
@@ -10519,7 +13155,7 @@ index 83fbcd0..725f81f 100644
 - 	}
 - 
 -@@ -6125,6 +6125,12 @@ static void rt2800_init_rfcsr_3290(struc
-+@@ -6585,6 +6592,12 @@ static void rt2800_init_rfcsr_3290(struc
++@@ -6608,6 +6615,12 @@ static void rt2800_init_rfcsr_3290(struc
   
   static void rt2800_init_rfcsr_3352(struct rt2x00_dev *rt2x00dev)
   {
@@ -10528,7 +13164,7 @@ index 83fbcd0..725f81f 100644
   
   	rt2800_rfcsr_write(rt2x00dev, 0, 0xf0);
 -@@ -6160,15 +6166,30 @@ static void rt2800_init_rfcsr_3352(struc
-+@@ -6620,15 +6633,30 @@ static void rt2800_init_rfcsr_3352(struc
++@@ -6643,15 +6656,30 @@ static void rt2800_init_rfcsr_3352(struc
   	rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
   	rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
   	rt2800_rfcsr_write(rt2x00dev, 33, 0x00);
@@ -10537,7 +13173,7 @@ index 83fbcd0..725f81f 100644
   	rt2800_rfcsr_write(rt2x00dev, 44, 0xdb);
   	rt2800_rfcsr_write(rt2x00dev, 45, 0xdb);
 -@@ -6176,15 +6197,20 @@ static void rt2800_init_rfcsr_3352(struc
-+@@ -6636,15 +6664,20 @@ static void rt2800_init_rfcsr_3352(struc
++@@ -6659,15 +6687,20 @@ static void rt2800_init_rfcsr_3352(struc
   	rt2800_rfcsr_write(rt2x00dev, 47, 0x0d);
   	rt2800_rfcsr_write(rt2x00dev, 48, 0x14);
   	rt2800_rfcsr_write(rt2x00dev, 49, 0x00);
@@ -10546,7 +13182,7 @@ index 83fbcd0..725f81f 100644
   	rt2800_rfcsr_write(rt2x00dev, 60, 0x00);
   	rt2800_rfcsr_write(rt2x00dev, 61, 0x00);
 -@@ -7051,6 +7077,7 @@ static int rt2800_init_eeprom(struct rt2
-+@@ -7665,6 +7698,7 @@ static int rt2800_init_eeprom(struct rt2
++@@ -7688,6 +7721,7 @@ static int rt2800_init_eeprom(struct rt2
   	 * RT53xx: defined in "EEPROM_CHIP_ID" field
   	 */
   	if (rt2x00_rt(rt2x00dev, RT3290) ||
@@ -10555,7 +13191,7 @@ index 83fbcd0..725f81f 100644
   	    rt2x00_rt(rt2x00dev, RT5392))
   		rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf);
 -@@ -7142,7 +7169,8 @@ static int rt2800_init_eeprom(struct rt2
-+@@ -7759,7 +7793,8 @@ static int rt2800_init_eeprom(struct rt2
++@@ -7782,7 +7816,8 @@ static int rt2800_init_eeprom(struct rt2
   	/*
   	 * Detect if this device has Bluetooth co-existence.
   	 */
@@ -10564,7 +13200,7 @@ index 83fbcd0..725f81f 100644
   
   	/*
 -@@ -7171,6 +7199,22 @@ static int rt2800_init_eeprom(struct rt2
-+@@ -7788,6 +7823,22 @@ static int rt2800_init_eeprom(struct rt2
++@@ -7811,6 +7846,22 @@ static int rt2800_init_eeprom(struct rt2
   					EIRP_MAX_TX_POWER_LIMIT)
   		__set_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags);
   
@@ -10614,14 +13250,14 @@ index 83fbcd0..725f81f 100644
   #define EEPROM_NIC_CONF1_BT_COEXIST		FIELD16(0x4000)
   #define EEPROM_NIC_CONF1_DAC_TEST		FIELD16(0x8000)
 diff --git a/package/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch b/package/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch
-index 478a0f2..6b29aa8 100644
+index 478a0f2..65af89a 100644
 --- a/package/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch
 +++ b/package/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch
 @@ -1,6 +1,6 @@
  --- a/drivers/net/wireless/rt2x00/rt2800lib.c
  +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
 -@@ -7491,6 +7491,27 @@ static const struct rf_channel rf_vals_5
-+@@ -8175,6 +8175,27 @@ static const struct rf_channel rf_vals_5
++@@ -8198,6 +8198,27 @@ static const struct rf_channel rf_vals_5
   	{196, 83, 0, 12, 1},
   };
   
@@ -10630,7 +13266,7 @@ index 478a0f2..6b29aa8 100644
   {
   	struct hw_mode_spec *spec = &rt2x00dev->spec;
 -@@ -7579,7 +7600,10 @@ static int rt2800_probe_hw_mode(struct r
-+@@ -8262,7 +8283,10 @@ static int rt2800_probe_hw_mode(struct r
++@@ -8285,7 +8306,10 @@ static int rt2800_probe_hw_mode(struct r
   	case RF5390:
   	case RF5392:
   		spec->num_channels = 14;
@@ -10639,7 +13275,7 @@ index 478a0f2..6b29aa8 100644
   
   	case RF3052:
 -@@ -7755,6 +7779,19 @@ static int rt2800_probe_rt(struct rt2x00
-+@@ -8445,6 +8469,19 @@ static int rt2800_probe_rt(struct rt2x00
++@@ -8468,6 +8492,19 @@ static int rt2800_probe_rt(struct rt2x00
   	return 0;
   }
   
@@ -10650,7 +13286,7 @@ index 478a0f2..6b29aa8 100644
 - 	int retval;
 -@@ -7784,6 +7821,15 @@ int rt2800_probe_hw(struct rt2x00_dev *r
 + 	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
-+@@ -8487,6 +8524,15 @@ int rt2800_probe_hw(struct rt2x00_dev *r
++@@ -8510,6 +8547,15 @@ int rt2800_probe_hw(struct rt2x00_dev *r
   	rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
   
   	/*
@@ -10668,7 +13304,7 @@ index f6b4808..119e95c 100644
   }
   
 diff --git a/package/mac80211/patches/616-rt2x00-support-rt5350.patch b/package/mac80211/patches/616-rt2x00-support-rt5350.patch
-index 3bafa16..fd897e9 100644
+index 3bafa16..41a7f34 100644
 --- a/package/mac80211/patches/616-rt2x00-support-rt5350.patch
 +++ b/package/mac80211/patches/616-rt2x00-support-rt5350.patch
 @@ -1,16 +1,16 @@
@@ -10687,7 +13323,7 @@ index 3bafa16..fd897e9 100644
  --- a/drivers/net/wireless/rt2x00/rt2800lib.c
  +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
 -@@ -2704,6 +2704,13 @@ static void rt2800_config_channel_rf53xx
-+@@ -2993,6 +2993,13 @@ static void rt2800_config_channel_rf53xx
++@@ -3038,6 +3038,13 @@ static void rt2800_config_channel_rf53xx
   
   				rt2800_rfcsr_write(rt2x00dev, 59,
   						   r59_non_bt[idx]);
@@ -10697,7 +13333,7 @@ index 3bafa16..fd897e9 100644
   	}
 -@@ -3141,6 +3148,7 @@ static void rt2800_config_channel(struct
 - 		rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info);
-+@@ -3471,6 +3478,7 @@ static void rt2800_config_channel(struct
++@@ -3516,6 +3523,7 @@ static void rt2800_config_channel(struct
 + 		rt2800_config_channel_rf3853(rt2x00dev, conf, rf, info);
   		break;
   	case RF3070:
@@ -10706,7 +13342,7 @@ index 3bafa16..fd897e9 100644
   	case RF5370:
   	case RF5372:
 -@@ -3158,6 +3166,7 @@ static void rt2800_config_channel(struct
-+@@ -3488,6 +3496,7 @@ static void rt2800_config_channel(struct
++@@ -3533,6 +3541,7 @@ static void rt2800_config_channel(struct
   	if (rt2x00_rf(rt2x00dev, RF3070) ||
   	    rt2x00_rf(rt2x00dev, RF3290) ||
   	    rt2x00_rf(rt2x00dev, RF3322) ||
@@ -10715,7 +13351,7 @@ index 3bafa16..fd897e9 100644
   	    rt2x00_rf(rt2x00dev, RF5370) ||
   	    rt2x00_rf(rt2x00dev, RF5372) ||
 -@@ -3398,7 +3407,8 @@ static void rt2800_config_channel(struct
-+@@ -3765,7 +3774,8 @@ static void rt2800_config_channel(struct
++@@ -3810,7 +3819,8 @@ static void rt2800_config_channel(struct
   	/*
   	 * Clear update flag
   	 */
@@ -10725,7 +13361,7 @@ index 3bafa16..fd897e9 100644
   		rt2800_bbp_write(rt2x00dev, 49, bbp);
 -@@ -4272,6 +4282,7 @@ void rt2800_vco_calibration(struct rt2x0
 - 	case RF3053:
-+@@ -4644,6 +4654,7 @@ void rt2800_vco_calibration(struct rt2x0
++@@ -4689,6 +4699,7 @@ void rt2800_vco_calibration(struct rt2x0
   	case RF3070:
   	case RF3290:
 + 	case RF3853:
@@ -10734,7 +13370,7 @@ index 3bafa16..fd897e9 100644
   	case RF5370:
   	case RF5372:
 -@@ -4668,6 +4679,8 @@ static int rt2800_init_registers(struct 
-+@@ -5078,6 +5089,8 @@ static int rt2800_init_registers(struct 
++@@ -5101,6 +5112,8 @@ static int rt2800_init_registers(struct 
   		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
   		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
   		rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
@@ -10743,7 +13379,7 @@ index 3bafa16..fd897e9 100644
   		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000);
   		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
 -@@ -5309,9 +5322,13 @@ static void rt2800_init_bbp_3352(struct 
-+@@ -5733,9 +5746,13 @@ static void rt2800_init_bbp_3352(struct 
++@@ -5756,9 +5769,13 @@ static void rt2800_init_bbp_3352(struct 
   
   	rt2800_bbp_write(rt2x00dev, 82, 0x62);
   
@@ -10752,7 +13388,7 @@ index 3bafa16..fd897e9 100644
   	rt2800_bbp_write(rt2x00dev, 86, 0x38);
   
 -@@ -5325,9 +5342,13 @@ static void rt2800_init_bbp_3352(struct 
-+@@ -5749,9 +5766,13 @@ static void rt2800_init_bbp_3352(struct 
++@@ -5772,9 +5789,13 @@ static void rt2800_init_bbp_3352(struct 
   
   	rt2800_bbp_write(rt2x00dev, 104, 0x92);
   
@@ -10761,7 +13397,7 @@ index 3bafa16..fd897e9 100644
   	rt2800_bbp_write(rt2x00dev, 120, 0x50);
   
 -@@ -5352,6 +5373,13 @@ static void rt2800_init_bbp_3352(struct 
-+@@ -5776,6 +5797,13 @@ static void rt2800_init_bbp_3352(struct 
++@@ -5799,6 +5820,13 @@ static void rt2800_init_bbp_3352(struct 
   	rt2800_bbp_write(rt2x00dev, 143, 0xa2);
   
   	rt2800_bbp_write(rt2x00dev, 148, 0xc8);
@@ -10770,7 +13406,7 @@ index 3bafa16..fd897e9 100644
   
   static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev)
 -@@ -5652,6 +5680,7 @@ static void rt2800_init_bbp(struct rt2x0
-+@@ -6117,6 +6145,7 @@ static void rt2800_init_bbp(struct rt2x0
++@@ -6140,6 +6168,7 @@ static void rt2800_init_bbp(struct rt2x0
   		rt2800_init_bbp_3290(rt2x00dev);
   		break;
   	case RT3352:
@@ -10780,7 +13416,7 @@ index 3bafa16..fd897e9 100644
   	case RT3390:
 -@@ -6462,6 +6491,76 @@ static void rt2800_init_rfcsr_3593(struc
 - 	/* TODO: enable stream mode support */
-+@@ -7068,6 +7097,76 @@ static void rt2800_init_rfcsr_3883(struc
++@@ -7091,6 +7120,76 @@ static void rt2800_init_rfcsr_3883(struc
 + 	rt2800_rfcsr_write(rt2x00dev, 20, rfcsr);
   }
   
@@ -10790,7 +13426,7 @@ index 3bafa16..fd897e9 100644
   {
   	rt2800_rf_init_calibration(rt2x00dev, 2);
 -@@ -6699,6 +6798,9 @@ static void rt2800_init_rfcsr(struct rt2
-+@@ -7308,6 +7407,9 @@ static void rt2800_init_rfcsr(struct rt2
++@@ -7331,6 +7430,9 @@ static void rt2800_init_rfcsr(struct rt2
   	case RT3593:
   		rt2800_init_rfcsr_3593(rt2x00dev);
   		break;
@@ -10799,7 +13435,7 @@ index 3bafa16..fd897e9 100644
   		rt2800_init_rfcsr_5390(rt2x00dev);
   		break;
 -@@ -6948,6 +7050,12 @@ static int rt2800_validate_eeprom(struct
-+@@ -7567,6 +7669,12 @@ static int rt2800_validate_eeprom(struct
++@@ -7590,6 +7692,12 @@ static int rt2800_validate_eeprom(struct
   		rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RF_TYPE, RF2820);
   		rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word);
   		rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
@@ -10810,7 +13446,7 @@ index 3bafa16..fd897e9 100644
 -@@ -7081,6 +7189,8 @@ static int rt2800_init_eeprom(struct rt2
 - 	    rt2x00_rt(rt2x00dev, RT5390) ||
 - 	    rt2x00_rt(rt2x00dev, RT5392))
-+@@ -7705,6 +7813,8 @@ static int rt2800_init_eeprom(struct rt2
++@@ -7728,6 +7836,8 @@ static int rt2800_init_eeprom(struct rt2
   		rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf);
 + 	else if (rt2x00_rt(rt2x00dev, RT3883))
 + 		rf = RF3853;
@@ -10821,7 +13457,7 @@ index 3bafa16..fd897e9 100644
   
 -@@ -7099,6 +7209,7 @@ static int rt2800_init_eeprom(struct rt2
 - 	case RF3290:
-+@@ -7724,6 +7834,7 @@ static int rt2800_init_eeprom(struct rt2
++@@ -7747,6 +7857,7 @@ static int rt2800_init_eeprom(struct rt2
   	case RF3320:
   	case RF3322:
 + 	case RF3853:
@@ -10830,7 +13466,7 @@ index 3bafa16..fd897e9 100644
   	case RF5370:
   	case RF5372:
 -@@ -7594,6 +7705,7 @@ static int rt2800_probe_hw_mode(struct r
-+@@ -8278,6 +8389,7 @@ static int rt2800_probe_hw_mode(struct r
++@@ -8301,6 +8412,7 @@ static int rt2800_probe_hw_mode(struct r
   	case RF3290:
   	case RF3320:
   	case RF3322:
@@ -10840,7 +13476,7 @@ index 3bafa16..fd897e9 100644
   	case RF5372:
 -@@ -7726,6 +7838,7 @@ static int rt2800_probe_hw_mode(struct r
 - 	case RF3053:
-+@@ -8416,6 +8528,7 @@ static int rt2800_probe_hw_mode(struct r
++@@ -8439,6 +8551,7 @@ static int rt2800_probe_hw_mode(struct r
   	case RF3070:
   	case RF3290:
 + 	case RF3853:
@@ -10850,7 +13486,7 @@ index 3bafa16..fd897e9 100644
   	case RF5372:
 -@@ -7764,6 +7877,7 @@ static int rt2800_probe_rt(struct rt2x00
 - 	case RT3390:
-+@@ -8455,6 +8568,7 @@ static int rt2800_probe_rt(struct rt2x00
++@@ -8478,6 +8591,7 @@ static int rt2800_probe_rt(struct rt2x00
   	case RT3572:
   	case RT3593:
 + 	case RT3883:
@@ -10858,7 +13494,7 @@ index 3bafa16..fd897e9 100644
   	case RT5390:
   	case RT5392:
 diff --git a/package/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch b/package/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch
-index f9186d8..ee473dc 100644
+index f9186d8..d966321 100644
 --- a/package/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch
 +++ b/package/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch
 @@ -1,6 +1,6 @@
@@ -10874,19 +13510,31 @@ index f9186d8..ee473dc 100644
   #include "rt2x00.h"
   #include "rt2800lib.h"
 -@@ -7298,6 +7299,17 @@ static int rt2800_init_eeprom(struct rt2
-+@@ -7923,6 +7924,17 @@ static int rt2800_init_eeprom(struct rt2
++@@ -7946,6 +7947,17 @@ static int rt2800_init_eeprom(struct rt2
   	rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
   	rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY);
   
+diff --git a/package/mac80211/patches/620-rt2x00-add-AP+STA-support.patch b/package/mac80211/patches/620-rt2x00-add-AP+STA-support.patch
+index 419cb60..ce667b8 100644
+--- a/package/mac80211/patches/620-rt2x00-add-AP+STA-support.patch
++++ b/package/mac80211/patches/620-rt2x00-add-AP+STA-support.patch
+@@ -1,6 +1,6 @@
+ --- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+ +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
+-@@ -1262,7 +1262,7 @@ static inline void rt2x00lib_set_if_comb
++@@ -1265,7 +1265,7 @@ static inline void rt2x00lib_set_if_comb
+  	 */
+  	if_limit = &rt2x00dev->if_limits_ap;
+  	if_limit->max = rt2x00dev->ops->max_ap_intf;
 diff --git a/package/mac80211/patches/620-rt2x00-rt3352-rf-id.patch b/package/mac80211/patches/620-rt2x00-rt3352-rf-id.patch
-index 5e67344..05bcd58 100644
+index 5e67344..90eab13 100644
 --- a/package/mac80211/patches/620-rt2x00-rt3352-rf-id.patch
 +++ b/package/mac80211/patches/620-rt2x00-rt3352-rf-id.patch
 @@ -1,6 +1,6 @@
  --- a/drivers/net/wireless/rt2x00/rt2800lib.c
  +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
 -@@ -7186,10 +7186,11 @@ static int rt2800_init_eeprom(struct rt2
-+@@ -7808,10 +7808,11 @@ static int rt2800_init_eeprom(struct rt2
++@@ -7831,10 +7831,11 @@ static int rt2800_init_eeprom(struct rt2
   	 * RT53xx: defined in "EEPROM_CHIP_ID" field
   	 */
   	if (rt2x00_rt(rt2x00dev, RT3290) ||
@@ -11028,7 +13676,7 @@ index dea9830..5a23967 100644
   	hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
   
 diff --git a/package/mac80211/patches/830-b43-workaround-pcie-bcm4716.patch b/package/mac80211/patches/830-b43-workaround-pcie-bcm4716.patch
-index e76758c..49b2468 100644
+index e76758c..b6db3ac 100644
 --- a/package/mac80211/patches/830-b43-workaround-pcie-bcm4716.patch
 +++ b/package/mac80211/patches/830-b43-workaround-pcie-bcm4716.patch
 @@ -19,7 +19,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
@@ -11040,20 +13688,33 @@ index e76758c..49b2468 100644
   	return dev->__using_pio_transfers;
   }
   
-@@ -53,9 +53,9 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+@@ -53,18 +53,20 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
   __printf(2, 3) void b43err(struct b43_wl *wl, const char *fmt, ...);
  --- a/drivers/net/wireless/b43/bus.h
  +++ b/drivers/net/wireless/b43/bus.h
 -@@ -60,6 +60,16 @@ static inline bool b43_bus_host_is_sdio(
 - 	return (dev->bus_type == B43_BUS_SSB &&
 - 		dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO);
-+@@ -70,6 +70,16 @@ static inline bool b43_bus_host_is_sdio(
++@@ -70,6 +70,18 @@ static inline bool b43_bus_host_is_sdio(
 + 	return false;
 + #endif
   }
  +static inline bool b43_bus_host_is_pci(struct b43_bus_dev *dev)
  +{
-@@ -72,7 +72,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+-+	if (dev->bus_type == B43_BUS_SSB)
+-+		return (dev->sdev->bus->bustype == SSB_BUSTYPE_PCI);
+ +#ifdef CPTCFG_B43_BCMA
+ +	if (dev->bus_type == B43_BUS_BCMA)
+ +		return (dev->bdev->bus->hosttype == BCMA_HOSTTYPE_PCI);
+ +#endif
+++#ifdef CPTCFG_B43_SSB
+++	if (dev->bus_type == B43_BUS_SSB)
+++		return (dev->sdev->bus->bustype == SSB_BUSTYPE_PCI);
+++#endif
+ +	return false;
+ +}
+  
+@@ -72,7 +74,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
   struct b43_bus_dev *b43_bus_dev_ssb_init(struct ssb_device *sdev);
  --- a/drivers/net/wireless/b43/main.c
  +++ b/drivers/net/wireless/b43/main.c
@@ -11062,7 +13723,7 @@ index e76758c..49b2468 100644
   		u16 radio24[3];
   
   		for (tmp = 0; tmp < 3; tmp++) {
-@@ -81,7 +81,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+@@ -81,7 +83,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
   			radio24[tmp] = b43_read16(dev, B43_MMIO_RADIO24_DATA);
   		}
   
@@ -11071,7 +13732,7 @@ index e76758c..49b2468 100644
   			else
   				tmp = 0x5205017F;
   		} else {
-@@ -96,7 +96,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+@@ -96,7 +98,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
   				<< 16;
  --- a/drivers/net/wireless/b43/phy_common.c
  +++ b/drivers/net/wireless/b43/phy_common.c
@@ -11080,7 +13741,7 @@ index e76758c..49b2468 100644
   {
   	assert_mac_suspended(dev);
   	dev->phy.ops->phy_write(dev, reg, value);
-@@ -197,7 +197,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+@@ -197,7 +199,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
   
  --- a/drivers/net/wireless/b43/phy_n.c
  +++ b/drivers/net/wireless/b43/phy_n.c
@@ -11089,7 +13750,7 @@ index e76758c..49b2468 100644
   static u16 b43_nphy_op_read(struct b43_wldev *dev, u16 reg)
   {
   	check_phyreg(dev, reg);
-@@ -214,7 +214,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+@@ -214,7 +216,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
   	b43_write16(dev, B43_MMIO_PHY_DATA, value);
   }
   
@@ -11098,7 +13759,7 @@ index e76758c..49b2468 100644
   				 u16 set)
   {
   	check_phyreg(dev, reg);
-@@ -223,16 +223,16 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+@@ -223,16 +225,16 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
   	b43_maskset16(dev, B43_MMIO_PHY_DATA, mask, set);
   }