X-Git-Url: https://git.archive.openwrt.org/?p=openwrt.git;a=blobdiff_plain;f=package%2Fkernel%2Fmac80211%2Fpatches%2F300-pending_work.patch;h=56a3d848776bfc38e2d34ec4d2d1a5d703e35cf8;hp=4b0337276d0bf55ec815877f20c37898512bfedd;hb=d149f3a8f857e61c08e50ffa76073ee17cb6e7e9;hpb=0fe930daac0d137ee20eb9da1d8f1f2eb747833a diff --git a/package/kernel/mac80211/patches/300-pending_work.patch b/package/kernel/mac80211/patches/300-pending_work.patch index 4b0337276d..56a3d84877 100644 --- a/package/kernel/mac80211/patches/300-pending_work.patch +++ b/package/kernel/mac80211/patches/300-pending_work.patch @@ -1,4753 +1,2922 @@ ---- a/drivers/net/wireless/ath/ath10k/mac.c -+++ b/drivers/net/wireless/ath/ath10k/mac.c -@@ -1351,12 +1351,12 @@ static int ath10k_update_channel_list(st - ch->allow_vht = true; - - ch->allow_ibss = -- !(channel->flags & IEEE80211_CHAN_NO_IBSS); -+ !(channel->flags & IEEE80211_CHAN_NO_IR); - - ch->ht40plus = - !(channel->flags & IEEE80211_CHAN_NO_HT40PLUS); - -- passive = channel->flags & IEEE80211_CHAN_PASSIVE_SCAN; -+ passive = channel->flags & IEEE80211_CHAN_NO_IR; - ch->passive = passive; - - ch->freq = channel->center_freq; ---- a/drivers/net/wireless/ath/ath9k/Kconfig -+++ b/drivers/net/wireless/ath/ath9k/Kconfig -@@ -90,7 +90,7 @@ config ATH9K_DFS_CERTIFIED - - config ATH9K_TX99 - bool "Atheros ath9k TX99 testing support" -- depends on CFG80211_CERTIFICATION_ONUS -+ depends on ATH9K_DEBUGFS && CFG80211_CERTIFICATION_ONUS - default n - ---help--- - Say N. This should only be enabled on systems undergoing -@@ -108,6 +108,14 @@ config ATH9K_TX99 - be evaluated to meet the RF exposure limits set forth in the - governmental SAR regulations. - -+config ATH9K_WOW -+ bool "Wake on Wireless LAN support (EXPERIMENTAL)" -+ depends on ATH9K && PM -+ default n -+ ---help--- -+ This option enables Wake on Wireless LAN support for certain cards. -+ Currently, AR9462 is supported. -+ - config ATH9K_LEGACY_RATE_CONTROL - bool "Atheros ath9k rate control" - depends on ATH9K ---- a/drivers/net/wireless/ath/ath9k/Makefile -+++ b/drivers/net/wireless/ath/ath9k/Makefile -@@ -13,9 +13,9 @@ ath9k-$(CPTCFG_ATH9K_PCI) += pci.o - ath9k-$(CPTCFG_ATH9K_AHB) += ahb.o - ath9k-$(CPTCFG_ATH9K_DEBUGFS) += debug.o - ath9k-$(CPTCFG_ATH9K_DFS_DEBUGFS) += dfs_debug.o --ath9k-$(CPTCFG_ATH9K_DFS_CERTIFIED) += \ -- dfs.o --ath9k-$(CONFIG_PM_SLEEP) += wow.o -+ath9k-$(CPTCFG_ATH9K_DFS_CERTIFIED) += dfs.o -+ath9k-$(CPTCFG_ATH9K_TX99) += tx99.o -+ath9k-$(CPTCFG_ATH9K_WOW) += wow.o - - obj-$(CPTCFG_ATH9K) += ath9k.o - -@@ -41,6 +41,8 @@ ath9k_hw-y:= \ - ar9003_eeprom.o \ - ar9003_paprd.o - -+ath9k_hw-$(CPTCFG_ATH9K_WOW) += ar9003_wow.o -+ - ath9k_hw-$(CPTCFG_ATH9K_BTCOEX_SUPPORT) += btcoex.o \ - ar9003_mci.o - obj-$(CPTCFG_ATH9K_HW) += ath9k_hw.o ---- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c -+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c -@@ -581,6 +581,13 @@ static void ar9003_tx_gain_table_mode6(s - ar9580_1p0_type6_tx_gain_table); +commit edcdf0989410a05a6a4b8438df4010447eaa7d9a +Author: Felix Fietkau +Date: Sun Jun 22 13:36:20 2014 +0200 + + Revert "cfg80211: Use 5MHz bandwidth by default when checking usable channels" + + It enables channels that are not supposed to be enabled according to the + regulatory rules. + + This reverts commit 8eca1fb692cc9557f386eddce75c300a3855d11a. + +commit 6e7341074823d2a45b81f2742cbf75f1da790031 +Author: Rafał Miłecki +Date: Sat May 31 19:40:45 2014 +0200 + + b43: disable 5 GHz on G-PHY + + This fixes regression introduced by adding some G-PHY devices to the + list of dual band devices. There is simply no support for 5 GHz on + G-PHY devices in b43. It results in: + WARNING: CPU: 0 PID: 79 at drivers/net/wireless/b43/phy_g.c:75 b43_gphy_channel_switch+0x125/0x130 [b43]() + b43-phy1 ERROR: PHY init: Channel switch to default failed + + Regression was introduced by the following commit: + + commit 773cfc508f4d64c14547ff8751b5cbd473124364 + Author: Rafał Miłecki + Date: Mon May 19 23:18:55 2014 +0200 + + b43: add more devices to the bands database + + Signed-off-by: Rafał Miłecki + Signed-off-by: John W. Linville + +commit 1186edbef91f15722e5bdf56326ce0abc2935ce7 +Author: Stanislaw Gruszka +Date: Tue Jun 10 12:51:06 2014 +0200 + + rt2x00: disable TKIP on USB + + On USB we can not get atomically TKIP key. We have to disable support + for TKIP acceleration on USB hardware to avoid bug as showed bellow. + + [ 860.827243] BUG: scheduling while atomic: hostapd/3397/0x00000002 + + [ 860.827280] Call Trace: + [ 860.827282] [] dump_stack+0x4d/0x66 + [ 860.827284] [] __schedule_bug+0x47/0x55 + [ 860.827285] [] __schedule+0x733/0x7b0 + [ 860.827287] [] schedule+0x29/0x70 + [ 860.827289] [] schedule_timeout+0x15a/0x2b0 + [ 860.827291] [] ? ftrace_raw_event_tick_stop+0xc0/0xc0 + [ 860.827294] [] ? __module_text_address+0x12/0x70 + [ 860.827296] [] wait_for_completion_timeout+0xb3/0x140 + [ 860.827298] [] ? wake_up_state+0x20/0x20 + [ 860.827301] [] usb_start_wait_urb+0x7d/0x150 + [ 860.827303] [] usb_control_msg+0xc5/0x110 + [ 860.827305] [] rt2x00usb_vendor_request+0xc6/0x160 [rt2x00usb] + [ 860.827307] [] rt2x00usb_vendor_req_buff_lock+0x75/0x150 [rt2x00usb] + [ 860.827309] [] rt2x00usb_vendor_request_buff+0xa3/0xe0 [rt2x00usb] + [ 860.827311] [] rt2x00usb_register_multiread+0x33/0x40 [rt2800usb] + [ 860.827314] [] rt2800_get_tkip_seq+0x39/0x50 [rt2800lib] + [ 860.827321] [] ieee80211_get_key+0x218/0x2a0 [mac80211] + [ 860.827322] [] ? __nlmsg_put+0x6c/0x80 + [ 860.827329] [] nl80211_get_key+0x22e/0x360 [cfg80211] + + Cc: stable@vger.kernel.org + Reported-and-tested-by: Peter Wu + Reported-and-tested-by: Pontus Fuchs + Signed-off-by: Stanislaw Gruszka + Signed-off-by: John W. Linville + +commit 5f313a15da92dda80ac4c9a137bc42d7d0b49adf +Author: Rafał Miłecki +Date: Thu Jun 12 09:28:38 2014 +0200 + + b43: fix frequency reported on G-PHY with /new/ firmware + +commit d3a58df87a2e4c2301ac843604202d290a48440b +Author: Avraham Stern +Date: Thu May 22 12:17:47 2014 +0300 + + mac80211: set new interfaces as idle upon init + + 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. + + Signed-off-by: Avraham Stern + Signed-off-by: Emmanuel Grumbach + Signed-off-by: Johannes Berg + +commit 923eaf367206e01f22c97aee22300e332d071916 +Author: Arik Nemtsov +Date: Mon May 26 14:40:51 2014 +0300 + + mac80211: don't check netdev state for debugfs read/write + + Doing so will lead to an oops for a p2p-dev interface, since it has + no netdev. + + Cc: stable@vger.kernel.org + Signed-off-by: Arik Nemtsov + Signed-off-by: Emmanuel Grumbach + Signed-off-by: Johannes Berg + +commit a9fb54169b197f31aff24c8d6270dd1e56cde395 +Author: 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 + Signed-off-by: Chaitanya T K + Acked-by: John W. Linville + [remove unneeded parentheses, fix rounding by using %.0f] + Signed-off-by: Johannes Berg + +commit c7d37a66e345df2fdf1aa7b2c9a6d3d53846ca5b +Author: Krzysztof Hałasa +Date: Mon May 26 14:14:46 2014 +0200 + + mac80211: fix IBSS join by initializing last_scan_completed + + 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 + [edit commit message slightly] + Cc: stable@vger.kernel.org + Signed-off-by: Johannes Berg + +commit 34171dc0d623be2c1032416bf7d3819f388ed70d +Author: Emmanuel Grumbach +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: + [] dump_stack+0x4d/0x66 + [] warn_slowpath_common+0x7d/0xa0 + [] warn_slowpath_fmt+0x4c/0x50 + [] cfg80211_chandef_dfs_required+0xbc/0x130 [cfg80211] + [] ieee80211_vif_use_channel+0x94/0x500 [mac80211] + [] ieee80211_add_virtual_monitor+0x1ab/0x5c0 [mac80211] + [] ieee80211_do_open+0xe75/0x1580 [mac80211] + [] ieee80211_open+0x69/0x70 [mac80211] + [snip] + + Fixes: 00ec75fc5a64 ("cfg80211: pass the actual iftype when calling cfg80211_chandef_dfs_required()") + Signed-off-by: Emmanuel Grumbach + Acked-by: Luciano Coelho + Signed-off-by: Johannes Berg + +commit d93cc72b37b4e2c314e1c499e80e8801907c2fea +Author: Michal Kazior +Date: Thu Jun 5 14:21:37 2014 +0200 + + mac80211: use csa counter offsets instead of csa_active + + 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. + + 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 + Signed-off-by: Johannes Berg + +commit d2746694fcdef24e0a7a1947d8c70082cde81a26 +Author: Michal Kazior +Date: Thu Jun 5 14:21:36 2014 +0200 + + mac80211: move csa counters from sdata to beacon/presp + + 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. + + While at it relax WARN_ON into WARN_ON_ONCE to + prevent spamming logs and racing. + + Signed-off-by: Michal Kazior + Signed-off-by: Johannes Berg + +commit 5dcb54f3a1a8cd7e0331e773487574f9743615db +Author: Janusz Dziedzic +Date: Thu Jun 5 08:12:57 2014 +0200 + + mac80211: allow tx via monitor iface when DFS + + Allow send frames using monitor interface + when DFS chandef and we pass CAC (beaconing + allowed). + + 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 + Signed-off-by: Johannes Berg + +commit 6f09a1beb0d2007572248c986780562219bd206f +Author: Johannes Berg +Date: Wed Jun 4 17:31:56 2014 +0200 + + cfg80211: make ethtool the driver's responsibility + + 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. + + To cleanly implement this in mac80211, introduce a new file and + move some code to appropriate places. + + Signed-off-by: Johannes Berg + +commit 6b0c6f133de8f90caeb1c4a902e6140567c5bf96 +Author: Johannes Berg +Date: Wed Jun 4 17:06:23 2014 +0200 + + mac80211: remove weak WEP IV accounting + + Since WEP is practically dead, there seems very little + point in keeping WEP weak IV accounting. + + Signed-off-by: Johannes Berg + +commit aecdc89fb4664c76baa4bbd46008f220532309ff +Author: Luciano Coelho +Date: Fri May 23 11:04:50 2014 +0300 + + ath9k/ath10k: remove unnecessary channel_switch_beacon callbacks + + 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. + + Cc: Michal Kazior + Signed-off-by: Luciano Coelho + Signed-off-by: Kalle Valo + +commit 60ccc107c9b9fb732fdee1f76bb2dad44f0e1798 +Author: Rajkumar Manoharan +Date: Tue May 27 16:58:02 2014 +0530 + + ath9k: Fix deadlock while updating p2p beacon timer + + pm_lock is taken twice while syncing HW TSF of p2p vif. + Fix this by taking the lock at caller side. + + Cc: Felix Fietkau + Signed-off-by: Rajkumar Manoharan + Signed-off-by: John W. Linville + +commit f3831a4e3903dbc1a57d5df56deb6a143fd001bc +Author: Stanislaw Gruszka +Date: Thu Jun 5 13:52:27 2014 +0200 + + rt2x00: do not initialize BCN_OFFSET registers + + We setup BCN_OFFSET{0,1} registers dynamically, don't have to + initialize them. + + Signed-off-by: Stanislaw Gruszka + +commit e5c58ca7a48d4c82f282749a978052c47fd95998 +Author: Stanislaw Gruszka +Date: Thu Jun 5 13:52:26 2014 +0200 + + rt2x00: change order when stop beaconing + + 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: Stanislaw Gruszka + +commit 382c1b9e03f52d0cd741ef1d942cad0f649f0744 +Author: Stanislaw Gruszka +Date: Thu Jun 5 13:52:25 2014 +0200 + + rt2x00: change default MAC_BSSID_DW1_BSS_BCN_NUM + + 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. + + Signed-off-by: Stanislaw Gruszka + +commit 3b400571dd033e46fa7e76c5bb92a3ce8198afa9 +Author: Stanislaw Gruszka +Date: Thu Jun 5 13:52:24 2014 +0200 + + rt2x00: change beaconing setup on RT2800 + + 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. + + 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. + + Reported-by: Matthias Fend + Signed-off-by: Stanislaw Gruszka + +commit 916e591b2cc41f7e572992175ca56d866d7bc958 +Author: Stanislaw Gruszka +Date: Thu Jun 5 13:52:23 2014 +0200 + + rt2x00: change beaconing locking + + This patch is needed for further changes to keep global variables + consistent when changing beaconing on diffrent vif's. + + Signed-off-by: Stanislaw Gruszka + +commit 930b0dffd1731f3f418f9132faea720a23b7af61 +Author: Johannes Berg +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 + Signed-off-by: Johannes Berg + +commit 6df35206bc6c1c6aad1d8077df5786b4a7f77873 +Author: Felix Fietkau +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 + +commit 7b7843a36fbcc568834404c7430ff895d8502131 +Author: Felix Fietkau +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 + Signed-off-by: Felix Fietkau + +commit 96892d6aa0a153423070addf3070bc79578b3897 +Author: Felix Fietkau +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 + +--- 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; } -+static void ar9003_tx_gain_table_mode7(struct ath_hw *ah) -+{ -+ if (AR_SREV_9340(ah)) -+ INIT_INI_ARRAY(&ah->iniModesTxGain, -+ ar9340_cus227_tx_gain_table_1p0); -+} -+ - typedef void (*ath_txgain_tab)(struct ath_hw *ah); - - static void ar9003_tx_gain_table_apply(struct ath_hw *ah) -@@ -593,6 +600,7 @@ static void ar9003_tx_gain_table_apply(s - ar9003_tx_gain_table_mode4, - ar9003_tx_gain_table_mode5, - ar9003_tx_gain_table_mode6, -+ ar9003_tx_gain_table_mode7, - }; - int idx = ar9003_hw_get_tx_gain_idx(ah); - -@@ -750,6 +758,9 @@ static void ar9003_hw_init_mode_gain_reg - static void ar9003_hw_configpcipowersave(struct ath_hw *ah, - bool power_off) +-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) { -+ unsigned int i; -+ struct ar5416IniArray *array; -+ + 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); + } + + 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; + + 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 + + clear_sta_flag(sta, WLAN_STA_PS_STA); + clear_sta_flag(sta, WLAN_STA_PS_DRIVER); ++ clear_sta_flag(sta, WLAN_STA_PS_DELIVER); + + 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); + +- cancel_work_sync(&sta->drv_unblock_wk); ++ cancel_work_sync(&sta->drv_deliver_wk); + /* - * Increase L1 Entry Latency. Some WB222 boards don't have - * this change in eeprom/OTP. -@@ -775,18 +786,13 @@ static void ar9003_hw_configpcipowersave - * Configire PCIE after Ini init. SERDES values now come from ini file - * This enables PCIe low power mode. - */ -- if (ah->config.pcieSerDesWrite) { -- unsigned int i; -- struct ar5416IniArray *array; -- -- array = power_off ? &ah->iniPcieSerdes : -- &ah->iniPcieSerdesLowPower; -- -- for (i = 0; i < array->ia_rows; i++) { -- REG_WRITE(ah, -- INI_RA(array, i, 0), -- INI_RA(array, i, 1)); -- } -+ array = power_off ? &ah->iniPcieSerdes : -+ &ah->iniPcieSerdesLowPower; -+ -+ for (i = 0; i < array->ia_rows; i++) { -+ REG_WRITE(ah, -+ INI_RA(array, i, 0), -+ INI_RA(array, i, 1)); + * 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; + + if (sta->rate_ctrl) +@@ -238,6 +241,10 @@ void sta_info_free(struct ieee80211_loca + kfree(sta->tx_lat); } + ++ rates = rcu_dereference_protected(sta->sta.rates, true); ++ if (rates) ++ kfree(rates); ++ + sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr); + + 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); } ---- a/drivers/net/wireless/ath/ath9k/ar9340_initvals.h -+++ b/drivers/net/wireless/ath/ath9k/ar9340_initvals.h -@@ -1447,4 +1447,106 @@ static const u32 ar9340_1p0_soc_preamble - {0x00007038, 0x000004c2}, - }; +-static void sta_unblock(struct work_struct *wk) ++static void sta_deliver_ps_frames(struct work_struct *wk) + { + struct sta_info *sta; -+static const u32 ar9340_cus227_tx_gain_table_1p0[][5] = { -+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ -+ {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, -+ {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, -+ {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, -+ {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, -+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, -+ {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -+ {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, -+ {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, -+ {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, -+ {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, -+ {0x0000a514, 0x1c000223, 0x1c000223, 0x11000400, 0x11000400}, -+ {0x0000a518, 0x21002220, 0x21002220, 0x15000402, 0x15000402}, -+ {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404}, -+ {0x0000a520, 0x2c022220, 0x2c022220, 0x1b000603, 0x1b000603}, -+ {0x0000a524, 0x30022222, 0x30022222, 0x1f000a02, 0x1f000a02}, -+ {0x0000a528, 0x35022225, 0x35022225, 0x23000a04, 0x23000a04}, -+ {0x0000a52c, 0x3b02222a, 0x3b02222a, 0x26000a20, 0x26000a20}, -+ {0x0000a530, 0x3f02222c, 0x3f02222c, 0x2a000e20, 0x2a000e20}, -+ {0x0000a534, 0x4202242a, 0x4202242a, 0x2e000e22, 0x2e000e22}, -+ {0x0000a538, 0x4702244a, 0x4702244a, 0x31000e24, 0x31000e24}, -+ {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x34001640, 0x34001640}, -+ {0x0000a540, 0x4e02246c, 0x4e02246c, 0x38001660, 0x38001660}, -+ {0x0000a544, 0x5302266c, 0x5302266c, 0x3b001861, 0x3b001861}, -+ {0x0000a548, 0x5702286c, 0x5702286c, 0x3e001a81, 0x3e001a81}, -+ {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x42001a83, 0x42001a83}, -+ {0x0000a550, 0x61024a6c, 0x61024a6c, 0x44001c84, 0x44001c84}, -+ {0x0000a554, 0x66026a6c, 0x66026a6c, 0x48001ce3, 0x48001ce3}, -+ {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x4c001ce5, 0x4c001ce5}, -+ {0x0000a55c, 0x7002708c, 0x7002708c, 0x50001ce9, 0x50001ce9}, -+ {0x0000a560, 0x7302b08a, 0x7302b08a, 0x54001ceb, 0x54001ceb}, -+ {0x0000a564, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, -+ {0x0000a568, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, -+ {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, -+ {0x0000a570, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, -+ {0x0000a574, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, -+ {0x0000a578, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, -+ {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, -+ {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, -+ {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, -+ {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, -+ {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, -+ {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, -+ {0x0000a594, 0x1c800223, 0x1c800223, 0x11800400, 0x11800400}, -+ {0x0000a598, 0x21820220, 0x21820220, 0x15800402, 0x15800402}, -+ {0x0000a59c, 0x27820223, 0x27820223, 0x19800404, 0x19800404}, -+ {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1b800603, 0x1b800603}, -+ {0x0000a5a4, 0x2f822222, 0x2f822222, 0x1f800a02, 0x1f800a02}, -+ {0x0000a5a8, 0x34822225, 0x34822225, 0x23800a04, 0x23800a04}, -+ {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x26800a20, 0x26800a20}, -+ {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2a800e20, 0x2a800e20}, -+ {0x0000a5b4, 0x4282242a, 0x4282242a, 0x2e800e22, 0x2e800e22}, -+ {0x0000a5b8, 0x4782244a, 0x4782244a, 0x31800e24, 0x31800e24}, -+ {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x34801640, 0x34801640}, -+ {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x38801660, 0x38801660}, -+ {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3b801861, 0x3b801861}, -+ {0x0000a5c8, 0x5782286c, 0x5782286c, 0x3e801a81, 0x3e801a81}, -+ {0x0000a5cc, 0x5c84286b, 0x5c84286b, 0x42801a83, 0x42801a83}, -+ {0x0000a5d0, 0x61842a6c, 0x61842a6c, 0x44801c84, 0x44801c84}, -+ {0x0000a5d4, 0x66862a6c, 0x66862a6c, 0x48801ce3, 0x48801ce3}, -+ {0x0000a5d8, 0x6b862e6c, 0x6b862e6c, 0x4c801ce5, 0x4c801ce5}, -+ {0x0000a5dc, 0x7086308c, 0x7086308c, 0x50801ce9, 0x50801ce9}, -+ {0x0000a5e0, 0x738a308a, 0x738a308a, 0x54801ceb, 0x54801ceb}, -+ {0x0000a5e4, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, -+ {0x0000a5e8, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, -+ {0x0000a5ec, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, -+ {0x0000a5f0, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, -+ {0x0000a5f4, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, -+ {0x0000a5f8, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, -+ {0x0000a5fc, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, -+ {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -+ {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -+ {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -+ {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -+ {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -+ {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, -+ {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501}, -+ {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501}, -+ {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03}, -+ {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, -+ {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04}, -+ {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005}, -+ {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, -+ {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, -+ {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, -+ {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, -+ {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, -+ {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, -+ {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, -+ {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, -+ {0x00016044, 0x056db2db, 0x056db2db, 0x03b6d2e4, 0x03b6d2e4}, -+ {0x00016048, 0x24925666, 0x24925666, 0x8e481266, 0x8e481266}, -+ {0x00016280, 0x01000015, 0x01000015, 0x01001015, 0x01001015}, -+ {0x00016288, 0x30318000, 0x30318000, 0x00318000, 0x00318000}, -+ {0x00016444, 0x056db2db, 0x056db2db, 0x03b6d2e4, 0x03b6d2e4}, -+ {0x00016448, 0x24925666, 0x24925666, 0x8e481266, 0x8e481266}, -+ {0x0000a3a4, 0x00000011, 0x00000011, 0x00000011, 0x00000011}, -+ {0x0000a3a8, 0x3c3c3c3c, 0x3c3c3c3c, 0x3c3c3c3c, 0x3c3c3c3c}, -+ {0x0000a3ac, 0x30303030, 0x30303030, 0x30303030, 0x30303030}, -+}; +- sta = container_of(wk, struct sta_info, drv_unblock_wk); ++ sta = container_of(wk, struct sta_info, drv_deliver_wk); + + if (sta->dead) + return; + +- 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); +- +- 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); +- +- 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 + + 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 + } + + ieee80211_add_pending_skbs(local, &pending); +- clear_sta_flag(sta, WLAN_STA_PS_DRIVER); +- clear_sta_flag(sta, WLAN_STA_PS_STA); + - #endif /* INITVALS_9340_H */ ---- a/drivers/net/wireless/ath/ath9k/ath9k.h -+++ b/drivers/net/wireless/ath/ath9k/ath9k.h -@@ -459,6 +459,7 @@ void ath_check_ani(struct ath_softc *sc) - int ath_update_survey_stats(struct ath_softc *sc); - void ath_update_survey_nf(struct ath_softc *sc, int channel); - void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type); -+void ath_ps_full_sleep(unsigned long data); - - /**********/ - /* BTCOEX */ -@@ -570,6 +571,34 @@ static inline void ath_fill_led_pin(stru ++ /* now we're no longer in the deliver code */ ++ clear_sta_flag(sta, WLAN_STA_PS_DELIVER); ++ ++ /* 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); + + atomic_dec(&ps->num_sta_ps); +@@ -1542,10 +1546,26 @@ void ieee80211_sta_block_awake(struct ie + + trace_api_sta_block_awake(sta->local, pubsta, block); + +- 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); ++ } } - #endif + EXPORT_SYMBOL(ieee80211_sta_block_awake); -+/************************/ -+/* Wake on Wireless LAN */ -+/************************/ +@@ -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; + } + -+#ifdef CONFIG_ATH9K_WOW -+void ath9k_init_wow(struct ieee80211_hw *hw); -+int ath9k_suspend(struct ieee80211_hw *hw, -+ struct cfg80211_wowlan *wowlan); -+int ath9k_resume(struct ieee80211_hw *hw); -+void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled); -+#else -+static inline void ath9k_init_wow(struct ieee80211_hw *hw) -+{ -+} -+static inline int ath9k_suspend(struct ieee80211_hw *hw, -+ struct cfg80211_wowlan *wowlan) ++void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) +{ -+ return 0; -+} -+static inline int ath9k_resume(struct ieee80211_hw *hw) -+{ -+ return 0; -+} -+static inline void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled) -+{ -+} -+#endif /* CONFIG_ATH9K_WOW */ ++ 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]); ++ } ++ } ++ ++ 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 ++ } + - /*******************************/ - /* Antenna diversity/combining */ - /*******************************/ -@@ -723,6 +752,7 @@ struct ath_softc { - struct work_struct hw_check_work; - struct work_struct hw_reset_work; - struct completion paprd_complete; -+ wait_queue_head_t tx_wait; - - unsigned int hw_busy_count; - unsigned long sc_flags; -@@ -759,6 +789,7 @@ struct ath_softc { - struct delayed_work tx_complete_work; - struct delayed_work hw_pll_work; - struct timer_list rx_poll_timer; -+ struct timer_list sleep_timer; - - #ifdef CPTCFG_ATH9K_BTCOEX_SUPPORT - struct ath_btcoex btcoex; -@@ -783,7 +814,7 @@ struct ath_softc { - bool tx99_state; - s16 tx99_power; - --#ifdef CONFIG_PM_SLEEP -+#ifdef CONFIG_ATH9K_WOW - atomic_t wow_got_bmiss_intr; - atomic_t wow_sleep_proc_intr; /* in the middle of WoW sleep ? */ - u32 wow_intr_before_sleep; -@@ -946,10 +977,25 @@ struct fft_sample_ht20_40 { - u8 data[SPECTRAL_HT20_40_NUM_BINS]; - } __packed; - --int ath9k_tx99_init(struct ath_softc *sc); --void ath9k_tx99_deinit(struct ath_softc *sc); -+/********/ -+/* TX99 */ -+/********/ ++ 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); + -+#ifdef CONFIG_ATH9K_TX99 -+void ath9k_tx99_init_debug(struct ath_softc *sc); - int ath9k_tx99_send(struct ath_softc *sc, struct sk_buff *skb, - struct ath_tx_control *txctl); -+#else -+static inline void ath9k_tx99_init_debug(struct ath_softc *sc) -+{ ++ if (thr != 0) { ++ sinfo->filled |= STATION_INFO_EXPECTED_THROUGHPUT; ++ sinfo->expected_throughput = thr; ++ } +} -+static inline int ath9k_tx99_send(struct ath_softc *sc, -+ struct sk_buff *skb, -+ struct ath_tx_control *txctl) +--- 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 + ++static void ieee80211_lost_packet(struct sta_info *sta, struct sk_buff *skb) +{ -+ return 0; ++ 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; +} -+#endif /* CONFIG_ATH9K_TX99 */ - - void ath9k_tasklet(unsigned long data); - int ath_cabq_update(struct ath_softc *); -@@ -966,6 +1012,9 @@ extern bool is_ath9k_unloaded; - - u8 ath9k_parse_mpdudensity(u8 mpdudensity); - irqreturn_t ath_isr(int irq, void *dev); -+int ath_reset(struct ath_softc *sc); -+void ath_cancel_work(struct ath_softc *sc); -+void ath_restart_work(struct ath_softc *sc); - int ath9k_init_device(u16 devid, struct ath_softc *sc, - const struct ath_bus_ops *bus_ops); - void ath9k_deinit_device(struct ath_softc *sc); ---- a/drivers/net/wireless/ath/ath9k/debug.c -+++ b/drivers/net/wireless/ath/ath9k/debug.c -@@ -1782,111 +1782,6 @@ void ath9k_deinit_debug(struct ath_softc - } - } - --static ssize_t read_file_tx99(struct file *file, char __user *user_buf, -- size_t count, loff_t *ppos) --{ -- struct ath_softc *sc = file->private_data; -- char buf[3]; -- unsigned int len; -- -- len = sprintf(buf, "%d\n", sc->tx99_state); -- return simple_read_from_buffer(user_buf, count, ppos, buf, len); --} -- --static ssize_t write_file_tx99(struct file *file, const char __user *user_buf, -- size_t count, loff_t *ppos) --{ -- struct ath_softc *sc = file->private_data; -- struct ath_common *common = ath9k_hw_common(sc->sc_ah); -- char buf[32]; -- bool start; -- ssize_t len; -- int r; -- -- if (sc->nvifs > 1) -- return -EOPNOTSUPP; -- -- len = min(count, sizeof(buf) - 1); -- if (copy_from_user(buf, user_buf, len)) -- return -EFAULT; -- -- if (strtobool(buf, &start)) -- return -EINVAL; -- -- if (start == sc->tx99_state) { -- if (!start) -- return count; -- ath_dbg(common, XMIT, "Resetting TX99\n"); -- ath9k_tx99_deinit(sc); -- } -- -- if (!start) { -- ath9k_tx99_deinit(sc); -- return count; -- } -- -- r = ath9k_tx99_init(sc); -- if (r) -- return r; -- -- return count; --} -- --static const struct file_operations fops_tx99 = { -- .read = read_file_tx99, -- .write = write_file_tx99, -- .open = simple_open, -- .owner = THIS_MODULE, -- .llseek = default_llseek, --}; -- --static ssize_t read_file_tx99_power(struct file *file, -- char __user *user_buf, -- size_t count, loff_t *ppos) --{ -- struct ath_softc *sc = file->private_data; -- char buf[32]; -- unsigned int len; -- -- len = sprintf(buf, "%d (%d dBm)\n", -- sc->tx99_power, -- sc->tx99_power / 2); -- -- return simple_read_from_buffer(user_buf, count, ppos, buf, len); --} -- --static ssize_t write_file_tx99_power(struct file *file, -- const char __user *user_buf, -- size_t count, loff_t *ppos) --{ -- struct ath_softc *sc = file->private_data; -- int r; -- u8 tx_power; -- -- r = kstrtou8_from_user(user_buf, count, 0, &tx_power); -- if (r) -- return r; -- -- if (tx_power > MAX_RATE_POWER) -- return -EINVAL; -- -- sc->tx99_power = tx_power; -- -- ath9k_ps_wakeup(sc); -- ath9k_hw_tx99_set_txpower(sc->sc_ah, sc->tx99_power); -- ath9k_ps_restore(sc); -- -- return count; --} -- --static const struct file_operations fops_tx99_power = { -- .read = read_file_tx99_power, -- .write = write_file_tx99_power, -- .open = simple_open, -- .owner = THIS_MODULE, -- .llseek = default_llseek, --}; -- - int ath9k_init_debug(struct ath_hw *ah) ++ + void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) { - struct ath_common *common = ath9k_hw_common(ah); -@@ -1903,6 +1798,7 @@ int ath9k_init_debug(struct ath_hw *ah) - #endif - - ath9k_dfs_init_debug(sc); -+ ath9k_tx99_init_debug(sc); - - debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc, - &fops_dma); -@@ -1978,15 +1874,6 @@ int ath9k_init_debug(struct ath_hw *ah) - debugfs_create_file("btcoex", S_IRUSR, sc->debug.debugfs_phy, sc, - &fops_btcoex); - #endif -- if (config_enabled(CPTCFG_ATH9K_TX99) && -- AR_SREV_9300_20_OR_LATER(ah)) { -- debugfs_create_file("tx99", S_IRUSR | S_IWUSR, -- sc->debug.debugfs_phy, sc, -- &fops_tx99); -- debugfs_create_file("tx99_power", S_IRUSR | S_IWUSR, -- sc->debug.debugfs_phy, sc, -- &fops_tx99_power); -- } + 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); + } + } - return 0; - } ---- a/drivers/net/wireless/ath/ath9k/hw.c -+++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - #include - - #include "hw.h" -@@ -454,7 +455,6 @@ static void ath9k_hw_init_config(struct +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -1107,6 +1107,8 @@ static void sta_ps_end(struct sta_info * + return; } - ah->config.rx_intr_mitigation = true; -- ah->config.pcieSerDesWrite = true; ++ set_sta_flag(sta, WLAN_STA_PS_DELIVER); ++ clear_sta_flag(sta, WLAN_STA_PS_STA); + ieee80211_sta_ps_deliver_wakeup(sta); + } - /* - * We need this for PCI devices only (Cardbus, PCI, miniPCI) -@@ -1502,8 +1502,9 @@ static bool ath9k_hw_channel_change(stru - int r; - - if (pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH) { -- band_switch = IS_CHAN_5GHZ(ah->curchan) != IS_CHAN_5GHZ(chan); -- mode_diff = (chan->channelFlags != ah->curchan->channelFlags); -+ u32 flags_diff = chan->channelFlags ^ ah->curchan->channelFlags; -+ band_switch = !!(flags_diff & CHANNEL_5GHZ); -+ mode_diff = !!(flags_diff & ~CHANNEL_HT); - } +--- 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, + }; - for (qnum = 0; qnum < AR_NUM_QCU; qnum++) { -@@ -1815,7 +1816,7 @@ static int ath9k_hw_do_fastcc(struct ath - * If cross-band fcc is not supoprted, bail out if channelFlags differ. - */ - if (!(pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH) && -- chan->channelFlags != ah->curchan->channelFlags) -+ ((chan->channelFlags ^ ah->curchan->channelFlags) & ~CHANNEL_HT)) - goto fail; - - if (!ath9k_hw_check_alive(ah)) -@@ -1856,10 +1857,12 @@ int ath9k_hw_reset(struct ath_hw *ah, st - struct ath9k_hw_cal_data *caldata, bool fastcc) + #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; + + 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); + +@@ -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 ath_common *common = ath9k_hw_common(ah); -+ struct timespec ts; - u32 saveLedState; - u32 saveDefAntenna; - u32 macStaId1; - u64 tsf = 0; -+ s64 usec = 0; - int r; - bool start_mci_reset = false; - bool save_fullsleep = ah->chip_fullsleep; -@@ -1902,10 +1905,10 @@ int ath9k_hw_reset(struct ath_hw *ah, st - - macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B; - -- /* For chips on which RTC reset is done, save TSF before it gets cleared */ -- if (AR_SREV_9100(ah) || -- (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))) -- tsf = ath9k_hw_gettsf64(ah); -+ /* Save TSF before chip reset, a cold reset clears it */ -+ tsf = ath9k_hw_gettsf64(ah); -+ getrawmonotonic(&ts); -+ usec = ts.tv_sec * 1000 + ts.tv_nsec / 1000; - - saveLedState = REG_READ(ah, AR_CFG_LED) & - (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL | -@@ -1938,8 +1941,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st + 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; + +@@ -1721,9 +1723,9 @@ netdev_tx_t ieee80211_monitor_start_xmit } - /* Restore TSF */ -- if (tsf) -- ath9k_hw_settsf64(ah, tsf); -+ getrawmonotonic(&ts); -+ usec = ts.tv_sec * 1000 + ts.tv_nsec / 1000 - usec; -+ ath9k_hw_settsf64(ah, tsf + usec); - - if (AR_SREV_9280_20_OR_LATER(ah)) - REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); ---- a/drivers/net/wireless/ath/ath9k/hw.h -+++ b/drivers/net/wireless/ath/ath9k/hw.h -@@ -283,7 +283,6 @@ struct ath9k_ops_config { - int additional_swba_backoff; - int ack_6mb; - u32 cwm_ignore_extcca; -- bool pcieSerDesWrite; - u8 pcie_clock_req; - u32 pcie_waen; - u8 analog_shiftreg; -@@ -920,7 +919,7 @@ struct ath_hw { - /* Enterprise mode cap */ - u32 ent_mode; - --#ifdef CONFIG_PM_SLEEP -+#ifdef CONFIG_ATH9K_WOW - u32 wow_event_mask; - #endif - bool is_clk_25mhz; -@@ -1126,7 +1125,7 @@ ath9k_hw_get_btcoex_scheme(struct ath_hw - #endif /* CPTCFG_ATH9K_BTCOEX_SUPPORT */ - - --#ifdef CONFIG_PM_SLEEP -+#ifdef CONFIG_ATH9K_WOW - const char *ath9k_hw_wow_event_to_string(u32 wow_event); - void ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern, - u8 *user_mask, int pattern_count, ---- a/drivers/net/wireless/ath/ath9k/init.c -+++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -683,6 +683,7 @@ static int ath9k_init_softc(u16 devid, s - common = ath9k_hw_common(ah); - sc->dfs_detector = dfs_pattern_detector_init(common, NL80211_DFS_UNSET); - sc->tx99_power = MAX_RATE_POWER + 1; -+ init_waitqueue_head(&sc->tx_wait); - - if (!pdata) { - ah->ah_flags |= AH_USE_EEPROM; -@@ -730,6 +731,7 @@ static int ath9k_init_softc(u16 devid, s - tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet, - (unsigned long)sc); - -+ setup_timer(&sc->sleep_timer, ath_ps_full_sleep, (unsigned long)sc); - INIT_WORK(&sc->hw_reset_work, ath_reset_work); - INIT_WORK(&sc->hw_check_work, ath_hw_check); - INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); -@@ -845,7 +847,8 @@ static const struct ieee80211_iface_limi - }; + 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; - static const struct ieee80211_iface_limit if_dfs_limits[] = { -- { .max = 1, .types = BIT(NL80211_IFTYPE_AP) }, -+ { .max = 1, .types = BIT(NL80211_IFTYPE_AP) | -+ BIT(NL80211_IFTYPE_ADHOC) }, - }; +@@ -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; - static const struct ieee80211_iface_combination if_comb[] = { -@@ -862,20 +865,11 @@ static const struct ieee80211_iface_comb - .max_interfaces = 1, - .num_different_channels = 1, - .beacon_int_infra_match = true, -- .radar_detect_widths = BIT(NL80211_CHAN_NO_HT) | -- BIT(NL80211_CHAN_HT20), -+ .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | -+ BIT(NL80211_CHAN_WIDTH_20), +- ieee80211_xmit(sdata, skb, chan->band); ++ ieee80211_xmit(sdata, skb, chandef->chan->band); + rcu_read_unlock(); + + 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; + + switch (sdata->vif.type) { + case NL80211_IFTYPE_AP: +@@ -2444,46 +2447,54 @@ static void ieee80211_set_csa(struct iee + return; } - }; --#ifdef CONFIG_PM --static const struct wiphy_wowlan_support ath9k_wowlan_support = { -- .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT, -- .n_patterns = MAX_NUM_USER_PATTERN, -- .pattern_min_len = 1, -- .pattern_max_len = MAX_PATTERN_SIZE, --}; --#endif ++ 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]; - - void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) - { - struct ath_hw *ah = sc->sc_ah; -@@ -925,16 +919,6 @@ void ath9k_set_hw_capab(struct ath_softc - hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_5_10_MHZ; - hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; - --#ifdef CONFIG_PM_SLEEP -- if ((ah->caps.hw_caps & ATH9K_HW_WOW_DEVICE_CAPABLE) && -- (sc->driver_data & ATH9K_PCI_WOW) && -- device_can_wakeup(sc->dev)) -- hw->wiphy->wowlan = &ath9k_wowlan_support; +- if (counter_offset_beacon) { +- if (WARN_ON(counter_offset_beacon >= beacon_data_len)) +- return; - -- atomic_set(&sc->wow_sleep_proc_intr, -1); -- atomic_set(&sc->wow_got_bmiss_intr, -1); --#endif +- beacon_data[counter_offset_beacon] = count; +- } - - hw->queues = 4; - hw->max_rates = 4; - hw->channel_change_time = 5000; -@@ -960,6 +944,7 @@ void ath9k_set_hw_capab(struct ath_softc - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = - &sc->sbands[IEEE80211_BAND_5GHZ]; - -+ ath9k_init_wow(hw); - ath9k_reload_chainmask_settings(sc); - - SET_IEEE80211_PERM_ADDR(hw, common->macaddr); -@@ -1058,6 +1043,7 @@ static void ath9k_deinit_softc(struct at - if (ATH_TXQ_SETUP(sc, i)) - ath_tx_cleanupq(sc, &sc->tx.txq[i]); - -+ del_timer_sync(&sc->sleep_timer); - ath9k_hw_deinit(sc->sc_ah); - if (sc->dfs_detector != NULL) - sc->dfs_detector->exit(sc->dfs_detector); ---- a/drivers/net/wireless/ath/ath9k/main.c -+++ b/drivers/net/wireless/ath/ath9k/main.c -@@ -82,6 +82,22 @@ static bool ath9k_setpower(struct ath_so - return ret; +- 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(); ++ ++ beacon_data[beacon->csa_counter_offsets[i]] = count; + } ++ ++ if (sdata->vif.type == NL80211_IFTYPE_AP && resp && ++ resp->csa_counter_offsets) ++ resp->data[resp->csa_counter_offsets[i]] = count; + } ++ rcu_read_unlock(); } -+void ath_ps_full_sleep(unsigned long data) -+{ -+ struct ath_softc *sc = (struct ath_softc *) data; -+ struct ath_common *common = ath9k_hw_common(sc->sc_ah); -+ bool reset; -+ -+ spin_lock(&common->cc_lock); -+ ath_hw_cycle_counters_update(common); -+ spin_unlock(&common->cc_lock); + 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; + -+ ath9k_hw_setrxabort(sc->sc_ah, 1); -+ ath9k_hw_stopdmarecv(sc->sc_ah, &reset); ++ rcu_read_lock(); + -+ ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); -+} ++ 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); + - void ath9k_ps_wakeup(struct ath_softc *sc) - { - struct ath_common *common = ath9k_hw_common(sc->sc_ah); -@@ -92,6 +108,7 @@ void ath9k_ps_wakeup(struct ath_softc *s - if (++sc->ps_usecount != 1) - goto unlock; - -+ del_timer_sync(&sc->sleep_timer); - power_mode = sc->sc_ah->power_mode; - ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); - -@@ -117,17 +134,17 @@ void ath9k_ps_restore(struct ath_softc * - struct ath_common *common = ath9k_hw_common(sc->sc_ah); - enum ath9k_power_mode mode; - unsigned long flags; -- bool reset; - - spin_lock_irqsave(&sc->sc_pm_lock, flags); - if (--sc->ps_usecount != 0) - goto unlock; - - if (sc->ps_idle) { -- ath9k_hw_setrxabort(sc->sc_ah, 1); -- ath9k_hw_stopdmarecv(sc->sc_ah, &reset); -- mode = ATH9K_PM_FULL_SLEEP; -- } else if (sc->ps_enabled && -+ mod_timer(&sc->sleep_timer, jiffies + HZ / 10); ++ if (!beacon) + goto unlock; -+ } -+ -+ if (sc->ps_enabled && - !(sc->ps_flags & (PS_WAIT_FOR_BEACON | - PS_WAIT_FOR_CAB | - PS_WAIT_FOR_PSPOLL_DATA | -@@ -163,13 +180,13 @@ static void __ath_cancel_work(struct ath - #endif - } --static void ath_cancel_work(struct ath_softc *sc) -+void ath_cancel_work(struct ath_softc *sc) - { - __ath_cancel_work(sc); - cancel_work_sync(&sc->hw_reset_work); +- 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); + +@@ -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; + } + +- 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; --static void ath_restart_work(struct ath_softc *sc) -+void ath_restart_work(struct ath_softc *sc) +- 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) { - ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); + 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 (sdata->vif.csa_active) { ++ if (beacon->csa_counter_offsets[0]) { + if (!is_template) + ieee80211_csa_update_counter(vif); + +- ieee80211_set_csa(sdata, presp); ++ ieee80211_set_csa(sdata, beacon); + } -@@ -487,6 +504,8 @@ void ath9k_tasklet(unsigned long data) - ath_tx_edma_tasklet(sc); - else - ath_tx_tasklet(sc); -+ -+ wake_up(&sc->tx_wait); - } +- 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; + +- 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); - ath9k_btcoex_handle_interrupt(sc, status); -@@ -579,7 +598,8 @@ irqreturn_t ath_isr(int irq, void *dev) +- ieee80211_set_csa(sdata, bcn); ++ ieee80211_set_csa(sdata, beacon); + } - goto chip_reset; - } --#ifdef CONFIG_PM_SLEEP -+ -+#ifdef CONFIG_ATH9K_WOW - if (status & ATH9K_INT_BMISS) { - if (atomic_read(&sc->wow_sleep_proc_intr) == 0) { - ath_dbg(common, ANY, "during WoW we got a BMISS\n"); -@@ -588,6 +608,8 @@ irqreturn_t ath_isr(int irq, void *dev) + 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; } + +- 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; } - #endif -+ -+ - if (status & ATH9K_INT_SWBA) - tasklet_schedule(&sc->bcon_tasklet); -@@ -627,7 +649,7 @@ chip_reset: - #undef SCHED_INTR - } + /* CSA offsets */ +- if (offs) { ++ if (offs && beacon) { + int i; --static int ath_reset(struct ath_softc *sc) -+int ath_reset(struct ath_softc *sc) - { - int r; + 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]; -@@ -1817,13 +1839,31 @@ static void ath9k_set_coverage_class(str - mutex_unlock(&sc->mutex); + 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)); } -+static bool ath9k_has_tx_pending(struct ath_softc *sc) ++static void rt2800_update_beacons_setup(struct rt2x00_dev *rt2x00dev) +{ -+ int i, npend; ++ struct data_queue *queue = rt2x00dev->bcn; ++ struct queue_entry *entry; ++ int i, bcn_num = 0; ++ u64 off, reg = 0; ++ u32 bssid_dw1; + -+ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { -+ if (!ATH_TXQ_SETUP(sc, i)) ++ /* ++ * 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++; ++ } + -+ if (!sc->tx.txq[i].axq_depth) -+ continue; ++ WARN_ON_ONCE(bcn_num != rt2x00dev->intf_beaconing); + -+ npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i]); -+ if (npend) -+ break; -+ } ++ rt2800_register_write(rt2x00dev, BCN_OFFSET0, (u32) reg); ++ rt2800_register_write(rt2x00dev, BCN_OFFSET1, (u32) (reg >> 32)); + -+ return !!npend; ++ /* ++ * 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); +} + - static void ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop) + void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) { - struct ath_softc *sc = hw->priv; - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); -- int timeout = 200; /* ms */ -- int i, j; -+ int timeout = HZ / 5; /* 200 ms */ - bool drain_txq; + 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); ++ ++ /* ++ * Change global beacons settings. ++ */ ++ rt2800_update_beacons_setup(rt2x00dev); + + /* + * 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); + + /* ++ * 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); + } + +@@ -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); - mutex_lock(&sc->mutex); -@@ -1841,25 +1881,9 @@ static void ath9k_flush(struct ieee80211 +--- 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; - } -- for (j = 0; j < timeout; j++) { -- bool npend = false; -- -- if (j) -- usleep_range(1000, 2000); -- -- for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { -- if (!ATH_TXQ_SETUP(sc, i)) -- continue; -- -- npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i]); -- -- if (npend) -- break; -- } -- -- if (!npend) -- break; -- } -+ if (wait_event_timeout(sc->tx_wait, !ath9k_has_tx_pending(sc), -+ timeout) > 0) -+ drop = false; +- 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); ++ } + } - if (drop) { - ath9k_ps_wakeup(sc); -@@ -2021,333 +2045,6 @@ static int ath9k_get_antenna(struct ieee - return 0; + 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); } --#ifdef CONFIG_PM_SLEEP -- --static void ath9k_wow_map_triggers(struct ath_softc *sc, -- struct cfg80211_wowlan *wowlan, -- u32 *wow_triggers) --{ -- if (wowlan->disconnect) -- *wow_triggers |= AH_WOW_LINK_CHANGE | -- AH_WOW_BEACON_MISS; -- if (wowlan->magic_pkt) -- *wow_triggers |= AH_WOW_MAGIC_PATTERN_EN; -- -- if (wowlan->n_patterns) -- *wow_triggers |= AH_WOW_USER_PATTERN_EN; -- -- sc->wow_enabled = *wow_triggers; -- --} -- --static void ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc) --{ -- struct ath_hw *ah = sc->sc_ah; -- struct ath_common *common = ath9k_hw_common(ah); -- int pattern_count = 0; -- int i, byte_cnt; -- u8 dis_deauth_pattern[MAX_PATTERN_SIZE]; -- u8 dis_deauth_mask[MAX_PATTERN_SIZE]; -- -- memset(dis_deauth_pattern, 0, MAX_PATTERN_SIZE); -- memset(dis_deauth_mask, 0, MAX_PATTERN_SIZE); -- -- /* -- * Create Dissassociate / Deauthenticate packet filter -- * -- * 2 bytes 2 byte 6 bytes 6 bytes 6 bytes -- * +--------------+----------+---------+--------+--------+---- -- * + Frame Control+ Duration + DA + SA + BSSID + -- * +--------------+----------+---------+--------+--------+---- -- * -- * The above is the management frame format for disassociate/ -- * deauthenticate pattern, from this we need to match the first byte -- * of 'Frame Control' and DA, SA, and BSSID fields -- * (skipping 2nd byte of FC and Duration feild. -- * -- * Disassociate pattern -- * -------------------- -- * Frame control = 00 00 1010 -- * DA, SA, BSSID = x:x:x:x:x:x -- * Pattern will be A0000000 | x:x:x:x:x:x | x:x:x:x:x:x -- * | x:x:x:x:x:x -- 22 bytes -- * -- * Deauthenticate pattern -- * ---------------------- -- * Frame control = 00 00 1100 -- * DA, SA, BSSID = x:x:x:x:x:x -- * Pattern will be C0000000 | x:x:x:x:x:x | x:x:x:x:x:x -- * | x:x:x:x:x:x -- 22 bytes -- */ -- -- /* Create Disassociate Pattern first */ -- -- byte_cnt = 0; -- -- /* Fill out the mask with all FF's */ -- -- for (i = 0; i < MAX_PATTERN_MASK_SIZE; i++) -- dis_deauth_mask[i] = 0xff; -- -- /* copy the first byte of frame control field */ -- dis_deauth_pattern[byte_cnt] = 0xa0; -- byte_cnt++; -- -- /* skip 2nd byte of frame control and Duration field */ -- byte_cnt += 3; -- -- /* -- * need not match the destination mac address, it can be a broadcast -- * mac address or an unicast to this station -- */ -- byte_cnt += 6; -- -- /* copy the source mac address */ -- memcpy((dis_deauth_pattern + byte_cnt), common->curbssid, ETH_ALEN); -- -- byte_cnt += 6; -- -- /* copy the bssid, its same as the source mac address */ -- -- memcpy((dis_deauth_pattern + byte_cnt), common->curbssid, ETH_ALEN); -- -- /* Create Disassociate pattern mask */ -- -- dis_deauth_mask[0] = 0xfe; -- dis_deauth_mask[1] = 0x03; -- dis_deauth_mask[2] = 0xc0; -- -- ath_dbg(common, WOW, "Adding disassoc/deauth patterns for WoW\n"); -- -- ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask, -- pattern_count, byte_cnt); -- -- pattern_count++; -- /* -- * for de-authenticate pattern, only the first byte of the frame -- * control field gets changed from 0xA0 to 0xC0 -- */ -- dis_deauth_pattern[0] = 0xC0; -- -- ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask, -- pattern_count, byte_cnt); + void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) +--- a/drivers/net/wireless/rt2x00/rt2x00mac.c ++++ b/drivers/net/wireless/rt2x00/rt2x00mac.c +@@ -487,6 +487,8 @@ int rt2x00mac_set_key(struct ieee80211_h + crypto.cipher = rt2x00crypto_key_to_cipher(key); + if (crypto.cipher == CIPHER_NONE) + return -EOPNOTSUPP; ++ if (crypto.cipher == CIPHER_TKIP && rt2x00_is_usb(rt2x00dev)) ++ return -EOPNOTSUPP; + + crypto.cmd = cmd; + +@@ -624,25 +626,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); + + 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 +659,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); + } + + /* +--- 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; + +- 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); + +- mutex_unlock(&intf->beacon_skb_mutex); - --static void ath9k_wow_add_pattern(struct ath_softc *sc, -- struct cfg80211_wowlan *wowlan) + return 0; + } + +-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) + { + struct rt2x00_intf *intf = vif_to_intf(vif); + struct skb_frame_desc *skbdesc; +@@ -815,19 +811,6 @@ int rt2x00queue_update_beacon_locked(str + + } + +-int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, +- struct ieee80211_vif *vif) -{ -- struct ath_hw *ah = sc->sc_ah; -- struct ath9k_wow_pattern *wow_pattern = NULL; -- struct cfg80211_pkt_pattern *patterns = wowlan->patterns; -- int mask_len; -- s8 i = 0; +- struct rt2x00_intf *intf = vif_to_intf(vif); +- int ret; - -- if (!wowlan->n_patterns) -- return; -- -- /* -- * Add the new user configured patterns -- */ -- for (i = 0; i < wowlan->n_patterns; i++) { -- -- wow_pattern = kzalloc(sizeof(*wow_pattern), GFP_KERNEL); +- mutex_lock(&intf->beacon_skb_mutex); +- ret = rt2x00queue_update_beacon_locked(rt2x00dev, vif); +- mutex_unlock(&intf->beacon_skb_mutex); - -- if (!wow_pattern) -- return; -- -- /* -- * TODO: convert the generic user space pattern to -- * appropriate chip specific/802.11 pattern. -- */ -- -- mask_len = DIV_ROUND_UP(wowlan->patterns[i].pattern_len, 8); -- memset(wow_pattern->pattern_bytes, 0, MAX_PATTERN_SIZE); -- memset(wow_pattern->mask_bytes, 0, MAX_PATTERN_SIZE); -- memcpy(wow_pattern->pattern_bytes, patterns[i].pattern, -- patterns[i].pattern_len); -- memcpy(wow_pattern->mask_bytes, patterns[i].mask, mask_len); -- wow_pattern->pattern_len = patterns[i].pattern_len; -- -- /* -- * just need to take care of deauth and disssoc pattern, -- * make sure we don't overwrite them. -- */ +- return ret; +-} - -- ath9k_hw_wow_apply_pattern(ah, wow_pattern->pattern_bytes, -- wow_pattern->mask_bytes, -- i + 2, -- wow_pattern->pattern_len); -- kfree(wow_pattern); + 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; + + if (!sc->p2p_ps_timer) +@@ -1767,14 +1766,9 @@ void ath9k_update_p2p_ps(struct ath_soft + return; + + 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 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); + 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); + } + +@@ -2232,14 +2230,6 @@ static void ath9k_sw_scan_complete(struc + clear_bit(ATH_OP_SCANNING, &common->op_flags); + } + +-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; -} - --static int ath9k_suspend(struct ieee80211_hw *hw, -- struct cfg80211_wowlan *wowlan) + 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); + } + +-static void ath10k_channel_switch_beacon(struct ieee80211_hw *hw, +- struct ieee80211_vif *vif, +- struct cfg80211_chan_def *chandef) -{ -- struct ath_softc *sc = hw->priv; -- struct ath_hw *ah = sc->sc_ah; -- struct ath_common *common = ath9k_hw_common(ah); -- u32 wow_triggers_enabled = 0; -- int ret = 0; -- -- mutex_lock(&sc->mutex); -- -- ath_cancel_work(sc); -- ath_stop_ani(sc); -- del_timer_sync(&sc->rx_poll_timer); -- -- if (test_bit(SC_OP_INVALID, &sc->sc_flags)) { -- ath_dbg(common, ANY, "Device not present\n"); -- ret = -EINVAL; -- goto fail_wow; -- } +- /* there's no need to do anything here. vif->csa_active is enough */ +- return; +-} - -- if (WARN_ON(!wowlan)) { -- ath_dbg(common, WOW, "None of the WoW triggers enabled\n"); -- ret = -EINVAL; -- goto fail_wow; + 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 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]; - } -- -- if (!device_can_wakeup(sc->dev)) { -- ath_dbg(common, WOW, "device_can_wakeup failed, WoW is not enabled\n"); -- ret = 1; -- goto fail_wow; +- 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); - } -- -- /* -- * none of the sta vifs are associated -- * and we are not currently handling multivif -- * cases, for instance we have to seperately -- * configure 'keep alive frame' for each -- * STA. -- */ -- -- if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) { -- ath_dbg(common, WOW, "None of the STA vifs are associated\n"); -- ret = 1; -- goto fail_wow; +- 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]); +- } - } - -- if (sc->nvifs > 1) { -- ath_dbg(common, WOW, "WoW for multivif is not yet supported\n"); -- ret = 1; -- goto fail_wow; +- 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 - } - -- ath9k_wow_map_triggers(sc, wowlan, &wow_triggers_enabled); -- -- ath_dbg(common, WOW, "WoW triggers enabled 0x%x\n", -- wow_triggers_enabled); +- 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); - -- ath9k_ps_wakeup(sc); +- if (thr != 0) { +- sinfo->filled |= STATION_INFO_EXPECTED_THROUGHPUT; +- sinfo->expected_throughput = thr; +- } +-} - -- ath9k_stop_btcoex(sc); +-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) - -- /* -- * Enable wake up on recieving disassoc/deauth -- * frame by default. -- */ -- ath9k_wow_add_disassoc_deauth_pattern(sc); +-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 (wow_triggers_enabled & AH_WOW_USER_PATTERN_EN) -- ath9k_wow_add_pattern(sc, wowlan); +- if (sset == ETH_SS_STATS) +- rv += STA_STATS_LEN; - -- spin_lock_bh(&sc->sc_pcu_lock); -- /* -- * To avoid false wake, we enable beacon miss interrupt only -- * when we go to sleep. We save the current interrupt mask -- * so we can restore it after the system wakes up -- */ -- sc->wow_intr_before_sleep = ah->imask; -- ah->imask &= ~ATH9K_INT_GLOBAL; -- ath9k_hw_disable_interrupts(ah); -- ah->imask = ATH9K_INT_BMISS | ATH9K_INT_GLOBAL; -- ath9k_hw_set_interrupts(ah); -- ath9k_hw_enable_interrupts(ah); +- rv += drv_get_et_sset_count(sdata, sset); - -- spin_unlock_bh(&sc->sc_pcu_lock); +- if (rv == 0) +- return -EOPNOTSUPP; +- return rv; +-} - -- /* -- * we can now sync irq and kill any running tasklets, since we already -- * disabled interrupts and not holding a spin lock +-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. - */ -- synchronize_irq(sc->irq); -- tasklet_kill(&sc->intr_tq); -- -- ath9k_hw_wow_enable(ah, wow_triggers_enabled); - -- ath9k_ps_restore(sc); -- ath_dbg(common, ANY, "WoW enabled in ath9k\n"); -- atomic_inc(&sc->wow_sleep_proc_intr); +- mutex_lock(&local->sta_mtx); - --fail_wow: -- mutex_unlock(&sc->mutex); -- return ret; --} +- if (sdata->vif.type == NL80211_IFTYPE_STATION) { +- sta = sta_info_get_bss(sdata, sdata->u.mgd.bssid); - --static int ath9k_resume(struct ieee80211_hw *hw) --{ -- struct ath_softc *sc = hw->priv; -- struct ath_hw *ah = sc->sc_ah; -- struct ath_common *common = ath9k_hw_common(ah); -- u32 wow_status; +- if (!(sta && !WARN_ON(sta->sdata->dev != dev))) +- goto do_survey; - -- mutex_lock(&sc->mutex); +- sinfo.filled = 0; +- sta_set_sinfo(sta, &sinfo); - -- ath9k_ps_wakeup(sc); +- i = 0; +- ADD_STA_STATS(sta); - -- spin_lock_bh(&sc->sc_pcu_lock); +- data[i++] = sta->sta_state; - -- ath9k_hw_disable_interrupts(ah); -- ah->imask = sc->wow_intr_before_sleep; -- ath9k_hw_set_interrupts(ah); -- ath9k_hw_enable_interrupts(ah); - -- spin_unlock_bh(&sc->sc_pcu_lock); +- 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++; - -- wow_status = ath9k_hw_wow_wakeup(ah); +- 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; - -- if (atomic_read(&sc->wow_got_bmiss_intr) == 0) { -- /* -- * some devices may not pick beacon miss -- * as the reason they woke up so we add -- * that here for that shortcoming. -- */ -- wow_status |= AH_WOW_BEACON_MISS; -- atomic_dec(&sc->wow_got_bmiss_intr); -- ath_dbg(common, ANY, "Beacon miss interrupt picked up during WoW sleep\n"); +- sinfo.filled = 0; +- sta_set_sinfo(sta, &sinfo); +- i = 0; +- ADD_STA_STATS(sta); +- } - } - -- atomic_dec(&sc->wow_sleep_proc_intr); +-do_survey: +- i = STA_STATS_LEN - STA_STATS_SURVEY_LEN; +- /* Get survey stats for current channel */ +- survey.filled = 0; - -- if (wow_status) { -- ath_dbg(common, ANY, "Waking up due to WoW triggers %s with WoW status = %x\n", -- ath9k_hw_wow_event_to_string(wow_status), wow_status); +- 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); - } - -- ath_restart_work(sc); -- ath9k_start_btcoex(sc); +- 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; - -- ath9k_ps_restore(sc); -- mutex_unlock(&sc->mutex); +- mutex_unlock(&local->sta_mtx); - -- return 0; +- if (WARN_ON(i != STA_STATS_LEN)) +- return; +- +- drv_get_et_stats(sdata, stats, &(data[STA_STATS_LEN])); -} - --static void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled) +-static void ieee80211_get_et_strings(struct wiphy *wiphy, +- struct net_device *dev, +- u32 sset, u8 *data) -{ -- struct ath_softc *sc = hw->priv; +- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); +- int sz_sta_stats = 0; - -- mutex_lock(&sc->mutex); -- device_init_wakeup(sc->dev, 1); -- device_set_wakeup_enable(sc->dev, enabled); -- mutex_unlock(&sc->mutex); +- 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])); -} - --#endif - static void ath9k_sw_scan_start(struct ieee80211_hw *hw) + 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; + +@@ -891,6 +571,11 @@ static int ieee80211_set_probe_resp(stru + new->len = resp_len; + memcpy(new->data, resp, resp_len); + ++ if (csa) ++ memcpy(new->csa_counter_offsets, csa->counter_offsets_presp, ++ csa->n_counter_offsets_presp * ++ sizeof(new->csa_counter_offsets[0])); ++ + 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 + } + + 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])); ++ } ++ + /* 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); + + 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; + +- 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; + +- 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 + + 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 ath_softc *sc = hw->priv; -@@ -2373,134 +2070,6 @@ static void ath9k_channel_switch_beacon( - sc->csa_vif = vif; ++ struct ieee80211_csa_settings csa = {}; + int err; + + switch (sdata->vif.type) { +@@ -3210,20 +2905,13 @@ static int ieee80211_set_csa_beacon(stru + IEEE80211_MAX_CSA_COUNTERS_NUM)) + return -EINVAL; + +- /* 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(); + } + + 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); } --static void ath9k_tx99_stop(struct ath_softc *sc) +-static int ieee80211_set_ringparam(struct wiphy *wiphy, u32 tx, u32 rx) -{ -- struct ath_hw *ah = sc->sc_ah; -- struct ath_common *common = ath9k_hw_common(ah); +- struct ieee80211_local *local = wiphy_priv(wiphy); - -- ath_drain_all_txq(sc); -- ath_startrecv(sc); -- -- ath9k_hw_set_interrupts(ah); -- ath9k_hw_enable_interrupts(ah); -- -- ieee80211_wake_queues(sc->hw); -- -- kfree_skb(sc->tx99_skb); -- sc->tx99_skb = NULL; -- sc->tx99_state = false; -- -- ath9k_hw_tx99_stop(sc->sc_ah); -- ath_dbg(common, XMIT, "TX99 stopped\n"); +- return drv_set_ringparam(local, tx, rx); -} - --static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc) +-static void ieee80211_get_ringparam(struct wiphy *wiphy, +- u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max) -{ -- static u8 PN9Data[] = {0xff, 0x87, 0xb8, 0x59, 0xb7, 0xa1, 0xcc, 0x24, -- 0x57, 0x5e, 0x4b, 0x9c, 0x0e, 0xe9, 0xea, 0x50, -- 0x2a, 0xbe, 0xb4, 0x1b, 0xb6, 0xb0, 0x5d, 0xf1, -- 0xe6, 0x9a, 0xe3, 0x45, 0xfd, 0x2c, 0x53, 0x18, -- 0x0c, 0xca, 0xc9, 0xfb, 0x49, 0x37, 0xe5, 0xa8, -- 0x51, 0x3b, 0x2f, 0x61, 0xaa, 0x72, 0x18, 0x84, -- 0x02, 0x23, 0x23, 0xab, 0x63, 0x89, 0x51, 0xb3, -- 0xe7, 0x8b, 0x72, 0x90, 0x4c, 0xe8, 0xfb, 0xc0}; -- u32 len = 1200; -- struct ieee80211_hw *hw = sc->hw; -- struct ieee80211_hdr *hdr; -- struct ieee80211_tx_info *tx_info; -- struct sk_buff *skb; -- -- skb = alloc_skb(len, GFP_KERNEL); -- if (!skb) -- return NULL; -- -- skb_put(skb, len); -- -- memset(skb->data, 0, len); -- -- hdr = (struct ieee80211_hdr *)skb->data; -- hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA); -- hdr->duration_id = 0; +- struct ieee80211_local *local = wiphy_priv(wiphy); - -- memcpy(hdr->addr1, hw->wiphy->perm_addr, ETH_ALEN); -- memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN); -- memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); -- -- hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); -- -- tx_info = IEEE80211_SKB_CB(skb); -- memset(tx_info, 0, sizeof(*tx_info)); -- tx_info->band = hw->conf.chandef.chan->band; -- tx_info->flags = IEEE80211_TX_CTL_NO_ACK; -- tx_info->control.vif = sc->tx99_vif; -- -- memcpy(skb->data + sizeof(*hdr), PN9Data, sizeof(PN9Data)); -- -- return skb; +- drv_get_ringparam(local, tx, tx_max, rx, rx_max); -} - --void ath9k_tx99_deinit(struct ath_softc *sc) --{ -- ath_reset(sc); -- -- ath9k_ps_wakeup(sc); -- ath9k_tx99_stop(sc); -- ath9k_ps_restore(sc); --} + 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; + } + - --int ath9k_tx99_init(struct ath_softc *sc) +-static bool ieee80211_wep_is_weak_iv(struct sk_buff *skb, +- struct ieee80211_key *key) -{ -- struct ieee80211_hw *hw = sc->hw; -- struct ath_hw *ah = sc->sc_ah; -- struct ath_common *common = ath9k_hw_common(ah); -- struct ath_tx_control txctl; -- int r; -- -- if (sc->sc_flags & SC_OP_INVALID) { -- ath_err(common, -- "driver is in invalid state unable to use TX99"); -- return -EINVAL; -- } -- -- sc->tx99_skb = ath9k_build_tx99_skb(sc); -- if (!sc->tx99_skb) -- return -ENOMEM; -- -- memset(&txctl, 0, sizeof(txctl)); -- txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO]; +- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; +- unsigned int hdrlen; +- u8 *ivpos; +- u32 iv; - -- ath_reset(sc); +- hdrlen = ieee80211_hdrlen(hdr->frame_control); +- ivpos = skb->data + hdrlen; +- iv = (ivpos[0] << 16) | (ivpos[1] << 8) | ivpos[2]; - -- ath9k_ps_wakeup(sc); -- -- ath9k_hw_disable_interrupts(ah); -- atomic_set(&ah->intr_ref_cnt, -1); -- ath_drain_all_txq(sc); -- ath_stoprecv(sc); -- -- sc->tx99_state = true; -- -- ieee80211_stop_queues(hw); -- -- if (sc->tx99_power == MAX_RATE_POWER + 1) -- sc->tx99_power = MAX_RATE_POWER; -- -- ath9k_hw_tx99_set_txpower(ah, sc->tx99_power); -- r = ath9k_tx99_send(sc, sc->tx99_skb, &txctl); -- if (r) { -- ath_dbg(common, XMIT, "Failed to xmit TX99 skb\n"); -- return r; -- } -- -- ath_dbg(common, XMIT, "TX99 xmit started using %d ( %ddBm)\n", -- sc->tx99_power, -- sc->tx99_power / 2); -- -- /* We leave the harware awake as it will be chugging on */ -- -- return 0; +- return ieee80211_wep_weak_iv(iv, key->conf.keylen); -} - - struct ieee80211_ops ath9k_ops = { - .tx = ath9k_tx, - .start = ath9k_start, -@@ -2531,7 +2100,7 @@ struct ieee80211_ops ath9k_ops = { - .set_antenna = ath9k_set_antenna, - .get_antenna = ath9k_get_antenna, - --#ifdef CONFIG_PM_SLEEP -+#ifdef CONFIG_ATH9K_WOW - .suspend = ath9k_suspend, - .resume = ath9k_resume, - .set_wakeup = ath9k_set_wakeup, ---- a/drivers/net/wireless/ath/ath9k/wow.c -+++ b/drivers/net/wireless/ath/ath9k/wow.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2012 Qualcomm Atheros, Inc. -+ * Copyright (c) 2013 Qualcomm Atheros, Inc. + 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 { * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above -@@ -14,409 +14,348 @@ - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * @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); + ++ ++/* 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; + }; --#include - #include "ath9k.h" --#include "reg.h" --#include "hw-ops.h" - --const char *ath9k_hw_wow_event_to_string(u32 wow_event) -+static const struct wiphy_wowlan_support ath9k_wowlan_support = { -+ .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT, -+ .n_patterns = MAX_NUM_USER_PATTERN, -+ .pattern_min_len = 1, -+ .pattern_max_len = MAX_PATTERN_SIZE, -+}; ++struct ieee80211_csa_settings { ++ const u16 *counter_offsets_beacon; ++ const u16 *counter_offsets_presp; + -+static void ath9k_wow_map_triggers(struct ath_softc *sc, -+ struct cfg80211_wowlan *wowlan, -+ u32 *wow_triggers) - { -- if (wow_event & AH_WOW_MAGIC_PATTERN_EN) -- return "Magic pattern"; -- if (wow_event & AH_WOW_USER_PATTERN_EN) -- return "User pattern"; -- if (wow_event & AH_WOW_LINK_CHANGE) -- return "Link change"; -- if (wow_event & AH_WOW_BEACON_MISS) -- return "Beacon miss"; -+ if (wowlan->disconnect) -+ *wow_triggers |= AH_WOW_LINK_CHANGE | -+ AH_WOW_BEACON_MISS; -+ if (wowlan->magic_pkt) -+ *wow_triggers |= AH_WOW_MAGIC_PATTERN_EN; ++ int n_counter_offsets_beacon; ++ int n_counter_offsets_presp; + -+ if (wowlan->n_patterns) -+ *wow_triggers |= AH_WOW_USER_PATTERN_EN; ++ u8 count; ++}; + -+ sc->wow_enabled = *wow_triggers; + 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; + }; -- return "unknown reason"; - } --EXPORT_SYMBOL(ath9k_hw_wow_event_to_string); + struct probe_resp { + struct rcu_head rcu_head; + int len; ++ u16 csa_counter_offsets[IEEE80211_MAX_CSA_COUNTERS_NUM]; + u8 data[0]; + }; --static void ath9k_hw_set_powermode_wow_sleep(struct ath_hw *ah) -+static void ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc) - { -+ struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); -+ int pattern_count = 0; -+ int i, byte_cnt; -+ u8 dis_deauth_pattern[MAX_PATTERN_SIZE]; -+ u8 dis_deauth_mask[MAX_PATTERN_SIZE]; +@@ -754,8 +767,6 @@ struct ieee80211_sub_if_data { + struct mac80211_qos_map __rcu *qos_map; -- REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); -+ memset(dis_deauth_pattern, 0, MAX_PATTERN_SIZE); -+ memset(dis_deauth_mask, 0, MAX_PATTERN_SIZE); + 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; -- /* set rx disable bit */ -- REG_WRITE(ah, AR_CR, AR_CR_RXD); -+ /* -+ * Create Dissassociate / Deauthenticate packet filter -+ * -+ * 2 bytes 2 byte 6 bytes 6 bytes 6 bytes -+ * +--------------+----------+---------+--------+--------+---- -+ * + Frame Control+ Duration + DA + SA + BSSID + -+ * +--------------+----------+---------+--------+--------+---- -+ * -+ * The above is the management frame format for disassociate/ -+ * deauthenticate pattern, from this we need to match the first byte -+ * of 'Frame Control' and DA, SA, and BSSID fields -+ * (skipping 2nd byte of FC and Duration feild. -+ * -+ * Disassociate pattern -+ * -------------------- -+ * Frame control = 00 00 1010 -+ * DA, SA, BSSID = x:x:x:x:x:x -+ * Pattern will be A0000000 | x:x:x:x:x:x | x:x:x:x:x:x -+ * | x:x:x:x:x:x -- 22 bytes -+ * -+ * Deauthenticate pattern -+ * ---------------------- -+ * Frame control = 00 00 1100 -+ * DA, SA, BSSID = x:x:x:x:x:x -+ * Pattern will be C0000000 | x:x:x:x:x:x | x:x:x:x:x:x -+ * | x:x:x:x:x:x -- 22 bytes -+ */ + /* 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); -- if (!ath9k_hw_wait(ah, AR_CR, AR_CR_RXE, 0, AH_WAIT_TIMEOUT)) { -- ath_err(common, "Failed to stop Rx DMA in 10ms AR_CR=0x%08x AR_DIAG_SW=0x%08x\n", -- REG_READ(ah, AR_CR), REG_READ(ah, AR_DIAG_SW)); -- return; -- } -+ /* Create Disassociate Pattern first */ -- REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_ON_INT); --} -+ byte_cnt = 0; ++extern const struct ethtool_ops ieee80211_ethtool_ops; ++ + #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; + + sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; + +@@ -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; + + sdata->noack_map = 0; + +@@ -1721,6 +1723,8 @@ int ieee80211_if_add(struct ieee80211_lo + + ndev->features |= local->hw.netdev_features; + ++ netdev_set_default_ethtool_ops(ndev, &ieee80211_ethtool_ops); ++ + 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" + + /* 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; + +- 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 + #include + #include "core.h" +-#include "ethtool.h" + #include "rdev-ops.h" + +-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 wireless_dev *wdev = dev->ieee80211_ptr; --static void ath9k_wow_create_keep_alive_pattern(struct ath_hw *ah) +@@ -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) -{ -- struct ath_common *common = ath9k_hw_common(ah); -- u8 sta_mac_addr[ETH_ALEN], ap_mac_addr[ETH_ALEN]; -- u32 ctl[13] = {0}; -- u32 data_word[KAL_NUM_DATA_WORDS]; -- u8 i; -- u32 wow_ka_data_word0; +- /* For now, return 0... */ +- return 0; +-} - -- memcpy(sta_mac_addr, common->macaddr, ETH_ALEN); -- memcpy(ap_mac_addr, common->curbssid, ETH_ALEN); +-static void cfg80211_get_regs(struct net_device *dev, struct ethtool_regs *regs, +- void *data) +-{ +- struct wireless_dev *wdev = dev->ieee80211_ptr; - -- /* set the transmit buffer */ -- ctl[0] = (KAL_FRAME_LEN | (MAX_RATE_POWER << 16)); -- ctl[1] = 0; -- ctl[3] = 0xb; /* OFDM_6M hardware value for this rate */ -- ctl[4] = 0; -- ctl[7] = (ah->txchainmask) << 2; -- ctl[2] = 0xf << 16; /* tx_tries 0 */ +- regs->version = wdev->wiphy->hw_version; +- regs->len = 0; +-} - -- for (i = 0; i < KAL_NUM_DESC_WORDS; i++) -- REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]); +-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); - -- REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]); +- memset(rp, 0, sizeof(*rp)); - -- data_word[0] = (KAL_FRAME_TYPE << 2) | (KAL_FRAME_SUB_TYPE << 4) | -- (KAL_TO_DS << 8) | (KAL_DURATION_ID << 16); -- data_word[1] = (ap_mac_addr[3] << 24) | (ap_mac_addr[2] << 16) | -- (ap_mac_addr[1] << 8) | (ap_mac_addr[0]); -- data_word[2] = (sta_mac_addr[1] << 24) | (sta_mac_addr[0] << 16) | -- (ap_mac_addr[5] << 8) | (ap_mac_addr[4]); -- data_word[3] = (sta_mac_addr[5] << 24) | (sta_mac_addr[4] << 16) | -- (sta_mac_addr[3] << 8) | (sta_mac_addr[2]); -- data_word[4] = (ap_mac_addr[3] << 24) | (ap_mac_addr[2] << 16) | -- (ap_mac_addr[1] << 8) | (ap_mac_addr[0]); -- data_word[5] = (ap_mac_addr[5] << 8) | (ap_mac_addr[4]); +- if (rdev->ops->get_ringparam) +- rdev_get_ringparam(rdev, &rp->tx_pending, &rp->tx_max_pending, +- &rp->rx_pending, &rp->rx_max_pending); +-} - -- if (AR_SREV_9462_20(ah)) { -- /* AR9462 2.0 has an extra descriptor word (time based -- * discard) compared to other chips */ -- REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + (12 * 4)), 0); -- wow_ka_data_word0 = AR_WOW_TXBUF(13); -- } else { -- wow_ka_data_word0 = AR_WOW_TXBUF(12); -- } -+ /* Fill out the mask with all FF's */ - -- for (i = 0; i < KAL_NUM_DATA_WORDS; i++) -- REG_WRITE(ah, (wow_ka_data_word0 + i*4), data_word[i]); -+ for (i = 0; i < MAX_PATTERN_MASK_SIZE; i++) -+ dis_deauth_mask[i] = 0xff; - +-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; -} -+ /* copy the first byte of frame control field */ -+ dis_deauth_pattern[byte_cnt] = 0xa0; -+ byte_cnt++; - --void ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern, -- u8 *user_mask, int pattern_count, -- int pattern_len) +- +-static int cfg80211_get_sset_count(struct net_device *dev, int sset) -{ -- int i; -- u32 pattern_val, mask_val; -- u32 set, clr; -+ /* skip 2nd byte of frame control and Duration field */ -+ byte_cnt += 3; - -- /* FIXME: should check count by querying the hardware capability */ -- if (pattern_count >= MAX_NUM_PATTERN) -- return; -+ /* -+ * need not match the destination mac address, it can be a broadcast -+ * mac address or an unicast to this station -+ */ -+ byte_cnt += 6; - -- REG_SET_BIT(ah, AR_WOW_PATTERN, BIT(pattern_count)); -+ /* copy the source mac address */ -+ memcpy((dis_deauth_pattern + byte_cnt), common->curbssid, ETH_ALEN); - -- /* set the registers for pattern */ -- for (i = 0; i < MAX_PATTERN_SIZE; i += 4) { -- memcpy(&pattern_val, user_pattern, 4); -- REG_WRITE(ah, (AR_WOW_TB_PATTERN(pattern_count) + i), -- pattern_val); -- user_pattern += 4; -- } -+ byte_cnt += 6; - -- /* set the registers for mask */ -- for (i = 0; i < MAX_PATTERN_MASK_SIZE; i += 4) { -- memcpy(&mask_val, user_mask, 4); -- REG_WRITE(ah, (AR_WOW_TB_MASK(pattern_count) + i), mask_val); -- user_mask += 4; -- } -+ /* copy the bssid, its same as the source mac address */ - -- /* set the pattern length to be matched -- * -- * AR_WOW_LENGTH1_REG1 -- * bit 31:24 pattern 0 length -- * bit 23:16 pattern 1 length -- * bit 15:8 pattern 2 length -- * bit 7:0 pattern 3 length -- * -- * AR_WOW_LENGTH1_REG2 -- * bit 31:24 pattern 4 length -- * bit 23:16 pattern 5 length -- * bit 15:8 pattern 6 length -- * bit 7:0 pattern 7 length -- * -- * the below logic writes out the new -- * pattern length for the corresponding -- * pattern_count, while masking out the -- * other fields -- */ -+ memcpy((dis_deauth_pattern + byte_cnt), common->curbssid, ETH_ALEN); - -- ah->wow_event_mask |= BIT(pattern_count + AR_WOW_PAT_FOUND_SHIFT); -+ /* Create Disassociate pattern mask */ - -- if (pattern_count < 4) { -- /* Pattern 0-3 uses AR_WOW_LENGTH1 register */ -- set = (pattern_len & AR_WOW_LENGTH_MAX) << -- AR_WOW_LEN1_SHIFT(pattern_count); -- clr = AR_WOW_LENGTH1_MASK(pattern_count); -- REG_RMW(ah, AR_WOW_LENGTH1, set, clr); -- } else { -- /* Pattern 4-7 uses AR_WOW_LENGTH2 register */ -- set = (pattern_len & AR_WOW_LENGTH_MAX) << -- AR_WOW_LEN2_SHIFT(pattern_count); -- clr = AR_WOW_LENGTH2_MASK(pattern_count); -- REG_RMW(ah, AR_WOW_LENGTH2, set, clr); -- } -+ dis_deauth_mask[0] = 0xfe; -+ dis_deauth_mask[1] = 0x03; -+ dis_deauth_mask[2] = 0xc0; - +- 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; -} --EXPORT_SYMBOL(ath9k_hw_wow_apply_pattern); -+ ath_dbg(common, WOW, "Adding disassoc/deauth patterns for WoW\n"); - --u32 ath9k_hw_wow_wakeup(struct ath_hw *ah) +- +-static void cfg80211_get_stats(struct net_device *dev, +- struct ethtool_stats *stats, u64 *data) -{ -- u32 wow_status = 0; -- u32 val = 0, rval; -+ ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask, -+ pattern_count, byte_cnt); - -+ pattern_count++; - /* -- * read the WoW status register to know -- * the wakeup reason -+ * for de-authenticate pattern, only the first byte of the frame -+ * control field gets changed from 0xA0 to 0xC0 - */ -- rval = REG_READ(ah, AR_WOW_PATTERN); -- val = AR_WOW_STATUS(rval); -+ dis_deauth_pattern[0] = 0xC0; - -- /* -- * mask only the WoW events that we have enabled. Sometimes -- * we have spurious WoW events from the AR_WOW_PATTERN -- * register. This mask will clean it up. -- */ -+ ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask, -+ pattern_count, byte_cnt); +- 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; + } -- val &= ah->wow_event_mask; -+} - -- if (val) { -- if (val & AR_WOW_MAGIC_PAT_FOUND) -- wow_status |= AH_WOW_MAGIC_PATTERN_EN; -- if (AR_WOW_PATTERN_FOUND(val)) -- wow_status |= AH_WOW_USER_PATTERN_EN; -- if (val & AR_WOW_KEEP_ALIVE_FAIL) -- wow_status |= AH_WOW_LINK_CHANGE; -- if (val & AR_WOW_BEACON_FAIL) -- wow_status |= AH_WOW_BEACON_MISS; -- } -+static void ath9k_wow_add_pattern(struct ath_softc *sc, -+ struct cfg80211_wowlan *wowlan) -+{ -+ struct ath_hw *ah = sc->sc_ah; -+ struct ath9k_wow_pattern *wow_pattern = NULL; -+ struct cfg80211_pkt_pattern *patterns = wowlan->patterns; -+ int mask_len; -+ s8 i = 0; -+ -+ if (!wowlan->n_patterns) -+ return; - - /* -- * set and clear WOW_PME_CLEAR registers for the chip to -- * generate next wow signal. -- * disable D3 before accessing other registers ? -+ * Add the new user configured patterns - */ -+ for (i = 0; i < wowlan->n_patterns; i++) { - -- /* do we need to check the bit value 0x01000000 (7-10) ?? */ -- REG_RMW(ah, AR_PCIE_PM_CTRL, AR_PMCTRL_WOW_PME_CLR, -- AR_PMCTRL_PWR_STATE_D1D3); -+ wow_pattern = kzalloc(sizeof(*wow_pattern), GFP_KERNEL); - -- /* -- * clear all events -- */ -- REG_WRITE(ah, AR_WOW_PATTERN, -- AR_WOW_CLEAR_EVENTS(REG_READ(ah, AR_WOW_PATTERN))); -+ if (!wow_pattern) -+ return; - -- /* -- * restore the beacon threshold to init value -- */ -- REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); -+ /* -+ * TODO: convert the generic user space pattern to -+ * appropriate chip specific/802.11 pattern. -+ */ - -- /* -- * Restore the way the PCI-E reset, Power-On-Reset, external -- * PCIE_POR_SHORT pins are tied to its original value. -- * Previously just before WoW sleep, we untie the PCI-E -- * reset to our Chip's Power On Reset so that any PCI-E -- * reset from the bus will not reset our chip -- */ -- if (ah->is_pciexpress) -- ath9k_hw_configpcipowersave(ah, false); -+ mask_len = DIV_ROUND_UP(wowlan->patterns[i].pattern_len, 8); -+ memset(wow_pattern->pattern_bytes, 0, MAX_PATTERN_SIZE); -+ memset(wow_pattern->mask_bytes, 0, MAX_PATTERN_SIZE); -+ memcpy(wow_pattern->pattern_bytes, patterns[i].pattern, -+ patterns[i].pattern_len); -+ memcpy(wow_pattern->mask_bytes, patterns[i].mask, mask_len); -+ wow_pattern->pattern_len = patterns[i].pattern_len; -+ -+ /* -+ * just need to take care of deauth and disssoc pattern, -+ * make sure we don't overwrite them. -+ */ -+ -+ ath9k_hw_wow_apply_pattern(ah, wow_pattern->pattern_bytes, -+ wow_pattern->mask_bytes, -+ i + 2, -+ wow_pattern->pattern_len); -+ kfree(wow_pattern); - -- ah->wow_event_mask = 0; -+ } - -- return wow_status; - } --EXPORT_SYMBOL(ath9k_hw_wow_wakeup); - --void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable) -+int ath9k_suspend(struct ieee80211_hw *hw, -+ struct cfg80211_wowlan *wowlan) - { -- u32 wow_event_mask; -- u32 set, clr; -+ struct ath_softc *sc = hw->priv; -+ struct ath_hw *ah = sc->sc_ah; -+ struct ath_common *common = ath9k_hw_common(ah); -+ u32 wow_triggers_enabled = 0; -+ int ret = 0; - -- /* -- * wow_event_mask is a mask to the AR_WOW_PATTERN register to -- * indicate which WoW events we have enabled. The WoW events -- * are from the 'pattern_enable' in this function and -- * 'pattern_count' of ath9k_hw_wow_apply_pattern() -- */ -- wow_event_mask = ah->wow_event_mask; -+ mutex_lock(&sc->mutex); - -- /* -- * Untie Power-on-Reset from the PCI-E-Reset. When we are in -- * WOW sleep, we do want the Reset from the PCI-E to disturb -- * our hw state -- */ -- if (ah->is_pciexpress) { -- /* -- * we need to untie the internal POR (power-on-reset) -- * to the external PCI-E reset. We also need to tie -- * the PCI-E Phy reset to the PCI-E reset. -- */ -- set = AR_WA_RESET_EN | AR_WA_POR_SHORT; -- clr = AR_WA_UNTIE_RESET_EN | AR_WA_D3_L1_DISABLE; -- REG_RMW(ah, AR_WA, set, clr); -+ ath_cancel_work(sc); -+ ath_stop_ani(sc); -+ del_timer_sync(&sc->rx_poll_timer); -+ -+ if (test_bit(SC_OP_INVALID, &sc->sc_flags)) { -+ ath_dbg(common, ANY, "Device not present\n"); -+ ret = -EINVAL; -+ goto fail_wow; - } - -- /* -- * set the power states appropriately and enable PME -- */ -- set = AR_PMCTRL_HOST_PME_EN | AR_PMCTRL_PWR_PM_CTRL_ENA | -- AR_PMCTRL_AUX_PWR_DET | AR_PMCTRL_WOW_PME_CLR; -+ if (WARN_ON(!wowlan)) { -+ ath_dbg(common, WOW, "None of the WoW triggers enabled\n"); -+ ret = -EINVAL; -+ goto fail_wow; -+ } - -- /* -- * set and clear WOW_PME_CLEAR registers for the chip -- * to generate next wow signal. -- */ -- REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set); -- clr = AR_PMCTRL_WOW_PME_CLR; -- REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr); -+ if (!device_can_wakeup(sc->dev)) { -+ ath_dbg(common, WOW, "device_can_wakeup failed, WoW is not enabled\n"); -+ ret = 1; -+ goto fail_wow; -+ } - - /* -- * Setup for: -- * - beacon misses -- * - magic pattern -- * - keep alive timeout -- * - pattern matching -+ * none of the sta vifs are associated -+ * and we are not currently handling multivif -+ * cases, for instance we have to seperately -+ * configure 'keep alive frame' for each -+ * STA. - */ - -- /* -- * Program default values for pattern backoff, aifs/slot/KAL count, -- * beacon miss timeout, KAL timeout, etc. -- */ -- set = AR_WOW_BACK_OFF_SHIFT(AR_WOW_PAT_BACKOFF); -- REG_SET_BIT(ah, AR_WOW_PATTERN, set); -+ if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) { -+ ath_dbg(common, WOW, "None of the STA vifs are associated\n"); -+ ret = 1; -+ goto fail_wow; -+ } -+ -+ if (sc->nvifs > 1) { -+ ath_dbg(common, WOW, "WoW for multivif is not yet supported\n"); -+ ret = 1; -+ goto fail_wow; -+ } - -- set = AR_WOW_AIFS_CNT(AR_WOW_CNT_AIFS_CNT) | -- AR_WOW_SLOT_CNT(AR_WOW_CNT_SLOT_CNT) | -- AR_WOW_KEEP_ALIVE_CNT(AR_WOW_CNT_KA_CNT); -- REG_SET_BIT(ah, AR_WOW_COUNT, set); -- -- if (pattern_enable & AH_WOW_BEACON_MISS) -- set = AR_WOW_BEACON_TIMO; -- /* We are not using beacon miss, program a large value */ -- else -- set = AR_WOW_BEACON_TIMO_MAX; -+ ath9k_wow_map_triggers(sc, wowlan, &wow_triggers_enabled); - -- REG_WRITE(ah, AR_WOW_BCN_TIMO, set); -+ ath_dbg(common, WOW, "WoW triggers enabled 0x%x\n", -+ wow_triggers_enabled); - -- /* -- * Keep alive timo in ms except AR9280 -- */ -- if (!pattern_enable) -- set = AR_WOW_KEEP_ALIVE_NEVER; -- else -- set = KAL_TIMEOUT * 32; -+ ath9k_ps_wakeup(sc); - -- REG_WRITE(ah, AR_WOW_KEEP_ALIVE_TIMO, set); -+ ath9k_stop_btcoex(sc); - - /* -- * Keep alive delay in us. based on 'power on clock', -- * therefore in usec -+ * Enable wake up on recieving disassoc/deauth -+ * frame by default. - */ -- set = KAL_DELAY * 1000; -- REG_WRITE(ah, AR_WOW_KEEP_ALIVE_DELAY, set); -+ ath9k_wow_add_disassoc_deauth_pattern(sc); - -- /* -- * Create keep alive pattern to respond to beacons -- */ -- ath9k_wow_create_keep_alive_pattern(ah); -+ if (wow_triggers_enabled & AH_WOW_USER_PATTERN_EN) -+ ath9k_wow_add_pattern(sc, wowlan); - -+ spin_lock_bh(&sc->sc_pcu_lock); - /* -- * Configure MAC WoW Registers -+ * To avoid false wake, we enable beacon miss interrupt only -+ * when we go to sleep. We save the current interrupt mask -+ * so we can restore it after the system wakes up - */ -- set = 0; -- /* Send keep alive timeouts anyway */ -- clr = AR_WOW_KEEP_ALIVE_AUTO_DIS; -- -- if (pattern_enable & AH_WOW_LINK_CHANGE) -- wow_event_mask |= AR_WOW_KEEP_ALIVE_FAIL; -- else -- set = AR_WOW_KEEP_ALIVE_FAIL_DIS; -+ sc->wow_intr_before_sleep = ah->imask; -+ ah->imask &= ~ATH9K_INT_GLOBAL; -+ ath9k_hw_disable_interrupts(ah); -+ ah->imask = ATH9K_INT_BMISS | ATH9K_INT_GLOBAL; -+ ath9k_hw_set_interrupts(ah); -+ ath9k_hw_enable_interrupts(ah); - -- set = AR_WOW_KEEP_ALIVE_FAIL_DIS; -- REG_RMW(ah, AR_WOW_KEEP_ALIVE, set, clr); -+ spin_unlock_bh(&sc->sc_pcu_lock); - - /* -- * we are relying on a bmiss failure. ensure we have -- * enough threshold to prevent false positives -+ * we can now sync irq and kill any running tasklets, since we already -+ * disabled interrupts and not holding a spin lock - */ -- REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_THR_BM_THR, -- AR_WOW_BMISSTHRESHOLD); -+ synchronize_irq(sc->irq); -+ tasklet_kill(&sc->intr_tq); -+ -+ ath9k_hw_wow_enable(ah, wow_triggers_enabled); - -- set = 0; -- clr = 0; -+ ath9k_ps_restore(sc); -+ ath_dbg(common, ANY, "WoW enabled in ath9k\n"); -+ atomic_inc(&sc->wow_sleep_proc_intr); - -- if (pattern_enable & AH_WOW_BEACON_MISS) { -- set = AR_WOW_BEACON_FAIL_EN; -- wow_event_mask |= AR_WOW_BEACON_FAIL; -- } else { -- clr = AR_WOW_BEACON_FAIL_EN; -+fail_wow: -+ mutex_unlock(&sc->mutex); -+ return ret; -+} -+ -+int ath9k_resume(struct ieee80211_hw *hw) -+{ -+ struct ath_softc *sc = hw->priv; -+ struct ath_hw *ah = sc->sc_ah; -+ struct ath_common *common = ath9k_hw_common(ah); -+ u32 wow_status; -+ -+ mutex_lock(&sc->mutex); -+ -+ ath9k_ps_wakeup(sc); -+ -+ spin_lock_bh(&sc->sc_pcu_lock); -+ -+ ath9k_hw_disable_interrupts(ah); -+ ah->imask = sc->wow_intr_before_sleep; -+ ath9k_hw_set_interrupts(ah); -+ ath9k_hw_enable_interrupts(ah); -+ -+ spin_unlock_bh(&sc->sc_pcu_lock); -+ -+ wow_status = ath9k_hw_wow_wakeup(ah); -+ -+ if (atomic_read(&sc->wow_got_bmiss_intr) == 0) { -+ /* -+ * some devices may not pick beacon miss -+ * as the reason they woke up so we add -+ * that here for that shortcoming. -+ */ -+ wow_status |= AH_WOW_BEACON_MISS; -+ atomic_dec(&sc->wow_got_bmiss_intr); -+ ath_dbg(common, ANY, "Beacon miss interrupt picked up during WoW sleep\n"); - } - -- REG_RMW(ah, AR_WOW_BCN_EN, set, clr); -+ atomic_dec(&sc->wow_sleep_proc_intr); - -- set = 0; -- clr = 0; -- /* -- * Enable the magic packet registers -- */ -- if (pattern_enable & AH_WOW_MAGIC_PATTERN_EN) { -- set = AR_WOW_MAGIC_EN; -- wow_event_mask |= AR_WOW_MAGIC_PAT_FOUND; -- } else { -- clr = AR_WOW_MAGIC_EN; -+ if (wow_status) { -+ ath_dbg(common, ANY, "Waking up due to WoW triggers %s with WoW status = %x\n", -+ ath9k_hw_wow_event_to_string(wow_status), wow_status); - } -- set |= AR_WOW_MAC_INTR_EN; -- REG_RMW(ah, AR_WOW_PATTERN, set, clr); - -- REG_WRITE(ah, AR_WOW_PATTERN_MATCH_LT_256B, -- AR_WOW_PATTERN_SUPPORTED); -+ ath_restart_work(sc); -+ ath9k_start_btcoex(sc); - -- /* -- * Set the power states appropriately and enable PME -- */ -- clr = 0; -- set = AR_PMCTRL_PWR_STATE_D1D3 | AR_PMCTRL_HOST_PME_EN | -- AR_PMCTRL_PWR_PM_CTRL_ENA; -+ ath9k_ps_restore(sc); -+ mutex_unlock(&sc->mutex); - -- clr = AR_PCIE_PM_CTRL_ENA; -- REG_RMW(ah, AR_PCIE_PM_CTRL, set, clr); -+ return 0; -+} - -- /* -- * this is needed to prevent the chip waking up -- * the host within 3-4 seconds with certain -- * platform/BIOS. The fix is to enable -- * D1 & D3 to match original definition and -- * also match the OTP value. Anyway this -- * is more related to SW WOW. -- */ -- clr = AR_PMCTRL_PWR_STATE_D1D3; -- REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr); -+void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled) -+{ -+ struct ath_softc *sc = hw->priv; - -- set = AR_PMCTRL_PWR_STATE_D1D3_REAL; -- REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set); -+ mutex_lock(&sc->mutex); -+ device_init_wakeup(sc->dev, 1); -+ device_set_wakeup_enable(sc->dev, enabled); -+ mutex_unlock(&sc->mutex); -+} - -- REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM); -+void ath9k_init_wow(struct ieee80211_hw *hw) -+{ -+ struct ath_softc *sc = hw->priv; - -- /* to bring down WOW power low margin */ -- set = BIT(13); -- REG_SET_BIT(ah, AR_PCIE_PHY_REG3, set); -- /* HW WoW */ -- clr = BIT(5); -- REG_CLR_BIT(ah, AR_PCU_MISC_MODE3, clr); -+ if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_WOW_DEVICE_CAPABLE) && -+ (sc->driver_data & ATH9K_PCI_WOW) && -+ device_can_wakeup(sc->dev)) -+ hw->wiphy->wowlan = &ath9k_wowlan_support; - -- ath9k_hw_set_powermode_wow_sleep(ah); -- ah->wow_event_mask = wow_event_mask; -+ atomic_set(&sc->wow_sleep_proc_intr, -1); -+ atomic_set(&sc->wow_got_bmiss_intr, -1); - } --EXPORT_SYMBOL(ath9k_hw_wow_enable); ---- a/drivers/net/wireless/ath/ath9k/xmit.c -+++ b/drivers/net/wireless/ath/ath9k/xmit.c -@@ -1786,6 +1786,9 @@ bool ath_drain_all_txq(struct ath_softc - if (!ATH_TXQ_SETUP(sc, i)) - continue; - -+ if (!sc->tx.txq[i].axq_depth) -+ continue; -+ - if (ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum)) - npend |= BIT(i); - } -@@ -2749,6 +2752,8 @@ void ath_tx_node_cleanup(struct ath_soft - } - } - -+#ifdef CONFIG_ATH9K_TX99 -+ - int ath9k_tx99_send(struct ath_softc *sc, struct sk_buff *skb, - struct ath_tx_control *txctl) - { -@@ -2791,3 +2796,5 @@ int ath9k_tx99_send(struct ath_softc *sc - - return 0; - } -+ -+#endif /* CONFIG_ATH9K_TX99 */ ---- a/drivers/net/wireless/ath/regd.c -+++ b/drivers/net/wireless/ath/regd.c -@@ -37,17 +37,17 @@ static int __ath_regd_init(struct ath_re - - /* We enable active scan on these a case by case basis by regulatory domain */ - #define ATH9K_2GHZ_CH12_13 REG_RULE(2467-10, 2472+10, 40, 0, 20,\ -- NL80211_RRF_PASSIVE_SCAN) -+ NL80211_RRF_NO_IR) - #define ATH9K_2GHZ_CH14 REG_RULE(2484-10, 2484+10, 40, 0, 20,\ -- NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM) -+ NL80211_RRF_NO_IR | NL80211_RRF_NO_OFDM) - - /* We allow IBSS on these on a case by case basis by regulatory domain */ - #define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5350+10, 80, 0, 30,\ -- NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS) -+ NL80211_RRF_NO_IR) - #define ATH9K_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 80, 0, 30,\ -- NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS) -+ NL80211_RRF_NO_IR) - #define ATH9K_5GHZ_5725_5850 REG_RULE(5725-10, 5850+10, 80, 0, 30,\ -- NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS) -+ NL80211_RRF_NO_IR) - - #define ATH9K_2GHZ_ALL ATH9K_2GHZ_CH01_11, \ - ATH9K_2GHZ_CH12_13, \ -@@ -224,17 +224,16 @@ ath_reg_apply_beaconing_flags(struct wip - * regulatory_hint(). - */ - if (!(reg_rule->flags & -- NL80211_RRF_NO_IBSS)) -+ NL80211_RRF_NO_IR)) - ch->flags &= -- ~IEEE80211_CHAN_NO_IBSS; -+ ~IEEE80211_CHAN_NO_IR; - if (!(reg_rule->flags & -- NL80211_RRF_PASSIVE_SCAN)) -+ NL80211_RRF_NO_IR)) - ch->flags &= -- ~IEEE80211_CHAN_PASSIVE_SCAN; -+ ~IEEE80211_CHAN_NO_IR; - } else { - if (ch->beacon_found) -- ch->flags &= ~(IEEE80211_CHAN_NO_IBSS | -- IEEE80211_CHAN_PASSIVE_SCAN); -+ ch->flags &= ~IEEE80211_CHAN_NO_IR; - } - } - } -@@ -260,11 +259,11 @@ ath_reg_apply_active_scan_flags(struct w - */ - if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { - ch = &sband->channels[11]; /* CH 12 */ -- if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) -- ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; -+ if (ch->flags & IEEE80211_CHAN_NO_IR) -+ ch->flags &= ~IEEE80211_CHAN_NO_IR; - ch = &sband->channels[12]; /* CH 13 */ -- if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) -- ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; -+ if (ch->flags & IEEE80211_CHAN_NO_IR) -+ ch->flags &= ~IEEE80211_CHAN_NO_IR; - return; - } - -@@ -278,17 +277,17 @@ ath_reg_apply_active_scan_flags(struct w - ch = &sband->channels[11]; /* CH 12 */ - reg_rule = freq_reg_info(wiphy, ch->center_freq); - if (!IS_ERR(reg_rule)) { -- if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) -- if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) -- ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; -+ if (!(reg_rule->flags & NL80211_RRF_NO_IR)) -+ if (ch->flags & IEEE80211_CHAN_NO_IR) -+ ch->flags &= ~IEEE80211_CHAN_NO_IR; - } - - ch = &sband->channels[12]; /* CH 13 */ - reg_rule = freq_reg_info(wiphy, ch->center_freq); - if (!IS_ERR(reg_rule)) { -- if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) -- if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) -- ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; -+ if (!(reg_rule->flags & NL80211_RRF_NO_IR)) -+ if (ch->flags & IEEE80211_CHAN_NO_IR) -+ ch->flags &= ~IEEE80211_CHAN_NO_IR; - } - } - -@@ -320,8 +319,8 @@ static void ath_reg_apply_radar_flags(st - */ - if (!(ch->flags & IEEE80211_CHAN_DISABLED)) - ch->flags |= IEEE80211_CHAN_RADAR | -- IEEE80211_CHAN_NO_IBSS | -- IEEE80211_CHAN_PASSIVE_SCAN; -+ IEEE80211_CHAN_NO_IR | -+ IEEE80211_CHAN_NO_IR; - } - } - ---- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c -+++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c -@@ -812,7 +812,7 @@ static s32 brcmf_p2p_run_escan(struct br - struct ieee80211_channel *chan = request->channels[i]; - - if (chan->flags & (IEEE80211_CHAN_RADAR | -- IEEE80211_CHAN_PASSIVE_SCAN)) -+ IEEE80211_CHAN_NO_IR)) - continue; - - chanspecs[i] = channel_to_chanspec(&p2p->cfg->d11inf, ---- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c -+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c -@@ -202,9 +202,9 @@ static struct ieee80211_supported_band _ - - /* This is to override regulatory domains defined in cfg80211 module (reg.c) - * By default world regulatory domain defined in reg.c puts the flags -- * NL80211_RRF_PASSIVE_SCAN and NL80211_RRF_NO_IBSS for 5GHz channels (for -- * 36..48 and 149..165). With respect to these flags, wpa_supplicant doesn't -- * start p2p operations on 5GHz channels. All the changes in world regulatory -+ * NL80211_RRF_NO_IR for 5GHz channels (for * 36..48 and 149..165). -+ * With respect to these flags, wpa_supplicant doesn't * start p2p -+ * operations on 5GHz channels. All the changes in world regulatory - * domain are to be done here. - */ - static const struct ieee80211_regdomain brcmf_regdom = { -@@ -5197,10 +5197,10 @@ static s32 brcmf_construct_reginfo(struc - if (channel & WL_CHAN_RADAR) - band_chan_arr[index].flags |= - (IEEE80211_CHAN_RADAR | -- IEEE80211_CHAN_NO_IBSS); -+ IEEE80211_CHAN_NO_IR); - if (channel & WL_CHAN_PASSIVE) - band_chan_arr[index].flags |= -- IEEE80211_CHAN_PASSIVE_SCAN; -+ IEEE80211_CHAN_NO_IR; - } - } - if (!update) ---- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c -+++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c -@@ -59,23 +59,20 @@ - - #define BRCM_2GHZ_2412_2462 REG_RULE(2412-10, 2462+10, 40, 0, 19, 0) - #define BRCM_2GHZ_2467_2472 REG_RULE(2467-10, 2472+10, 20, 0, 19, \ -- NL80211_RRF_PASSIVE_SCAN | \ -- NL80211_RRF_NO_IBSS) -+ NL80211_RRF_NO_IR) - - #define BRCM_5GHZ_5180_5240 REG_RULE(5180-10, 5240+10, 40, 0, 21, \ -- NL80211_RRF_PASSIVE_SCAN | \ -- NL80211_RRF_NO_IBSS) -+ NL80211_RRF_NO_IR) - #define BRCM_5GHZ_5260_5320 REG_RULE(5260-10, 5320+10, 40, 0, 21, \ -- NL80211_RRF_PASSIVE_SCAN | \ -+ NL80211_RRF_NO_IR | \ - NL80211_RRF_DFS | \ -- NL80211_RRF_NO_IBSS) -+ NL80211_RRF_NO_IR) - #define BRCM_5GHZ_5500_5700 REG_RULE(5500-10, 5700+10, 40, 0, 21, \ -- NL80211_RRF_PASSIVE_SCAN | \ -+ NL80211_RRF_NO_IR | \ - NL80211_RRF_DFS | \ -- NL80211_RRF_NO_IBSS) -+ NL80211_RRF_NO_IR) - #define BRCM_5GHZ_5745_5825 REG_RULE(5745-10, 5825+10, 40, 0, 21, \ -- NL80211_RRF_PASSIVE_SCAN | \ -- NL80211_RRF_NO_IBSS) -+ NL80211_RRF_NO_IR) - - static const struct ieee80211_regdomain brcms_regdom_x2 = { - .n_reg_rules = 6, -@@ -395,7 +392,7 @@ brcms_c_channel_set_chanspec(struct brcm - brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false); - - brcms_b_set_chanspec(wlc->hw, chanspec, -- !!(ch->flags & IEEE80211_CHAN_PASSIVE_SCAN), -+ !!(ch->flags & IEEE80211_CHAN_NO_IR), - &txpwr); - } - -@@ -657,8 +654,8 @@ static void brcms_reg_apply_radar_flags( - */ - if (!(ch->flags & IEEE80211_CHAN_DISABLED)) - ch->flags |= IEEE80211_CHAN_RADAR | -- IEEE80211_CHAN_NO_IBSS | -- IEEE80211_CHAN_PASSIVE_SCAN; -+ IEEE80211_CHAN_NO_IR | -+ IEEE80211_CHAN_NO_IR; - } - } - -@@ -688,14 +685,13 @@ brcms_reg_apply_beaconing_flags(struct w - if (IS_ERR(rule)) - continue; - -- if (!(rule->flags & NL80211_RRF_NO_IBSS)) -- ch->flags &= ~IEEE80211_CHAN_NO_IBSS; -- if (!(rule->flags & NL80211_RRF_PASSIVE_SCAN)) -+ if (!(rule->flags & NL80211_RRF_NO_IR)) -+ ch->flags &= ~IEEE80211_CHAN_NO_IR; -+ if (!(rule->flags & NL80211_RRF_NO_IR)) - ch->flags &= -- ~IEEE80211_CHAN_PASSIVE_SCAN; -+ ~IEEE80211_CHAN_NO_IR; - } else if (ch->beacon_found) { -- ch->flags &= ~(IEEE80211_CHAN_NO_IBSS | -- IEEE80211_CHAN_PASSIVE_SCAN); -+ ch->flags &= ~IEEE80211_CHAN_NO_IR; - } - } - } ---- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c -+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c -@@ -125,13 +125,13 @@ static struct ieee80211_channel brcms_2g - CHAN2GHZ(10, 2457, IEEE80211_CHAN_NO_HT40PLUS), - CHAN2GHZ(11, 2462, IEEE80211_CHAN_NO_HT40PLUS), - CHAN2GHZ(12, 2467, -- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS | -+ IEEE80211_CHAN_NO_IR | - IEEE80211_CHAN_NO_HT40PLUS), - CHAN2GHZ(13, 2472, -- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS | -+ IEEE80211_CHAN_NO_IR | - IEEE80211_CHAN_NO_HT40PLUS), - CHAN2GHZ(14, 2484, -- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS | -+ IEEE80211_CHAN_NO_IR | - IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS | - IEEE80211_CHAN_NO_OFDM) - }; -@@ -144,51 +144,51 @@ static struct ieee80211_channel brcms_5g - CHAN5GHZ(48, IEEE80211_CHAN_NO_HT40PLUS), - /* UNII-2 */ - CHAN5GHZ(52, -- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | -- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), -+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IR | -+ IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS), - CHAN5GHZ(56, -- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | -- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), -+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IR | -+ IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS), - CHAN5GHZ(60, -- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | -- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), -+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IR | -+ IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS), - CHAN5GHZ(64, -- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | -- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), -+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IR | -+ IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS), - /* MID */ - CHAN5GHZ(100, -- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | -- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), -+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IR | -+ IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS), - CHAN5GHZ(104, -- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | -- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), -+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IR | -+ IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS), - CHAN5GHZ(108, -- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | -- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), -+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IR | -+ IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS), - CHAN5GHZ(112, -- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | -- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), -+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IR | -+ IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS), - CHAN5GHZ(116, -- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | -- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), -+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IR | -+ IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS), - CHAN5GHZ(120, -- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | -- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), -+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IR | -+ IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS), - CHAN5GHZ(124, -- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | -- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), -+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IR | -+ IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS), - CHAN5GHZ(128, -- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | -- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), -+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IR | -+ IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS), - CHAN5GHZ(132, -- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | -- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS), -+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IR | -+ IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS), - CHAN5GHZ(136, -- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | -- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS), -+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IR | -+ IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS), - CHAN5GHZ(140, -- IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS | -- IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS | -+ IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IR | -+ IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS | - IEEE80211_CHAN_NO_HT40MINUS), - /* UNII-3 */ - CHAN5GHZ(149, IEEE80211_CHAN_NO_HT40MINUS), ---- a/drivers/net/wireless/cw1200/scan.c -+++ b/drivers/net/wireless/cw1200/scan.c -@@ -197,9 +197,9 @@ void cw1200_scan_work(struct work_struct - if ((*it)->band != first->band) - break; - if (((*it)->flags ^ first->flags) & -- IEEE80211_CHAN_PASSIVE_SCAN) -+ IEEE80211_CHAN_NO_IR) - break; -- if (!(first->flags & IEEE80211_CHAN_PASSIVE_SCAN) && -+ if (!(first->flags & IEEE80211_CHAN_NO_IR) && - (*it)->max_power != first->max_power) - break; - } -@@ -210,7 +210,7 @@ void cw1200_scan_work(struct work_struct - else - scan.max_tx_rate = WSM_TRANSMIT_RATE_1; - scan.num_probes = -- (first->flags & IEEE80211_CHAN_PASSIVE_SCAN) ? 0 : 2; -+ (first->flags & IEEE80211_CHAN_NO_IR) ? 0 : 2; - scan.num_ssids = priv->scan.n_ssids; - scan.ssids = &priv->scan.ssids[0]; - scan.num_channels = it - priv->scan.curr; -@@ -233,7 +233,7 @@ void cw1200_scan_work(struct work_struct - } - for (i = 0; i < scan.num_channels; ++i) { - scan.ch[i].number = priv->scan.curr[i]->hw_value; -- if (priv->scan.curr[i]->flags & IEEE80211_CHAN_PASSIVE_SCAN) { -+ if (priv->scan.curr[i]->flags & IEEE80211_CHAN_NO_IR) { - scan.ch[i].min_chan_time = 50; - scan.ch[i].max_chan_time = 100; - } else { -@@ -241,7 +241,7 @@ void cw1200_scan_work(struct work_struct - scan.ch[i].max_chan_time = 25; - } - } -- if (!(first->flags & IEEE80211_CHAN_PASSIVE_SCAN) && -+ if (!(first->flags & IEEE80211_CHAN_NO_IR) && - priv->scan.output_power != first->max_power) { - priv->scan.output_power = first->max_power; - wsm_set_output_power(priv, ---- a/drivers/net/wireless/ipw2x00/ipw2100.c -+++ b/drivers/net/wireless/ipw2x00/ipw2100.c -@@ -1934,10 +1934,10 @@ static int ipw2100_wdev_init(struct net_ - bg_band->channels[i].max_power = geo->bg[i].max_power; - if (geo->bg[i].flags & LIBIPW_CH_PASSIVE_ONLY) - bg_band->channels[i].flags |= -- IEEE80211_CHAN_PASSIVE_SCAN; -+ IEEE80211_CHAN_NO_IR; - if (geo->bg[i].flags & LIBIPW_CH_NO_IBSS) - bg_band->channels[i].flags |= -- IEEE80211_CHAN_NO_IBSS; -+ IEEE80211_CHAN_NO_IR; - if (geo->bg[i].flags & LIBIPW_CH_RADAR_DETECT) - bg_band->channels[i].flags |= - IEEE80211_CHAN_RADAR; ---- a/drivers/net/wireless/ipw2x00/ipw2200.c -+++ b/drivers/net/wireless/ipw2x00/ipw2200.c -@@ -11472,10 +11472,10 @@ static int ipw_wdev_init(struct net_devi - bg_band->channels[i].max_power = geo->bg[i].max_power; - if (geo->bg[i].flags & LIBIPW_CH_PASSIVE_ONLY) - bg_band->channels[i].flags |= -- IEEE80211_CHAN_PASSIVE_SCAN; -+ IEEE80211_CHAN_NO_IR; - if (geo->bg[i].flags & LIBIPW_CH_NO_IBSS) - bg_band->channels[i].flags |= -- IEEE80211_CHAN_NO_IBSS; -+ IEEE80211_CHAN_NO_IR; - if (geo->bg[i].flags & LIBIPW_CH_RADAR_DETECT) - bg_band->channels[i].flags |= - IEEE80211_CHAN_RADAR; -@@ -11511,10 +11511,10 @@ static int ipw_wdev_init(struct net_devi - a_band->channels[i].max_power = geo->a[i].max_power; - if (geo->a[i].flags & LIBIPW_CH_PASSIVE_ONLY) - a_band->channels[i].flags |= -- IEEE80211_CHAN_PASSIVE_SCAN; -+ IEEE80211_CHAN_NO_IR; - if (geo->a[i].flags & LIBIPW_CH_NO_IBSS) - a_band->channels[i].flags |= -- IEEE80211_CHAN_NO_IBSS; -+ IEEE80211_CHAN_NO_IR; - if (geo->a[i].flags & LIBIPW_CH_RADAR_DETECT) - a_band->channels[i].flags |= - IEEE80211_CHAN_RADAR; ---- a/drivers/net/wireless/iwlegacy/3945-mac.c -+++ b/drivers/net/wireless/iwlegacy/3945-mac.c -@@ -1595,7 +1595,7 @@ il3945_get_channels_for_scan(struct il_p - * and use long active_dwell time. - */ - if (!is_active || il_is_channel_passive(ch_info) || -- (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) { -+ (chan->flags & IEEE80211_CHAN_NO_IR)) { - scan_ch->type = 0; /* passive */ - if (IL_UCODE_API(il->ucode_ver) == 1) - scan_ch->active_dwell = ---- a/drivers/net/wireless/iwlegacy/4965-mac.c -+++ b/drivers/net/wireless/iwlegacy/4965-mac.c -@@ -805,7 +805,7 @@ il4965_get_channels_for_scan(struct il_p - } - - if (!is_active || il_is_channel_passive(ch_info) || -- (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) -+ (chan->flags & IEEE80211_CHAN_NO_IR)) - scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; - else - scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; ---- a/drivers/net/wireless/iwlegacy/common.c -+++ b/drivers/net/wireless/iwlegacy/common.c -@@ -3447,10 +3447,10 @@ il_init_geos(struct il_priv *il) - - if (il_is_channel_valid(ch)) { - if (!(ch->flags & EEPROM_CHANNEL_IBSS)) -- geo_ch->flags |= IEEE80211_CHAN_NO_IBSS; -+ geo_ch->flags |= IEEE80211_CHAN_NO_IR; - - if (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) -- geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN; -+ geo_ch->flags |= IEEE80211_CHAN_NO_IR; - - if (ch->flags & EEPROM_CHANNEL_RADAR) - geo_ch->flags |= IEEE80211_CHAN_RADAR; ---- a/drivers/net/wireless/iwlegacy/debug.c -+++ b/drivers/net/wireless/iwlegacy/debug.c -@@ -567,12 +567,12 @@ il_dbgfs_channels_read(struct file *file - flags & IEEE80211_CHAN_RADAR ? - " (IEEE 802.11h required)" : "", - ((channels[i]. -- flags & IEEE80211_CHAN_NO_IBSS) || -+ flags & IEEE80211_CHAN_NO_IR) || - (channels[i]. - flags & IEEE80211_CHAN_RADAR)) ? "" : - ", IBSS", - channels[i]. -- flags & IEEE80211_CHAN_PASSIVE_SCAN ? -+ flags & IEEE80211_CHAN_NO_IR ? - "passive only" : "active/passive"); - } - supp_band = il_get_hw_mode(il, IEEE80211_BAND_5GHZ); -@@ -594,12 +594,12 @@ il_dbgfs_channels_read(struct file *file - flags & IEEE80211_CHAN_RADAR ? - " (IEEE 802.11h required)" : "", - ((channels[i]. -- flags & IEEE80211_CHAN_NO_IBSS) || -+ flags & IEEE80211_CHAN_NO_IR) || - (channels[i]. - flags & IEEE80211_CHAN_RADAR)) ? "" : - ", IBSS", - channels[i]. -- flags & IEEE80211_CHAN_PASSIVE_SCAN ? -+ flags & IEEE80211_CHAN_NO_IR ? - "passive only" : "active/passive"); - } - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); ---- a/drivers/net/wireless/iwlwifi/dvm/debugfs.c -+++ b/drivers/net/wireless/iwlwifi/dvm/debugfs.c -@@ -352,12 +352,12 @@ static ssize_t iwl_dbgfs_channels_read(s - channels[i].max_power, - channels[i].flags & IEEE80211_CHAN_RADAR ? - " (IEEE 802.11h required)" : "", -- ((channels[i].flags & IEEE80211_CHAN_NO_IBSS) -+ ((channels[i].flags & IEEE80211_CHAN_NO_IR) - || (channels[i].flags & - IEEE80211_CHAN_RADAR)) ? "" : - ", IBSS", - channels[i].flags & -- IEEE80211_CHAN_PASSIVE_SCAN ? -+ IEEE80211_CHAN_NO_IR ? - "passive only" : "active/passive"); - } - supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ); -@@ -375,12 +375,12 @@ static ssize_t iwl_dbgfs_channels_read(s - channels[i].max_power, - channels[i].flags & IEEE80211_CHAN_RADAR ? - " (IEEE 802.11h required)" : "", -- ((channels[i].flags & IEEE80211_CHAN_NO_IBSS) -+ ((channels[i].flags & IEEE80211_CHAN_NO_IR) - || (channels[i].flags & - IEEE80211_CHAN_RADAR)) ? "" : - ", IBSS", - channels[i].flags & -- IEEE80211_CHAN_PASSIVE_SCAN ? -+ IEEE80211_CHAN_NO_IR ? - "passive only" : "active/passive"); - } - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); ---- a/drivers/net/wireless/iwlwifi/dvm/scan.c -+++ b/drivers/net/wireless/iwlwifi/dvm/scan.c -@@ -544,7 +544,7 @@ static int iwl_get_channels_for_scan(str - channel = chan->hw_value; - scan_ch->channel = cpu_to_le16(channel); - -- if (!is_active || (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) -+ if (!is_active || (chan->flags & IEEE80211_CHAN_NO_IR)) - scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; - else - scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; ---- a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c -+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c -@@ -614,10 +614,10 @@ static int iwl_init_channel_map(struct d - channel->flags = IEEE80211_CHAN_NO_HT40; - - if (!(eeprom_ch->flags & EEPROM_CHANNEL_IBSS)) -- channel->flags |= IEEE80211_CHAN_NO_IBSS; -+ channel->flags |= IEEE80211_CHAN_NO_IR; - - if (!(eeprom_ch->flags & EEPROM_CHANNEL_ACTIVE)) -- channel->flags |= IEEE80211_CHAN_PASSIVE_SCAN; -+ channel->flags |= IEEE80211_CHAN_NO_IR; - - if (eeprom_ch->flags & EEPROM_CHANNEL_RADAR) - channel->flags |= IEEE80211_CHAN_RADAR; ---- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c -+++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c -@@ -223,10 +223,10 @@ static int iwl_init_channel_map(struct d - channel->flags |= IEEE80211_CHAN_NO_160MHZ; - - if (!(ch_flags & NVM_CHANNEL_IBSS)) -- channel->flags |= IEEE80211_CHAN_NO_IBSS; -+ channel->flags |= IEEE80211_CHAN_NO_IR; - - if (!(ch_flags & NVM_CHANNEL_ACTIVE)) -- channel->flags |= IEEE80211_CHAN_PASSIVE_SCAN; -+ channel->flags |= IEEE80211_CHAN_NO_IR; - - if (ch_flags & NVM_CHANNEL_RADAR) - channel->flags |= IEEE80211_CHAN_RADAR; ---- a/drivers/net/wireless/iwlwifi/mvm/scan.c -+++ b/drivers/net/wireless/iwlwifi/mvm/scan.c -@@ -192,7 +192,7 @@ static void iwl_mvm_scan_fill_channels(s - for (i = 0; i < cmd->channel_count; i++) { - chan->channel = cpu_to_le16(req->channels[i]->hw_value); - chan->type = cpu_to_le32(type); -- if (req->channels[i]->flags & IEEE80211_CHAN_PASSIVE_SCAN) -+ if (req->channels[i]->flags & IEEE80211_CHAN_NO_IR) - chan->type &= cpu_to_le32(~SCAN_CHANNEL_TYPE_ACTIVE); - chan->active_dwell = cpu_to_le16(active_dwell); - chan->passive_dwell = cpu_to_le16(passive_dwell); -@@ -642,7 +642,7 @@ static void iwl_build_channel_cfg(struct - channels->iter_count[index] = cpu_to_le16(1); - channels->iter_interval[index] = 0; - -- if (!(s_band->channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN)) -+ if (!(s_band->channels[i].flags & IEEE80211_CHAN_NO_IR)) - channels->type[index] |= - cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_ACTIVE); - ---- a/drivers/net/wireless/mac80211_hwsim.c -+++ b/drivers/net/wireless/mac80211_hwsim.c -@@ -159,7 +159,7 @@ static const struct ieee80211_regdomain - .reg_rules = { - REG_RULE(2412-10, 2462+10, 40, 0, 20, 0), - REG_RULE(5725-10, 5850+10, 40, 0, 30, -- NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), -+ NL80211_RRF_NO_IR), - } - }; - -@@ -1485,7 +1485,7 @@ static void hw_scan_work(struct work_str - req->channels[hwsim->scan_chan_idx]->center_freq); - - hwsim->tmp_chan = req->channels[hwsim->scan_chan_idx]; -- if (hwsim->tmp_chan->flags & IEEE80211_CHAN_PASSIVE_SCAN || -+ if (hwsim->tmp_chan->flags & IEEE80211_CHAN_NO_IR || - !req->n_ssids) { - dwell = 120; - } else { ---- a/drivers/net/wireless/mwifiex/cfg80211.c -+++ b/drivers/net/wireless/mwifiex/cfg80211.c -@@ -50,24 +50,24 @@ static const struct ieee80211_regdomain - REG_RULE(2412-10, 2462+10, 40, 3, 20, 0), - /* Channel 12 - 13 */ - REG_RULE(2467-10, 2472+10, 20, 3, 20, -- NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), -+ NL80211_RRF_NO_IR), - /* Channel 14 */ - REG_RULE(2484-10, 2484+10, 20, 3, 20, -- NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS | -+ NL80211_RRF_NO_IR | - NL80211_RRF_NO_OFDM), - /* Channel 36 - 48 */ - REG_RULE(5180-10, 5240+10, 40, 3, 20, -- NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), -+ NL80211_RRF_NO_IR), - /* Channel 149 - 165 */ - REG_RULE(5745-10, 5825+10, 40, 3, 20, -- NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), -+ NL80211_RRF_NO_IR), - /* Channel 52 - 64 */ - REG_RULE(5260-10, 5320+10, 40, 3, 30, -- NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS | -+ NL80211_RRF_NO_IR | - NL80211_RRF_DFS), - /* Channel 100 - 140 */ - REG_RULE(5500-10, 5700+10, 40, 3, 30, -- NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS | -+ NL80211_RRF_NO_IR | - NL80211_RRF_DFS), - } - }; -@@ -1968,7 +1968,7 @@ mwifiex_cfg80211_scan(struct wiphy *wiph - user_scan_cfg->chan_list[i].chan_number = chan->hw_value; - user_scan_cfg->chan_list[i].radio_type = chan->band; - -- if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) -+ if (chan->flags & IEEE80211_CHAN_NO_IR) - user_scan_cfg->chan_list[i].scan_type = - MWIFIEX_SCAN_TYPE_PASSIVE; - else ---- a/drivers/net/wireless/mwifiex/scan.c -+++ b/drivers/net/wireless/mwifiex/scan.c -@@ -515,14 +515,14 @@ mwifiex_scan_create_channel_list(struct - scan_chan_list[chan_idx].max_scan_time = - cpu_to_le16((u16) user_scan_in-> - chan_list[0].scan_time); -- else if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) -+ else if (ch->flags & IEEE80211_CHAN_NO_IR) - scan_chan_list[chan_idx].max_scan_time = - cpu_to_le16(adapter->passive_scan_time); - else - scan_chan_list[chan_idx].max_scan_time = - cpu_to_le16(adapter->active_scan_time); - -- if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) -+ if (ch->flags & IEEE80211_CHAN_NO_IR) - scan_chan_list[chan_idx].chan_scan_mode_bitmap - |= MWIFIEX_PASSIVE_SCAN; - else ---- a/drivers/net/wireless/rt2x00/rt2x00lib.h -+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h -@@ -146,7 +146,7 @@ void rt2x00queue_remove_l2pad(struct sk_ - * @local: frame is not from mac80211 - */ - int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, -- bool local); -+ struct ieee80211_sta *sta, bool local); - - /** - * rt2x00queue_update_beacon - Send new beacon from mac80211 ---- a/drivers/net/wireless/rt2x00/rt2x00mac.c -+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c -@@ -90,7 +90,7 @@ static int rt2x00mac_tx_rts_cts(struct r - frag_skb->data, data_length, tx_info, - (struct ieee80211_rts *)(skb->data)); - -- retval = rt2x00queue_write_tx_frame(queue, skb, true); -+ retval = rt2x00queue_write_tx_frame(queue, skb, NULL, true); - if (retval) { - dev_kfree_skb_any(skb); - rt2x00_warn(rt2x00dev, "Failed to send RTS/CTS frame\n"); -@@ -151,7 +151,7 @@ void rt2x00mac_tx(struct ieee80211_hw *h - goto exit_fail; - } - -- if (unlikely(rt2x00queue_write_tx_frame(queue, skb, false))) -+ if (unlikely(rt2x00queue_write_tx_frame(queue, skb, control->sta, false))) - goto exit_fail; - - /* ---- a/drivers/net/wireless/rt2x00/rt2x00queue.c -+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c -@@ -635,7 +635,7 @@ static void rt2x00queue_bar_check(struct - } - - int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, -- bool local) -+ struct ieee80211_sta *sta, bool local) - { - struct ieee80211_tx_info *tx_info; - struct queue_entry *entry; -@@ -649,7 +649,7 @@ int rt2x00queue_write_tx_frame(struct da - * after that we are free to use the skb->cb array - * for our information. - */ -- rt2x00queue_create_tx_descriptor(queue->rt2x00dev, skb, &txdesc, NULL); -+ rt2x00queue_create_tx_descriptor(queue->rt2x00dev, skb, &txdesc, sta); - - /* - * All information is retrieved from the skb->cb array, ---- a/drivers/net/wireless/rtl818x/rtl8187/dev.c -+++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c -@@ -416,7 +416,7 @@ static int rtl8187_init_urbs(struct ieee - struct rtl8187_rx_info *info; - int ret = 0; - -- while (skb_queue_len(&priv->rx_queue) < 16) { -+ while (skb_queue_len(&priv->rx_queue) < 32) { - skb = __dev_alloc_skb(RTL8187_MAX_RX, GFP_KERNEL); - if (!skb) { - ret = -ENOMEM; ---- a/drivers/net/wireless/rtlwifi/base.c -+++ b/drivers/net/wireless/rtlwifi/base.c -@@ -1078,8 +1078,8 @@ u8 rtl_is_special_data(struct ieee80211_ - - ip = (struct iphdr *)((u8 *) skb->data + mac_hdr_len + - SNAP_SIZE + PROTOC_TYPE_SIZE); -- ether_type = *(u16 *) ((u8 *) skb->data + mac_hdr_len + SNAP_SIZE); -- /* ether_type = ntohs(ether_type); */ -+ ether_type = be16_to_cpu(*(__be16 *)((u8 *)skb->data + mac_hdr_len + -+ SNAP_SIZE)); - - if (ETH_P_IP == ether_type) { - if (IPPROTO_UDP == ip->protocol) { ---- a/drivers/net/wireless/rtlwifi/regd.c -+++ b/drivers/net/wireless/rtlwifi/regd.c -@@ -59,30 +59,27 @@ static struct country_code_to_enum_rd al - */ - #define RTL819x_2GHZ_CH12_13 \ - REG_RULE(2467-10, 2472+10, 40, 0, 20,\ -- NL80211_RRF_PASSIVE_SCAN) -+ NL80211_RRF_NO_IR) - - #define RTL819x_2GHZ_CH14 \ - REG_RULE(2484-10, 2484+10, 40, 0, 20, \ -- NL80211_RRF_PASSIVE_SCAN | \ -+ NL80211_RRF_NO_IR | \ - NL80211_RRF_NO_OFDM) - - /* 5G chan 36 - chan 64*/ - #define RTL819x_5GHZ_5150_5350 \ - REG_RULE(5150-10, 5350+10, 40, 0, 30, \ -- NL80211_RRF_PASSIVE_SCAN | \ -- NL80211_RRF_NO_IBSS) -+ NL80211_RRF_NO_IR) - - /* 5G chan 100 - chan 165*/ - #define RTL819x_5GHZ_5470_5850 \ - REG_RULE(5470-10, 5850+10, 40, 0, 30, \ -- NL80211_RRF_PASSIVE_SCAN | \ -- NL80211_RRF_NO_IBSS) -+ NL80211_RRF_NO_IR) - - /* 5G chan 149 - chan 165*/ - #define RTL819x_5GHZ_5725_5850 \ - REG_RULE(5725-10, 5850+10, 40, 0, 30, \ -- NL80211_RRF_PASSIVE_SCAN | \ -- NL80211_RRF_NO_IBSS) -+ NL80211_RRF_NO_IR) - - #define RTL819x_5GHZ_ALL \ - (RTL819x_5GHZ_5150_5350, RTL819x_5GHZ_5470_5850) -@@ -185,16 +182,15 @@ static void _rtl_reg_apply_beaconing_fla - *regulatory_hint(). - */ - -- if (!(reg_rule->flags & NL80211_RRF_NO_IBSS)) -- ch->flags &= ~IEEE80211_CHAN_NO_IBSS; -+ if (!(reg_rule->flags & NL80211_RRF_NO_IR)) -+ ch->flags &= ~IEEE80211_CHAN_NO_IR; - if (!(reg_rule-> -- flags & NL80211_RRF_PASSIVE_SCAN)) -+ flags & NL80211_RRF_NO_IR)) - ch->flags &= -- ~IEEE80211_CHAN_PASSIVE_SCAN; -+ ~IEEE80211_CHAN_NO_IR; - } else { - if (ch->beacon_found) -- ch->flags &= ~(IEEE80211_CHAN_NO_IBSS | -- IEEE80211_CHAN_PASSIVE_SCAN); -+ ch->flags &= ~IEEE80211_CHAN_NO_IR; - } - } - } -@@ -219,11 +215,11 @@ static void _rtl_reg_apply_active_scan_f - */ - if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { - ch = &sband->channels[11]; /* CH 12 */ -- if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) -- ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; -+ if (ch->flags & IEEE80211_CHAN_NO_IR) -+ ch->flags &= ~IEEE80211_CHAN_NO_IR; - ch = &sband->channels[12]; /* CH 13 */ -- if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) -- ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; -+ if (ch->flags & IEEE80211_CHAN_NO_IR) -+ ch->flags &= ~IEEE80211_CHAN_NO_IR; - return; - } - -@@ -237,17 +233,17 @@ static void _rtl_reg_apply_active_scan_f - ch = &sband->channels[11]; /* CH 12 */ - reg_rule = freq_reg_info(wiphy, ch->center_freq); - if (!IS_ERR(reg_rule)) { -- if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) -- if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) -- ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; -+ if (!(reg_rule->flags & NL80211_RRF_NO_IR)) -+ if (ch->flags & IEEE80211_CHAN_NO_IR) -+ ch->flags &= ~IEEE80211_CHAN_NO_IR; - } - - ch = &sband->channels[12]; /* CH 13 */ - reg_rule = freq_reg_info(wiphy, ch->center_freq); - if (!IS_ERR(reg_rule)) { -- if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) -- if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) -- ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; -+ if (!(reg_rule->flags & NL80211_RRF_NO_IR)) -+ if (ch->flags & IEEE80211_CHAN_NO_IR) -+ ch->flags &= ~IEEE80211_CHAN_NO_IR; - } - } - -@@ -284,8 +280,8 @@ static void _rtl_reg_apply_radar_flags(s - */ - if (!(ch->flags & IEEE80211_CHAN_DISABLED)) - ch->flags |= IEEE80211_CHAN_RADAR | -- IEEE80211_CHAN_NO_IBSS | -- IEEE80211_CHAN_PASSIVE_SCAN; -+ IEEE80211_CHAN_NO_IR | -+ IEEE80211_CHAN_NO_IR; - } - } - ---- a/drivers/net/wireless/ti/wl12xx/scan.c -+++ b/drivers/net/wireless/ti/wl12xx/scan.c -@@ -47,7 +47,7 @@ static int wl1271_get_scan_channels(stru - * In active scans, we only scan channels not - * marked as passive. - */ -- (passive || !(flags & IEEE80211_CHAN_PASSIVE_SCAN))) { -+ (passive || !(flags & IEEE80211_CHAN_NO_IR))) { - wl1271_debug(DEBUG_SCAN, "band %d, center_freq %d ", - req->channels[i]->band, - req->channels[i]->center_freq); ---- a/drivers/net/wireless/ti/wlcore/cmd.c -+++ b/drivers/net/wireless/ti/wlcore/cmd.c -@@ -1688,7 +1688,7 @@ int wlcore_cmd_regdomain_config_locked(s - - if (channel->flags & (IEEE80211_CHAN_DISABLED | - IEEE80211_CHAN_RADAR | -- IEEE80211_CHAN_PASSIVE_SCAN)) -+ IEEE80211_CHAN_NO_IR)) - continue; - - ch_bit_idx = wlcore_get_reg_conf_ch_idx(b, ch); ---- a/drivers/net/wireless/ti/wlcore/main.c -+++ b/drivers/net/wireless/ti/wlcore/main.c -@@ -91,8 +91,7 @@ static void wl1271_reg_notify(struct wip - continue; - - if (ch->flags & IEEE80211_CHAN_RADAR) -- ch->flags |= IEEE80211_CHAN_NO_IBSS | -- IEEE80211_CHAN_PASSIVE_SCAN; -+ ch->flags |= IEEE80211_CHAN_NO_IR; - - } - ---- a/drivers/net/wireless/ti/wlcore/scan.c -+++ b/drivers/net/wireless/ti/wlcore/scan.c -@@ -189,14 +189,14 @@ wlcore_scan_get_channels(struct wl1271 * - flags = req_channels[i]->flags; - - if (force_passive) -- flags |= IEEE80211_CHAN_PASSIVE_SCAN; -+ flags |= IEEE80211_CHAN_NO_IR; - - if ((req_channels[i]->band == band) && - !(flags & IEEE80211_CHAN_DISABLED) && - (!!(flags & IEEE80211_CHAN_RADAR) == radar) && - /* if radar is set, we ignore the passive flag */ - (radar || -- !!(flags & IEEE80211_CHAN_PASSIVE_SCAN) == passive)) { -+ !!(flags & IEEE80211_CHAN_NO_IR) == passive)) { - - - if (flags & IEEE80211_CHAN_RADAR) { -@@ -221,7 +221,7 @@ wlcore_scan_get_channels(struct wl1271 * - (band == IEEE80211_BAND_2GHZ) && - (channels[j].channel >= 12) && - (channels[j].channel <= 14) && -- (flags & IEEE80211_CHAN_PASSIVE_SCAN) && -+ (flags & IEEE80211_CHAN_NO_IR) && - !force_passive) { - /* pactive channels treated as DFS */ - channels[j].flags = SCAN_CHANNEL_FLAGS_DFS; -@@ -244,7 +244,7 @@ wlcore_scan_get_channels(struct wl1271 * - max_dwell_time_active, - flags & IEEE80211_CHAN_RADAR ? - ", DFS" : "", -- flags & IEEE80211_CHAN_PASSIVE_SCAN ? -+ flags & IEEE80211_CHAN_NO_IR ? - ", PASSIVE" : ""); - j++; - } ---- a/include/net/cfg80211.h -+++ b/include/net/cfg80211.h -@@ -91,9 +91,8 @@ enum ieee80211_band { - * Channel flags set by the regulatory control code. - * - * @IEEE80211_CHAN_DISABLED: This channel is disabled. -- * @IEEE80211_CHAN_PASSIVE_SCAN: Only passive scanning is permitted -- * on this channel. -- * @IEEE80211_CHAN_NO_IBSS: IBSS is not allowed on this channel. -+ * @IEEE80211_CHAN_NO_IR: do not initiate radiation, this includes -+ * sending probe requests or beaconing. - * @IEEE80211_CHAN_RADAR: Radar detection is required on this channel. - * @IEEE80211_CHAN_NO_HT40PLUS: extension channel above this channel - * is not permitted. -@@ -113,8 +112,8 @@ enum ieee80211_band { - */ - enum ieee80211_channel_flags { - IEEE80211_CHAN_DISABLED = 1<<0, -- IEEE80211_CHAN_PASSIVE_SCAN = 1<<1, -- IEEE80211_CHAN_NO_IBSS = 1<<2, -+ IEEE80211_CHAN_NO_IR = 1<<1, -+ /* hole at 1<<2 */ - IEEE80211_CHAN_RADAR = 1<<3, - IEEE80211_CHAN_NO_HT40PLUS = 1<<4, - IEEE80211_CHAN_NO_HT40MINUS = 1<<5, -@@ -4149,6 +4148,7 @@ void cfg80211_radar_event(struct wiphy * - /** - * cfg80211_cac_event - Channel availability check (CAC) event - * @netdev: network device -+ * @chandef: chandef for the current channel - * @event: type of event - * @gfp: context flags - * -@@ -4157,6 +4157,7 @@ void cfg80211_radar_event(struct wiphy * - * also by full-MAC drivers. - */ - void cfg80211_cac_event(struct net_device *netdev, -+ const struct cfg80211_chan_def *chandef, - enum nl80211_radar_event event, gfp_t gfp); - - ---- a/include/uapi/linux/nl80211.h -+++ b/include/uapi/linux/nl80211.h -@@ -1508,6 +1508,9 @@ enum nl80211_commands { - * to react to radar events, e.g. initiate a channel switch or leave the - * IBSS network. - * -+ * @NL80211_ATTR_SUPPORT_5_10_MHZ: A flag indicating that the device supports -+ * 5 MHz and 10 MHz channel bandwidth. -+ * - * @NL80211_ATTR_MAX: highest attribute number currently defined - * @__NL80211_ATTR_AFTER_LAST: internal use - */ -@@ -1824,6 +1827,8 @@ enum nl80211_attrs { - - NL80211_ATTR_HANDLE_DFS, - -+ NL80211_ATTR_SUPPORT_5_10_MHZ, -+ - /* add attributes here, update the policy in nl80211.c */ - - __NL80211_ATTR_AFTER_LAST, -@@ -2224,10 +2229,9 @@ enum nl80211_band_attr { - * @NL80211_FREQUENCY_ATTR_FREQ: Frequency in MHz - * @NL80211_FREQUENCY_ATTR_DISABLED: Channel is disabled in current - * regulatory domain. -- * @NL80211_FREQUENCY_ATTR_PASSIVE_SCAN: Only passive scanning is -- * permitted on this channel in current regulatory domain. -- * @NL80211_FREQUENCY_ATTR_NO_IBSS: IBSS networks are not permitted -- * on this channel in current regulatory domain. -+ * @NL80211_FREQUENCY_ATTR_NO_IR: no mechanisms that initiate radiation -+ * are permitted on this channel, this includes sending probe -+ * requests, or modes of operation that require beaconing. - * @NL80211_FREQUENCY_ATTR_RADAR: Radar detection is mandatory - * on this channel in current regulatory domain. - * @NL80211_FREQUENCY_ATTR_MAX_TX_POWER: Maximum transmission power in mBm -@@ -2254,8 +2258,8 @@ enum nl80211_frequency_attr { - __NL80211_FREQUENCY_ATTR_INVALID, - NL80211_FREQUENCY_ATTR_FREQ, - NL80211_FREQUENCY_ATTR_DISABLED, -- NL80211_FREQUENCY_ATTR_PASSIVE_SCAN, -- NL80211_FREQUENCY_ATTR_NO_IBSS, -+ NL80211_FREQUENCY_ATTR_NO_IR, -+ __NL80211_FREQUENCY_ATTR_NO_IBSS, - NL80211_FREQUENCY_ATTR_RADAR, - NL80211_FREQUENCY_ATTR_MAX_TX_POWER, - NL80211_FREQUENCY_ATTR_DFS_STATE, -@@ -2271,6 +2275,9 @@ enum nl80211_frequency_attr { - }; - - #define NL80211_FREQUENCY_ATTR_MAX_TX_POWER NL80211_FREQUENCY_ATTR_MAX_TX_POWER -+#define NL80211_FREQUENCY_ATTR_PASSIVE_SCAN NL80211_FREQUENCY_ATTR_NO_IR -+#define NL80211_FREQUENCY_ATTR_NO_IBSS NL80211_FREQUENCY_ATTR_NO_IR -+#define NL80211_FREQUENCY_ATTR_NO_IR NL80211_FREQUENCY_ATTR_NO_IR - - /** - * enum nl80211_bitrate_attr - bitrate attributes -@@ -2413,8 +2420,9 @@ enum nl80211_sched_scan_match_attr { - * @NL80211_RRF_DFS: DFS support is required to be used - * @NL80211_RRF_PTP_ONLY: this is only for Point To Point links - * @NL80211_RRF_PTMP_ONLY: this is only for Point To Multi Point links -- * @NL80211_RRF_PASSIVE_SCAN: passive scan is required -- * @NL80211_RRF_NO_IBSS: no IBSS is allowed -+ * @NL80211_RRF_NO_IR: no mechanisms that initiate radiation are allowed, -+ * this includes probe requests or modes of operation that require -+ * beaconing. - */ - enum nl80211_reg_rule_flags { - NL80211_RRF_NO_OFDM = 1<<0, -@@ -2424,10 +2432,17 @@ enum nl80211_reg_rule_flags { - NL80211_RRF_DFS = 1<<4, - NL80211_RRF_PTP_ONLY = 1<<5, - NL80211_RRF_PTMP_ONLY = 1<<6, -- NL80211_RRF_PASSIVE_SCAN = 1<<7, -- NL80211_RRF_NO_IBSS = 1<<8, -+ NL80211_RRF_NO_IR = 1<<7, -+ __NL80211_RRF_NO_IBSS = 1<<8, - }; - -+#define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR -+#define NL80211_RRF_NO_IBSS NL80211_RRF_NO_IR -+#define NL80211_RRF_NO_IR NL80211_RRF_NO_IR -+ -+/* For backport compatibility with older userspace */ -+#define NL80211_RRF_NO_IR_ALL (NL80211_RRF_NO_IR | __NL80211_RRF_NO_IBSS) -+ - /** - * enum nl80211_dfs_regions - regulatory DFS regions - * ---- a/net/mac80211/cfg.c -+++ b/net/mac80211/cfg.c -@@ -1050,6 +1050,7 @@ static int ieee80211_stop_ap(struct wiph - struct ieee80211_local *local = sdata->local; - struct beacon_data *old_beacon; - struct probe_resp *old_probe_resp; -+ struct cfg80211_chan_def chandef; - - old_beacon = rtnl_dereference(sdata->u.ap.beacon); - if (!old_beacon) -@@ -1091,8 +1092,10 @@ static int ieee80211_stop_ap(struct wiph - ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); - - if (sdata->wdev.cac_started) { -+ chandef = sdata->vif.bss_conf.chandef; - cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); -- cfg80211_cac_event(sdata->dev, NL80211_RADAR_CAC_ABORTED, -+ cfg80211_cac_event(sdata->dev, &chandef, -+ NL80211_RADAR_CAC_ABORTED, - GFP_KERNEL); - } - ---- a/net/mac80211/iface.c -+++ b/net/mac80211/iface.c -@@ -749,6 +749,7 @@ static void ieee80211_do_stop(struct iee - u32 hw_reconf_flags = 0; - int i, flushed; - struct ps_data *ps; -+ struct cfg80211_chan_def chandef; - - clear_bit(SDATA_STATE_RUNNING, &sdata->state); - -@@ -828,11 +829,13 @@ static void ieee80211_do_stop(struct iee - cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); - - if (sdata->wdev.cac_started) { -+ chandef = sdata->vif.bss_conf.chandef; - WARN_ON(local->suspended); - mutex_lock(&local->iflist_mtx); - ieee80211_vif_release_channel(sdata); - mutex_unlock(&local->iflist_mtx); -- cfg80211_cac_event(sdata->dev, NL80211_RADAR_CAC_ABORTED, -+ cfg80211_cac_event(sdata->dev, &chandef, -+ NL80211_RADAR_CAC_ABORTED, - GFP_KERNEL); - } - -@@ -1340,7 +1343,6 @@ static void ieee80211_setup_sdata(struct - sdata->vif.bss_conf.bssid = NULL; - break; - case NL80211_IFTYPE_AP_VLAN: -- break; - case NL80211_IFTYPE_P2P_DEVICE: - sdata->vif.bss_conf.bssid = sdata->vif.addr; - break; ---- a/net/mac80211/mlme.c -+++ b/net/mac80211/mlme.c -@@ -1398,10 +1398,12 @@ void ieee80211_dfs_cac_timer_work(struct - struct ieee80211_sub_if_data *sdata = - container_of(delayed_work, struct ieee80211_sub_if_data, - dfs_cac_timer_work); -+ struct cfg80211_chan_def chandef = sdata->vif.bss_conf.chandef; - - ieee80211_vif_release_channel(sdata); -- -- cfg80211_cac_event(sdata->dev, NL80211_RADAR_CAC_FINISHED, GFP_KERNEL); -+ cfg80211_cac_event(sdata->dev, &chandef, -+ NL80211_RADAR_CAC_FINISHED, -+ GFP_KERNEL); - } - - /* MLME */ ---- a/net/mac80211/rx.c -+++ b/net/mac80211/rx.c -@@ -729,9 +729,7 @@ static void ieee80211_release_reorder_fr - lockdep_assert_held(&tid_agg_rx->reorder_lock); - - while (ieee80211_sn_less(tid_agg_rx->head_seq_num, head_seq_num)) { -- index = ieee80211_sn_sub(tid_agg_rx->head_seq_num, -- tid_agg_rx->ssn) % -- tid_agg_rx->buf_size; -+ index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size; - ieee80211_release_reorder_frame(sdata, tid_agg_rx, index, - frames); - } -@@ -757,8 +755,7 @@ static void ieee80211_sta_reorder_releas - lockdep_assert_held(&tid_agg_rx->reorder_lock); - - /* release the buffer until next missing frame */ -- index = ieee80211_sn_sub(tid_agg_rx->head_seq_num, -- tid_agg_rx->ssn) % tid_agg_rx->buf_size; -+ index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size; - if (!tid_agg_rx->reorder_buf[index] && - tid_agg_rx->stored_mpdu_num) { - /* -@@ -793,15 +790,11 @@ static void ieee80211_sta_reorder_releas - } else while (tid_agg_rx->reorder_buf[index]) { - ieee80211_release_reorder_frame(sdata, tid_agg_rx, index, - frames); -- index = ieee80211_sn_sub(tid_agg_rx->head_seq_num, -- tid_agg_rx->ssn) % -- tid_agg_rx->buf_size; -+ index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size; - } - - if (tid_agg_rx->stored_mpdu_num) { -- j = index = ieee80211_sn_sub(tid_agg_rx->head_seq_num, -- tid_agg_rx->ssn) % -- tid_agg_rx->buf_size; -+ j = index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size; - - for (; j != (index - 1) % tid_agg_rx->buf_size; - j = (j + 1) % tid_agg_rx->buf_size) { -@@ -861,8 +854,7 @@ static bool ieee80211_sta_manage_reorder - - /* Now the new frame is always in the range of the reordering buffer */ - -- index = ieee80211_sn_sub(mpdu_seq_num, -- tid_agg_rx->ssn) % tid_agg_rx->buf_size; -+ index = mpdu_seq_num % tid_agg_rx->buf_size; - - /* check if we already stored this frame */ - if (tid_agg_rx->reorder_buf[index]) { ---- a/net/mac80211/scan.c -+++ b/net/mac80211/scan.c -@@ -526,7 +526,7 @@ static int __ieee80211_start_scan(struct - ieee80211_hw_config(local, 0); - - if ((req->channels[0]->flags & -- IEEE80211_CHAN_PASSIVE_SCAN) || -+ IEEE80211_CHAN_NO_IR) || - !local->scan_req->n_ssids) { - next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; - } else { -@@ -572,7 +572,7 @@ ieee80211_scan_get_channel_time(struct i - * TODO: channel switching also consumes quite some time, - * add that delay as well to get a better estimation - */ -- if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) -+ if (chan->flags & IEEE80211_CHAN_NO_IR) - return IEEE80211_PASSIVE_CHANNEL_TIME; - return IEEE80211_PROBE_DELAY + IEEE80211_CHANNEL_TIME; - } -@@ -696,7 +696,7 @@ static void ieee80211_scan_state_set_cha - * - * In any case, it is not necessary for a passive scan. - */ -- if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN || -+ if (chan->flags & IEEE80211_CHAN_NO_IR || - !local->scan_req->n_ssids) { - *next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; - local->next_scan_state = SCAN_DECISION; -@@ -881,7 +881,7 @@ int ieee80211_request_ibss_scan(struct i - struct ieee80211_channel *tmp_ch = - &local->hw.wiphy->bands[band]->channels[i]; - -- if (tmp_ch->flags & (IEEE80211_CHAN_NO_IBSS | -+ if (tmp_ch->flags & (IEEE80211_CHAN_NO_IR | - IEEE80211_CHAN_DISABLED)) - continue; - -@@ -895,7 +895,7 @@ int ieee80211_request_ibss_scan(struct i - - local->int_scan_req->n_channels = n_ch; - } else { -- if (WARN_ON_ONCE(chan->flags & (IEEE80211_CHAN_NO_IBSS | -+ if (WARN_ON_ONCE(chan->flags & (IEEE80211_CHAN_NO_IR | - IEEE80211_CHAN_DISABLED))) - goto unlock; - ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -1728,8 +1728,7 @@ 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_IBSS | IEEE80211_CHAN_RADAR | -- IEEE80211_CHAN_PASSIVE_SCAN))) -+ if ((chan->flags & (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_RADAR))) - goto fail_rcu; - - ieee80211_xmit(sdata, skb, chan->band); ---- a/net/mac80211/util.c -+++ b/net/mac80211/util.c -@@ -2259,14 +2259,17 @@ u64 ieee80211_calculate_rx_timestamp(str - void ieee80211_dfs_cac_cancel(struct ieee80211_local *local) - { - struct ieee80211_sub_if_data *sdata; -+ struct cfg80211_chan_def chandef; - - mutex_lock(&local->iflist_mtx); - list_for_each_entry(sdata, &local->interfaces, list) { - cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); - - if (sdata->wdev.cac_started) { -+ chandef = sdata->vif.bss_conf.chandef; - ieee80211_vif_release_channel(sdata); - cfg80211_cac_event(sdata->dev, -+ &chandef, - NL80211_RADAR_CAC_ABORTED, - GFP_KERNEL); - } ---- a/net/wireless/chan.c -+++ b/net/wireless/chan.c -@@ -277,6 +277,32 @@ void cfg80211_set_dfs_state(struct wiphy - width, dfs_state); - } - -+static u32 cfg80211_get_start_freq(u32 center_freq, -+ u32 bandwidth) -+{ -+ u32 start_freq; -+ -+ if (bandwidth <= 20) -+ start_freq = center_freq; -+ else -+ start_freq = center_freq - bandwidth/2 + 10; -+ -+ return start_freq; -+} -+ -+static u32 cfg80211_get_end_freq(u32 center_freq, -+ u32 bandwidth) -+{ -+ u32 end_freq; -+ -+ if (bandwidth <= 20) -+ end_freq = center_freq; -+ else -+ end_freq = center_freq + bandwidth/2 - 10; -+ -+ return end_freq; -+} -+ - static int cfg80211_get_chans_dfs_required(struct wiphy *wiphy, - u32 center_freq, - u32 bandwidth) -@@ -284,13 +310,8 @@ static int cfg80211_get_chans_dfs_requir - struct ieee80211_channel *c; - u32 freq, start_freq, end_freq; - -- if (bandwidth <= 20) { -- start_freq = center_freq; -- end_freq = center_freq; -- } else { -- start_freq = center_freq - bandwidth/2 + 10; -- end_freq = center_freq + bandwidth/2 - 10; -- } -+ start_freq = cfg80211_get_start_freq(center_freq, bandwidth); -+ end_freq = cfg80211_get_end_freq(center_freq, bandwidth); - - for (freq = start_freq; freq <= end_freq; freq += 20) { - c = ieee80211_get_channel(wiphy, freq); -@@ -330,33 +351,159 @@ int cfg80211_chandef_dfs_required(struct - } - EXPORT_SYMBOL(cfg80211_chandef_dfs_required); - --static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, -- u32 center_freq, u32 bandwidth, -- u32 prohibited_flags) -+static int cfg80211_get_chans_dfs_usable(struct wiphy *wiphy, -+ u32 center_freq, -+ u32 bandwidth) - { - struct ieee80211_channel *c; - u32 freq, start_freq, end_freq; -+ int count = 0; - -- if (bandwidth <= 20) { -- start_freq = center_freq; -- end_freq = center_freq; -- } else { -- start_freq = center_freq - bandwidth/2 + 10; -- end_freq = center_freq + bandwidth/2 - 10; -+ start_freq = cfg80211_get_start_freq(center_freq, bandwidth); -+ end_freq = cfg80211_get_end_freq(center_freq, bandwidth); -+ -+ /* -+ * Check entire range of channels for the bandwidth. -+ * Check all channels are DFS channels (DFS_USABLE or -+ * DFS_AVAILABLE). Return number of usable channels -+ * (require CAC). Allow DFS and non-DFS channel mix. -+ */ -+ for (freq = start_freq; freq <= end_freq; freq += 20) { -+ c = ieee80211_get_channel(wiphy, freq); -+ if (!c) -+ return -EINVAL; -+ -+ if (c->flags & IEEE80211_CHAN_DISABLED) -+ return -EINVAL; -+ -+ if (c->flags & IEEE80211_CHAN_RADAR) { -+ if (c->dfs_state == NL80211_DFS_UNAVAILABLE) -+ return -EINVAL; -+ -+ if (c->dfs_state == NL80211_DFS_USABLE) -+ count++; -+ } -+ } -+ -+ return count; -+} -+ -+bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy, -+ const struct cfg80211_chan_def *chandef) -+{ -+ int width; -+ int r1, r2 = 0; -+ -+ if (WARN_ON(!cfg80211_chandef_valid(chandef))) -+ return false; -+ -+ width = cfg80211_chandef_get_width(chandef); -+ if (width < 0) -+ return false; -+ -+ r1 = cfg80211_get_chans_dfs_usable(wiphy, chandef->center_freq1, -+ width); -+ -+ if (r1 < 0) -+ return false; -+ -+ switch (chandef->width) { -+ case NL80211_CHAN_WIDTH_80P80: -+ WARN_ON(!chandef->center_freq2); -+ r2 = cfg80211_get_chans_dfs_usable(wiphy, -+ chandef->center_freq2, -+ width); -+ if (r2 < 0) -+ return false; -+ break; -+ default: -+ WARN_ON(chandef->center_freq2); -+ break; - } - -+ return (r1 + r2 > 0); -+} -+ -+ -+static bool cfg80211_get_chans_dfs_available(struct wiphy *wiphy, -+ u32 center_freq, -+ u32 bandwidth) -+{ -+ struct ieee80211_channel *c; -+ u32 freq, start_freq, end_freq; -+ -+ start_freq = cfg80211_get_start_freq(center_freq, bandwidth); -+ end_freq = cfg80211_get_end_freq(center_freq, bandwidth); -+ -+ /* -+ * Check entire range of channels for the bandwidth. -+ * If any channel in between is disabled or has not -+ * had gone through CAC return false -+ */ - for (freq = start_freq; freq <= end_freq; freq += 20) { - c = ieee80211_get_channel(wiphy, freq); - if (!c) - return false; - -- /* check for radar flags */ -- if ((prohibited_flags & c->flags & IEEE80211_CHAN_RADAR) && -+ if (c->flags & IEEE80211_CHAN_DISABLED) -+ return false; -+ -+ if ((c->flags & IEEE80211_CHAN_RADAR) && - (c->dfs_state != NL80211_DFS_AVAILABLE)) - return false; -+ } -+ -+ return true; -+} -+ -+static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy, -+ const struct cfg80211_chan_def *chandef) -+{ -+ int width; -+ int r; -+ -+ if (WARN_ON(!cfg80211_chandef_valid(chandef))) -+ return false; - -- /* check for the other flags */ -- if (c->flags & prohibited_flags & ~IEEE80211_CHAN_RADAR) -+ width = cfg80211_chandef_get_width(chandef); -+ if (width < 0) -+ return false; -+ -+ r = cfg80211_get_chans_dfs_available(wiphy, chandef->center_freq1, -+ width); -+ -+ /* If any of channels unavailable for cf1 just return */ -+ if (!r) -+ return r; -+ -+ switch (chandef->width) { -+ case NL80211_CHAN_WIDTH_80P80: -+ WARN_ON(!chandef->center_freq2); -+ r = cfg80211_get_chans_dfs_available(wiphy, -+ chandef->center_freq2, -+ width); -+ default: -+ WARN_ON(chandef->center_freq2); -+ break; -+ } -+ -+ return r; -+} -+ -+ -+static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, -+ u32 center_freq, u32 bandwidth, -+ u32 prohibited_flags) -+{ -+ struct ieee80211_channel *c; -+ u32 freq, start_freq, end_freq; -+ -+ start_freq = cfg80211_get_start_freq(center_freq, bandwidth); -+ end_freq = cfg80211_get_end_freq(center_freq, bandwidth); -+ -+ for (freq = start_freq; freq <= end_freq; freq += 20) { -+ c = ieee80211_get_channel(wiphy, freq); -+ if (!c || c->flags & prohibited_flags) - return false; - } - -@@ -462,14 +609,19 @@ bool cfg80211_reg_can_beacon(struct wiph - struct cfg80211_chan_def *chandef) - { - bool res; -+ u32 prohibited_flags = IEEE80211_CHAN_DISABLED | -+ IEEE80211_CHAN_NO_IR | -+ IEEE80211_CHAN_RADAR; - - trace_cfg80211_reg_can_beacon(wiphy, chandef); - -- res = cfg80211_chandef_usable(wiphy, chandef, -- IEEE80211_CHAN_DISABLED | -- IEEE80211_CHAN_PASSIVE_SCAN | -- IEEE80211_CHAN_NO_IBSS | -- IEEE80211_CHAN_RADAR); -+ if (cfg80211_chandef_dfs_required(wiphy, chandef) > 0 && -+ cfg80211_chandef_dfs_available(wiphy, chandef)) { -+ /* We can skip IEEE80211_CHAN_NO_IR if chandef dfs available */ -+ prohibited_flags = IEEE80211_CHAN_DISABLED; -+ } -+ -+ res = cfg80211_chandef_usable(wiphy, chandef, prohibited_flags); - - trace_cfg80211_return_bool(res); - return res; ---- a/net/wireless/core.h -+++ b/net/wireless/core.h -@@ -382,6 +382,19 @@ int cfg80211_can_use_iftype_chan(struct - enum cfg80211_chan_mode chanmode, - u8 radar_detect); - -+/** -+ * cfg80211_chandef_dfs_usable - checks if chandef is DFS usable -+ * @wiphy: the wiphy to validate against -+ * @chandef: the channel definition to check -+ * -+ * Checks if chandef is usable and we can/need start CAC on such channel. -+ * -+ * Return: Return true if all channels available and at least -+ * one channel require CAC (NL80211_DFS_USABLE) -+ */ -+bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy, -+ const struct cfg80211_chan_def *chandef); -+ - void cfg80211_set_dfs_state(struct wiphy *wiphy, - const struct cfg80211_chan_def *chandef, - enum nl80211_dfs_state dfs_state); ---- a/net/wireless/genregdb.awk -+++ b/net/wireless/genregdb.awk -@@ -107,10 +107,13 @@ active && /^[ \t]*\(/ { - } else if (flagarray[arg] == "PTMP-ONLY") { - flags = flags "\n\t\t\tNL80211_RRF_PTMP_ONLY | " - } else if (flagarray[arg] == "PASSIVE-SCAN") { -- flags = flags "\n\t\t\tNL80211_RRF_PASSIVE_SCAN | " -+ flags = flags "\n\t\t\tNL80211_RRF_NO_IR | " - } else if (flagarray[arg] == "NO-IBSS") { -- flags = flags "\n\t\t\tNL80211_RRF_NO_IBSS | " -+ flags = flags "\n\t\t\tNL80211_RRF_NO_IR | " -+ } else if (flagarray[arg] == "NO-IR") { -+ flags = flags "\n\t\t\tNL80211_RRF_NO_IR | " - } -+ - } - flags = flags "0" - printf "\t\tREG_RULE(%d, %d, %d, %d, %d, %s),\n", start, end, bw, gain, power, flags ---- a/net/wireless/ibss.c -+++ b/net/wireless/ibss.c -@@ -274,7 +274,7 @@ int cfg80211_ibss_wext_join(struct cfg80 - - for (i = 0; i < sband->n_channels; i++) { - chan = &sband->channels[i]; -- if (chan->flags & IEEE80211_CHAN_NO_IBSS) -+ if (chan->flags & IEEE80211_CHAN_NO_IR) - continue; - if (chan->flags & IEEE80211_CHAN_DISABLED) - continue; -@@ -345,7 +345,7 @@ int cfg80211_ibss_wext_siwfreq(struct ne - chan = ieee80211_get_channel(wdev->wiphy, freq); - if (!chan) - return -EINVAL; -- if (chan->flags & IEEE80211_CHAN_NO_IBSS || -+ if (chan->flags & IEEE80211_CHAN_NO_IR || - chan->flags & IEEE80211_CHAN_DISABLED) - return -EINVAL; - } ---- a/net/wireless/mesh.c -+++ b/net/wireless/mesh.c -@@ -141,8 +141,7 @@ int __cfg80211_join_mesh(struct cfg80211 - - for (i = 0; i < sband->n_channels; i++) { - chan = &sband->channels[i]; -- if (chan->flags & (IEEE80211_CHAN_NO_IBSS | -- IEEE80211_CHAN_PASSIVE_SCAN | -+ if (chan->flags & (IEEE80211_CHAN_NO_IR | - IEEE80211_CHAN_DISABLED | - IEEE80211_CHAN_RADAR)) - continue; ---- a/net/wireless/mlme.c -+++ b/net/wireless/mlme.c -@@ -763,12 +763,12 @@ void cfg80211_radar_event(struct wiphy * - EXPORT_SYMBOL(cfg80211_radar_event); - - void cfg80211_cac_event(struct net_device *netdev, -+ const struct cfg80211_chan_def *chandef, - enum nl80211_radar_event event, gfp_t gfp) - { - struct wireless_dev *wdev = netdev->ieee80211_ptr; - struct wiphy *wiphy = wdev->wiphy; - struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); -- struct cfg80211_chan_def chandef; - unsigned long timeout; - - trace_cfg80211_cac_event(netdev, event); -@@ -779,14 +779,12 @@ void cfg80211_cac_event(struct net_devic - if (WARN_ON(!wdev->channel)) - return; - -- cfg80211_chandef_create(&chandef, wdev->channel, NL80211_CHAN_NO_HT); -- - switch (event) { - case NL80211_RADAR_CAC_FINISHED: - timeout = wdev->cac_start_time + - msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS); - WARN_ON(!time_after_eq(jiffies, timeout)); -- cfg80211_set_dfs_state(wiphy, &chandef, NL80211_DFS_AVAILABLE); -+ cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE); - break; - case NL80211_RADAR_CAC_ABORTED: - break; -@@ -796,6 +794,6 @@ void cfg80211_cac_event(struct net_devic - } - wdev->cac_started = false; - -- nl80211_radar_notify(rdev, &chandef, event, netdev, gfp); -+ nl80211_radar_notify(rdev, chandef, event, netdev, gfp); - } - EXPORT_SYMBOL(cfg80211_cac_event); ---- a/net/wireless/nl80211.c -+++ b/net/wireless/nl80211.c -@@ -545,12 +545,12 @@ static int nl80211_msg_put_channel(struc - if ((chan->flags & IEEE80211_CHAN_DISABLED) && - nla_put_flag(msg, NL80211_FREQUENCY_ATTR_DISABLED)) - goto nla_put_failure; -- if ((chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) && -- nla_put_flag(msg, NL80211_FREQUENCY_ATTR_PASSIVE_SCAN)) -- goto nla_put_failure; -- if ((chan->flags & IEEE80211_CHAN_NO_IBSS) && -- nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IBSS)) -- goto nla_put_failure; -+ if (chan->flags & IEEE80211_CHAN_NO_IR) { -+ if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IR)) -+ goto nla_put_failure; -+ if (nla_put_flag(msg, __NL80211_FREQUENCY_ATTR_NO_IBSS)) -+ goto nla_put_failure; -+ } - if (chan->flags & IEEE80211_CHAN_RADAR) { - if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR)) - goto nla_put_failure; -@@ -1229,7 +1229,7 @@ static int nl80211_send_wiphy(struct cfg - nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP)) - goto nla_put_failure; - if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ) && -- nla_put_flag(msg, WIPHY_FLAG_SUPPORTS_5_10_MHZ)) -+ nla_put_flag(msg, NL80211_ATTR_SUPPORT_5_10_MHZ)) - goto nla_put_failure; - - state->split_start++; -@@ -2170,7 +2170,7 @@ static inline u64 wdev_id(struct wireles - } - - static int nl80211_send_chandef(struct sk_buff *msg, -- struct cfg80211_chan_def *chandef) -+ const struct cfg80211_chan_def *chandef) - { - WARN_ON(!cfg80211_chandef_valid(chandef)); - -@@ -5653,7 +5653,7 @@ static int nl80211_start_radar_detection - if (err == 0) - return -EINVAL; - -- if (chandef.chan->dfs_state != NL80211_DFS_USABLE) -+ if (!cfg80211_chandef_dfs_usable(wdev->wiphy, &chandef)) - return -EINVAL; - - if (!rdev->ops->start_radar_detection) -@@ -10882,7 +10882,7 @@ EXPORT_SYMBOL(cfg80211_cqm_txe_notify); - - void - nl80211_radar_notify(struct cfg80211_registered_device *rdev, -- struct cfg80211_chan_def *chandef, -+ const struct cfg80211_chan_def *chandef, - enum nl80211_radar_event event, - struct net_device *netdev, gfp_t gfp) - { ---- a/net/wireless/nl80211.h -+++ b/net/wireless/nl80211.h -@@ -70,7 +70,7 @@ int nl80211_send_mgmt(struct cfg80211_re - - void - nl80211_radar_notify(struct cfg80211_registered_device *rdev, -- struct cfg80211_chan_def *chandef, -+ const struct cfg80211_chan_def *chandef, - enum nl80211_radar_event event, - struct net_device *netdev, gfp_t gfp); - ---- a/net/wireless/reg.c -+++ b/net/wireless/reg.c -@@ -163,35 +163,29 @@ static const struct ieee80211_regdomain - REG_RULE(2412-10, 2462+10, 40, 6, 20, 0), - /* IEEE 802.11b/g, channels 12..13. */ - REG_RULE(2467-10, 2472+10, 40, 6, 20, -- NL80211_RRF_PASSIVE_SCAN | -- NL80211_RRF_NO_IBSS), -+ NL80211_RRF_NO_IR), - /* IEEE 802.11 channel 14 - Only JP enables - * this and for 802.11b only */ - REG_RULE(2484-10, 2484+10, 20, 6, 20, -- NL80211_RRF_PASSIVE_SCAN | -- NL80211_RRF_NO_IBSS | -+ NL80211_RRF_NO_IR | - NL80211_RRF_NO_OFDM), - /* IEEE 802.11a, channel 36..48 */ - REG_RULE(5180-10, 5240+10, 160, 6, 20, -- NL80211_RRF_PASSIVE_SCAN | -- NL80211_RRF_NO_IBSS), -+ NL80211_RRF_NO_IR), - - /* IEEE 802.11a, channel 52..64 - DFS required */ - REG_RULE(5260-10, 5320+10, 160, 6, 20, -- NL80211_RRF_PASSIVE_SCAN | -- NL80211_RRF_NO_IBSS | -+ NL80211_RRF_NO_IR | - NL80211_RRF_DFS), - - /* IEEE 802.11a, channel 100..144 - DFS required */ - REG_RULE(5500-10, 5720+10, 160, 6, 20, -- NL80211_RRF_PASSIVE_SCAN | -- NL80211_RRF_NO_IBSS | -+ NL80211_RRF_NO_IR | - NL80211_RRF_DFS), - - /* IEEE 802.11a, channel 149..165 */ - REG_RULE(5745-10, 5825+10, 80, 6, 20, -- NL80211_RRF_PASSIVE_SCAN | -- NL80211_RRF_NO_IBSS), -+ NL80211_RRF_NO_IR), - - /* IEEE 802.11ad (60gHz), channels 1..3 */ - REG_RULE(56160+2160*1-1080, 56160+2160*3+1080, 2160, 0, 0, 0), -@@ -698,10 +692,8 @@ regdom_intersect(const struct ieee80211_ - static u32 map_regdom_flags(u32 rd_flags) - { - u32 channel_flags = 0; -- if (rd_flags & NL80211_RRF_PASSIVE_SCAN) -- channel_flags |= IEEE80211_CHAN_PASSIVE_SCAN; -- if (rd_flags & NL80211_RRF_NO_IBSS) -- channel_flags |= IEEE80211_CHAN_NO_IBSS; -+ if (rd_flags & NL80211_RRF_NO_IR_ALL) -+ channel_flags |= IEEE80211_CHAN_NO_IR; - if (rd_flags & NL80211_RRF_DFS) - channel_flags |= IEEE80211_CHAN_RADAR; - if (rd_flags & NL80211_RRF_NO_OFDM) -@@ -1066,13 +1058,8 @@ static void handle_reg_beacon(struct wip - chan_before.center_freq = chan->center_freq; - chan_before.flags = chan->flags; - -- if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) { -- chan->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; -- channel_changed = true; -- } -- -- if (chan->flags & IEEE80211_CHAN_NO_IBSS) { -- chan->flags &= ~IEEE80211_CHAN_NO_IBSS; -+ if (chan->flags & IEEE80211_CHAN_NO_IR) { -+ chan->flags &= ~IEEE80211_CHAN_NO_IR; - channel_changed = true; - } - ---- /dev/null -+++ b/drivers/net/wireless/ath/ath9k/ar9003_wow.c -@@ -0,0 +1,422 @@ -+/* -+ * Copyright (c) 2012 Qualcomm Atheros, Inc. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include -+#include "ath9k.h" -+#include "reg.h" -+#include "hw-ops.h" -+ -+const char *ath9k_hw_wow_event_to_string(u32 wow_event) -+{ -+ if (wow_event & AH_WOW_MAGIC_PATTERN_EN) -+ return "Magic pattern"; -+ if (wow_event & AH_WOW_USER_PATTERN_EN) -+ return "User pattern"; -+ if (wow_event & AH_WOW_LINK_CHANGE) -+ return "Link change"; -+ if (wow_event & AH_WOW_BEACON_MISS) -+ return "Beacon miss"; -+ -+ return "unknown reason"; -+} -+EXPORT_SYMBOL(ath9k_hw_wow_event_to_string); -+ -+static void ath9k_hw_set_powermode_wow_sleep(struct ath_hw *ah) -+{ -+ struct ath_common *common = ath9k_hw_common(ah); -+ -+ REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); -+ -+ /* set rx disable bit */ -+ REG_WRITE(ah, AR_CR, AR_CR_RXD); -+ -+ if (!ath9k_hw_wait(ah, AR_CR, AR_CR_RXE, 0, AH_WAIT_TIMEOUT)) { -+ ath_err(common, "Failed to stop Rx DMA in 10ms AR_CR=0x%08x AR_DIAG_SW=0x%08x\n", -+ REG_READ(ah, AR_CR), REG_READ(ah, AR_DIAG_SW)); -+ return; -+ } -+ -+ REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_ON_INT); -+} -+ -+static void ath9k_wow_create_keep_alive_pattern(struct ath_hw *ah) -+{ -+ struct ath_common *common = ath9k_hw_common(ah); -+ u8 sta_mac_addr[ETH_ALEN], ap_mac_addr[ETH_ALEN]; -+ u32 ctl[13] = {0}; -+ u32 data_word[KAL_NUM_DATA_WORDS]; -+ u8 i; -+ u32 wow_ka_data_word0; -+ -+ memcpy(sta_mac_addr, common->macaddr, ETH_ALEN); -+ memcpy(ap_mac_addr, common->curbssid, ETH_ALEN); -+ -+ /* set the transmit buffer */ -+ ctl[0] = (KAL_FRAME_LEN | (MAX_RATE_POWER << 16)); -+ ctl[1] = 0; -+ ctl[3] = 0xb; /* OFDM_6M hardware value for this rate */ -+ ctl[4] = 0; -+ ctl[7] = (ah->txchainmask) << 2; -+ ctl[2] = 0xf << 16; /* tx_tries 0 */ -+ -+ for (i = 0; i < KAL_NUM_DESC_WORDS; i++) -+ REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]); -+ -+ REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]); -+ -+ data_word[0] = (KAL_FRAME_TYPE << 2) | (KAL_FRAME_SUB_TYPE << 4) | -+ (KAL_TO_DS << 8) | (KAL_DURATION_ID << 16); -+ data_word[1] = (ap_mac_addr[3] << 24) | (ap_mac_addr[2] << 16) | -+ (ap_mac_addr[1] << 8) | (ap_mac_addr[0]); -+ data_word[2] = (sta_mac_addr[1] << 24) | (sta_mac_addr[0] << 16) | -+ (ap_mac_addr[5] << 8) | (ap_mac_addr[4]); -+ data_word[3] = (sta_mac_addr[5] << 24) | (sta_mac_addr[4] << 16) | -+ (sta_mac_addr[3] << 8) | (sta_mac_addr[2]); -+ data_word[4] = (ap_mac_addr[3] << 24) | (ap_mac_addr[2] << 16) | -+ (ap_mac_addr[1] << 8) | (ap_mac_addr[0]); -+ data_word[5] = (ap_mac_addr[5] << 8) | (ap_mac_addr[4]); -+ -+ if (AR_SREV_9462_20(ah)) { -+ /* AR9462 2.0 has an extra descriptor word (time based -+ * discard) compared to other chips */ -+ REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + (12 * 4)), 0); -+ wow_ka_data_word0 = AR_WOW_TXBUF(13); -+ } else { -+ wow_ka_data_word0 = AR_WOW_TXBUF(12); -+ } -+ -+ for (i = 0; i < KAL_NUM_DATA_WORDS; i++) -+ REG_WRITE(ah, (wow_ka_data_word0 + i*4), data_word[i]); -+ -+} -+ -+void ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern, -+ u8 *user_mask, int pattern_count, -+ int pattern_len) -+{ -+ int i; -+ u32 pattern_val, mask_val; -+ u32 set, clr; -+ -+ /* FIXME: should check count by querying the hardware capability */ -+ if (pattern_count >= MAX_NUM_PATTERN) -+ return; -+ -+ REG_SET_BIT(ah, AR_WOW_PATTERN, BIT(pattern_count)); -+ -+ /* set the registers for pattern */ -+ for (i = 0; i < MAX_PATTERN_SIZE; i += 4) { -+ memcpy(&pattern_val, user_pattern, 4); -+ REG_WRITE(ah, (AR_WOW_TB_PATTERN(pattern_count) + i), -+ pattern_val); -+ user_pattern += 4; -+ } -+ -+ /* set the registers for mask */ -+ for (i = 0; i < MAX_PATTERN_MASK_SIZE; i += 4) { -+ memcpy(&mask_val, user_mask, 4); -+ REG_WRITE(ah, (AR_WOW_TB_MASK(pattern_count) + i), mask_val); -+ user_mask += 4; -+ } -+ -+ /* set the pattern length to be matched -+ * -+ * AR_WOW_LENGTH1_REG1 -+ * bit 31:24 pattern 0 length -+ * bit 23:16 pattern 1 length -+ * bit 15:8 pattern 2 length -+ * bit 7:0 pattern 3 length -+ * -+ * AR_WOW_LENGTH1_REG2 -+ * bit 31:24 pattern 4 length -+ * bit 23:16 pattern 5 length -+ * bit 15:8 pattern 6 length -+ * bit 7:0 pattern 7 length -+ * -+ * the below logic writes out the new -+ * pattern length for the corresponding -+ * pattern_count, while masking out the -+ * other fields -+ */ -+ -+ ah->wow_event_mask |= BIT(pattern_count + AR_WOW_PAT_FOUND_SHIFT); -+ -+ if (pattern_count < 4) { -+ /* Pattern 0-3 uses AR_WOW_LENGTH1 register */ -+ set = (pattern_len & AR_WOW_LENGTH_MAX) << -+ AR_WOW_LEN1_SHIFT(pattern_count); -+ clr = AR_WOW_LENGTH1_MASK(pattern_count); -+ REG_RMW(ah, AR_WOW_LENGTH1, set, clr); -+ } else { -+ /* Pattern 4-7 uses AR_WOW_LENGTH2 register */ -+ set = (pattern_len & AR_WOW_LENGTH_MAX) << -+ AR_WOW_LEN2_SHIFT(pattern_count); -+ clr = AR_WOW_LENGTH2_MASK(pattern_count); -+ REG_RMW(ah, AR_WOW_LENGTH2, set, clr); -+ } -+ -+} -+EXPORT_SYMBOL(ath9k_hw_wow_apply_pattern); -+ -+u32 ath9k_hw_wow_wakeup(struct ath_hw *ah) -+{ -+ u32 wow_status = 0; -+ u32 val = 0, rval; -+ -+ /* -+ * read the WoW status register to know -+ * the wakeup reason -+ */ -+ rval = REG_READ(ah, AR_WOW_PATTERN); -+ val = AR_WOW_STATUS(rval); -+ -+ /* -+ * mask only the WoW events that we have enabled. Sometimes -+ * we have spurious WoW events from the AR_WOW_PATTERN -+ * register. This mask will clean it up. -+ */ -+ -+ val &= ah->wow_event_mask; -+ -+ if (val) { -+ if (val & AR_WOW_MAGIC_PAT_FOUND) -+ wow_status |= AH_WOW_MAGIC_PATTERN_EN; -+ if (AR_WOW_PATTERN_FOUND(val)) -+ wow_status |= AH_WOW_USER_PATTERN_EN; -+ if (val & AR_WOW_KEEP_ALIVE_FAIL) -+ wow_status |= AH_WOW_LINK_CHANGE; -+ if (val & AR_WOW_BEACON_FAIL) -+ wow_status |= AH_WOW_BEACON_MISS; -+ } -+ -+ /* -+ * set and clear WOW_PME_CLEAR registers for the chip to -+ * generate next wow signal. -+ * disable D3 before accessing other registers ? -+ */ -+ -+ /* do we need to check the bit value 0x01000000 (7-10) ?? */ -+ REG_RMW(ah, AR_PCIE_PM_CTRL, AR_PMCTRL_WOW_PME_CLR, -+ AR_PMCTRL_PWR_STATE_D1D3); -+ -+ /* -+ * clear all events -+ */ -+ REG_WRITE(ah, AR_WOW_PATTERN, -+ AR_WOW_CLEAR_EVENTS(REG_READ(ah, AR_WOW_PATTERN))); -+ -+ /* -+ * restore the beacon threshold to init value -+ */ -+ REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); -+ -+ /* -+ * Restore the way the PCI-E reset, Power-On-Reset, external -+ * PCIE_POR_SHORT pins are tied to its original value. -+ * Previously just before WoW sleep, we untie the PCI-E -+ * reset to our Chip's Power On Reset so that any PCI-E -+ * reset from the bus will not reset our chip -+ */ -+ if (ah->is_pciexpress) -+ ath9k_hw_configpcipowersave(ah, false); -+ -+ ah->wow_event_mask = 0; -+ -+ return wow_status; -+} -+EXPORT_SYMBOL(ath9k_hw_wow_wakeup); -+ -+void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable) -+{ -+ u32 wow_event_mask; -+ u32 set, clr; -+ -+ /* -+ * wow_event_mask is a mask to the AR_WOW_PATTERN register to -+ * indicate which WoW events we have enabled. The WoW events -+ * are from the 'pattern_enable' in this function and -+ * 'pattern_count' of ath9k_hw_wow_apply_pattern() -+ */ -+ wow_event_mask = ah->wow_event_mask; -+ -+ /* -+ * Untie Power-on-Reset from the PCI-E-Reset. When we are in -+ * WOW sleep, we do want the Reset from the PCI-E to disturb -+ * our hw state -+ */ -+ if (ah->is_pciexpress) { -+ /* -+ * we need to untie the internal POR (power-on-reset) -+ * to the external PCI-E reset. We also need to tie -+ * the PCI-E Phy reset to the PCI-E reset. -+ */ -+ set = AR_WA_RESET_EN | AR_WA_POR_SHORT; -+ clr = AR_WA_UNTIE_RESET_EN | AR_WA_D3_L1_DISABLE; -+ REG_RMW(ah, AR_WA, set, clr); -+ } -+ -+ /* -+ * set the power states appropriately and enable PME -+ */ -+ set = AR_PMCTRL_HOST_PME_EN | AR_PMCTRL_PWR_PM_CTRL_ENA | -+ AR_PMCTRL_AUX_PWR_DET | AR_PMCTRL_WOW_PME_CLR; -+ -+ /* -+ * set and clear WOW_PME_CLEAR registers for the chip -+ * to generate next wow signal. -+ */ -+ REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set); -+ clr = AR_PMCTRL_WOW_PME_CLR; -+ REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr); -+ -+ /* -+ * Setup for: -+ * - beacon misses -+ * - magic pattern -+ * - keep alive timeout -+ * - pattern matching -+ */ -+ -+ /* -+ * Program default values for pattern backoff, aifs/slot/KAL count, -+ * beacon miss timeout, KAL timeout, etc. -+ */ -+ set = AR_WOW_BACK_OFF_SHIFT(AR_WOW_PAT_BACKOFF); -+ REG_SET_BIT(ah, AR_WOW_PATTERN, set); -+ -+ set = AR_WOW_AIFS_CNT(AR_WOW_CNT_AIFS_CNT) | -+ AR_WOW_SLOT_CNT(AR_WOW_CNT_SLOT_CNT) | -+ AR_WOW_KEEP_ALIVE_CNT(AR_WOW_CNT_KA_CNT); -+ REG_SET_BIT(ah, AR_WOW_COUNT, set); -+ -+ if (pattern_enable & AH_WOW_BEACON_MISS) -+ set = AR_WOW_BEACON_TIMO; -+ /* We are not using beacon miss, program a large value */ -+ else -+ set = AR_WOW_BEACON_TIMO_MAX; -+ -+ REG_WRITE(ah, AR_WOW_BCN_TIMO, set); -+ -+ /* -+ * Keep alive timo in ms except AR9280 -+ */ -+ if (!pattern_enable) -+ set = AR_WOW_KEEP_ALIVE_NEVER; -+ else -+ set = KAL_TIMEOUT * 32; -+ -+ REG_WRITE(ah, AR_WOW_KEEP_ALIVE_TIMO, set); -+ -+ /* -+ * Keep alive delay in us. based on 'power on clock', -+ * therefore in usec -+ */ -+ set = KAL_DELAY * 1000; -+ REG_WRITE(ah, AR_WOW_KEEP_ALIVE_DELAY, set); -+ -+ /* -+ * Create keep alive pattern to respond to beacons -+ */ -+ ath9k_wow_create_keep_alive_pattern(ah); -+ -+ /* -+ * Configure MAC WoW Registers -+ */ -+ set = 0; -+ /* Send keep alive timeouts anyway */ -+ clr = AR_WOW_KEEP_ALIVE_AUTO_DIS; -+ -+ if (pattern_enable & AH_WOW_LINK_CHANGE) -+ wow_event_mask |= AR_WOW_KEEP_ALIVE_FAIL; -+ else -+ set = AR_WOW_KEEP_ALIVE_FAIL_DIS; -+ -+ set = AR_WOW_KEEP_ALIVE_FAIL_DIS; -+ REG_RMW(ah, AR_WOW_KEEP_ALIVE, set, clr); -+ -+ /* -+ * we are relying on a bmiss failure. ensure we have -+ * enough threshold to prevent false positives -+ */ -+ REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_THR_BM_THR, -+ AR_WOW_BMISSTHRESHOLD); -+ -+ set = 0; -+ clr = 0; -+ -+ if (pattern_enable & AH_WOW_BEACON_MISS) { -+ set = AR_WOW_BEACON_FAIL_EN; -+ wow_event_mask |= AR_WOW_BEACON_FAIL; -+ } else { -+ clr = AR_WOW_BEACON_FAIL_EN; -+ } -+ -+ REG_RMW(ah, AR_WOW_BCN_EN, set, clr); -+ -+ set = 0; -+ clr = 0; -+ /* -+ * Enable the magic packet registers -+ */ -+ if (pattern_enable & AH_WOW_MAGIC_PATTERN_EN) { -+ set = AR_WOW_MAGIC_EN; -+ wow_event_mask |= AR_WOW_MAGIC_PAT_FOUND; -+ } else { -+ clr = AR_WOW_MAGIC_EN; -+ } -+ set |= AR_WOW_MAC_INTR_EN; -+ REG_RMW(ah, AR_WOW_PATTERN, set, clr); -+ -+ REG_WRITE(ah, AR_WOW_PATTERN_MATCH_LT_256B, -+ AR_WOW_PATTERN_SUPPORTED); -+ -+ /* -+ * Set the power states appropriately and enable PME -+ */ -+ clr = 0; -+ set = AR_PMCTRL_PWR_STATE_D1D3 | AR_PMCTRL_HOST_PME_EN | -+ AR_PMCTRL_PWR_PM_CTRL_ENA; -+ -+ clr = AR_PCIE_PM_CTRL_ENA; -+ REG_RMW(ah, AR_PCIE_PM_CTRL, set, clr); -+ -+ /* -+ * this is needed to prevent the chip waking up -+ * the host within 3-4 seconds with certain -+ * platform/BIOS. The fix is to enable -+ * D1 & D3 to match original definition and -+ * also match the OTP value. Anyway this -+ * is more related to SW WOW. -+ */ -+ clr = AR_PMCTRL_PWR_STATE_D1D3; -+ REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr); -+ -+ set = AR_PMCTRL_PWR_STATE_D1D3_REAL; -+ REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set); -+ -+ REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM); -+ -+ /* to bring down WOW power low margin */ -+ set = BIT(13); -+ REG_SET_BIT(ah, AR_PCIE_PHY_REG3, set); -+ /* HW WoW */ -+ clr = BIT(5); -+ REG_CLR_BIT(ah, AR_PCU_MISC_MODE3, clr); -+ -+ ath9k_hw_set_powermode_wow_sleep(ah); -+ ah->wow_event_mask = wow_event_mask; -+} -+EXPORT_SYMBOL(ath9k_hw_wow_enable); +-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 + } + + 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) + ); + +-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) + ); + +-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) + ); + +-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) + ); + +-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) +-); +- +-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/drivers/net/wireless/ath/ath9k/tx99.c -@@ -0,0 +1,263 @@ ++++ b/net/mac80211/ethtool.c +@@ -0,0 +1,244 @@ +/* -+ * Copyright (c) 2013 Qualcomm Atheros, Inc. ++ * mac80211 ethtool hooks for cfg80211 + * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. ++ * Copied from cfg.c - originally ++ * Copyright 2006-2010 Johannes Berg ++ * Copyright 2014 Intel Corporation (Author: Johannes Berg) + * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * This file is GPLv2 as found in COPYING. + */ -+ -+#include "ath9k.h" -+ -+static void ath9k_tx99_stop(struct ath_softc *sc) ++#include ++#include ++#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 ath_hw *ah = sc->sc_ah; -+ struct ath_common *common = ath9k_hw_common(ah); -+ -+ ath_drain_all_txq(sc); -+ ath_startrecv(sc); -+ -+ ath9k_hw_set_interrupts(ah); -+ ath9k_hw_enable_interrupts(ah); -+ -+ ieee80211_wake_queues(sc->hw); ++ struct ieee80211_local *local = wiphy_priv(dev->ieee80211_ptr->wiphy); + -+ kfree_skb(sc->tx99_skb); -+ sc->tx99_skb = NULL; -+ sc->tx99_state = false; ++ if (rp->rx_mini_pending != 0 || rp->rx_jumbo_pending != 0) ++ return -EINVAL; + -+ ath9k_hw_tx99_stop(sc->sc_ah); -+ ath_dbg(common, XMIT, "TX99 stopped\n"); ++ return drv_set_ringparam(local, rp->tx_pending, rp->rx_pending); +} + -+static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc) ++static void ieee80211_get_ringparam(struct net_device *dev, ++ struct ethtool_ringparam *rp) +{ -+ static u8 PN9Data[] = {0xff, 0x87, 0xb8, 0x59, 0xb7, 0xa1, 0xcc, 0x24, -+ 0x57, 0x5e, 0x4b, 0x9c, 0x0e, 0xe9, 0xea, 0x50, -+ 0x2a, 0xbe, 0xb4, 0x1b, 0xb6, 0xb0, 0x5d, 0xf1, -+ 0xe6, 0x9a, 0xe3, 0x45, 0xfd, 0x2c, 0x53, 0x18, -+ 0x0c, 0xca, 0xc9, 0xfb, 0x49, 0x37, 0xe5, 0xa8, -+ 0x51, 0x3b, 0x2f, 0x61, 0xaa, 0x72, 0x18, 0x84, -+ 0x02, 0x23, 0x23, 0xab, 0x63, 0x89, 0x51, 0xb3, -+ 0xe7, 0x8b, 0x72, 0x90, 0x4c, 0xe8, 0xfb, 0xc0}; -+ u32 len = 1200; -+ struct ieee80211_hw *hw = sc->hw; -+ struct ieee80211_hdr *hdr; -+ struct ieee80211_tx_info *tx_info; -+ struct sk_buff *skb; -+ -+ skb = alloc_skb(len, GFP_KERNEL); -+ if (!skb) -+ return NULL; ++ struct ieee80211_local *local = wiphy_priv(dev->ieee80211_ptr->wiphy); + -+ skb_put(skb, len); ++ memset(rp, 0, sizeof(*rp)); + -+ memset(skb->data, 0, len); -+ -+ hdr = (struct ieee80211_hdr *)skb->data; -+ hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA); -+ hdr->duration_id = 0; ++ drv_get_ringparam(local, &rp->tx_pending, &rp->tx_max_pending, ++ &rp->rx_pending, &rp->rx_max_pending); ++} + -+ memcpy(hdr->addr1, hw->wiphy->perm_addr, ETH_ALEN); -+ memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN); -+ memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); ++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) + -+ hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); ++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; + -+ tx_info = IEEE80211_SKB_CB(skb); -+ memset(tx_info, 0, sizeof(*tx_info)); -+ tx_info->band = hw->conf.chandef.chan->band; -+ tx_info->flags = IEEE80211_TX_CTL_NO_ACK; -+ tx_info->control.vif = sc->tx99_vif; ++ if (sset == ETH_SS_STATS) ++ rv += STA_STATS_LEN; + -+ memcpy(skb->data + sizeof(*hdr), PN9Data, sizeof(PN9Data)); ++ rv += drv_get_et_sset_count(sdata, sset); + -+ return skb; ++ if (rv == 0) ++ return -EOPNOTSUPP; ++ return rv; +} + -+static void ath9k_tx99_deinit(struct ath_softc *sc) ++static void ieee80211_get_stats(struct net_device *dev, ++ struct ethtool_stats *stats, ++ u64 *data) +{ -+ ath_reset(sc); -+ -+ ath9k_ps_wakeup(sc); -+ ath9k_tx99_stop(sc); -+ ath9k_ps_restore(sc); -+} ++ 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. ++ */ + -+static int ath9k_tx99_init(struct ath_softc *sc) -+{ -+ struct ieee80211_hw *hw = sc->hw; -+ struct ath_hw *ah = sc->sc_ah; -+ struct ath_common *common = ath9k_hw_common(ah); -+ struct ath_tx_control txctl; -+ int r; ++ mutex_lock(&local->sta_mtx); + -+ if (test_bit(SC_OP_INVALID, &sc->sc_flags)) { -+ ath_err(common, -+ "driver is in invalid state unable to use TX99"); -+ return -EINVAL; -+ } ++ if (sdata->vif.type == NL80211_IFTYPE_STATION) { ++ sta = sta_info_get_bss(sdata, sdata->u.mgd.bssid); + -+ sc->tx99_skb = ath9k_build_tx99_skb(sc); -+ if (!sc->tx99_skb) -+ return -ENOMEM; ++ if (!(sta && !WARN_ON(sta->sdata->dev != dev))) ++ goto do_survey; + -+ memset(&txctl, 0, sizeof(txctl)); -+ txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO]; ++ sinfo.filled = 0; ++ sta_set_sinfo(sta, &sinfo); + -+ ath_reset(sc); ++ i = 0; ++ ADD_STA_STATS(sta); + -+ ath9k_ps_wakeup(sc); ++ data[i++] = sta->sta_state; + -+ ath9k_hw_disable_interrupts(ah); -+ atomic_set(&ah->intr_ref_cnt, -1); -+ ath_drain_all_txq(sc); -+ ath_stoprecv(sc); + -+ sc->tx99_state = true; ++ 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++; + -+ ieee80211_stop_queues(hw); ++ 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); ++ } ++ } + -+ if (sc->tx99_power == MAX_RATE_POWER + 1) -+ sc->tx99_power = MAX_RATE_POWER; ++do_survey: ++ i = STA_STATS_LEN - STA_STATS_SURVEY_LEN; ++ /* Get survey stats for current channel */ ++ survey.filled = 0; + -+ ath9k_hw_tx99_set_txpower(ah, sc->tx99_power); -+ r = ath9k_tx99_send(sc, sc->tx99_skb, &txctl); -+ if (r) { -+ ath_dbg(common, XMIT, "Failed to xmit TX99 skb\n"); -+ return r; ++ 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); + } + -+ ath_dbg(common, XMIT, "TX99 xmit started using %d ( %ddBm)\n", -+ sc->tx99_power, -+ sc->tx99_power / 2); -+ -+ /* We leave the harware awake as it will be chugging on */ ++ 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; + -+ return 0; -+} ++ mutex_unlock(&local->sta_mtx); + -+static ssize_t read_file_tx99(struct file *file, char __user *user_buf, -+ size_t count, loff_t *ppos) -+{ -+ struct ath_softc *sc = file->private_data; -+ char buf[3]; -+ unsigned int len; ++ if (WARN_ON(i != STA_STATS_LEN)) ++ return; + -+ len = sprintf(buf, "%d\n", sc->tx99_state); -+ return simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ drv_get_et_stats(sdata, stats, &(data[STA_STATS_LEN])); +} + -+static ssize_t write_file_tx99(struct file *file, const char __user *user_buf, -+ size_t count, loff_t *ppos) ++static void ieee80211_get_strings(struct net_device *dev, u32 sset, u8 *data) +{ -+ struct ath_softc *sc = file->private_data; -+ struct ath_common *common = ath9k_hw_common(sc->sc_ah); -+ char buf[32]; -+ bool start; -+ ssize_t len; -+ int r; -+ -+ if (sc->nvifs > 1) -+ return -EOPNOTSUPP; -+ -+ len = min(count, sizeof(buf) - 1); -+ if (copy_from_user(buf, user_buf, len)) -+ return -EFAULT; ++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ int sz_sta_stats = 0; + -+ if (strtobool(buf, &start)) -+ return -EINVAL; -+ -+ if (start == sc->tx99_state) { -+ if (!start) -+ return count; -+ ath_dbg(common, XMIT, "Resetting TX99\n"); -+ ath9k_tx99_deinit(sc); -+ } -+ -+ if (!start) { -+ ath9k_tx99_deinit(sc); -+ return count; ++ if (sset == ETH_SS_STATS) { ++ sz_sta_stats = sizeof(ieee80211_gstrings_sta_stats); ++ memcpy(data, ieee80211_gstrings_sta_stats, sz_sta_stats); + } -+ -+ r = ath9k_tx99_init(sc); -+ if (r) -+ return r; -+ -+ return count; ++ drv_get_et_strings(sdata, sset, &(data[sz_sta_stats])); +} + -+static const struct file_operations fops_tx99 = { -+ .read = read_file_tx99, -+ .write = write_file_tx99, -+ .open = simple_open, -+ .owner = THIS_MODULE, -+ .llseek = default_llseek, -+}; -+ -+static ssize_t read_file_tx99_power(struct file *file, -+ char __user *user_buf, -+ size_t count, loff_t *ppos) ++static int ieee80211_get_regs_len(struct net_device *dev) +{ -+ struct ath_softc *sc = file->private_data; -+ char buf[32]; -+ unsigned int len; -+ -+ len = sprintf(buf, "%d (%d dBm)\n", -+ sc->tx99_power, -+ sc->tx99_power / 2); -+ -+ return simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ return 0; +} + -+static ssize_t write_file_tx99_power(struct file *file, -+ const char __user *user_buf, -+ size_t count, loff_t *ppos) ++static void ieee80211_get_regs(struct net_device *dev, ++ struct ethtool_regs *regs, ++ void *data) +{ -+ struct ath_softc *sc = file->private_data; -+ int r; -+ u8 tx_power; -+ -+ r = kstrtou8_from_user(user_buf, count, 0, &tx_power); -+ if (r) -+ return r; -+ -+ if (tx_power > MAX_RATE_POWER) -+ return -EINVAL; -+ -+ sc->tx99_power = tx_power; ++ struct wireless_dev *wdev = dev->ieee80211_ptr; + -+ ath9k_ps_wakeup(sc); -+ ath9k_hw_tx99_set_txpower(sc->sc_ah, sc->tx99_power); -+ ath9k_ps_restore(sc); -+ -+ return count; ++ regs->version = wdev->wiphy->hw_version; ++ regs->len = 0; +} + -+static const struct file_operations fops_tx99_power = { -+ .read = read_file_tx99_power, -+ .write = write_file_tx99_power, -+ .open = simple_open, -+ .owner = THIS_MODULE, -+ .llseek = default_llseek, ++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, +}; -+ -+void ath9k_tx99_init_debug(struct ath_softc *sc) -+{ -+ if (!AR_SREV_9300_20_OR_LATER(sc->sc_ah)) -+ return; -+ -+ debugfs_create_file("tx99", S_IRUSR | S_IWUSR, -+ sc->debug.debugfs_phy, sc, -+ &fops_tx99); -+ debugfs_create_file("tx99_power", S_IRUSR | S_IWUSR, -+ sc->debug.debugfs_phy, sc, -+ &fops_tx99_power); -+} ---- a/drivers/net/wireless/ath/ath9k/dfs_debug.c -+++ b/drivers/net/wireless/ath/ath9k/dfs_debug.c -@@ -44,14 +44,20 @@ static ssize_t read_file_dfs(struct file - if (buf == NULL) - return -ENOMEM; - -- if (sc->dfs_detector) -- dfs_pool_stats = sc->dfs_detector->get_stats(sc->dfs_detector); -- - len += scnprintf(buf + len, size - len, "DFS support for " - "macVersion = 0x%x, macRev = 0x%x: %s\n", - hw_ver->macVersion, hw_ver->macRev, - (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_DFS) ? - "enabled" : "disabled"); -+ -+ if (!sc->dfs_detector) { -+ len += scnprintf(buf + len, size - len, -+ "DFS detector not enabled\n"); -+ goto exit; -+ } -+ -+ dfs_pool_stats = sc->dfs_detector->get_stats(sc->dfs_detector); -+ - len += scnprintf(buf + len, size - len, "Pulse detector statistics:\n"); - ATH9K_DFS_STAT("pulse events reported ", pulses_total); - ATH9K_DFS_STAT("invalid pulse events ", pulses_no_dfs); -@@ -76,6 +82,7 @@ static ssize_t read_file_dfs(struct file - ATH9K_DFS_POOL_STAT("Seqs. alloc error ", pseq_alloc_error); - ATH9K_DFS_POOL_STAT("Seqs. in use ", pseq_used); - -+exit: - if (len > size) - len = size; - ---- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c -+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c -@@ -641,11 +641,12 @@ static void ar9003_hw_override_ini(struc - else - ah->enabled_cals &= ~TX_IQ_CAL; - -- if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE) -- ah->enabled_cals |= TX_CL_CAL; -- else -- ah->enabled_cals &= ~TX_CL_CAL; +--- 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; } -+ -+ if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE) -+ ah->enabled_cals |= TX_CL_CAL; -+ else -+ ah->enabled_cals &= ~TX_CL_CAL; - } - - static void ar9003_hw_prog_ini(struct ath_hw *ah, -@@ -701,6 +702,54 @@ static int ar9550_hw_get_modes_txgain_in - return ret; - } -+static void ar9003_doubler_fix(struct ath_hw *ah) -+{ -+ if (AR_SREV_9300(ah) || AR_SREV_9580(ah) || AR_SREV_9550(ah)) { -+ REG_RMW(ah, AR_PHY_65NM_CH0_RXTX2, -+ 1 << AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK_S | -+ 1 << AR_PHY_65NM_CH0_RXTX2_SYNTHOVR_MASK_S, 0); -+ REG_RMW(ah, AR_PHY_65NM_CH1_RXTX2, -+ 1 << AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK_S | -+ 1 << AR_PHY_65NM_CH0_RXTX2_SYNTHOVR_MASK_S, 0); -+ REG_RMW(ah, AR_PHY_65NM_CH2_RXTX2, -+ 1 << AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK_S | -+ 1 << AR_PHY_65NM_CH0_RXTX2_SYNTHOVR_MASK_S, 0); -+ -+ udelay(200); -+ -+ REG_CLR_BIT(ah, AR_PHY_65NM_CH0_RXTX2, -+ AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK); -+ REG_CLR_BIT(ah, AR_PHY_65NM_CH1_RXTX2, -+ AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK); -+ REG_CLR_BIT(ah, AR_PHY_65NM_CH2_RXTX2, -+ AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK); -+ -+ udelay(1); -+ -+ REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_RXTX2, -+ AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK, 1); -+ REG_RMW_FIELD(ah, AR_PHY_65NM_CH1_RXTX2, -+ AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK, 1); -+ REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX2, -+ AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK, 1); -+ -+ udelay(200); -+ -+ REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_SYNTH12, -+ AR_PHY_65NM_CH0_SYNTH12_VREFMUL3, 0xf); -+ -+ REG_RMW(ah, AR_PHY_65NM_CH0_RXTX2, 0, -+ 1 << AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK_S | -+ 1 << AR_PHY_65NM_CH0_RXTX2_SYNTHOVR_MASK_S); -+ REG_RMW(ah, AR_PHY_65NM_CH1_RXTX2, 0, -+ 1 << AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK_S | -+ 1 << AR_PHY_65NM_CH0_RXTX2_SYNTHOVR_MASK_S); -+ REG_RMW(ah, AR_PHY_65NM_CH2_RXTX2, 0, -+ 1 << AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK_S | -+ 1 << AR_PHY_65NM_CH0_RXTX2_SYNTHOVR_MASK_S); -+ } -+} -+ - static int ar9003_hw_process_ini(struct ath_hw *ah, - struct ath9k_channel *chan) - { -@@ -726,6 +775,8 @@ static int ar9003_hw_process_ini(struct - modesIndex); +@@ -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; + + /* 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() -+ ar9003_doubler_fix(ah); -+ - /* - * RXGAIN initvals. - */ ---- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h -+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h -@@ -656,13 +656,24 @@ - #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x00000001 : 0x00000002) - #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT_S ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0 : 1) - #define AR_PHY_65NM_CH0_SYNTH7 0x16098 -+#define AR_PHY_65NM_CH0_SYNTH12 0x160ac - #define AR_PHY_65NM_CH0_BIAS1 0x160c0 - #define AR_PHY_65NM_CH0_BIAS2 0x160c4 - #define AR_PHY_65NM_CH0_BIAS4 0x160cc -+#define AR_PHY_65NM_CH0_RXTX2 0x16104 -+#define AR_PHY_65NM_CH1_RXTX2 0x16504 -+#define AR_PHY_65NM_CH2_RXTX2 0x16904 - #define AR_PHY_65NM_CH0_RXTX4 0x1610c - #define AR_PHY_65NM_CH1_RXTX4 0x1650c - #define AR_PHY_65NM_CH2_RXTX4 0x1690c - -+#define AR_PHY_65NM_CH0_SYNTH12_VREFMUL3 0x00780000 -+#define AR_PHY_65NM_CH0_SYNTH12_VREFMUL3_S 19 -+#define AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK 0x00000004 -+#define AR_PHY_65NM_CH0_RXTX2_SYNTHON_MASK_S 2 -+#define AR_PHY_65NM_CH0_RXTX2_SYNTHOVR_MASK 0x00000008 -+#define AR_PHY_65NM_CH0_RXTX2_SYNTHOVR_MASK_S 3 -+ - #define AR_CH0_TOP (AR_SREV_9300(ah) ? 0x16288 : \ - (((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x1628c : 0x16280))) - #define AR_CH0_TOP_XPABIASLVL (AR_SREV_9550(ah) ? 0x3c0 : 0x300) ---- a/drivers/net/wireless/rt2x00/rt2x00dev.c -+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c -@@ -181,6 +181,7 @@ static void rt2x00lib_autowakeup(struct - static void rt2x00lib_bc_buffer_iter(void *data, u8 *mac, - struct ieee80211_vif *vif) - { -+ struct ieee80211_tx_control control = {}; - struct rt2x00_dev *rt2x00dev = data; - struct sk_buff *skb; - -@@ -195,7 +196,7 @@ static void rt2x00lib_bc_buffer_iter(voi - */ - skb = ieee80211_get_buffered_bc(rt2x00dev->hw, vif); - while (skb) { -- rt2x00mac_tx(rt2x00dev->hw, NULL, skb); -+ rt2x00mac_tx(rt2x00dev->hw, &control, skb); - skb = ieee80211_get_buffered_bc(rt2x00dev->hw, vif); - } - } ---- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c -+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c -@@ -1040,8 +1040,8 @@ static void ar9003_hw_cl_cal_post_proc(s } + 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++ } --static bool ar9003_hw_init_cal(struct ath_hw *ah, -- struct ath9k_channel *chan) -+static bool ar9003_hw_init_cal_pcoem(struct ath_hw *ah, -+ struct ath9k_channel *chan) - { - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_hw_cal_data *caldata = ah->caldata; -@@ -1228,13 +1228,109 @@ skip_tx_iqcal: - return true; - } +--- 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; -+static bool ar9003_hw_init_cal_soc(struct ath_hw *ah, -+ struct ath9k_channel *chan) -+{ -+ struct ath_common *common = ath9k_hw_common(ah); -+ struct ath9k_hw_cal_data *caldata = ah->caldata; -+ bool txiqcal_done = false; -+ bool is_reusable = true, status = true; -+ bool run_agc_cal = false, sep_iq_cal = false; -+ -+ /* Use chip chainmask only for calibration */ -+ ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask); -+ -+ if (ah->enabled_cals & TX_CL_CAL) { -+ REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); -+ run_agc_cal = true; -+ } -+ -+ if (IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan)) -+ goto skip_tx_iqcal; -+ -+ /* Do Tx IQ Calibration */ -+ REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1, -+ AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, -+ DELPT); -+ -+ /* -+ * For AR9485 or later chips, TxIQ cal runs as part of -+ * AGC calibration. Specifically, AR9550 in SoC chips. -+ */ -+ if (ah->enabled_cals & TX_IQ_ON_AGC_CAL) { -+ txiqcal_done = true; -+ run_agc_cal = true; -+ } else { -+ sep_iq_cal = true; -+ run_agc_cal = true; -+ } -+ -+ /* -+ * In the SoC family, this will run for AR9300, AR9331 and AR9340. -+ */ -+ if (sep_iq_cal) { -+ txiqcal_done = ar9003_hw_tx_iq_cal_run(ah); -+ REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); -+ udelay(5); -+ REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); -+ } -+ -+skip_tx_iqcal: -+ if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) { -+ /* Calibrate the AGC */ -+ REG_WRITE(ah, AR_PHY_AGC_CONTROL, -+ REG_READ(ah, AR_PHY_AGC_CONTROL) | -+ AR_PHY_AGC_CONTROL_CAL); -+ -+ /* Poll for offset calibration complete */ -+ status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, -+ AR_PHY_AGC_CONTROL_CAL, -+ 0, AH_WAIT_TIMEOUT); -+ } -+ -+ if (!status) { -+ ath_dbg(common, CALIBRATE, -+ "offset calibration failed to complete in %d ms; noisy environment?\n", -+ AH_WAIT_TIMEOUT / 1000); -+ return false; -+ } -+ -+ if (txiqcal_done) -+ ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable); -+ -+ /* Revert chainmask to runtime parameters */ -+ ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); -+ -+ /* Initialize list pointers */ -+ ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; -+ -+ INIT_CAL(&ah->iq_caldata); -+ INSERT_CAL(ah, &ah->iq_caldata); -+ ath_dbg(common, CALIBRATE, "enabling IQ Calibration\n"); -+ -+ /* Initialize current pointer to first element in list */ -+ ah->cal_list_curr = ah->cal_list; -+ -+ if (ah->cal_list_curr) -+ ath9k_hw_reset_calibration(ah, ah->cal_list_curr); -+ -+ if (caldata) -+ caldata->CalValid = 0; -+ -+ return true; -+} -+ - void ar9003_hw_attach_calib_ops(struct ath_hw *ah) - { - struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); - struct ath_hw_ops *ops = ath9k_hw_ops(ah); + 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); -+ if (AR_SREV_9485(ah) || AR_SREV_9462(ah) || AR_SREV_9565(ah)) -+ priv_ops->init_cal = ar9003_hw_init_cal_pcoem; -+ else -+ priv_ops->init_cal = ar9003_hw_init_cal_soc; -+ - priv_ops->init_cal_settings = ar9003_hw_init_cal_settings; -- priv_ops->init_cal = ar9003_hw_init_cal; - priv_ops->setup_calibration = ar9003_hw_setup_calibration; - - ops->calibrate = ar9003_hw_calibrate; ---- a/drivers/net/wireless/ath/ath9k/common.c -+++ b/drivers/net/wireless/ath/ath9k/common.c -@@ -98,10 +98,8 @@ struct ath9k_channel *ath9k_cmn_get_chan - { - struct ieee80211_channel *curchan = chandef->chan; - struct ath9k_channel *channel; -- u8 chan_idx; + if (ret >= 0) +@@ -62,8 +61,7 @@ static ssize_t ieee80211_if_write( + + ret = -ENODEV; + rtnl_lock(); +- if (sdata->dev->reg_state == NETREG_REGISTERED) +- ret = (*write)(sdata, buf, count); ++ ret = (*write)(sdata, buf, count); + rtnl_unlock(); + + return ret; +--- a/drivers/net/wireless/b43/xmit.c ++++ b/drivers/net/wireless/b43/xmit.c +@@ -811,9 +811,13 @@ void b43_rx(struct b43_wldev *dev, struc + break; + case B43_PHYTYPE_G: + status.band = IEEE80211_BAND_2GHZ; +- /* chanid is the radio channel cookie value as used +- * to tune the radio. */ +- status.freq = chanid + 2400; ++ /* Somewhere between 478.104 and 508.1084 firmware for G-PHY ++ * has been modified to be compatible with N-PHY and others. ++ */ ++ if (dev->fw.rev >= 508) ++ status.freq = ieee80211_channel_to_frequency(chanid, status.band); ++ else ++ status.freq = chanid + 2400; + break; + case B43_PHYTYPE_N: + case B43_PHYTYPE_LP: +--- a/drivers/net/wireless/b43/main.c ++++ b/drivers/net/wireless/b43/main.c +@@ -5216,6 +5216,7 @@ static int b43_wireless_core_attach(stru + /* We don't support 5 GHz on some PHYs yet */ + switch (dev->phy.type) { + case B43_PHYTYPE_A: ++ case B43_PHYTYPE_G: + case B43_PHYTYPE_N: + case B43_PHYTYPE_LP: + case B43_PHYTYPE_HT: +--- a/net/wireless/reg.c ++++ b/net/wireless/reg.c +@@ -935,7 +935,7 @@ freq_reg_info_regd(struct wiphy *wiphy, + if (!band_rule_found) + band_rule_found = freq_in_rule_band(fr, center_freq); + +- bw_fits = reg_does_bw_fit(fr, center_freq, MHZ_TO_KHZ(5)); ++ bw_fits = reg_does_bw_fit(fr, center_freq, MHZ_TO_KHZ(20)); -- chan_idx = curchan->hw_value; -- channel = &ah->channels[chan_idx]; -+ channel = &ah->channels[curchan->hw_value]; - ath9k_cmn_update_ichannel(channel, chandef); + if (band_rule_found && bw_fits) + return rr; +@@ -1019,10 +1019,10 @@ static void chan_reg_rule_print_dbg(cons + } + #endif - return channel; +-/* Find an ieee80211_reg_rule such that a 5MHz channel with frequency +- * chan->center_freq fits there. +- * If there is no such reg_rule, disable the channel, otherwise set the +- * flags corresponding to the bandwidths allowed in the particular reg_rule ++/* ++ * Note that right now we assume the desired channel bandwidth ++ * is always 20 MHz for each individual channel (HT40 uses 20 MHz ++ * per channel, the primary and the extension channel). + */ + static void handle_channel(struct wiphy *wiphy, + enum nl80211_reg_initiator initiator, +@@ -1083,12 +1083,8 @@ static void handle_channel(struct wiphy + if (reg_rule->flags & NL80211_RRF_AUTO_BW) + max_bandwidth_khz = reg_get_max_bandwidth(regd, reg_rule); + +- if (max_bandwidth_khz < MHZ_TO_KHZ(10)) +- bw_flags = IEEE80211_CHAN_NO_10MHZ; +- if (max_bandwidth_khz < MHZ_TO_KHZ(20)) +- bw_flags |= IEEE80211_CHAN_NO_20MHZ; + if (max_bandwidth_khz < MHZ_TO_KHZ(40)) +- bw_flags |= IEEE80211_CHAN_NO_HT40; ++ bw_flags = IEEE80211_CHAN_NO_HT40; + if (max_bandwidth_khz < MHZ_TO_KHZ(80)) + bw_flags |= IEEE80211_CHAN_NO_80MHZ; + if (max_bandwidth_khz < MHZ_TO_KHZ(160)) +@@ -1522,12 +1518,8 @@ static void handle_channel_custom(struct + if (reg_rule->flags & NL80211_RRF_AUTO_BW) + max_bandwidth_khz = reg_get_max_bandwidth(regd, reg_rule); + +- if (max_bandwidth_khz < MHZ_TO_KHZ(10)) +- bw_flags = IEEE80211_CHAN_NO_10MHZ; +- if (max_bandwidth_khz < MHZ_TO_KHZ(20)) +- bw_flags |= IEEE80211_CHAN_NO_20MHZ; + if (max_bandwidth_khz < MHZ_TO_KHZ(40)) +- bw_flags |= IEEE80211_CHAN_NO_HT40; ++ bw_flags = IEEE80211_CHAN_NO_HT40; + if (max_bandwidth_khz < MHZ_TO_KHZ(80)) + bw_flags |= IEEE80211_CHAN_NO_80MHZ; + if (max_bandwidth_khz < MHZ_TO_KHZ(160))