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, ¶ms->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(®, MAC_BSSID_DW1_BSS_ID_MASK, 3); ++- rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_BCN_NUM, 7); +++ rt2x00_set_field32(®, 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, ®); ++- rt2x00_set_field32(®, BCN_OFFSET0_BCN0, ++- rt2800_get_beacon_offset(rt2x00dev, 0)); ++- rt2x00_set_field32(®, BCN_OFFSET0_BCN1, ++- rt2800_get_beacon_offset(rt2x00dev, 1)); ++- rt2x00_set_field32(®, BCN_OFFSET0_BCN2, ++- rt2800_get_beacon_offset(rt2x00dev, 2)); ++- rt2x00_set_field32(®, BCN_OFFSET0_BCN3, ++- rt2800_get_beacon_offset(rt2x00dev, 3)); ++- rt2800_register_write(rt2x00dev, BCN_OFFSET0, reg); ++- ++- rt2800_register_read(rt2x00dev, BCN_OFFSET1, ®); ++- rt2x00_set_field32(®, BCN_OFFSET1_BCN4, ++- rt2800_get_beacon_offset(rt2x00dev, 4)); ++- rt2x00_set_field32(®, BCN_OFFSET1_BCN5, ++- rt2800_get_beacon_offset(rt2x00dev, 5)); ++- rt2x00_set_field32(®, BCN_OFFSET1_BCN6, ++- rt2800_get_beacon_offset(rt2x00dev, 6)); ++- rt2x00_set_field32(®, 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, ¶ms->beacon); +++ err = ieee80211_assign_beacon(sdata, ¶ms->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, ¶ms->beacon_csa); +++ err = ieee80211_assign_beacon(sdata, ¶ms->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(¶ms->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, ®); + rt2x00_set_field32(®, 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(®, 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, ®); @@ -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, ®); + rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE); @@ -9328,7 +11924,7 @@ index 0000000..95423d1 + rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2); + else + rt2x00_set_field32(®, 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); }