diff options
author | Felix Fietkau <nbd@openwrt.org> | 2014-05-23 18:48:35 +0000 |
---|---|---|
committer | Felix Fietkau <nbd@openwrt.org> | 2014-05-23 18:48:35 +0000 |
commit | 4e5453c94cd5f16a55548a5688c421ee58ca3f7e (patch) | |
tree | fda1569005e6ddbeaf8338e2bebba581805e9c7a /package/kernel/mac80211/patches/300-pending_work.patch | |
parent | b82d436d9b0cd6703e2b902e544c4b8c80c6e54f (diff) | |
download | upstream-4e5453c94cd5f16a55548a5688c421ee58ca3f7e.tar.gz upstream-4e5453c94cd5f16a55548a5688c421ee58ca3f7e.tar.bz2 upstream-4e5453c94cd5f16a55548a5688c421ee58ca3f7e.zip |
mac80211: update to wireless-testing 2014-05-22
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@40834 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'package/kernel/mac80211/patches/300-pending_work.patch')
-rw-r--r-- | package/kernel/mac80211/patches/300-pending_work.patch | 4390 |
1 files changed, 85 insertions, 4305 deletions
diff --git a/package/kernel/mac80211/patches/300-pending_work.patch b/package/kernel/mac80211/patches/300-pending_work.patch index dc1e2650fa..0a2e86b1d7 100644 --- a/package/kernel/mac80211/patches/300-pending_work.patch +++ b/package/kernel/mac80211/patches/300-pending_work.patch @@ -1,4323 +1,41 @@ -commit ff9655bebd25d35ab13c2515a029723b69949720 +commit 6df35206bc6c1c6aad1d8077df5786b4a7f77873 Author: Felix Fietkau <nbd@openwrt.org> -Date: Mon May 19 21:20:49 2014 +0200 - - ath9k: avoid passing buffers to the hardware during flush - - The commit "ath9k: fix possible hang on flush" changed the receive code - to always link rx descriptors of processed frames, even when flushing. - In some cases, this leads to flushed rx buffers being passed to the - hardware while rx is already stopped. - - Signed-off-by: Felix Fietkau <nbd@openwrt.org> - -commit 46c5d7d207a2a0725066c0928fd19b8c578b7d4f -Author: Oleksij Rempel <linux@rempel-privat.de> -Date: Tue May 20 00:02:03 2014 +0200 - - ath9k_htc: fix build with disabled debug - - CC [M] drivers/net/wireless/ath/ath9k/htc_drv_txrx.o - drivers/net/wireless/ath/ath9k/htc_drv_txrx.c: In function ‘ath9k_rx_prepare’: - drivers/net/wireless/ath/ath9k/htc_drv_txrx.c:1006:2: warning: passing argument 2 of ‘ath9k_htc_err_stat_rx’ from incompatible pointer type [enabled by default] - ath9k_htc_err_stat_rx(priv, &rx_stats); - ^ - In file included from drivers/net/wireless/ath/ath9k/htc_drv_txrx.c:17:0: - drivers/net/wireless/ath/ath9k/htc.h:380:20: note: expected ‘struct ath_htc_rx_status *’ but argument is of type ‘struct ath_rx_status *’ - static inline void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv, - - Signed-off-by: Oleksij Rempel <linux@rempel-privat.de> - -commit 2d331334e9dc5659fdf9a89326c34c3db5a15279 -Author: Johannes Berg <johannes.berg@intel.com> -Date: Mon May 19 17:59:50 2014 +0200 - - cfg80211: constify wowlan/coalesce mask/pattern pointers - - This requires changing the nl80211 parsing code a bit to use - intermediate pointers for the allocation, but clarifies the - API towards the drivers. - - Signed-off-by: Johannes Berg <johannes.berg@intel.com> - -commit 6788105c46babaa6938cbacb72fdf20bec4bb2e3 -Author: Johannes Berg <johannes.berg@intel.com> -Date: Mon May 19 17:53:16 2014 +0200 - - cfg80211: constify more pointers in the cfg80211 API - - This also propagates through the drivers. - - The orinoco driver uses the cfg80211 API structs for internal - bookkeeping, and so needs a (void *) cast that removes the - const - but that's OK because it allocates those pointers. - - Signed-off-by: Johannes Berg <johannes.berg@intel.com> - -commit c3d95010fd881da0fa0a4e88532412f5d0c092f6 -Author: Johannes Berg <johannes.berg@intel.com> -Date: Mon May 19 17:19:31 2014 +0200 - - cfg80211: constify MAC addresses in cfg80211 ops - - This propagates through all the drivers and mac80211. - - Signed-off-by: Johannes Berg <johannes.berg@intel.com> - -commit ddf1e6f0f0354c601af7d42e5ace4b51f8b0bffc -Author: Luciano Coelho <luciano.coelho@intel.com> -Date: Thu May 15 20:32:08 2014 +0300 - - mac80211: fix csa_counter_offs argument name in docbook - - The csa_counter_offs was erroneously described as csa_offs in - the docbook section. - - This fixes two warnings when making htmldocs (at least): - - Warning(include/net/mac80211.h:3428): No description found for parameter 'csa_counter_offs[IEEE80211_MAX_CSA_COUNTERS_NUM]' - Warning(include/net/mac80211.h:3428): Excess struct/union/enum/typedef member 'csa_offs' description in 'ieee80211_mutable_offsets' - - Signed-off-by: Luciano Coelho <luciano.coelho@intel.com> - Signed-off-by: Johannes Berg <johannes.berg@intel.com> - -commit 202322d1c04b8e498bd5bb78606fcf3941512b35 -Author: Luciano Coelho <luciano.coelho@intel.com> -Date: Thu May 15 20:18:09 2014 +0300 - - cfg80211: add documentation for max_num_csa_counters - - Move the comment in the structure to a description of the - max_num_csa_counters field in the docbook area. - - This fixes a warning when building htmldocs (at least): - - Warning(include/net/cfg80211.h:3064): No description found for parameter 'max_num_csa_counters' - - Signed-off-by: Luciano Coelho <luciano.coelho@intel.com> - Signed-off-by: Johannes Berg <johannes.berg@intel.com> - -commit 457a33192f64b7637e8fd0ae0e9f32701c908603 -Author: Johannes Berg <johannes.berg@intel.com> -Date: Mon May 19 11:24:19 2014 +0200 - - mac80211: minstrel-ht: small clarifications - - Antonio and I were looking over this code and some things - didn't immediately make sense, so we came up with two small - clarifications. - - Signed-off-by: Johannes Berg <johannes.berg@intel.com> - -commit 1e35dce952a64a957de97ae1f2bb19301756b936 -Author: Andrei Otcheretianski <andrei.otcheretianski@intel.com> -Date: Fri May 9 14:11:50 2014 +0300 - - mac80211: Handle the CSA counters correctly - - Make the beacon CSA counters part of ieee80211_mutable_offsets and don't - decrement CSA counters when generating a beacon template. This permits the - driver to offload the CSA counters handling. Since mac80211 updates the probe - responses with the correct counter, the driver should sync the counter's value - with mac80211 using ieee80211_csa_update_counter function. - - Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com> - Signed-off-by: Luciano Coelho <luciano.coelho@intel.com> - Signed-off-by: Johannes Berg <johannes.berg@intel.com> - -commit e7b5c449815d28a2105fde5b42e112f78cc711ac -Author: Andrei Otcheretianski <andrei.otcheretianski@intel.com> -Date: Fri May 9 14:11:49 2014 +0300 - - mac80211: Provide ieee80211_beacon_get_template API - - Add a new API ieee80211_beacon_get_template, which doesn't - affect DTIM counter and should be used if the device generates beacon - frames, and new beacon template is needed. In addition set the offsets - to TIM IE for MESH interface. - - Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com> - Signed-off-by: Luciano Coelho <luciano.coelho@intel.com> - Signed-off-by: Johannes Berg <johannes.berg@intel.com> - -commit e54eda80273ce8aded058c3c9365dca2342e2e75 -Author: Andrei Otcheretianski <andrei.otcheretianski@intel.com> -Date: Fri May 9 14:11:47 2014 +0300 - - mac80211: Support multiple CSA counters - - Support up to IEEE80211_MAX_CSA_COUNTERS_NUM csa counters. - This is defined to be 2 now, to support both CSA and eCSA - counters. - - Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com> - Signed-off-by: Luciano Coelho <luciano.coelho@intel.com> - Signed-off-by: Johannes Berg <johannes.berg@intel.com> - -commit 678e87c3b929dd60d59470e8981eb551cee10319 -Author: Andrei Otcheretianski <andrei.otcheretianski@intel.com> -Date: Fri May 9 14:11:46 2014 +0300 - - cfg80211: Support multiple CSA counters - - Change the type of NL80211_ATTR_CSA_C_OFF_BEACON and - NL80211_ATTR_CSA_C_OFF_PRESP to be NLA_BINARY which allows - userspace to use beacons and probe responses with - multiple CSA counters. - This isn't breaking the API since userspace can - continue to use nla_put_u16 for this attributes, which - is equivalent to a single element u16 array. - In addition advertise max number of supported CSA counters. - This is needed when using CSA and eCSA IEs together. - - Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com> - Signed-off-by: Luciano Coelho <luciano.coelho@intel.com> - Signed-off-by: Johannes Berg <johannes.berg@intel.com> - -commit 93f4867a966cc8645659031bbd44a9bb4b78485f -Author: Andrei Otcheretianski <andrei.otcheretianski@intel.com> -Date: Fri May 9 14:11:45 2014 +0300 - - mac80211: Update CSA counters in mgmt frames - - Track current csa counter value and use it - to update mgmt frames at the provided offsets. - - Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com> - Signed-off-by: Luciano Coelho <luciano.coelho@intel.com> - Signed-off-by: Johannes Berg <johannes.berg@intel.com> +Date: Fri May 23 19:58:14 2014 +0200 -commit 6c8461fcc03ff4d250027e47f53315b5e0ec43aa -Author: Andrei Otcheretianski <andrei.otcheretianski@intel.com> -Date: Fri May 9 14:11:44 2014 +0300 - - cfg80211: Add API to update CSA counters in mgmt frames - - Add NL80211_ATTR_CSA_C_OFFSETS_TX which holds an array - of offsets to the CSA counters which should be updated - when sending a management frames with NL80211_CMD_FRAME. + mac80211: reduce packet loss notifications under load - This API should be used by the drivers that wish to keep the - CSA counter updated in probe responses, but do not implement - probe response offloading and so, do not use - ieee80211_proberesp_get function. + 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. - Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com> - Signed-off-by: Luciano Coelho <luciano.coelho@intel.com> - Signed-off-by: Johannes Berg <johannes.berg@intel.com> - -commit 7d09fc9f1903b3d5e7d046bdf10467f37a97c4f9 -Author: Luciano Coelho <luciano.coelho@intel.com> -Date: Thu May 15 13:05:39 2014 +0300 - - cfg80211: pass the actual iftype when calling cfg80211_chandef_dfs_required() - - There is no need to pass NL80211_IFTYPE_UNSPECIFIED when calling - cfg80211_chandef_dfs_required() since we always already have the - interface type. So, pass the actual interface type instead. - - Additionally, have cfg80211_chandef_dfs_required() WARN if the passed - interface type is NL80211_IFTYPE_UNSPECIFIED, so we can detect - problems more easily. - - Tested-by: Janusz Dziedzic <janusz.dziedzic@tieto.com> - Reported-by: Eliad Peller <eliad@wizery.com> - Signed-off-by: Luciano Coelho <luciano.coelho@intel.com> - Signed-off-by: Johannes Berg <johannes.berg@intel.com> - -commit 2b7443b15f26ecb98281474666383cf2a882fbad -Author: Janusz Dziedzic <janusz.dziedzic@tieto.com> -Date: Wed May 14 13:25:04 2014 +0200 - - cfg80211: fix start_radar_detection issue + Reduce the number of false positives by checking the A-MPDU status flag + and treating a failed A-MPDU as a single packet. - After patch: - cfg80211/mac80211: refactor cfg80211_chandef_dfs_required() - - start_radar_detection always fail with -EINVAL. - - Acked-by: Luciano Coelho <luciano.coelho@intel.com> - Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com> - Signed-off-by: Johannes Berg <johannes.berg@intel.com> + Signed-off-by: Felix Fietkau <nbd@openwrt.org> -commit 4f46eb8b28f96aca212a364e0fa847eb5333df67 +commit 7b7843a36fbcc568834404c7430ff895d8502131 Author: Felix Fietkau <nbd@openwrt.org> -Date: Mon May 5 11:48:40 2014 +0200 +Date: Fri May 23 19:26:32 2014 +0200 - cfg80211: allow restricting supported dfs regions - - At the moment, the ath9k/ath10k DFS module only supports detecting ETSI - radar patterns. - Add a bitmap in the interface combinations, indicating which DFS regions - are supported by the detector. If unset, support for all regions is - assumed. + mac80211: fix a memory leak on sta rate selection table + Cc: stable@vger.kernel.org + Reported-by: Christophe Prévotaux <cprevotaux@nltinc.com> Signed-off-by: Felix Fietkau <nbd@openwrt.org> - Signed-off-by: Johannes Berg <johannes.berg@intel.com> - -commit 0277b034768d1800a00829a755fc56b925aa6b95 -Author: Johannes Berg <johannes.berg@intel.com> -Date: Wed Apr 30 14:19:04 2014 +0200 - - mac80211: handle failed restart/resume better - - When the driver fails during HW restart or resume, the whole - stack goes into a very confused state with interfaces being - up while the hardware is down etc. - - Address this by shutting down everything; we'll run into a - lot of warnings in the process but that's better than having - the whole stack get messed up. - - Reviewed-by: Arik Nemtsov <arik@wizery.com> - Signed-off-by: Johannes Berg <johannes.berg@intel.com> - -commit 43fd71bc4b83d24981e90ca178f505cf6a6b16dc -Author: Luciano Coelho <luciano.coelho@intel.com> -Date: Wed May 7 20:05:12 2014 +0300 - - mac80211: fix sparse warning caused by __ieee80211_channel_switch() - - Commit 59af6928 (mac80211: fix CSA tx queue stopping) introduced a - sparse warning: - - net/mac80211/cfg.c:3274:5: warning: symbol '__ieee80211_channel_switch' was not declared. Should it be static? - - Fix it by declaring the function static. - - Signed-off-by: Luciano Coelho <luciano.coelho@intel.com> - Signed-off-by: Johannes Berg <johannes.berg@intel.com> - -commit dd4371e2957db19870bb22ab84e841e1ac6e8997 -Author: Luciano Coelho <luciano.coelho@intel.com> -Date: Wed May 7 19:07:05 2014 +0300 - - cfg80211: fix docbook warning - - When trying to generate documentation, at least xmldocs, we get the - following warning: - - Warning(include/net/cfg80211.h:461): No description found for parameter 'nl80211_iftype' - - Fix it by adding the iftype argument name to the - cfg80211_chandef_dfs_required() function declaration. - - Reported-and-tested-by: Masanari Iida <standby24x7@gmail.com> - Signed-off-by: Luciano Coelho <luciano.coelho@intel.com> - Signed-off-by: Johannes Berg <johannes.berg@intel.com> - -commit 56de850ae960f096c784ec07864ca5b71abd16e6 -Author: Michal Kazior <michal.kazior@tieto.com> -Date: Thu May 8 09:10:02 2014 +0200 - - mac80211: disconnect iface if CSA unexpectedly fails - - It doesn't make much sense to leave a crippled - interface running. - - As a side effect this will unblock tx queues with - CSA reason immediately after failure instead of - until after userspace requests interface to stop. - - This also gives userspace an opportunity to - indirectly see CSA failure. - - Signed-off-by: Michal Kazior <michal.kazior@tieto.com> - [small code cleanup] - Signed-off-by: Johannes Berg <johannes.berg@intel.com> - -commit f5894c4f19e55bb1ea6376031fe9d47d7528be9e -Author: Loic Poulain <loic.poulain@intel.com> -Date: Wed May 7 11:38:11 2014 +0200 - - rfkill-gpio: Use gpio cansleep version - - If gpio controller requires waiting for read and write - GPIO values, then we have to use the gpio cansleep api. - Fix the rfkill_gpio_set_power which calls only the - nonsleep version (causing kernel warning). - There is no problem to use the cansleep version here - because we are not in IRQ handler or similar context - (cf rfkill_set_block). - - Signed-off-by: Loic Poulain <loic.poulain@intel.com> - Signed-off-by: Johannes Berg <johannes.berg@intel.com> - -commit 47fdf5d4f3704d2db9d1c0f647f788edef104fc8 -Author: Michal Kazior <michal.kazior@tieto.com> -Date: Wed Apr 9 15:45:36 2014 +0200 - - mac80211: ignore cqm during csa - - It is not guaranteed that multi-vif channel - switching is tightly synchronized. It makes sense - to ignore cqm (missing beacons, et al) while csa - is progressing and re-check it after it completes. - - Signed-off-by: Michal Kazior <michal.kazior@tieto.com> - Signed-off-by: Johannes Berg <johannes.berg@intel.com> - -commit 1a8ed386e1684b266a15dacf675102ae53361ee5 -Author: Michal Kazior <michal.kazior@tieto.com> -Date: Wed Apr 9 15:11:01 2014 +0200 - - cfg80211: export interface stopping function - - This exports a new cfg80211_stop_iface() function. - - This is intended for driver internal interface - combination management and channel switching. - - Due to locking issues (it re-enters driver) the - call is asynchronous and uses cfg80211 event - list/worker. - - Signed-off-by: Michal Kazior <michal.kazior@tieto.com> - Signed-off-by: Johannes Berg <johannes.berg@intel.com> - -commit 573f31d6d0e572ff8186c45a1ecd9273242233e6 -Author: Michal Kazior <michal.kazior@tieto.com> -Date: Wed Apr 9 15:11:00 2014 +0200 - mac80211: split CSA finalize function - - Improves readability and modularity. - - Signed-off-by: Michal Kazior <michal.kazior@tieto.com> - Signed-off-by: Johannes Berg <johannes.berg@intel.com> - -commit 2d104d52e7c7640d68f29f2136dbe3938b7bc9ba -Author: Michal Kazior <michal.kazior@tieto.com> -Date: Wed Apr 9 15:10:59 2014 +0200 - - mac80211: fix CSA tx queue stopping - - It was possible for tx queues to be stuck stopped - if AP CSA finalization failed. In that case - neither stop_ap nor do_stop woke the queues up. - This means it was impossible to perform tx at all - until driver was reloaded or a successful CSA was - performed later. - - It was possible to solve this in a simpler manner - however this is more robust and future proof - (having multi-vif CSA in mind). - - New sdata->csa_block_tx is introduced to keep - track of which interfaces requested tx to be - blocked for CSA. This is required because mac80211 - stops all tx queues for that purpose. This means - queues must be awoken only when last tx-blocking - CSA interface is finished. - - It is still possible to have tx queues stopped - after CSA failure but as soon as offending - interfaces are stopped from userspace (stop_ap or - ifdown) tx queues are woken up properly. - - Signed-off-by: Michal Kazior <michal.kazior@tieto.com> - Signed-off-by: Johannes Berg <johannes.berg@intel.com> - -commit 6be615d6d42aa7fdab6c4278031d8fa0953e594f -Author: Johannes Berg <johannes.berg@intel.com> -Date: Wed Apr 9 21:31:13 2014 +0200 - - mac80211: mark local variable __maybe_unused - - The 'local' variable in __ieee80211_vif_copy_chanctx_to_vlans() - is only used/needed when lockdep is compiled in, mark it as such - to avoid compile warnings in the other case. - - While at it, fix some indentation where it's used. - - Reviewed-by: Luciano Coelho <luciano.coelho@intel.com> - Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> - Signed-off-by: Johannes Berg <johannes.berg@intel.com> - -commit 43279e584aeb78aa0c853728db047b58156c0753 -Author: Arik Nemtsov <arik@wizery.com> -Date: Thu May 1 10:17:28 2014 +0300 - - mac80211: move TDLS code to another file - - With new additions planned, this code is getting too big for cfg.c. - - Signed-off-by: Arik Nemtsov <arikx.nemtsov@intel.com> - Signed-off-by: Johannes Berg <johannes.berg@intel.com> - -commit bf9c234b83c77f1ebbcbab73de2a9e4a5d4aafc6 -Author: Arik Nemtsov <arik@wizery.com> -Date: Thu May 1 10:17:27 2014 +0300 - - mac80211: set an external flag for TDLS stations - - Expose a new tdls flag for the public ieee80211_sta struct. - This can be used in some rate control decisions. - - Signed-off-by: Arik Nemtsov <arikx.nemtsov@intel.com> - Signed-off-by: Johannes Berg <johannes.berg@intel.com> - -commit 910e65141a17f645ab85dae1a497e64ebe63df70 -Author: Johannes Berg <johannes.berg@intel.com> -Date: Tue Apr 29 17:55:26 2014 +0200 - - mac80211: remove BUG_ON usage - - These BUG_ON statements should never trigger, but in the unlikely - event that somebody does manage don't stop everything but simply - exit the code path with an error. - - Leave the one BUG_ON where changing it would result in a NULL - pointer dereference. - - Signed-off-by: Johannes Berg <johannes.berg@intel.com> - -commit ff36b582a10285530351aab036087b57ddb4ae2b -Author: Johannes Berg <johannes.berg@intel.com> -Date: Tue Apr 29 17:52:36 2014 +0200 +commit 96892d6aa0a153423070addf3070bc79578b3897 +Author: Felix Fietkau <nbd@openwrt.org> +Date: Mon May 19 21:20:49 2014 +0200 - cfg80211: remove BUG_ON usage + ath9k: avoid passing buffers to the hardware during flush - These really can't trigger unless somebody messes up the code, - but don't make debugging it needlessly complicated, WARN and - return instead of BUG_ON(). + 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: Johannes Berg <johannes.berg@intel.com> + Signed-off-by: Felix Fietkau <nbd@openwrt.org> ---- a/drivers/net/wireless/ath/ath6kl/cfg80211.c -+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c -@@ -1759,7 +1759,7 @@ static bool is_rate_ht40(s32 rate, u8 *m - } - - static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev, -- u8 *mac, struct station_info *sinfo) -+ const u8 *mac, struct station_info *sinfo) - { - struct ath6kl *ar = ath6kl_priv(dev); - struct ath6kl_vif *vif = netdev_priv(dev); -@@ -2974,7 +2974,7 @@ static int ath6kl_stop_ap(struct wiphy * - static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - - static int ath6kl_del_station(struct wiphy *wiphy, struct net_device *dev, -- u8 *mac) -+ const u8 *mac) - { - struct ath6kl *ar = ath6kl_priv(dev); - struct ath6kl_vif *vif = netdev_priv(dev); -@@ -2985,7 +2985,8 @@ static int ath6kl_del_station(struct wip - } - - static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev, -- u8 *mac, struct station_parameters *params) -+ const u8 *mac, -+ struct station_parameters *params) - { - struct ath6kl *ar = ath6kl_priv(dev); - struct ath6kl_vif *vif = netdev_priv(dev); ---- a/drivers/net/wireless/ath/ath6kl/wmi.c -+++ b/drivers/net/wireless/ath/ath6kl/wmi.c -@@ -2320,7 +2320,7 @@ int ath6kl_wmi_addkey_cmd(struct wmi *wm - return ret; - } - --int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, u8 *krk) -+int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, const u8 *krk) - { - struct sk_buff *skb; - struct wmi_add_krk_cmd *cmd; ---- a/drivers/net/wireless/ath/ath6kl/wmi.h -+++ b/drivers/net/wireless/ath/ath6kl/wmi.h -@@ -2616,7 +2616,7 @@ int ath6kl_wmi_addkey_cmd(struct wmi *wm - u8 *key_material, - u8 key_op_ctrl, u8 *mac_addr, - enum wmi_sync_flag sync_flag); --int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, u8 *krk); -+int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, const u8 *krk); - int ath6kl_wmi_deletekey_cmd(struct wmi *wmi, u8 if_idx, u8 key_index); - int ath6kl_wmi_setpmkid_cmd(struct wmi *wmi, u8 if_idx, const u8 *bssid, - const u8 *pmkid, bool set); ---- a/drivers/net/wireless/ath/ath9k/htc.h -+++ b/drivers/net/wireless/ath/ath9k/htc.h -@@ -378,7 +378,7 @@ void ath9k_htc_get_et_stats(struct ieee8 - #define TX_QSTAT_INC(c) do { } while (0) - - static inline void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv, -- struct ath_htc_rx_status *rxs) -+ struct ath_rx_status *rs); - { - } - ---- a/drivers/net/wireless/ath/wil6210/cfg80211.c -+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c -@@ -172,7 +172,7 @@ static int wil_cid_fill_sinfo(struct wil - - static int wil_cfg80211_get_station(struct wiphy *wiphy, - struct net_device *ndev, -- u8 *mac, struct station_info *sinfo) -+ const u8 *mac, struct station_info *sinfo) - { - struct wil6210_priv *wil = wiphy_to_wil(wiphy); - int rc; -@@ -671,7 +671,7 @@ static int wil_cfg80211_stop_ap(struct w - } - - static int wil_cfg80211_del_station(struct wiphy *wiphy, -- struct net_device *dev, u8 *mac) -+ struct net_device *dev, const u8 *mac) - { - struct wil6210_priv *wil = wiphy_to_wil(wiphy); - ---- a/drivers/net/wireless/ath/wil6210/main.c -+++ b/drivers/net/wireless/ath/wil6210/main.c -@@ -81,7 +81,7 @@ static void wil_disconnect_cid(struct wi - memset(&sta->stats, 0, sizeof(sta->stats)); - } - --static void _wil6210_disconnect(struct wil6210_priv *wil, void *bssid) -+static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid) - { - int cid = -ENOENT; - struct net_device *ndev = wil_to_ndev(wil); -@@ -252,7 +252,7 @@ int wil_priv_init(struct wil6210_priv *w - return 0; - } - --void wil6210_disconnect(struct wil6210_priv *wil, void *bssid) -+void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid) - { - del_timer_sync(&wil->connect_timer); - _wil6210_disconnect(wil, bssid); ---- a/drivers/net/wireless/ath/wil6210/wil6210.h -+++ b/drivers/net/wireless/ath/wil6210/wil6210.h -@@ -508,7 +508,7 @@ void wil_wdev_free(struct wil6210_priv * - int wmi_set_mac_address(struct wil6210_priv *wil, void *addr); - int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan); - int wmi_pcp_stop(struct wil6210_priv *wil); --void wil6210_disconnect(struct wil6210_priv *wil, void *bssid); -+void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid); - - int wil_rx_init(struct wil6210_priv *wil); - void wil_rx_fini(struct wil6210_priv *wil); ---- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c -+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c -@@ -2236,7 +2236,7 @@ brcmf_cfg80211_config_default_mgmt_key(s - - static s32 - brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, -- u8 *mac, struct station_info *sinfo) -+ const u8 *mac, struct station_info *sinfo) - { - struct brcmf_if *ifp = netdev_priv(ndev); - struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; -@@ -4014,7 +4014,7 @@ brcmf_cfg80211_change_beacon(struct wiph - - static int - brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, -- u8 *mac) -+ const u8 *mac) - { - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); - struct brcmf_scb_val_le scbval; -@@ -4242,7 +4242,7 @@ static int brcmf_convert_nl80211_tdls_op - } - - static int brcmf_cfg80211_tdls_oper(struct wiphy *wiphy, -- struct net_device *ndev, u8 *peer, -+ struct net_device *ndev, const u8 *peer, - enum nl80211_tdls_operation oper) - { - struct brcmf_if *ifp; ---- a/drivers/net/wireless/libertas/cfg.c -+++ b/drivers/net/wireless/libertas/cfg.c -@@ -1006,9 +1006,8 @@ struct cmd_key_material { - } __packed; - - static int lbs_set_key_material(struct lbs_private *priv, -- int key_type, -- int key_info, -- u8 *key, u16 key_len) -+ int key_type, int key_info, -+ const u8 *key, u16 key_len) - { - struct cmd_key_material cmd; - int ret; -@@ -1610,7 +1609,7 @@ static int lbs_cfg_del_key(struct wiphy - */ - - static int lbs_cfg_get_station(struct wiphy *wiphy, struct net_device *dev, -- u8 *mac, struct station_info *sinfo) -+ const u8 *mac, struct station_info *sinfo) - { - struct lbs_private *priv = wiphy_priv(wiphy); - s8 signal, noise; ---- a/drivers/net/wireless/libertas/defs.h -+++ b/drivers/net/wireless/libertas/defs.h -@@ -90,7 +90,8 @@ do { if ((lbs_debug & (grp)) == (grp)) \ - #define lbs_deb_cfg80211(fmt, args...) LBS_DEB_LL(LBS_DEB_CFG80211, " cfg80211", fmt, ##args) - - #ifdef DEBUG --static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, int len) -+static inline void lbs_deb_hex(unsigned int grp, const char *prompt, -+ const u8 *buf, int len) - { - int i = 0; - ---- a/drivers/net/wireless/mwifiex/11n.h -+++ b/drivers/net/wireless/mwifiex/11n.h -@@ -200,7 +200,7 @@ static inline int mwifiex_is_sta_11n_ena - } - - static inline u8 --mwifiex_tdls_peer_11n_enabled(struct mwifiex_private *priv, u8 *ra) -+mwifiex_tdls_peer_11n_enabled(struct mwifiex_private *priv, const u8 *ra) - { - struct mwifiex_sta_node *node = mwifiex_get_sta_entry(priv, ra); - if (node) ---- a/drivers/net/wireless/mwifiex/cfg80211.c -+++ b/drivers/net/wireless/mwifiex/cfg80211.c -@@ -994,7 +994,7 @@ mwifiex_dump_station_info(struct mwifiex - */ - static int - mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, -- u8 *mac, struct station_info *sinfo) -+ const u8 *mac, struct station_info *sinfo) - { - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - -@@ -1270,7 +1270,7 @@ static int mwifiex_cfg80211_change_beaco - */ - static int - mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, -- u8 *mac) -+ const u8 *mac) - { - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - struct mwifiex_sta_node *sta_node; -@@ -2629,7 +2629,7 @@ static int mwifiex_cfg80211_set_coalesce - */ - static int - mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, -- u8 *peer, u8 action_code, u8 dialog_token, -+ const u8 *peer, u8 action_code, u8 dialog_token, - u16 status_code, u32 peer_capability, - const u8 *extra_ies, size_t extra_ies_len) - { -@@ -2701,7 +2701,7 @@ mwifiex_cfg80211_tdls_mgmt(struct wiphy - - static int - mwifiex_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, -- u8 *peer, enum nl80211_tdls_operation action) -+ const u8 *peer, enum nl80211_tdls_operation action) - { - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - -@@ -2748,9 +2748,8 @@ mwifiex_cfg80211_tdls_oper(struct wiphy - } - - static int --mwifiex_cfg80211_add_station(struct wiphy *wiphy, -- struct net_device *dev, -- u8 *mac, struct station_parameters *params) -+mwifiex_cfg80211_add_station(struct wiphy *wiphy, struct net_device *dev, -+ const u8 *mac, struct station_parameters *params) - { - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - -@@ -2765,9 +2764,9 @@ mwifiex_cfg80211_add_station(struct wiph - } - - static int --mwifiex_cfg80211_change_station(struct wiphy *wiphy, -- struct net_device *dev, -- u8 *mac, struct station_parameters *params) -+mwifiex_cfg80211_change_station(struct wiphy *wiphy, struct net_device *dev, -+ const u8 *mac, -+ struct station_parameters *params) - { - int ret; - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); ---- a/drivers/net/wireless/mwifiex/main.h -+++ b/drivers/net/wireless/mwifiex/main.h -@@ -910,8 +910,6 @@ int mwifiex_handle_uap_rx_forward(struct - struct sk_buff *skb); - int mwifiex_process_sta_event(struct mwifiex_private *); - int mwifiex_process_uap_event(struct mwifiex_private *); --struct mwifiex_sta_node * --mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac); - void mwifiex_delete_all_station_list(struct mwifiex_private *priv); - void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb); - void *mwifiex_process_uap_txpd(struct mwifiex_private *, struct sk_buff *skb); -@@ -1220,26 +1218,26 @@ void mwifiex_dnld_txpwr_table(struct mwi - extern const struct ethtool_ops mwifiex_ethtool_ops; - - void mwifiex_del_all_sta_list(struct mwifiex_private *priv); --void mwifiex_del_sta_entry(struct mwifiex_private *priv, u8 *mac); -+void mwifiex_del_sta_entry(struct mwifiex_private *priv, const u8 *mac); - void - mwifiex_set_sta_ht_cap(struct mwifiex_private *priv, const u8 *ies, - int ies_len, struct mwifiex_sta_node *node); - struct mwifiex_sta_node * --mwifiex_add_sta_entry(struct mwifiex_private *priv, u8 *mac); -+mwifiex_add_sta_entry(struct mwifiex_private *priv, const u8 *mac); - struct mwifiex_sta_node * --mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac); --int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, u8 *peer, -+mwifiex_get_sta_entry(struct mwifiex_private *priv, const u8 *mac); -+int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, const u8 *peer, - u8 action_code, u8 dialog_token, - u16 status_code, const u8 *extra_ies, - size_t extra_ies_len); --int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, -- u8 *peer, u8 action_code, u8 dialog_token, -- u16 status_code, const u8 *extra_ies, -- size_t extra_ies_len); -+int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, const u8 *peer, -+ u8 action_code, u8 dialog_token, -+ u16 status_code, const u8 *extra_ies, -+ size_t extra_ies_len); - void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv, - u8 *buf, int len); --int mwifiex_tdls_oper(struct mwifiex_private *priv, u8 *peer, u8 action); --int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, u8 *mac); -+int mwifiex_tdls_oper(struct mwifiex_private *priv, const u8 *peer, u8 action); -+int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, const u8 *mac); - void mwifiex_disable_all_tdls_links(struct mwifiex_private *priv); - bool mwifiex_is_bss_in_11ac_mode(struct mwifiex_private *priv); - u8 mwifiex_get_center_freq_index(struct mwifiex_private *priv, u8 band, ---- a/drivers/net/wireless/mwifiex/tdls.c -+++ b/drivers/net/wireless/mwifiex/tdls.c -@@ -25,8 +25,8 @@ - #define TDLS_RESP_FIX_LEN 8 - #define TDLS_CONFIRM_FIX_LEN 6 - --static void --mwifiex_restore_tdls_packets(struct mwifiex_private *priv, u8 *mac, u8 status) -+static void mwifiex_restore_tdls_packets(struct mwifiex_private *priv, -+ const u8 *mac, u8 status) - { - struct mwifiex_ra_list_tbl *ra_list; - struct list_head *tid_list; -@@ -84,7 +84,8 @@ mwifiex_restore_tdls_packets(struct mwif - return; - } - --static void mwifiex_hold_tdls_packets(struct mwifiex_private *priv, u8 *mac) -+static void mwifiex_hold_tdls_packets(struct mwifiex_private *priv, -+ const u8 *mac) - { - struct mwifiex_ra_list_tbl *ra_list; - struct list_head *ra_list_head; -@@ -228,7 +229,7 @@ mwifiex_tdls_add_ht_oper(struct mwifiex_ - } - - static int mwifiex_tdls_add_vht_oper(struct mwifiex_private *priv, -- u8 *mac, struct sk_buff *skb) -+ const u8 *mac, struct sk_buff *skb) - { - struct mwifiex_bssdescriptor *bss_desc; - struct ieee80211_vht_operation *vht_oper; -@@ -367,8 +368,9 @@ static void mwifiex_tdls_add_qos_capab(s - } - - static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv, -- u8 *peer, u8 action_code, u8 dialog_token, -- u16 status_code, struct sk_buff *skb) -+ const u8 *peer, u8 action_code, -+ u8 dialog_token, -+ u16 status_code, struct sk_buff *skb) - { - struct ieee80211_tdls_data *tf; - int ret; -@@ -506,7 +508,8 @@ static int mwifiex_prep_tdls_encap_data( - } - - static void --mwifiex_tdls_add_link_ie(struct sk_buff *skb, u8 *src_addr, u8 *peer, u8 *bssid) -+mwifiex_tdls_add_link_ie(struct sk_buff *skb, const u8 *src_addr, -+ const u8 *peer, const u8 *bssid) - { - struct ieee80211_tdls_lnkie *lnkid; - -@@ -520,8 +523,8 @@ mwifiex_tdls_add_link_ie(struct sk_buff - memcpy(lnkid->resp_sta, peer, ETH_ALEN); - } - --int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, -- u8 *peer, u8 action_code, u8 dialog_token, -+int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, const u8 *peer, -+ u8 action_code, u8 dialog_token, - u16 status_code, const u8 *extra_ies, - size_t extra_ies_len) - { -@@ -613,7 +616,8 @@ int mwifiex_send_tdls_data_frame(struct - } - - static int --mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv, u8 *peer, -+mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv, -+ const u8 *peer, - u8 action_code, u8 dialog_token, - u16 status_code, struct sk_buff *skb) - { -@@ -691,10 +695,10 @@ mwifiex_construct_tdls_action_frame(stru - return 0; - } - --int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, -- u8 *peer, u8 action_code, u8 dialog_token, -- u16 status_code, const u8 *extra_ies, -- size_t extra_ies_len) -+int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, const u8 *peer, -+ u8 action_code, u8 dialog_token, -+ u16 status_code, const u8 *extra_ies, -+ size_t extra_ies_len) - { - struct sk_buff *skb; - struct mwifiex_txinfo *tx_info; -@@ -901,7 +905,7 @@ void mwifiex_process_tdls_action_frame(s - } - - static int --mwifiex_tdls_process_config_link(struct mwifiex_private *priv, u8 *peer) -+mwifiex_tdls_process_config_link(struct mwifiex_private *priv, const u8 *peer) - { - struct mwifiex_sta_node *sta_ptr; - struct mwifiex_ds_tdls_oper tdls_oper; -@@ -922,7 +926,7 @@ mwifiex_tdls_process_config_link(struct - } - - static int --mwifiex_tdls_process_create_link(struct mwifiex_private *priv, u8 *peer) -+mwifiex_tdls_process_create_link(struct mwifiex_private *priv, const u8 *peer) - { - struct mwifiex_sta_node *sta_ptr; - struct mwifiex_ds_tdls_oper tdls_oper; -@@ -949,7 +953,7 @@ mwifiex_tdls_process_create_link(struct - } - - static int --mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, u8 *peer) -+mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, const u8 *peer) - { - struct mwifiex_sta_node *sta_ptr; - struct mwifiex_ds_tdls_oper tdls_oper; -@@ -978,7 +982,7 @@ mwifiex_tdls_process_disable_link(struct - } - - static int --mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, u8 *peer) -+mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, const u8 *peer) - { - struct mwifiex_sta_node *sta_ptr; - struct ieee80211_mcs_info mcs; -@@ -1035,7 +1039,7 @@ mwifiex_tdls_process_enable_link(struct - return 0; - } - --int mwifiex_tdls_oper(struct mwifiex_private *priv, u8 *peer, u8 action) -+int mwifiex_tdls_oper(struct mwifiex_private *priv, const u8 *peer, u8 action) - { - switch (action) { - case MWIFIEX_TDLS_ENABLE_LINK: -@@ -1050,7 +1054,7 @@ int mwifiex_tdls_oper(struct mwifiex_pri - return 0; - } - --int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, u8 *mac) -+int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, const u8 *mac) - { - struct mwifiex_sta_node *sta_ptr; - ---- a/drivers/net/wireless/mwifiex/util.c -+++ b/drivers/net/wireless/mwifiex/util.c -@@ -259,7 +259,7 @@ int mwifiex_complete_cmd(struct mwifiex_ - * NULL is returned if station entry is not found in associated STA list. - */ - struct mwifiex_sta_node * --mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac) -+mwifiex_get_sta_entry(struct mwifiex_private *priv, const u8 *mac) - { - struct mwifiex_sta_node *node; - -@@ -280,7 +280,7 @@ mwifiex_get_sta_entry(struct mwifiex_pri - * If received mac address is NULL, NULL is returned. - */ - struct mwifiex_sta_node * --mwifiex_add_sta_entry(struct mwifiex_private *priv, u8 *mac) -+mwifiex_add_sta_entry(struct mwifiex_private *priv, const u8 *mac) - { - struct mwifiex_sta_node *node; - unsigned long flags; -@@ -332,7 +332,7 @@ mwifiex_set_sta_ht_cap(struct mwifiex_pr - } - - /* This function will delete a station entry from station list */ --void mwifiex_del_sta_entry(struct mwifiex_private *priv, u8 *mac) -+void mwifiex_del_sta_entry(struct mwifiex_private *priv, const u8 *mac) - { - struct mwifiex_sta_node *node; - unsigned long flags; ---- a/drivers/net/wireless/mwifiex/wmm.c -+++ b/drivers/net/wireless/mwifiex/wmm.c -@@ -92,7 +92,7 @@ mwifiex_wmm_ac_debug_print(const struct - * The function also initializes the list with the provided RA. - */ - static struct mwifiex_ra_list_tbl * --mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, u8 *ra) -+mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, const u8 *ra) - { - struct mwifiex_ra_list_tbl *ra_list; - -@@ -139,8 +139,7 @@ static u8 mwifiex_get_random_ba_threshol - * This function allocates and adds a RA list for all TIDs - * with the given RA. - */ --void --mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra) -+void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra) - { - int i; - struct mwifiex_ra_list_tbl *ra_list; -@@ -566,7 +565,7 @@ mwifiex_clean_txrx(struct mwifiex_privat - */ - static struct mwifiex_ra_list_tbl * - mwifiex_wmm_get_ralist_node(struct mwifiex_private *priv, u8 tid, -- u8 *ra_addr) -+ const u8 *ra_addr) - { - struct mwifiex_ra_list_tbl *ra_list; - -@@ -587,7 +586,8 @@ mwifiex_wmm_get_ralist_node(struct mwifi - * retrieved. - */ - struct mwifiex_ra_list_tbl * --mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, u8 *ra_addr) -+mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, -+ const u8 *ra_addr) - { - struct mwifiex_ra_list_tbl *ra_list; - ---- a/drivers/net/wireless/mwifiex/wmm.h -+++ b/drivers/net/wireless/mwifiex/wmm.h -@@ -99,7 +99,7 @@ mwifiex_wmm_is_ra_list_empty(struct list - - void mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv, - struct sk_buff *skb); --void mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra); -+void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra); - void mwifiex_rotate_priolists(struct mwifiex_private *priv, - struct mwifiex_ra_list_tbl *ra, int tid); - -@@ -123,7 +123,8 @@ void mwifiex_wmm_setup_ac_downgrade(stru - int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv, - const struct host_cmd_ds_command *resp); - struct mwifiex_ra_list_tbl * --mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, u8 *ra_addr); -+mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, -+ const u8 *ra_addr); - u8 mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid); - - #endif /* !_MWIFIEX_WMM_H_ */ ---- a/drivers/net/wireless/orinoco/hw.c -+++ b/drivers/net/wireless/orinoco/hw.c -@@ -988,8 +988,8 @@ int __orinoco_hw_setup_enc(struct orinoc - * tsc must be NULL or up to 8 bytes - */ - int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx, -- int set_tx, u8 *key, u8 *rsc, size_t rsc_len, -- u8 *tsc, size_t tsc_len) -+ int set_tx, const u8 *key, const u8 *rsc, -+ size_t rsc_len, const u8 *tsc, size_t tsc_len) - { - struct { - __le16 idx; ---- a/drivers/net/wireless/orinoco/hw.h -+++ b/drivers/net/wireless/orinoco/hw.h -@@ -38,8 +38,8 @@ int __orinoco_hw_set_wap(struct orinoco_ - int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv); - int __orinoco_hw_setup_enc(struct orinoco_private *priv); - int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx, -- int set_tx, u8 *key, u8 *rsc, size_t rsc_len, -- u8 *tsc, size_t tsc_len); -+ int set_tx, const u8 *key, const u8 *rsc, -+ size_t rsc_len, const u8 *tsc, size_t tsc_len); - int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx); - int __orinoco_hw_set_multicast_list(struct orinoco_private *priv, - struct net_device *dev, ---- a/drivers/net/wireless/orinoco/wext.c -+++ b/drivers/net/wireless/orinoco/wext.c -@@ -52,9 +52,9 @@ static int orinoco_set_key(struct orinoc - priv->keys[index].seq_len = seq_len; - - if (key_len) -- memcpy(priv->keys[index].key, key, key_len); -+ memcpy((void *)priv->keys[index].key, key, key_len); - if (seq_len) -- memcpy(priv->keys[index].seq, seq, seq_len); -+ memcpy((void *)priv->keys[index].seq, seq, seq_len); - - switch (alg) { - case ORINOCO_ALG_TKIP: ---- a/drivers/net/wireless/rndis_wlan.c -+++ b/drivers/net/wireless/rndis_wlan.c -@@ -517,7 +517,7 @@ static int rndis_set_default_key(struct - u8 key_index, bool unicast, bool multicast); - - static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev, -- u8 *mac, struct station_info *sinfo); -+ const u8 *mac, struct station_info *sinfo); - - static int rndis_dump_station(struct wiphy *wiphy, struct net_device *dev, - int idx, u8 *mac, struct station_info *sinfo); -@@ -2490,7 +2490,7 @@ static void rndis_fill_station_info(stru - } - - static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev, -- u8 *mac, struct station_info *sinfo) -+ const u8 *mac, struct station_info *sinfo) - { - struct rndis_wlan_private *priv = wiphy_priv(wiphy); - struct usbnet *usbdev = priv->usbdev; ---- a/drivers/net/wireless/ti/wlcore/main.c -+++ b/drivers/net/wireless/ti/wlcore/main.c -@@ -1416,7 +1416,7 @@ void wl1271_rx_filter_free(struct wl12xx - - int wl1271_rx_filter_alloc_field(struct wl12xx_rx_filter *filter, - u16 offset, u8 flags, -- u8 *pattern, u8 len) -+ const u8 *pattern, u8 len) - { - struct wl12xx_rx_filter_field *field; - ---- a/drivers/net/wireless/ti/wlcore/wlcore_i.h -+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h -@@ -512,8 +512,8 @@ int wl1271_recalc_rx_streaming(struct wl - void wl12xx_queue_recovery_work(struct wl1271 *wl); - size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen); - int wl1271_rx_filter_alloc_field(struct wl12xx_rx_filter *filter, -- u16 offset, u8 flags, -- u8 *pattern, u8 len); -+ u16 offset, u8 flags, -+ const u8 *pattern, u8 len); - void wl1271_rx_filter_free(struct wl12xx_rx_filter *filter); - struct wl12xx_rx_filter *wl1271_rx_filter_alloc(void); - int wl1271_rx_filter_get_fields_size(struct wl12xx_rx_filter *filter); ---- a/include/net/cfg80211.h -+++ b/include/net/cfg80211.h -@@ -341,8 +341,8 @@ struct vif_params { - * @seq_len: length of @seq. - */ - struct key_params { -- u8 *key; -- u8 *seq; -+ const u8 *key; -+ const u8 *seq; - int key_len; - int seq_len; - u32 cipher; -@@ -458,7 +458,7 @@ bool cfg80211_chandef_usable(struct wiph - */ - int cfg80211_chandef_dfs_required(struct wiphy *wiphy, - const struct cfg80211_chan_def *chandef, -- enum nl80211_iftype); -+ enum nl80211_iftype iftype); - - /** - * ieee80211_chandef_rate_flags - returns rate flags for a channel -@@ -694,8 +694,10 @@ struct cfg80211_ap_settings { - * - * @chandef: defines the channel to use after the switch - * @beacon_csa: beacon data while performing the switch -- * @counter_offset_beacon: offset for the counter within the beacon (tail) -- * @counter_offset_presp: offset for the counter within the probe response -+ * @counter_offsets_beacon: offsets of the counters within the beacon (tail) -+ * @counter_offsets_presp: offsets of the counters within the probe response -+ * @n_counter_offsets_beacon: number of csa counters the beacon (tail) -+ * @n_counter_offsets_presp: number of csa counters in the probe response - * @beacon_after: beacon data to be used on the new channel - * @radar_required: whether radar detection is required on the new channel - * @block_tx: whether transmissions should be blocked while changing -@@ -704,7 +706,10 @@ struct cfg80211_ap_settings { - struct cfg80211_csa_settings { - struct cfg80211_chan_def chandef; - struct cfg80211_beacon_data beacon_csa; -- u16 counter_offset_beacon, counter_offset_presp; -+ const u16 *counter_offsets_beacon; -+ const u16 *counter_offsets_presp; -+ unsigned int n_counter_offsets_beacon; -+ unsigned int n_counter_offsets_presp; - struct cfg80211_beacon_data beacon_after; - bool radar_required; - bool block_tx; -@@ -1164,7 +1169,7 @@ struct bss_parameters { - int use_cts_prot; - int use_short_preamble; - int use_short_slot_time; -- u8 *basic_rates; -+ const u8 *basic_rates; - u8 basic_rates_len; - int ap_isolate; - int ht_opmode; -@@ -1694,10 +1699,10 @@ struct cfg80211_disassoc_request { - * @ht_capa_mask: The bits of ht_capa which are to be used. - */ - struct cfg80211_ibss_params { -- u8 *ssid; -- u8 *bssid; -+ const u8 *ssid; -+ const u8 *bssid; - struct cfg80211_chan_def chandef; -- u8 *ie; -+ const u8 *ie; - u8 ssid_len, ie_len; - u16 beacon_interval; - u32 basic_rates; -@@ -1806,8 +1811,8 @@ struct cfg80211_bitrate_mask { - * @pmkid: The PMK material itself. - */ - struct cfg80211_pmksa { -- u8 *bssid; -- u8 *pmkid; -+ const u8 *bssid; -+ const u8 *pmkid; - }; - - /** -@@ -1822,7 +1827,7 @@ struct cfg80211_pmksa { - * memory, free @mask only! - */ - struct cfg80211_pkt_pattern { -- u8 *mask, *pattern; -+ const u8 *mask, *pattern; - int pattern_len; - int pkt_offset; - }; -@@ -1986,6 +1991,8 @@ struct cfg80211_update_ft_ies_params { - * @len: buffer length - * @no_cck: don't use cck rates for this frame - * @dont_wait_for_ack: tells the low level not to wait for an ack -+ * @n_csa_offsets: length of csa_offsets array -+ * @csa_offsets: array of all the csa offsets in the frame - */ - struct cfg80211_mgmt_tx_params { - struct ieee80211_channel *chan; -@@ -1995,6 +2002,8 @@ struct cfg80211_mgmt_tx_params { - size_t len; - bool no_cck; - bool dont_wait_for_ack; -+ int n_csa_offsets; -+ const u16 *csa_offsets; - }; - - /** -@@ -2336,28 +2345,29 @@ struct cfg80211_ops { - - - int (*add_station)(struct wiphy *wiphy, struct net_device *dev, -- u8 *mac, struct station_parameters *params); -+ const u8 *mac, -+ struct station_parameters *params); - int (*del_station)(struct wiphy *wiphy, struct net_device *dev, -- u8 *mac); -+ const u8 *mac); - int (*change_station)(struct wiphy *wiphy, struct net_device *dev, -- u8 *mac, struct station_parameters *params); -+ const u8 *mac, -+ struct station_parameters *params); - int (*get_station)(struct wiphy *wiphy, struct net_device *dev, -- u8 *mac, struct station_info *sinfo); -+ const u8 *mac, struct station_info *sinfo); - int (*dump_station)(struct wiphy *wiphy, struct net_device *dev, -- int idx, u8 *mac, struct station_info *sinfo); -+ int idx, u8 *mac, struct station_info *sinfo); - - int (*add_mpath)(struct wiphy *wiphy, struct net_device *dev, -- u8 *dst, u8 *next_hop); -+ const u8 *dst, const u8 *next_hop); - int (*del_mpath)(struct wiphy *wiphy, struct net_device *dev, -- u8 *dst); -+ const u8 *dst); - int (*change_mpath)(struct wiphy *wiphy, struct net_device *dev, -- u8 *dst, u8 *next_hop); -+ const u8 *dst, const u8 *next_hop); - int (*get_mpath)(struct wiphy *wiphy, struct net_device *dev, -- u8 *dst, u8 *next_hop, -- struct mpath_info *pinfo); -+ u8 *dst, u8 *next_hop, struct mpath_info *pinfo); - int (*dump_mpath)(struct wiphy *wiphy, struct net_device *dev, -- int idx, u8 *dst, u8 *next_hop, -- struct mpath_info *pinfo); -+ int idx, u8 *dst, u8 *next_hop, -+ struct mpath_info *pinfo); - int (*get_mesh_config)(struct wiphy *wiphy, - struct net_device *dev, - struct mesh_config *conf); -@@ -2487,11 +2497,11 @@ struct cfg80211_ops { - struct cfg80211_gtk_rekey_data *data); - - int (*tdls_mgmt)(struct wiphy *wiphy, struct net_device *dev, -- u8 *peer, u8 action_code, u8 dialog_token, -+ const u8 *peer, u8 action_code, u8 dialog_token, - u16 status_code, u32 peer_capability, - const u8 *buf, size_t len); - int (*tdls_oper)(struct wiphy *wiphy, struct net_device *dev, -- u8 *peer, enum nl80211_tdls_operation oper); -+ const u8 *peer, enum nl80211_tdls_operation oper); - - int (*probe_client)(struct wiphy *wiphy, struct net_device *dev, - const u8 *peer, u64 *cookie); -@@ -2638,6 +2648,7 @@ struct ieee80211_iface_limit { - * between infrastructure and AP types must match. This is required - * only in special cases. - * @radar_detect_widths: bitmap of channel widths supported for radar detection -+ * @radar_detect_regions: bitmap of regions supported for radar detection - * - * With this structure the driver can describe which interface - * combinations it supports concurrently. -@@ -2695,6 +2706,7 @@ struct ieee80211_iface_combination { - u8 n_limits; - bool beacon_int_infra_match; - u8 radar_detect_widths; -+ u8 radar_detect_regions; - }; - - struct ieee80211_txrx_stypes { -@@ -2925,6 +2937,11 @@ struct wiphy_vendor_command { - * (including P2P GO) or 0 to indicate no such limit is advertised. The - * driver is allowed to advertise a theoretical limit that it can reach in - * some cases, but may not always reach. -+ * -+ * @max_num_csa_counters: Number of supported csa_counters in beacons -+ * and probe responses. This value should be set if the driver -+ * wishes to limit the number of csa counters. Default (0) means -+ * infinite. - */ - struct wiphy { - /* assign these fields before you register the wiphy */ -@@ -3045,6 +3062,8 @@ struct wiphy { - - u16 max_ap_assoc_sta; - -+ u8 max_num_csa_counters; -+ - char priv[0] __aligned(NETDEV_ALIGN); - }; - -@@ -3273,7 +3292,7 @@ struct wireless_dev { - struct cfg80211_ibss_params ibss; - struct cfg80211_connect_params connect; - struct cfg80211_cached_keys *keys; -- u8 *ie; -+ const u8 *ie; - size_t ie_len; - u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; - u8 ssid[IEEE80211_MAX_SSID_LEN]; -@@ -3514,7 +3533,8 @@ int ieee80211_data_to_8023(struct sk_buf - * Return: 0 on success, or a negative error code. - */ - int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr, -- enum nl80211_iftype iftype, u8 *bssid, bool qos); -+ enum nl80211_iftype iftype, const u8 *bssid, -+ bool qos); - - /** - * ieee80211_amsdu_to_8023s - decode an IEEE 802.11n A-MSDU frame -@@ -4315,7 +4335,7 @@ void cfg80211_roamed_bss(struct net_devi - * and not try to connect to any AP any more. - */ - void cfg80211_disconnected(struct net_device *dev, u16 reason, -- u8 *ie, size_t ie_len, gfp_t gfp); -+ const u8 *ie, size_t ie_len, gfp_t gfp); - - /** - * cfg80211_ready_on_channel - notification of remain_on_channel start -@@ -4771,6 +4791,35 @@ int cfg80211_iter_combinations(struct wi - void *data), - void *data); - -+/* -+ * cfg80211_stop_iface - trigger interface disconnection -+ * -+ * @wiphy: the wiphy -+ * @wdev: wireless device -+ * @gfp: context flags -+ * -+ * Trigger interface to be stopped as if AP was stopped, IBSS/mesh left, STA -+ * disconnected. -+ * -+ * Note: This doesn't need any locks and is asynchronous. -+ */ -+void cfg80211_stop_iface(struct wiphy *wiphy, struct wireless_dev *wdev, -+ gfp_t gfp); -+ -+/** -+ * cfg80211_shutdown_all_interfaces - shut down all interfaces for a wiphy -+ * @wiphy: the wiphy to shut down -+ * -+ * This function shuts down all interfaces belonging to this wiphy by -+ * calling dev_close() (and treating non-netdev interfaces as needed). -+ * It shouldn't really be used unless there are some fatal device errors -+ * that really can't be recovered in any other way. -+ * -+ * Callers must hold the RTNL and be able to deal with callbacks into -+ * the driver while the function is running. -+ */ -+void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy); -+ - /* Logging, debugging and troubleshooting/diagnostic helpers. */ - - /* wiphy_printk helpers, similar to dev_printk */ ---- a/include/net/mac80211.h -+++ b/include/net/mac80211.h -@@ -1113,7 +1113,9 @@ enum ieee80211_vif_flags { - * @addr: address of this interface - * @p2p: indicates whether this AP or STA interface is a p2p - * interface, i.e. a GO or p2p-sta respectively -- * @csa_active: marks whether a channel switch is going on -+ * @csa_active: marks whether a channel switch is going on. Internally it is -+ * write-protected by sdata_lock and local->mtx so holding either is fine -+ * for read access. - * @driver_flags: flags/capabilities the driver has for this interface, - * these need to be set (or cleared) when the interface is added - * or, if supported by the driver, the interface type is changed -@@ -1374,6 +1376,7 @@ struct ieee80211_sta_rates { - * the station moves to associated state. - * @smps_mode: current SMPS mode (off, static or dynamic) - * @rates: rate control selection table -+ * @tdls: indicates whether the STA is a TDLS peer - */ - struct ieee80211_sta { - u32 supp_rates[IEEE80211_NUM_BANDS]; -@@ -1388,6 +1391,7 @@ struct ieee80211_sta { - enum ieee80211_sta_rx_bandwidth bandwidth; - enum ieee80211_smps_mode smps_mode; - struct ieee80211_sta_rates __rcu *rates; -+ bool tdls; - - /* must be last */ - u8 drv_priv[0] __aligned(sizeof(void *)); -@@ -3407,6 +3411,47 @@ void ieee80211_tx_status_irqsafe(struct - */ - void ieee80211_report_low_ack(struct ieee80211_sta *sta, u32 num_packets); - -+#define IEEE80211_MAX_CSA_COUNTERS_NUM 2 -+ -+/** -+ * struct ieee80211_mutable_offsets - mutable beacon offsets -+ * @tim_offset: position of TIM element -+ * @tim_length: size of TIM element -+ * @csa_counter_offs: array of IEEE80211_MAX_CSA_COUNTERS_NUM offsets -+ * to CSA counters. This array can contain zero values which -+ * should be ignored. -+ */ -+struct ieee80211_mutable_offsets { -+ u16 tim_offset; -+ u16 tim_length; -+ -+ u16 csa_counter_offs[IEEE80211_MAX_CSA_COUNTERS_NUM]; -+}; -+ -+/** -+ * ieee80211_beacon_get_template - beacon template generation function -+ * @hw: pointer obtained from ieee80211_alloc_hw(). -+ * @vif: &struct ieee80211_vif pointer from the add_interface callback. -+ * @offs: &struct ieee80211_mutable_offsets pointer to struct that will -+ * receive the offsets that may be updated by the driver. -+ * -+ * If the driver implements beaconing modes, it must use this function to -+ * obtain the beacon template. -+ * -+ * This function should be used if the beacon frames are generated by the -+ * device, and then the driver must use the returned beacon as the template -+ * The driver or the device are responsible to update the DTIM and, when -+ * applicable, the CSA count. -+ * -+ * The driver is responsible for freeing the returned skb. -+ * -+ * Return: The beacon template. %NULL on error. -+ */ -+struct sk_buff * -+ieee80211_beacon_get_template(struct ieee80211_hw *hw, -+ struct ieee80211_vif *vif, -+ struct ieee80211_mutable_offsets *offs); -+ - /** - * ieee80211_beacon_get_tim - beacon generation function - * @hw: pointer obtained from ieee80211_alloc_hw(). -@@ -3418,16 +3463,12 @@ void ieee80211_report_low_ack(struct iee - * Set to 0 if invalid (in non-AP modes). - * - * If the driver implements beaconing modes, it must use this function to -- * obtain the beacon frame/template. -+ * obtain the beacon frame. - * - * If the beacon frames are generated by the host system (i.e., not in - * hardware/firmware), the driver uses this function to get each beacon -- * frame from mac80211 -- it is responsible for calling this function -- * before the beacon is needed (e.g. based on hardware interrupt). -- * -- * If the beacon frames are generated by the device, then the driver -- * must use the returned beacon as the template and change the TIM IE -- * according to the current DTIM parameters/TIM bitmap. -+ * frame from mac80211 -- it is responsible for calling this function exactly -+ * once before the beacon is needed (e.g. based on hardware interrupt). - * - * The driver is responsible for freeing the returned skb. - * -@@ -3453,6 +3494,20 @@ static inline struct sk_buff *ieee80211_ - } - - /** -+ * ieee80211_csa_update_counter - request mac80211 to decrement the csa counter -+ * @vif: &struct ieee80211_vif pointer from the add_interface callback. -+ * -+ * The csa counter should be updated after each beacon transmission. -+ * This function is called implicitly when -+ * ieee80211_beacon_get/ieee80211_beacon_get_tim are called, however if the -+ * beacon frames are generated by the device, the driver should call this -+ * function after each beacon transmission to sync mac80211's csa counters. -+ * -+ * Return: new csa counter value -+ */ -+u8 ieee80211_csa_update_counter(struct ieee80211_vif *vif); -+ -+/** - * ieee80211_csa_finish - notify mac80211 about channel switch - * @vif: &struct ieee80211_vif pointer from the add_interface callback. - * ---- a/include/uapi/linux/nl80211.h -+++ b/include/uapi/linux/nl80211.h -@@ -503,6 +503,9 @@ - * TX status event pertaining to the TX request. - * %NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the - * management frames at CCK rate or not in 2GHz band. -+ * %NL80211_ATTR_CSA_C_OFFSETS_TX is an array of offsets to CSA -+ * counters which will be updated to the current value. This attribute -+ * is used during CSA period. - * @NL80211_CMD_FRAME_WAIT_CANCEL: When an off-channel TX was requested, this - * command may be used with the corresponding cookie to cancel the wait - * time if it is known that it is no longer necessary. -@@ -1525,10 +1528,10 @@ enum nl80211_commands { - * operation). - * @NL80211_ATTR_CSA_IES: Nested set of attributes containing the IE information - * for the time while performing a channel switch. -- * @NL80211_ATTR_CSA_C_OFF_BEACON: Offset of the channel switch counter -- * field in the beacons tail (%NL80211_ATTR_BEACON_TAIL). -- * @NL80211_ATTR_CSA_C_OFF_PRESP: Offset of the channel switch counter -- * field in the probe response (%NL80211_ATTR_PROBE_RESP). -+ * @NL80211_ATTR_CSA_C_OFF_BEACON: An array of offsets (u16) to the channel -+ * switch counters in the beacons tail (%NL80211_ATTR_BEACON_TAIL). -+ * @NL80211_ATTR_CSA_C_OFF_PRESP: An array of offsets (u16) to the channel -+ * switch counters in the probe response (%NL80211_ATTR_PROBE_RESP). - * - * @NL80211_ATTR_RXMGMT_FLAGS: flags for nl80211_send_mgmt(), u32. - * As specified in the &enum nl80211_rxmgmt_flags. -@@ -1576,6 +1579,11 @@ enum nl80211_commands { - * advertise values that cannot always be met. In such cases, an attempt - * to add a new station entry with @NL80211_CMD_NEW_STATION may fail. - * -+ * @NL80211_ATTR_CSA_C_OFFSETS_TX: An array of csa counter offsets (u16) which -+ * should be updated when the frame is transmitted. -+ * @NL80211_ATTR_MAX_CSA_COUNTERS: U8 attribute used to advertise the maximum -+ * supported number of csa counters. -+ * - * @NL80211_ATTR_TDLS_PEER_CAPABILITY: flags for TDLS peer capabilities, u32. - * As specified in the &enum nl80211_tdls_peer_capability. - * -@@ -1920,6 +1928,9 @@ enum nl80211_attrs { - - NL80211_ATTR_IFACE_SOCKET_OWNER, - -+ NL80211_ATTR_CSA_C_OFFSETS_TX, -+ NL80211_ATTR_MAX_CSA_COUNTERS, -+ - /* add attributes here, update the policy in nl80211.c */ - - __NL80211_ATTR_AFTER_LAST, -@@ -3688,6 +3699,8 @@ enum nl80211_iface_limit_attrs { - * different channels may be used within this group. - * @NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS: u32 attribute containing the bitmap - * of supported channel widths for radar detection. -+ * @NL80211_IFACE_COMB_RADAR_DETECT_REGIONS: u32 attribute containing the bitmap -+ * of supported regulatory regions for radar detection. - * @NUM_NL80211_IFACE_COMB: number of attributes - * @MAX_NL80211_IFACE_COMB: highest attribute number - * -@@ -3721,6 +3734,7 @@ enum nl80211_if_combination_attrs { - NL80211_IFACE_COMB_STA_AP_BI_MATCH, - NL80211_IFACE_COMB_NUM_CHANNELS, - NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS, -+ NL80211_IFACE_COMB_RADAR_DETECT_REGIONS, - - /* keep last */ - NUM_NL80211_IFACE_COMB, ---- a/net/mac80211/Makefile -+++ b/net/mac80211/Makefile -@@ -25,7 +25,8 @@ mac80211-y := \ - wme.o \ - event.o \ - chan.o \ -- trace.o mlme.o -+ trace.o mlme.o \ -+ tdls.o - - mac80211-$(CPTCFG_MAC80211_LEDS) += led.o - mac80211-$(CPTCFG_MAC80211_DEBUGFS) += \ ---- a/net/mac80211/cfg.c -+++ b/net/mac80211/cfg.c -@@ -777,7 +777,7 @@ static void ieee80211_get_et_strings(str - } - - static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, -- int idx, u8 *mac, struct station_info *sinfo) -+ int idx, u8 *mac, struct station_info *sinfo) - { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - struct ieee80211_local *local = sdata->local; -@@ -807,7 +807,7 @@ static int ieee80211_dump_survey(struct - } - - static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, -- u8 *mac, struct station_info *sinfo) -+ const u8 *mac, struct station_info *sinfo) - { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - struct ieee80211_local *local = sdata->local; -@@ -1084,6 +1084,31 @@ static int ieee80211_change_beacon(struc - return 0; - } - -+bool ieee80211_csa_needs_block_tx(struct ieee80211_local *local) -+{ -+ struct ieee80211_sub_if_data *sdata; -+ -+ lockdep_assert_held(&local->mtx); -+ -+ rcu_read_lock(); -+ list_for_each_entry_rcu(sdata, &local->interfaces, list) { -+ if (!ieee80211_sdata_running(sdata)) -+ continue; -+ -+ if (!sdata->vif.csa_active) -+ continue; -+ -+ if (!sdata->csa_block_tx) -+ continue; -+ -+ rcu_read_unlock(); -+ return true; -+ } -+ rcu_read_unlock(); -+ -+ return false; -+} -+ - static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) - { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); -@@ -1101,7 +1126,14 @@ static int ieee80211_stop_ap(struct wiph - old_probe_resp = sdata_dereference(sdata->u.ap.probe_resp, sdata); - - /* abort any running channel switch */ -+ mutex_lock(&local->mtx); - sdata->vif.csa_active = false; -+ if (!ieee80211_csa_needs_block_tx(local)) -+ ieee80211_wake_queues_by_reason(&local->hw, -+ IEEE80211_MAX_QUEUE_MAP, -+ IEEE80211_QUEUE_STOP_REASON_CSA); -+ mutex_unlock(&local->mtx); -+ - kfree(sdata->u.ap.next_beacon); - sdata->u.ap.next_beacon = NULL; - -@@ -1425,7 +1457,8 @@ static int sta_apply_parameters(struct i - } - - static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, -- u8 *mac, struct station_parameters *params) -+ const u8 *mac, -+ struct station_parameters *params) - { - struct ieee80211_local *local = wiphy_priv(wiphy); - struct sta_info *sta; -@@ -1459,6 +1492,8 @@ static int ieee80211_add_station(struct - if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) { - sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); - sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); -+ } else { -+ sta->sta.tdls = true; - } - - err = sta_apply_parameters(local, sta, params); -@@ -1492,7 +1527,7 @@ static int ieee80211_add_station(struct - } - - static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, -- u8 *mac) -+ const u8 *mac) - { - struct ieee80211_sub_if_data *sdata; - -@@ -1506,7 +1541,7 @@ static int ieee80211_del_station(struct - } - - static int ieee80211_change_station(struct wiphy *wiphy, -- struct net_device *dev, u8 *mac, -+ struct net_device *dev, const u8 *mac, - struct station_parameters *params) - { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); -@@ -1631,7 +1666,7 @@ out_err: - - #ifdef CPTCFG_MAC80211_MESH - static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, -- u8 *dst, u8 *next_hop) -+ const u8 *dst, const u8 *next_hop) - { - struct ieee80211_sub_if_data *sdata; - struct mesh_path *mpath; -@@ -1659,7 +1694,7 @@ static int ieee80211_add_mpath(struct wi - } - - static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev, -- u8 *dst) -+ const u8 *dst) - { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - -@@ -1670,9 +1705,8 @@ static int ieee80211_del_mpath(struct wi - return 0; - } - --static int ieee80211_change_mpath(struct wiphy *wiphy, -- struct net_device *dev, -- u8 *dst, u8 *next_hop) -+static int ieee80211_change_mpath(struct wiphy *wiphy, struct net_device *dev, -+ const u8 *dst, const u8 *next_hop) - { - struct ieee80211_sub_if_data *sdata; - struct mesh_path *mpath; -@@ -1764,8 +1798,8 @@ static int ieee80211_get_mpath(struct wi - } - - static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, -- int idx, u8 *dst, u8 *next_hop, -- struct mpath_info *pinfo) -+ int idx, u8 *dst, u8 *next_hop, -+ struct mpath_info *pinfo) - { - struct ieee80211_sub_if_data *sdata; - struct mesh_path *mpath; -@@ -3019,26 +3053,11 @@ void ieee80211_csa_finish(struct ieee802 - } - EXPORT_SYMBOL(ieee80211_csa_finish); - --static void ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata) -+static int ieee80211_set_after_csa_beacon(struct ieee80211_sub_if_data *sdata, -+ u32 *changed) - { -- struct ieee80211_local *local = sdata->local; -- int err, changed = 0; -- -- sdata_assert_lock(sdata); -- -- mutex_lock(&local->mtx); -- sdata->radar_required = sdata->csa_radar_required; -- err = ieee80211_vif_change_channel(sdata, &changed); -- mutex_unlock(&local->mtx); -- if (WARN_ON(err < 0)) -- return; -- -- if (!local->use_chanctx) { -- local->_oper_chandef = sdata->csa_chandef; -- ieee80211_hw_config(local, 0); -- } -+ int err; - -- sdata->vif.csa_active = false; - switch (sdata->vif.type) { - case NL80211_IFTYPE_AP: - err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon); -@@ -3046,35 +3065,75 @@ static void ieee80211_csa_finalize(struc - sdata->u.ap.next_beacon = NULL; - - if (err < 0) -- return; -- changed |= err; -+ return err; -+ *changed |= err; - break; - case NL80211_IFTYPE_ADHOC: - err = ieee80211_ibss_finish_csa(sdata); - if (err < 0) -- return; -- changed |= err; -+ return err; -+ *changed |= err; - break; - #ifdef CPTCFG_MAC80211_MESH - case NL80211_IFTYPE_MESH_POINT: - err = ieee80211_mesh_finish_csa(sdata); - if (err < 0) -- return; -- changed |= err; -+ return err; -+ *changed |= err; - break; - #endif - default: - WARN_ON(1); -- return; -+ return -EINVAL; - } - -+ -+ return 0; -+} -+ -+static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata) -+{ -+ struct ieee80211_local *local = sdata->local; -+ u32 changed = 0; -+ int err; -+ -+ sdata_assert_lock(sdata); -+ lockdep_assert_held(&local->mtx); -+ -+ sdata->radar_required = sdata->csa_radar_required; -+ err = ieee80211_vif_change_channel(sdata, &changed); -+ if (err < 0) -+ return err; -+ -+ if (!local->use_chanctx) { -+ local->_oper_chandef = sdata->csa_chandef; -+ ieee80211_hw_config(local, 0); -+ } -+ -+ sdata->vif.csa_active = false; -+ -+ err = ieee80211_set_after_csa_beacon(sdata, &changed); -+ if (err) -+ return err; -+ - ieee80211_bss_info_change_notify(sdata, changed); -+ cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef); - -- ieee80211_wake_queues_by_reason(&sdata->local->hw, -+ if (!ieee80211_csa_needs_block_tx(local)) -+ ieee80211_wake_queues_by_reason(&local->hw, - IEEE80211_MAX_QUEUE_MAP, - IEEE80211_QUEUE_STOP_REASON_CSA); - -- cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef); -+ return 0; -+} -+ -+static void ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata) -+{ -+ if (__ieee80211_csa_finalize(sdata)) { -+ sdata_info(sdata, "failed to finalize CSA, disconnecting\n"); -+ cfg80211_stop_iface(sdata->local->hw.wiphy, &sdata->wdev, -+ GFP_KERNEL); -+ } - } - - void ieee80211_csa_finalize_work(struct work_struct *work) -@@ -3082,8 +3141,11 @@ void ieee80211_csa_finalize_work(struct - struct ieee80211_sub_if_data *sdata = - container_of(work, struct ieee80211_sub_if_data, - csa_finalize_work); -+ struct ieee80211_local *local = sdata->local; - - sdata_lock(sdata); -+ mutex_lock(&local->mtx); -+ - /* AP might have been stopped while waiting for the lock. */ - if (!sdata->vif.csa_active) - goto unlock; -@@ -3094,6 +3156,7 @@ void ieee80211_csa_finalize_work(struct - ieee80211_csa_finalize(sdata); - - unlock: -+ mutex_unlock(&local->mtx); - sdata_unlock(sdata); - } - -@@ -3129,9 +3192,25 @@ static int ieee80211_set_csa_beacon(stru - if (params->count <= 1) - break; - -- sdata->csa_counter_offset_beacon = -- params->counter_offset_beacon; -- sdata->csa_counter_offset_presp = params->counter_offset_presp; -+ if ((params->n_counter_offsets_beacon > -+ IEEE80211_MAX_CSA_COUNTERS_NUM) || -+ (params->n_counter_offsets_presp > -+ 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)); -+ - err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa); - if (err < 0) { - kfree(sdata->u.ap.next_beacon); -@@ -3220,8 +3299,9 @@ static int ieee80211_set_csa_beacon(stru - return 0; - } - --int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, -- struct cfg80211_csa_settings *params) -+static int -+__ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, -+ struct cfg80211_csa_settings *params) - { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - struct ieee80211_local *local = sdata->local; -@@ -3230,6 +3310,7 @@ int ieee80211_channel_switch(struct wiph - int err, num_chanctx, changed = 0; - - sdata_assert_lock(sdata); -+ lockdep_assert_held(&local->mtx); - - if (!list_empty(&local->roc_list) || local->scanning) - return -EBUSY; -@@ -3272,15 +3353,16 @@ int ieee80211_channel_switch(struct wiph - return err; - - sdata->csa_radar_required = params->radar_required; -- -- if (params->block_tx) -- ieee80211_stop_queues_by_reason(&local->hw, -- IEEE80211_MAX_QUEUE_MAP, -- IEEE80211_QUEUE_STOP_REASON_CSA); -- - 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) -+ ieee80211_stop_queues_by_reason(&local->hw, -+ IEEE80211_MAX_QUEUE_MAP, -+ IEEE80211_QUEUE_STOP_REASON_CSA); -+ - if (changed) { - ieee80211_bss_info_change_notify(sdata, changed); - drv_channel_switch_beacon(sdata, ¶ms->chandef); -@@ -3292,6 +3374,20 @@ int ieee80211_channel_switch(struct wiph - return 0; - } - -+int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, -+ struct cfg80211_csa_settings *params) -+{ -+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); -+ struct ieee80211_local *local = sdata->local; -+ int err; -+ -+ mutex_lock(&local->mtx); -+ err = __ieee80211_channel_switch(wiphy, dev, params); -+ mutex_unlock(&local->mtx); -+ -+ return err; -+} -+ - static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, - struct cfg80211_mgmt_tx_params *params, - u64 *cookie) -@@ -3304,6 +3400,7 @@ static int ieee80211_mgmt_tx(struct wiph - bool need_offchan = false; - u32 flags; - int ret; -+ u8 *data; - - if (params->dont_wait_for_ack) - flags = IEEE80211_TX_CTL_NO_ACK; -@@ -3397,7 +3494,20 @@ static int ieee80211_mgmt_tx(struct wiph - } - skb_reserve(skb, local->hw.extra_tx_headroom); - -- memcpy(skb_put(skb, params->len), params->buf, params->len); -+ data = skb_put(skb, params->len); -+ memcpy(data, params->buf, params->len); -+ -+ /* Update CSA counters */ -+ if (sdata->vif.csa_active && -+ (sdata->vif.type == NL80211_IFTYPE_AP || -+ sdata->vif.type == NL80211_IFTYPE_ADHOC) && -+ params->n_csa_offsets) { -+ int i; -+ u8 c = sdata->csa_current_counter; -+ -+ for (i = 0; i < params->n_csa_offsets; i++) -+ data[params->csa_offsets[i]] = c; -+ } - - IEEE80211_SKB_CB(skb)->flags = flags; - -@@ -3506,320 +3616,6 @@ static int ieee80211_set_rekey_data(stru - return 0; - } - --static void ieee80211_tdls_add_ext_capab(struct sk_buff *skb) --{ -- u8 *pos = (void *)skb_put(skb, 7); -- -- *pos++ = WLAN_EID_EXT_CAPABILITY; -- *pos++ = 5; /* len */ -- *pos++ = 0x0; -- *pos++ = 0x0; -- *pos++ = 0x0; -- *pos++ = 0x0; -- *pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED; --} -- --static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata) --{ -- struct ieee80211_local *local = sdata->local; -- u16 capab; -- -- capab = 0; -- if (ieee80211_get_sdata_band(sdata) != IEEE80211_BAND_2GHZ) -- return capab; -- -- if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE)) -- capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME; -- if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE)) -- capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; -- -- return capab; --} -- --static void ieee80211_tdls_add_link_ie(struct sk_buff *skb, u8 *src_addr, -- u8 *peer, u8 *bssid) --{ -- struct ieee80211_tdls_lnkie *lnkid; -- -- lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie)); -- -- lnkid->ie_type = WLAN_EID_LINK_ID; -- lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2; -- -- memcpy(lnkid->bssid, bssid, ETH_ALEN); -- memcpy(lnkid->init_sta, src_addr, ETH_ALEN); -- memcpy(lnkid->resp_sta, peer, ETH_ALEN); --} -- --static int --ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, -- u8 *peer, u8 action_code, u8 dialog_token, -- u16 status_code, struct sk_buff *skb) --{ -- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); -- enum ieee80211_band band = ieee80211_get_sdata_band(sdata); -- struct ieee80211_tdls_data *tf; -- -- tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u)); -- -- memcpy(tf->da, peer, ETH_ALEN); -- memcpy(tf->sa, sdata->vif.addr, ETH_ALEN); -- tf->ether_type = cpu_to_be16(ETH_P_TDLS); -- tf->payload_type = WLAN_TDLS_SNAP_RFTYPE; -- -- switch (action_code) { -- case WLAN_TDLS_SETUP_REQUEST: -- tf->category = WLAN_CATEGORY_TDLS; -- tf->action_code = WLAN_TDLS_SETUP_REQUEST; -- -- skb_put(skb, sizeof(tf->u.setup_req)); -- tf->u.setup_req.dialog_token = dialog_token; -- tf->u.setup_req.capability = -- cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); -- -- ieee80211_add_srates_ie(sdata, skb, false, band); -- ieee80211_add_ext_srates_ie(sdata, skb, false, band); -- ieee80211_tdls_add_ext_capab(skb); -- break; -- case WLAN_TDLS_SETUP_RESPONSE: -- tf->category = WLAN_CATEGORY_TDLS; -- tf->action_code = WLAN_TDLS_SETUP_RESPONSE; -- -- skb_put(skb, sizeof(tf->u.setup_resp)); -- tf->u.setup_resp.status_code = cpu_to_le16(status_code); -- tf->u.setup_resp.dialog_token = dialog_token; -- tf->u.setup_resp.capability = -- cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); -- -- ieee80211_add_srates_ie(sdata, skb, false, band); -- ieee80211_add_ext_srates_ie(sdata, skb, false, band); -- ieee80211_tdls_add_ext_capab(skb); -- break; -- case WLAN_TDLS_SETUP_CONFIRM: -- tf->category = WLAN_CATEGORY_TDLS; -- tf->action_code = WLAN_TDLS_SETUP_CONFIRM; -- -- skb_put(skb, sizeof(tf->u.setup_cfm)); -- tf->u.setup_cfm.status_code = cpu_to_le16(status_code); -- tf->u.setup_cfm.dialog_token = dialog_token; -- break; -- case WLAN_TDLS_TEARDOWN: -- tf->category = WLAN_CATEGORY_TDLS; -- tf->action_code = WLAN_TDLS_TEARDOWN; -- -- skb_put(skb, sizeof(tf->u.teardown)); -- tf->u.teardown.reason_code = cpu_to_le16(status_code); -- break; -- case WLAN_TDLS_DISCOVERY_REQUEST: -- tf->category = WLAN_CATEGORY_TDLS; -- tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST; -- -- skb_put(skb, sizeof(tf->u.discover_req)); -- tf->u.discover_req.dialog_token = dialog_token; -- break; -- default: -- return -EINVAL; -- } -- -- return 0; --} -- --static int --ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, -- u8 *peer, u8 action_code, u8 dialog_token, -- u16 status_code, struct sk_buff *skb) --{ -- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); -- enum ieee80211_band band = ieee80211_get_sdata_band(sdata); -- struct ieee80211_mgmt *mgmt; -- -- mgmt = (void *)skb_put(skb, 24); -- memset(mgmt, 0, 24); -- memcpy(mgmt->da, peer, ETH_ALEN); -- memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); -- memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); -- -- mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | -- IEEE80211_STYPE_ACTION); -- -- switch (action_code) { -- case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: -- skb_put(skb, 1 + sizeof(mgmt->u.action.u.tdls_discover_resp)); -- mgmt->u.action.category = WLAN_CATEGORY_PUBLIC; -- mgmt->u.action.u.tdls_discover_resp.action_code = -- WLAN_PUB_ACTION_TDLS_DISCOVER_RES; -- mgmt->u.action.u.tdls_discover_resp.dialog_token = -- dialog_token; -- mgmt->u.action.u.tdls_discover_resp.capability = -- cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); -- -- ieee80211_add_srates_ie(sdata, skb, false, band); -- ieee80211_add_ext_srates_ie(sdata, skb, false, band); -- ieee80211_tdls_add_ext_capab(skb); -- break; -- default: -- return -EINVAL; -- } -- -- return 0; --} -- --static int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, -- u8 *peer, u8 action_code, u8 dialog_token, -- u16 status_code, u32 peer_capability, -- const u8 *extra_ies, size_t extra_ies_len) --{ -- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); -- struct ieee80211_local *local = sdata->local; -- struct sk_buff *skb = NULL; -- bool send_direct; -- int ret; -- -- if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) -- return -ENOTSUPP; -- -- /* make sure we are in managed mode, and associated */ -- if (sdata->vif.type != NL80211_IFTYPE_STATION || -- !sdata->u.mgd.associated) -- return -EINVAL; -- -- tdls_dbg(sdata, "TDLS mgmt action %d peer %pM\n", -- action_code, peer); -- -- skb = dev_alloc_skb(local->hw.extra_tx_headroom + -- max(sizeof(struct ieee80211_mgmt), -- sizeof(struct ieee80211_tdls_data)) + -- 50 + /* supported rates */ -- 7 + /* ext capab */ -- extra_ies_len + -- sizeof(struct ieee80211_tdls_lnkie)); -- if (!skb) -- return -ENOMEM; -- -- skb_reserve(skb, local->hw.extra_tx_headroom); -- -- switch (action_code) { -- case WLAN_TDLS_SETUP_REQUEST: -- case WLAN_TDLS_SETUP_RESPONSE: -- case WLAN_TDLS_SETUP_CONFIRM: -- case WLAN_TDLS_TEARDOWN: -- case WLAN_TDLS_DISCOVERY_REQUEST: -- ret = ieee80211_prep_tdls_encap_data(wiphy, dev, peer, -- action_code, dialog_token, -- status_code, skb); -- send_direct = false; -- break; -- case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: -- ret = ieee80211_prep_tdls_direct(wiphy, dev, peer, action_code, -- dialog_token, status_code, -- skb); -- send_direct = true; -- break; -- default: -- ret = -ENOTSUPP; -- break; -- } -- -- if (ret < 0) -- goto fail; -- -- if (extra_ies_len) -- memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len); -- -- /* the TDLS link IE is always added last */ -- switch (action_code) { -- case WLAN_TDLS_SETUP_REQUEST: -- case WLAN_TDLS_SETUP_CONFIRM: -- case WLAN_TDLS_TEARDOWN: -- case WLAN_TDLS_DISCOVERY_REQUEST: -- /* we are the initiator */ -- ieee80211_tdls_add_link_ie(skb, sdata->vif.addr, peer, -- sdata->u.mgd.bssid); -- break; -- case WLAN_TDLS_SETUP_RESPONSE: -- case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: -- /* we are the responder */ -- ieee80211_tdls_add_link_ie(skb, peer, sdata->vif.addr, -- sdata->u.mgd.bssid); -- break; -- default: -- ret = -ENOTSUPP; -- goto fail; -- } -- -- if (send_direct) { -- ieee80211_tx_skb(sdata, skb); -- return 0; -- } -- -- /* -- * According to 802.11z: Setup req/resp are sent in AC_BK, otherwise -- * we should default to AC_VI. -- */ -- switch (action_code) { -- case WLAN_TDLS_SETUP_REQUEST: -- case WLAN_TDLS_SETUP_RESPONSE: -- skb_set_queue_mapping(skb, IEEE80211_AC_BK); -- skb->priority = 2; -- break; -- default: -- skb_set_queue_mapping(skb, IEEE80211_AC_VI); -- skb->priority = 5; -- break; -- } -- -- /* disable bottom halves when entering the Tx path */ -- local_bh_disable(); -- ret = ieee80211_subif_start_xmit(skb, dev); -- local_bh_enable(); -- -- return ret; -- --fail: -- dev_kfree_skb(skb); -- return ret; --} -- --static int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, -- u8 *peer, enum nl80211_tdls_operation oper) --{ -- struct sta_info *sta; -- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); -- -- if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) -- return -ENOTSUPP; -- -- if (sdata->vif.type != NL80211_IFTYPE_STATION) -- return -EINVAL; -- -- tdls_dbg(sdata, "TDLS oper %d peer %pM\n", oper, peer); -- -- switch (oper) { -- case NL80211_TDLS_ENABLE_LINK: -- rcu_read_lock(); -- sta = sta_info_get(sdata, peer); -- if (!sta) { -- rcu_read_unlock(); -- return -ENOLINK; -- } -- -- set_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH); -- rcu_read_unlock(); -- break; -- case NL80211_TDLS_DISABLE_LINK: -- return sta_info_destroy_addr(sdata, peer); -- case NL80211_TDLS_TEARDOWN: -- case NL80211_TDLS_SETUP: -- case NL80211_TDLS_DISCOVERY_REQ: -- /* We don't support in-driver setup/teardown/discovery */ -- return -ENOTSUPP; -- default: -- return -ENOTSUPP; -- } -- -- return 0; --} -- - static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, - const u8 *peer, u64 *cookie) - { ---- a/net/mac80211/chan.c -+++ b/net/mac80211/chan.c -@@ -855,7 +855,7 @@ static void - __ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata, - bool clear) - { -- struct ieee80211_local *local = sdata->local; -+ struct ieee80211_local *local __maybe_unused = sdata->local; - struct ieee80211_sub_if_data *vlan; - struct ieee80211_chanctx_conf *conf; - -@@ -871,7 +871,7 @@ __ieee80211_vif_copy_chanctx_to_vlans(st - * to a channel context that has already been freed. - */ - conf = rcu_dereference_protected(sdata->vif.chanctx_conf, -- lockdep_is_held(&local->chanctx_mtx)); -+ lockdep_is_held(&local->chanctx_mtx)); - WARN_ON(!conf); - - if (clear) ---- a/net/mac80211/driver-ops.h -+++ b/net/mac80211/driver-ops.h -@@ -5,11 +5,11 @@ - #include "ieee80211_i.h" - #include "trace.h" - --static inline void check_sdata_in_driver(struct ieee80211_sub_if_data *sdata) -+static inline bool check_sdata_in_driver(struct ieee80211_sub_if_data *sdata) - { -- WARN(!(sdata->flags & IEEE80211_SDATA_IN_DRIVER), -- "%s: Failed check-sdata-in-driver check, flags: 0x%x\n", -- sdata->dev ? sdata->dev->name : sdata->name, sdata->flags); -+ return !WARN(!(sdata->flags & IEEE80211_SDATA_IN_DRIVER), -+ "%s: Failed check-sdata-in-driver check, flags: 0x%x\n", -+ sdata->dev ? sdata->dev->name : sdata->name, sdata->flags); - } - - static inline struct ieee80211_sub_if_data * -@@ -168,7 +168,8 @@ static inline int drv_change_interface(s - - might_sleep(); - -- check_sdata_in_driver(sdata); -+ if (!check_sdata_in_driver(sdata)) -+ return -EIO; - - trace_drv_change_interface(local, sdata, type, p2p); - ret = local->ops->change_interface(&local->hw, &sdata->vif, type, p2p); -@@ -181,7 +182,8 @@ static inline void drv_remove_interface( - { - might_sleep(); - -- check_sdata_in_driver(sdata); -+ if (!check_sdata_in_driver(sdata)) -+ return; - - trace_drv_remove_interface(local, sdata); - local->ops->remove_interface(&local->hw, &sdata->vif); -@@ -219,7 +221,8 @@ static inline void drv_bss_info_changed( - sdata->vif.type == NL80211_IFTYPE_MONITOR)) - return; - -- check_sdata_in_driver(sdata); -+ if (!check_sdata_in_driver(sdata)) -+ return; - - trace_drv_bss_info_changed(local, sdata, info, changed); - if (local->ops->bss_info_changed) -@@ -278,7 +281,8 @@ static inline int drv_set_key(struct iee - might_sleep(); - - sdata = get_bss_sdata(sdata); -- check_sdata_in_driver(sdata); -+ if (!check_sdata_in_driver(sdata)) -+ return -EIO; - - trace_drv_set_key(local, cmd, sdata, sta, key); - ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key); -@@ -298,7 +302,8 @@ static inline void drv_update_tkip_key(s - ista = &sta->sta; - - sdata = get_bss_sdata(sdata); -- check_sdata_in_driver(sdata); -+ if (!check_sdata_in_driver(sdata)) -+ return; - - trace_drv_update_tkip_key(local, sdata, conf, ista, iv32); - if (local->ops->update_tkip_key) -@@ -315,7 +320,8 @@ static inline int drv_hw_scan(struct iee - - might_sleep(); - -- check_sdata_in_driver(sdata); -+ if (!check_sdata_in_driver(sdata)) -+ return -EIO; - - trace_drv_hw_scan(local, sdata); - ret = local->ops->hw_scan(&local->hw, &sdata->vif, req); -@@ -328,7 +334,8 @@ static inline void drv_cancel_hw_scan(st - { - might_sleep(); - -- check_sdata_in_driver(sdata); -+ if (!check_sdata_in_driver(sdata)) -+ return; - - trace_drv_cancel_hw_scan(local, sdata); - local->ops->cancel_hw_scan(&local->hw, &sdata->vif); -@@ -345,7 +352,8 @@ drv_sched_scan_start(struct ieee80211_lo - - might_sleep(); - -- check_sdata_in_driver(sdata); -+ if (!check_sdata_in_driver(sdata)) -+ return -EIO; - - trace_drv_sched_scan_start(local, sdata); - ret = local->ops->sched_scan_start(&local->hw, &sdata->vif, -@@ -361,7 +369,8 @@ static inline int drv_sched_scan_stop(st - - might_sleep(); - -- check_sdata_in_driver(sdata); -+ if (!check_sdata_in_driver(sdata)) -+ return -EIO; - - trace_drv_sched_scan_stop(local, sdata); - ret = local->ops->sched_scan_stop(&local->hw, &sdata->vif); -@@ -462,7 +471,8 @@ static inline void drv_sta_notify(struct - struct ieee80211_sta *sta) - { - sdata = get_bss_sdata(sdata); -- check_sdata_in_driver(sdata); -+ if (!check_sdata_in_driver(sdata)) -+ return; - - trace_drv_sta_notify(local, sdata, cmd, sta); - if (local->ops->sta_notify) -@@ -479,7 +489,8 @@ static inline int drv_sta_add(struct iee - might_sleep(); - - sdata = get_bss_sdata(sdata); -- check_sdata_in_driver(sdata); -+ if (!check_sdata_in_driver(sdata)) -+ return -EIO; - - trace_drv_sta_add(local, sdata, sta); - if (local->ops->sta_add) -@@ -497,7 +508,8 @@ static inline void drv_sta_remove(struct - might_sleep(); - - sdata = get_bss_sdata(sdata); -- check_sdata_in_driver(sdata); -+ if (!check_sdata_in_driver(sdata)) -+ return; - - trace_drv_sta_remove(local, sdata, sta); - if (local->ops->sta_remove) -@@ -515,7 +527,8 @@ static inline void drv_sta_add_debugfs(s - might_sleep(); - - sdata = get_bss_sdata(sdata); -- check_sdata_in_driver(sdata); -+ if (!check_sdata_in_driver(sdata)) -+ return; - - if (local->ops->sta_add_debugfs) - local->ops->sta_add_debugfs(&local->hw, &sdata->vif, -@@ -545,7 +558,8 @@ static inline void drv_sta_pre_rcu_remov - might_sleep(); - - sdata = get_bss_sdata(sdata); -- check_sdata_in_driver(sdata); -+ if (!check_sdata_in_driver(sdata)) -+ return; - - trace_drv_sta_pre_rcu_remove(local, sdata, &sta->sta); - if (local->ops->sta_pre_rcu_remove) -@@ -566,7 +580,8 @@ int drv_sta_state(struct ieee80211_local - might_sleep(); - - sdata = get_bss_sdata(sdata); -- check_sdata_in_driver(sdata); -+ if (!check_sdata_in_driver(sdata)) -+ return -EIO; - - trace_drv_sta_state(local, sdata, &sta->sta, old_state, new_state); - if (local->ops->sta_state) { -@@ -590,7 +605,8 @@ static inline void drv_sta_rc_update(str - struct ieee80211_sta *sta, u32 changed) - { - sdata = get_bss_sdata(sdata); -- check_sdata_in_driver(sdata); -+ if (!check_sdata_in_driver(sdata)) -+ return; - - WARN_ON(changed & IEEE80211_RC_SUPP_RATES_CHANGED && - (sdata->vif.type != NL80211_IFTYPE_ADHOC && -@@ -612,7 +628,8 @@ static inline int drv_conf_tx(struct iee - - might_sleep(); - -- check_sdata_in_driver(sdata); -+ if (!check_sdata_in_driver(sdata)) -+ return -EIO; - - trace_drv_conf_tx(local, sdata, ac, params); - if (local->ops->conf_tx) -@@ -629,7 +646,8 @@ static inline u64 drv_get_tsf(struct iee - - might_sleep(); - -- check_sdata_in_driver(sdata); -+ if (!check_sdata_in_driver(sdata)) -+ return ret; - - trace_drv_get_tsf(local, sdata); - if (local->ops->get_tsf) -@@ -644,7 +662,8 @@ static inline void drv_set_tsf(struct ie - { - might_sleep(); - -- check_sdata_in_driver(sdata); -+ if (!check_sdata_in_driver(sdata)) -+ return; - - trace_drv_set_tsf(local, sdata, tsf); - if (local->ops->set_tsf) -@@ -657,7 +676,8 @@ static inline void drv_reset_tsf(struct - { - might_sleep(); - -- check_sdata_in_driver(sdata); -+ if (!check_sdata_in_driver(sdata)) -+ return; - - trace_drv_reset_tsf(local, sdata); - if (local->ops->reset_tsf) -@@ -689,7 +709,8 @@ static inline int drv_ampdu_action(struc - might_sleep(); - - sdata = get_bss_sdata(sdata); -- check_sdata_in_driver(sdata); -+ if (!check_sdata_in_driver(sdata)) -+ return -EIO; - - trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, buf_size); - -@@ -733,8 +754,8 @@ static inline void drv_flush(struct ieee - - might_sleep(); - -- if (sdata) -- check_sdata_in_driver(sdata); -+ if (sdata && !check_sdata_in_driver(sdata)) -+ return; - - trace_drv_flush(local, queues, drop); - if (local->ops->flush) -@@ -854,7 +875,8 @@ static inline int drv_set_bitrate_mask(s - - might_sleep(); - -- check_sdata_in_driver(sdata); -+ if (!check_sdata_in_driver(sdata)) -+ return -EIO; - - trace_drv_set_bitrate_mask(local, sdata, mask); - if (local->ops->set_bitrate_mask) -@@ -869,7 +891,8 @@ static inline void drv_set_rekey_data(st - struct ieee80211_sub_if_data *sdata, - struct cfg80211_gtk_rekey_data *data) - { -- check_sdata_in_driver(sdata); -+ if (!check_sdata_in_driver(sdata)) -+ return; - - trace_drv_set_rekey_data(local, sdata, data); - if (local->ops->set_rekey_data) -@@ -937,7 +960,8 @@ static inline void drv_mgd_prepare_tx(st - { - might_sleep(); - -- check_sdata_in_driver(sdata); -+ if (!check_sdata_in_driver(sdata)) -+ return; - WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION); - - trace_drv_mgd_prepare_tx(local, sdata); -@@ -964,6 +988,9 @@ static inline int drv_add_chanctx(struct - static inline void drv_remove_chanctx(struct ieee80211_local *local, - struct ieee80211_chanctx *ctx) - { -+ if (WARN_ON(!ctx->driver_present)) -+ return; -+ - trace_drv_remove_chanctx(local, ctx); - if (local->ops->remove_chanctx) - local->ops->remove_chanctx(&local->hw, &ctx->conf); -@@ -989,7 +1016,8 @@ static inline int drv_assign_vif_chanctx - { - int ret = 0; - -- check_sdata_in_driver(sdata); -+ if (!check_sdata_in_driver(sdata)) -+ return -EIO; - - trace_drv_assign_vif_chanctx(local, sdata, ctx); - if (local->ops->assign_vif_chanctx) { -@@ -1007,7 +1035,8 @@ static inline void drv_unassign_vif_chan - struct ieee80211_sub_if_data *sdata, - struct ieee80211_chanctx *ctx) - { -- check_sdata_in_driver(sdata); -+ if (!check_sdata_in_driver(sdata)) -+ return; - - trace_drv_unassign_vif_chanctx(local, sdata, ctx); - if (local->ops->unassign_vif_chanctx) { -@@ -1024,7 +1053,8 @@ static inline int drv_start_ap(struct ie - { - int ret = 0; - -- check_sdata_in_driver(sdata); -+ if (!check_sdata_in_driver(sdata)) -+ return -EIO; - - trace_drv_start_ap(local, sdata, &sdata->vif.bss_conf); - if (local->ops->start_ap) -@@ -1036,7 +1066,8 @@ static inline int drv_start_ap(struct ie - static inline void drv_stop_ap(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata) - { -- check_sdata_in_driver(sdata); -+ if (!check_sdata_in_driver(sdata)) -+ return; - - trace_drv_stop_ap(local, sdata); - if (local->ops->stop_ap) -@@ -1059,7 +1090,8 @@ drv_set_default_unicast_key(struct ieee8 - struct ieee80211_sub_if_data *sdata, - int key_idx) - { -- check_sdata_in_driver(sdata); -+ if (!check_sdata_in_driver(sdata)) -+ return; - - WARN_ON_ONCE(key_idx < -1 || key_idx > 3); - -@@ -1101,7 +1133,8 @@ static inline int drv_join_ibss(struct i - int ret = 0; - - might_sleep(); -- check_sdata_in_driver(sdata); -+ if (!check_sdata_in_driver(sdata)) -+ return -EIO; - - trace_drv_join_ibss(local, sdata, &sdata->vif.bss_conf); - if (local->ops->join_ibss) -@@ -1114,7 +1147,8 @@ static inline void drv_leave_ibss(struct - struct ieee80211_sub_if_data *sdata) - { - might_sleep(); -- check_sdata_in_driver(sdata); -+ if (!check_sdata_in_driver(sdata)) -+ return; - - trace_drv_leave_ibss(local, sdata); - if (local->ops->leave_ibss) ---- 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 = (pos - presp->head); -+ sdata->csa_counter_offset_beacon[0] = (pos - presp->head); - *pos++ = csa_settings->count; - } - ---- a/net/mac80211/ieee80211_i.h -+++ b/net/mac80211/ieee80211_i.h -@@ -754,9 +754,10 @@ struct ieee80211_sub_if_data { - struct mac80211_qos_map __rcu *qos_map; - - struct work_struct csa_finalize_work; -- int csa_counter_offset_beacon; -- int csa_counter_offset_presp; -+ 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; - - struct list_head assigned_chanctx_list; /* protected by chanctx_mtx */ -@@ -766,6 +767,7 @@ struct ieee80211_sub_if_data { - struct ieee80211_chanctx *reserved_chanctx; - struct cfg80211_chan_def reserved_chandef; - bool reserved_radar_required; -+ u8 csa_current_counter; - - /* used to reconfigure hardware SM PS */ - struct work_struct recalc_smps; -@@ -1462,6 +1464,7 @@ __ieee80211_request_sched_scan_start(str - int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, - struct cfg80211_sched_scan_request *req); - int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata); -+void ieee80211_sched_scan_end(struct ieee80211_local *local); - void ieee80211_sched_scan_stopped_work(struct work_struct *work); - - /* off-channel helpers */ -@@ -1476,6 +1479,7 @@ void ieee80211_sw_roc_work(struct work_s - void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc); - - /* channel switch handling */ -+bool ieee80211_csa_needs_block_tx(struct ieee80211_local *local); - void ieee80211_csa_finalize_work(struct work_struct *work); - int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_csa_settings *params); -@@ -1837,6 +1841,15 @@ int ieee80211_check_combinations(struct - u8 radar_detect); - int ieee80211_max_num_channels(struct ieee80211_local *local); - -+/* TDLS */ -+int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, -+ const u8 *peer, u8 action_code, u8 dialog_token, -+ u16 status_code, u32 peer_capability, -+ const u8 *extra_ies, size_t extra_ies_len); -+int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, -+ const u8 *peer, enum nl80211_tdls_operation oper); -+ -+ - #ifdef CPTCFG_MAC80211_NOINLINE - #define debug_noinline noinline - #else ---- a/net/mac80211/iface.c -+++ b/net/mac80211/iface.c -@@ -838,8 +838,15 @@ static void ieee80211_do_stop(struct iee - - cancel_work_sync(&sdata->recalc_smps); - sdata_lock(sdata); -+ mutex_lock(&local->mtx); - sdata->vif.csa_active = false; -+ if (!ieee80211_csa_needs_block_tx(local)) -+ ieee80211_wake_queues_by_reason(&local->hw, -+ IEEE80211_MAX_QUEUE_MAP, -+ IEEE80211_QUEUE_STOP_REASON_CSA); -+ mutex_unlock(&local->mtx); - sdata_unlock(sdata); -+ - cancel_work_sync(&sdata->csa_finalize_work); - - cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); ---- a/net/mac80211/key.c -+++ b/net/mac80211/key.c -@@ -325,7 +325,8 @@ ieee80211_key_alloc(u32 cipher, int idx, - struct ieee80211_key *key; - int i, j, err; - -- BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS); -+ if (WARN_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)) -+ return ERR_PTR(-EINVAL); - - key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL); - if (!key) -@@ -481,8 +482,8 @@ int ieee80211_key_link(struct ieee80211_ - int idx, ret; - bool pairwise; - -- BUG_ON(!sdata); -- BUG_ON(!key); -+ if (WARN_ON(!sdata || !key)) -+ return -EINVAL; - - pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE; - idx = key->conf.keyidx; ---- a/net/mac80211/main.c -+++ b/net/mac80211/main.c -@@ -956,6 +956,8 @@ int ieee80211_register_hw(struct ieee802 - if (local->hw.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) - local->hw.wiphy->flags |= WIPHY_FLAG_TDLS_EXTERNAL_SETUP; - -+ local->hw.wiphy->max_num_csa_counters = IEEE80211_MAX_CSA_COUNTERS_NUM; -+ - result = wiphy_register(local->hw.wiphy); - if (result < 0) - goto fail_wiphy_register; ---- 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 = hdr_len + 6; -+ sdata->csa_counter_offset_beacon[0] = hdr_len + 6; - *pos++ = csa->settings.count; - *pos++ = WLAN_EID_CHAN_SWITCH_PARAM; - *pos++ = 6; ---- a/net/mac80211/mesh_pathtbl.c -+++ b/net/mac80211/mesh_pathtbl.c -@@ -287,8 +287,10 @@ static void mesh_path_move_to_queue(stru - struct sk_buff_head failq; - unsigned long flags; - -- BUG_ON(gate_mpath == from_mpath); -- BUG_ON(!gate_mpath->next_hop); -+ if (WARN_ON(gate_mpath == from_mpath)) -+ return; -+ if (WARN_ON(!gate_mpath->next_hop)) -+ return; - - __skb_queue_head_init(&failq); - ---- a/net/mac80211/mesh_sync.c -+++ b/net/mac80211/mesh_sync.c -@@ -171,7 +171,7 @@ static void mesh_sync_offset_adjust_tbtt - u8 cap; - - WARN_ON(ifmsh->mesh_sp_id != IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET); -- BUG_ON(!rcu_read_lock_held()); -+ WARN_ON(!rcu_read_lock_held()); - cap = beacon->meshconf->meshconf_cap; - - spin_lock_bh(&ifmsh->sync_offset_lock); ---- a/net/mac80211/mlme.c -+++ b/net/mac80211/mlme.c -@@ -975,16 +975,23 @@ static void ieee80211_chswitch_work(stru - /* XXX: shouldn't really modify cfg80211-owned data! */ - ifmgd->associated->channel = sdata->csa_chandef.chan; - -+ ieee80211_bss_info_change_notify(sdata, changed); -+ -+ mutex_lock(&local->mtx); -+ sdata->vif.csa_active = false; - /* XXX: wait for a beacon first? */ -- ieee80211_wake_queues_by_reason(&local->hw, -+ if (!ieee80211_csa_needs_block_tx(local)) -+ ieee80211_wake_queues_by_reason(&local->hw, - IEEE80211_MAX_QUEUE_MAP, - IEEE80211_QUEUE_STOP_REASON_CSA); -+ mutex_unlock(&local->mtx); - -- ieee80211_bss_info_change_notify(sdata, changed); -- -- out: -- sdata->vif.csa_active = false; - ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; -+ -+ ieee80211_sta_reset_beacon_monitor(sdata); -+ ieee80211_sta_reset_conn_monitor(sdata); -+ -+out: - sdata_unlock(sdata); - } - -@@ -1100,12 +1107,16 @@ ieee80211_sta_process_chanswitch(struct - mutex_unlock(&local->chanctx_mtx); - - sdata->csa_chandef = csa_ie.chandef; -+ -+ mutex_lock(&local->mtx); - sdata->vif.csa_active = true; -+ sdata->csa_block_tx = csa_ie.mode; - -- if (csa_ie.mode) -+ if (sdata->csa_block_tx) - ieee80211_stop_queues_by_reason(&local->hw, -- IEEE80211_MAX_QUEUE_MAP, -- IEEE80211_QUEUE_STOP_REASON_CSA); -+ IEEE80211_MAX_QUEUE_MAP, -+ IEEE80211_QUEUE_STOP_REASON_CSA); -+ mutex_unlock(&local->mtx); - - if (local->ops->channel_switch) { - /* use driver's channel switch callback */ -@@ -1817,6 +1828,12 @@ static void ieee80211_set_disassoc(struc - ifmgd->flags = 0; - mutex_lock(&local->mtx); - ieee80211_vif_release_channel(sdata); -+ -+ sdata->vif.csa_active = false; -+ if (!ieee80211_csa_needs_block_tx(local)) -+ ieee80211_wake_queues_by_reason(&local->hw, -+ IEEE80211_MAX_QUEUE_MAP, -+ IEEE80211_QUEUE_STOP_REASON_CSA); - mutex_unlock(&local->mtx); - - sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; -@@ -2045,6 +2062,7 @@ EXPORT_SYMBOL(ieee80211_ap_probereq_get) - - static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) - { -+ struct ieee80211_local *local = sdata->local; - struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; - -@@ -2058,10 +2076,14 @@ static void __ieee80211_disconnect(struc - WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, - true, frame_buf); - ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; -+ -+ mutex_lock(&local->mtx); - sdata->vif.csa_active = false; -- ieee80211_wake_queues_by_reason(&sdata->local->hw, -+ if (!ieee80211_csa_needs_block_tx(local)) -+ ieee80211_wake_queues_by_reason(&local->hw, - IEEE80211_MAX_QUEUE_MAP, - IEEE80211_QUEUE_STOP_REASON_CSA); -+ mutex_unlock(&local->mtx); - - cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, - IEEE80211_DEAUTH_FRAME_LEN); -@@ -3546,6 +3568,9 @@ static void ieee80211_sta_bcn_mon_timer( - if (local->quiescing) - return; - -+ if (sdata->vif.csa_active) -+ return; -+ - sdata->u.mgd.connection_loss = false; - ieee80211_queue_work(&sdata->local->hw, - &sdata->u.mgd.beacon_connection_loss_work); -@@ -3561,6 +3586,9 @@ static void ieee80211_sta_conn_mon_timer - if (local->quiescing) - return; - -+ if (sdata->vif.csa_active) -+ return; -+ - ieee80211_queue_work(&local->hw, &ifmgd->monitor_work); - } - ---- a/net/mac80211/rc80211_minstrel_ht.c -+++ b/net/mac80211/rc80211_minstrel_ht.c -@@ -22,7 +22,7 @@ - #define MCS_NBITS (AVG_PKT_SIZE << 3) - - /* Number of symbols for a packet with (bps) bits per symbol */ --#define MCS_NSYMS(bps) ((MCS_NBITS + (bps) - 1) / (bps)) -+#define MCS_NSYMS(bps) DIV_ROUND_UP(MCS_NBITS, (bps)) - - /* Transmission time (nanoseconds) for a packet containing (syms) symbols */ - #define MCS_SYMBOL_TIME(sgi, syms) \ -@@ -226,8 +226,9 @@ minstrel_ht_calc_tp(struct minstrel_ht_s - nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len); - - nsecs += minstrel_mcs_groups[group].duration[rate]; -- tp = 1000000 * ((prob * 1000) / nsecs); - -+ /* prob is scaled - see MINSTREL_FRAC above */ -+ tp = 1000000 * ((prob * 1000) / nsecs); - mr->cur_tp = MINSTREL_TRUNC(tp); - } - ---- a/net/mac80211/scan.c -+++ b/net/mac80211/scan.c -@@ -1076,12 +1076,8 @@ void ieee80211_sched_scan_results(struct - } - EXPORT_SYMBOL(ieee80211_sched_scan_results); - --void ieee80211_sched_scan_stopped_work(struct work_struct *work) -+void ieee80211_sched_scan_end(struct ieee80211_local *local) - { -- struct ieee80211_local *local = -- container_of(work, struct ieee80211_local, -- sched_scan_stopped_work); -- - mutex_lock(&local->mtx); - - if (!rcu_access_pointer(local->sched_scan_sdata)) { -@@ -1099,6 +1095,15 @@ void ieee80211_sched_scan_stopped_work(s - cfg80211_sched_scan_stopped(local->hw.wiphy); - } - -+void ieee80211_sched_scan_stopped_work(struct work_struct *work) -+{ -+ struct ieee80211_local *local = -+ container_of(work, struct ieee80211_local, -+ sched_scan_stopped_work); -+ -+ ieee80211_sched_scan_end(local); -+} -+ - void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw) - { - struct ieee80211_local *local = hw_to_local(hw); ---- /dev/null -+++ b/net/mac80211/tdls.c -@@ -0,0 +1,325 @@ -+/* -+ * mac80211 TDLS handling code -+ * -+ * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> -+ * Copyright 2014, Intel Corporation -+ * -+ * This file is GPLv2 as found in COPYING. -+ */ -+ -+#include <linux/ieee80211.h> -+#include "ieee80211_i.h" -+ -+static void ieee80211_tdls_add_ext_capab(struct sk_buff *skb) -+{ -+ u8 *pos = (void *)skb_put(skb, 7); -+ -+ *pos++ = WLAN_EID_EXT_CAPABILITY; -+ *pos++ = 5; /* len */ -+ *pos++ = 0x0; -+ *pos++ = 0x0; -+ *pos++ = 0x0; -+ *pos++ = 0x0; -+ *pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED; -+} -+ -+static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata) -+{ -+ struct ieee80211_local *local = sdata->local; -+ u16 capab; -+ -+ capab = 0; -+ if (ieee80211_get_sdata_band(sdata) != IEEE80211_BAND_2GHZ) -+ return capab; -+ -+ if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE)) -+ capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME; -+ if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE)) -+ capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; -+ -+ return capab; -+} -+ -+static void ieee80211_tdls_add_link_ie(struct sk_buff *skb, const u8 *src_addr, -+ const u8 *peer, const u8 *bssid) -+{ -+ struct ieee80211_tdls_lnkie *lnkid; -+ -+ lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie)); -+ -+ lnkid->ie_type = WLAN_EID_LINK_ID; -+ lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2; -+ -+ memcpy(lnkid->bssid, bssid, ETH_ALEN); -+ memcpy(lnkid->init_sta, src_addr, ETH_ALEN); -+ memcpy(lnkid->resp_sta, peer, ETH_ALEN); -+} -+ -+static int -+ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, -+ const u8 *peer, u8 action_code, u8 dialog_token, -+ u16 status_code, struct sk_buff *skb) -+{ -+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); -+ enum ieee80211_band band = ieee80211_get_sdata_band(sdata); -+ struct ieee80211_tdls_data *tf; -+ -+ tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u)); -+ -+ memcpy(tf->da, peer, ETH_ALEN); -+ memcpy(tf->sa, sdata->vif.addr, ETH_ALEN); -+ tf->ether_type = cpu_to_be16(ETH_P_TDLS); -+ tf->payload_type = WLAN_TDLS_SNAP_RFTYPE; -+ -+ switch (action_code) { -+ case WLAN_TDLS_SETUP_REQUEST: -+ tf->category = WLAN_CATEGORY_TDLS; -+ tf->action_code = WLAN_TDLS_SETUP_REQUEST; -+ -+ skb_put(skb, sizeof(tf->u.setup_req)); -+ tf->u.setup_req.dialog_token = dialog_token; -+ tf->u.setup_req.capability = -+ cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); -+ -+ ieee80211_add_srates_ie(sdata, skb, false, band); -+ ieee80211_add_ext_srates_ie(sdata, skb, false, band); -+ ieee80211_tdls_add_ext_capab(skb); -+ break; -+ case WLAN_TDLS_SETUP_RESPONSE: -+ tf->category = WLAN_CATEGORY_TDLS; -+ tf->action_code = WLAN_TDLS_SETUP_RESPONSE; -+ -+ skb_put(skb, sizeof(tf->u.setup_resp)); -+ tf->u.setup_resp.status_code = cpu_to_le16(status_code); -+ tf->u.setup_resp.dialog_token = dialog_token; -+ tf->u.setup_resp.capability = -+ cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); -+ -+ ieee80211_add_srates_ie(sdata, skb, false, band); -+ ieee80211_add_ext_srates_ie(sdata, skb, false, band); -+ ieee80211_tdls_add_ext_capab(skb); -+ break; -+ case WLAN_TDLS_SETUP_CONFIRM: -+ tf->category = WLAN_CATEGORY_TDLS; -+ tf->action_code = WLAN_TDLS_SETUP_CONFIRM; -+ -+ skb_put(skb, sizeof(tf->u.setup_cfm)); -+ tf->u.setup_cfm.status_code = cpu_to_le16(status_code); -+ tf->u.setup_cfm.dialog_token = dialog_token; -+ break; -+ case WLAN_TDLS_TEARDOWN: -+ tf->category = WLAN_CATEGORY_TDLS; -+ tf->action_code = WLAN_TDLS_TEARDOWN; -+ -+ skb_put(skb, sizeof(tf->u.teardown)); -+ tf->u.teardown.reason_code = cpu_to_le16(status_code); -+ break; -+ case WLAN_TDLS_DISCOVERY_REQUEST: -+ tf->category = WLAN_CATEGORY_TDLS; -+ tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST; -+ -+ skb_put(skb, sizeof(tf->u.discover_req)); -+ tf->u.discover_req.dialog_token = dialog_token; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int -+ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, -+ const u8 *peer, u8 action_code, u8 dialog_token, -+ u16 status_code, struct sk_buff *skb) -+{ -+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); -+ enum ieee80211_band band = ieee80211_get_sdata_band(sdata); -+ struct ieee80211_mgmt *mgmt; -+ -+ mgmt = (void *)skb_put(skb, 24); -+ memset(mgmt, 0, 24); -+ memcpy(mgmt->da, peer, ETH_ALEN); -+ memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); -+ memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); -+ -+ mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | -+ IEEE80211_STYPE_ACTION); -+ -+ switch (action_code) { -+ case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: -+ skb_put(skb, 1 + sizeof(mgmt->u.action.u.tdls_discover_resp)); -+ mgmt->u.action.category = WLAN_CATEGORY_PUBLIC; -+ mgmt->u.action.u.tdls_discover_resp.action_code = -+ WLAN_PUB_ACTION_TDLS_DISCOVER_RES; -+ mgmt->u.action.u.tdls_discover_resp.dialog_token = -+ dialog_token; -+ mgmt->u.action.u.tdls_discover_resp.capability = -+ cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); -+ -+ ieee80211_add_srates_ie(sdata, skb, false, band); -+ ieee80211_add_ext_srates_ie(sdata, skb, false, band); -+ ieee80211_tdls_add_ext_capab(skb); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, -+ const u8 *peer, u8 action_code, u8 dialog_token, -+ u16 status_code, u32 peer_capability, -+ const u8 *extra_ies, size_t extra_ies_len) -+{ -+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); -+ struct ieee80211_local *local = sdata->local; -+ struct sk_buff *skb = NULL; -+ bool send_direct; -+ int ret; -+ -+ if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) -+ return -ENOTSUPP; -+ -+ /* make sure we are in managed mode, and associated */ -+ if (sdata->vif.type != NL80211_IFTYPE_STATION || -+ !sdata->u.mgd.associated) -+ return -EINVAL; -+ -+ tdls_dbg(sdata, "TDLS mgmt action %d peer %pM\n", -+ action_code, peer); -+ -+ skb = dev_alloc_skb(local->hw.extra_tx_headroom + -+ max(sizeof(struct ieee80211_mgmt), -+ sizeof(struct ieee80211_tdls_data)) + -+ 50 + /* supported rates */ -+ 7 + /* ext capab */ -+ extra_ies_len + -+ sizeof(struct ieee80211_tdls_lnkie)); -+ if (!skb) -+ return -ENOMEM; -+ -+ skb_reserve(skb, local->hw.extra_tx_headroom); -+ -+ switch (action_code) { -+ case WLAN_TDLS_SETUP_REQUEST: -+ case WLAN_TDLS_SETUP_RESPONSE: -+ case WLAN_TDLS_SETUP_CONFIRM: -+ case WLAN_TDLS_TEARDOWN: -+ case WLAN_TDLS_DISCOVERY_REQUEST: -+ ret = ieee80211_prep_tdls_encap_data(wiphy, dev, peer, -+ action_code, dialog_token, -+ status_code, skb); -+ send_direct = false; -+ break; -+ case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: -+ ret = ieee80211_prep_tdls_direct(wiphy, dev, peer, action_code, -+ dialog_token, status_code, -+ skb); -+ send_direct = true; -+ break; -+ default: -+ ret = -ENOTSUPP; -+ break; -+ } -+ -+ if (ret < 0) -+ goto fail; -+ -+ if (extra_ies_len) -+ memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len); -+ -+ /* the TDLS link IE is always added last */ -+ switch (action_code) { -+ case WLAN_TDLS_SETUP_REQUEST: -+ case WLAN_TDLS_SETUP_CONFIRM: -+ case WLAN_TDLS_TEARDOWN: -+ case WLAN_TDLS_DISCOVERY_REQUEST: -+ /* we are the initiator */ -+ ieee80211_tdls_add_link_ie(skb, sdata->vif.addr, peer, -+ sdata->u.mgd.bssid); -+ break; -+ case WLAN_TDLS_SETUP_RESPONSE: -+ case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: -+ /* we are the responder */ -+ ieee80211_tdls_add_link_ie(skb, peer, sdata->vif.addr, -+ sdata->u.mgd.bssid); -+ break; -+ default: -+ ret = -ENOTSUPP; -+ goto fail; -+ } -+ -+ if (send_direct) { -+ ieee80211_tx_skb(sdata, skb); -+ return 0; -+ } -+ -+ /* -+ * According to 802.11z: Setup req/resp are sent in AC_BK, otherwise -+ * we should default to AC_VI. -+ */ -+ switch (action_code) { -+ case WLAN_TDLS_SETUP_REQUEST: -+ case WLAN_TDLS_SETUP_RESPONSE: -+ skb_set_queue_mapping(skb, IEEE80211_AC_BK); -+ skb->priority = 2; -+ break; -+ default: -+ skb_set_queue_mapping(skb, IEEE80211_AC_VI); -+ skb->priority = 5; -+ break; -+ } -+ -+ /* disable bottom halves when entering the Tx path */ -+ local_bh_disable(); -+ ret = ieee80211_subif_start_xmit(skb, dev); -+ local_bh_enable(); -+ -+ return ret; -+ -+fail: -+ dev_kfree_skb(skb); -+ return ret; -+} -+ -+int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, -+ const u8 *peer, enum nl80211_tdls_operation oper) -+{ -+ struct sta_info *sta; -+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); -+ -+ if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) -+ return -ENOTSUPP; -+ -+ if (sdata->vif.type != NL80211_IFTYPE_STATION) -+ return -EINVAL; -+ -+ tdls_dbg(sdata, "TDLS oper %d peer %pM\n", oper, peer); -+ -+ switch (oper) { -+ case NL80211_TDLS_ENABLE_LINK: -+ rcu_read_lock(); -+ sta = sta_info_get(sdata, peer); -+ if (!sta) { -+ rcu_read_unlock(); -+ return -ENOLINK; -+ } -+ -+ set_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH); -+ rcu_read_unlock(); -+ break; -+ case NL80211_TDLS_DISABLE_LINK: -+ return sta_info_destroy_addr(sdata, peer); -+ case NL80211_TDLS_TEARDOWN: -+ case NL80211_TDLS_SETUP: -+ case NL80211_TDLS_DISCOVERY_REQ: -+ /* We don't support in-driver setup/teardown/discovery */ -+ return -ENOTSUPP; -+ default: -+ return -ENOTSUPP; -+ } -+ -+ return 0; -+} ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -2330,7 +2330,8 @@ void ieee80211_tx_pending(unsigned long - /* functions for drivers to get certain frames */ - - static void __ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, -- struct ps_data *ps, struct sk_buff *skb) -+ struct ps_data *ps, struct sk_buff *skb, -+ bool is_template) - { - u8 *pos, *tim; - int aid0 = 0; -@@ -2343,11 +2344,12 @@ static void __ieee80211_beacon_add_tim(s - * checking byte-for-byte */ - have_bits = !bitmap_empty((unsigned long *)ps->tim, - IEEE80211_MAX_AID+1); -- -- if (ps->dtim_count == 0) -- ps->dtim_count = sdata->vif.bss_conf.dtim_period - 1; -- else -- ps->dtim_count--; -+ if (!is_template) { -+ if (ps->dtim_count == 0) -+ ps->dtim_count = sdata->vif.bss_conf.dtim_period - 1; -+ else -+ ps->dtim_count--; -+ } - - tim = pos = (u8 *) skb_put(skb, 6); - *pos++ = WLAN_EID_TIM; -@@ -2393,7 +2395,8 @@ static void __ieee80211_beacon_add_tim(s - } - - static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, -- struct ps_data *ps, struct sk_buff *skb) -+ struct ps_data *ps, struct sk_buff *skb, -+ bool is_template) - { - struct ieee80211_local *local = sdata->local; - -@@ -2405,24 +2408,24 @@ static int ieee80211_beacon_add_tim(stru - * of the tim bitmap in mac80211 and the driver. - */ - if (local->tim_in_locked_section) { -- __ieee80211_beacon_add_tim(sdata, ps, skb); -+ __ieee80211_beacon_add_tim(sdata, ps, skb, is_template); - } else { - spin_lock_bh(&local->tim_lock); -- __ieee80211_beacon_add_tim(sdata, ps, skb); -+ __ieee80211_beacon_add_tim(sdata, ps, skb, is_template); - spin_unlock_bh(&local->tim_lock); - } - - return 0; - } - --static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata, -- struct beacon_data *beacon) -+static void ieee80211_set_csa(struct ieee80211_sub_if_data *sdata, -+ struct beacon_data *beacon) - { - struct probe_resp *resp; -- int counter_offset_beacon = sdata->csa_counter_offset_beacon; -- int counter_offset_presp = sdata->csa_counter_offset_presp; - u8 *beacon_data; - size_t beacon_data_len; -+ int i; -+ u8 count = sdata->csa_current_counter; - - switch (sdata->vif.type) { - case NL80211_IFTYPE_AP: -@@ -2440,40 +2443,57 @@ static void ieee80211_update_csa(struct - default: - return; - } -- if (WARN_ON(counter_offset_beacon >= beacon_data_len)) -- return; - -- /* Warn if the driver did not check for/react to csa -- * completeness. A beacon with CSA counter set to 0 should -- * never occur, because a counter of 1 means switch just -- * before the next beacon. -- */ -- if (WARN_ON(beacon_data[counter_offset_beacon] == 1)) -- return; -+ for (i = 0; i < IEEE80211_MAX_CSA_COUNTERS_NUM; ++i) { -+ u16 counter_offset_beacon = -+ sdata->csa_counter_offset_beacon[i]; -+ u16 counter_offset_presp = sdata->csa_counter_offset_presp[i]; -+ -+ if (counter_offset_beacon) { -+ if (WARN_ON(counter_offset_beacon >= beacon_data_len)) -+ return; - -- beacon_data[counter_offset_beacon]--; -+ beacon_data[counter_offset_beacon] = count; -+ } - -- if (sdata->vif.type == NL80211_IFTYPE_AP && counter_offset_presp) { -- rcu_read_lock(); -- resp = rcu_dereference(sdata->u.ap.probe_resp); -+ if (sdata->vif.type == NL80211_IFTYPE_AP && -+ counter_offset_presp) { -+ rcu_read_lock(); -+ resp = rcu_dereference(sdata->u.ap.probe_resp); - -- /* if nl80211 accepted the offset, this should not happen. */ -- if (WARN_ON(!resp)) { -+ /* If nl80211 accepted the offset, this should -+ * not happen. -+ */ -+ if (WARN_ON(!resp)) { -+ rcu_read_unlock(); -+ return; -+ } -+ resp->data[counter_offset_presp] = count; - rcu_read_unlock(); -- return; - } -- resp->data[counter_offset_presp]--; -- rcu_read_unlock(); - } - } - -+u8 ieee80211_csa_update_counter(struct ieee80211_vif *vif) -+{ -+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); -+ -+ sdata->csa_current_counter--; -+ -+ /* the counter should never reach 0 */ -+ WARN_ON(!sdata->csa_current_counter); -+ -+ return sdata->csa_current_counter; -+} -+EXPORT_SYMBOL(ieee80211_csa_update_counter); -+ - bool ieee80211_csa_is_complete(struct ieee80211_vif *vif) - { - struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); - struct beacon_data *beacon = NULL; - u8 *beacon_data; - size_t beacon_data_len; -- int counter_beacon = sdata->csa_counter_offset_beacon; -+ int counter_beacon = sdata->csa_counter_offset_beacon[0]; - int ret = false; - - if (!ieee80211_sdata_running(sdata)) -@@ -2523,9 +2543,11 @@ bool ieee80211_csa_is_complete(struct ie - } - EXPORT_SYMBOL(ieee80211_csa_is_complete); - --struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, -- struct ieee80211_vif *vif, -- u16 *tim_offset, u16 *tim_length) -+static struct sk_buff * -+__ieee80211_beacon_get(struct ieee80211_hw *hw, -+ struct ieee80211_vif *vif, -+ struct ieee80211_mutable_offsets *offs, -+ bool is_template) - { - struct ieee80211_local *local = hw_to_local(hw); - struct sk_buff *skb = NULL; -@@ -2534,6 +2556,7 @@ struct sk_buff *ieee80211_beacon_get_tim - enum ieee80211_band band; - struct ieee80211_tx_rate_control txrc; - struct ieee80211_chanctx_conf *chanctx_conf; -+ int csa_off_base = 0; - - rcu_read_lock(); - -@@ -2543,18 +2566,20 @@ struct sk_buff *ieee80211_beacon_get_tim - if (!ieee80211_sdata_running(sdata) || !chanctx_conf) - goto out; - -- if (tim_offset) -- *tim_offset = 0; -- if (tim_length) -- *tim_length = 0; -+ if (offs) -+ memset(offs, 0, sizeof(*offs)); - - if (sdata->vif.type == NL80211_IFTYPE_AP) { - struct ieee80211_if_ap *ap = &sdata->u.ap; - struct beacon_data *beacon = rcu_dereference(ap->beacon); - - if (beacon) { -- if (sdata->vif.csa_active) -- ieee80211_update_csa(sdata, beacon); -+ if (sdata->vif.csa_active) { -+ if (!is_template) -+ ieee80211_csa_update_counter(vif); -+ -+ ieee80211_set_csa(sdata, beacon); -+ } - - /* - * headroom, head length, -@@ -2571,12 +2596,16 @@ struct sk_buff *ieee80211_beacon_get_tim - memcpy(skb_put(skb, beacon->head_len), beacon->head, - beacon->head_len); - -- ieee80211_beacon_add_tim(sdata, &ap->ps, skb); -+ ieee80211_beacon_add_tim(sdata, &ap->ps, skb, -+ is_template); -+ -+ if (offs) { -+ offs->tim_offset = beacon->head_len; -+ offs->tim_length = skb->len - beacon->head_len; - -- if (tim_offset) -- *tim_offset = beacon->head_len; -- if (tim_length) -- *tim_length = skb->len - beacon->head_len; -+ /* for AP the csa offsets are from tail */ -+ csa_off_base = skb->len; -+ } - - if (beacon->tail) - memcpy(skb_put(skb, beacon->tail_len), -@@ -2591,9 +2620,12 @@ struct sk_buff *ieee80211_beacon_get_tim - if (!presp) - goto out; - -- if (sdata->vif.csa_active) -- ieee80211_update_csa(sdata, presp); -+ if (sdata->vif.csa_active) { -+ if (!is_template) -+ ieee80211_csa_update_counter(vif); - -+ ieee80211_set_csa(sdata, presp); -+ } - - skb = dev_alloc_skb(local->tx_headroom + presp->head_len + - local->hw.extra_beacon_tailroom); -@@ -2613,8 +2645,17 @@ struct sk_buff *ieee80211_beacon_get_tim - if (!bcn) - goto out; - -- if (sdata->vif.csa_active) -- ieee80211_update_csa(sdata, bcn); -+ if (sdata->vif.csa_active) { -+ if (!is_template) -+ /* TODO: For mesh csa_counter is in TU, so -+ * decrementing it by one isn't correct, but -+ * for now we leave it consistent with overall -+ * mac80211's behavior. -+ */ -+ ieee80211_csa_update_counter(vif); -+ -+ ieee80211_set_csa(sdata, bcn); -+ } - - if (ifmsh->sync_ops) - ifmsh->sync_ops->adjust_tbtt(sdata, bcn); -@@ -2628,13 +2669,33 @@ struct sk_buff *ieee80211_beacon_get_tim - goto out; - skb_reserve(skb, local->tx_headroom); - memcpy(skb_put(skb, bcn->head_len), bcn->head, bcn->head_len); -- ieee80211_beacon_add_tim(sdata, &ifmsh->ps, skb); -+ 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; -+ } -+ - memcpy(skb_put(skb, bcn->tail_len), bcn->tail, bcn->tail_len); - } else { - WARN_ON(1); - goto out; - } - -+ /* CSA offsets */ -+ if (offs) { -+ int i; -+ -+ for (i = 0; i < IEEE80211_MAX_CSA_COUNTERS_NUM; i++) { -+ u16 csa_off = sdata->csa_counter_offset_beacon[i]; -+ -+ if (!csa_off) -+ continue; -+ -+ offs->csa_counter_offs[i] = csa_off_base + csa_off; -+ } -+ } -+ - band = chanctx_conf->def.chan->band; - - info = IEEE80211_SKB_CB(skb); -@@ -2665,6 +2726,32 @@ struct sk_buff *ieee80211_beacon_get_tim - out: - rcu_read_unlock(); - return skb; -+ -+} -+ -+struct sk_buff * -+ieee80211_beacon_get_template(struct ieee80211_hw *hw, -+ struct ieee80211_vif *vif, -+ struct ieee80211_mutable_offsets *offs) -+{ -+ return __ieee80211_beacon_get(hw, vif, offs, true); -+} -+EXPORT_SYMBOL(ieee80211_beacon_get_template); -+ -+struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, -+ struct ieee80211_vif *vif, -+ u16 *tim_offset, u16 *tim_length) -+{ -+ struct ieee80211_mutable_offsets offs = {}; -+ struct sk_buff *bcn = __ieee80211_beacon_get(hw, vif, &offs, false); -+ -+ if (tim_offset) -+ *tim_offset = offs.tim_offset; -+ -+ if (tim_length) -+ *tim_length = offs.tim_length; -+ -+ return bcn; - } - EXPORT_SYMBOL(ieee80211_beacon_get_tim); - ---- a/net/mac80211/util.c -+++ b/net/mac80211/util.c -@@ -1457,6 +1457,44 @@ void ieee80211_stop_device(struct ieee80 - drv_stop(local); - } - -+static void ieee80211_handle_reconfig_failure(struct ieee80211_local *local) -+{ -+ struct ieee80211_sub_if_data *sdata; -+ struct ieee80211_chanctx *ctx; -+ -+ /* -+ * We get here if during resume the device can't be restarted properly. -+ * We might also get here if this happens during HW reset, which is a -+ * slightly different situation and we need to drop all connections in -+ * the latter case. -+ * -+ * Ask cfg80211 to turn off all interfaces, this will result in more -+ * warnings but at least we'll then get into a clean stopped state. -+ */ -+ -+ local->resuming = false; -+ local->suspended = false; -+ local->started = false; -+ -+ /* scheduled scan clearly can't be running any more, but tell -+ * cfg80211 and clear local state -+ */ -+ ieee80211_sched_scan_end(local); -+ -+ list_for_each_entry(sdata, &local->interfaces, list) -+ sdata->flags &= ~IEEE80211_SDATA_IN_DRIVER; -+ -+ /* Mark channel contexts as not being in the driver any more to avoid -+ * removing them from the driver during the shutdown process... -+ */ -+ mutex_lock(&local->chanctx_mtx); -+ list_for_each_entry(ctx, &local->chanctx_list, list) -+ ctx->driver_present = false; -+ mutex_unlock(&local->chanctx_mtx); -+ -+ cfg80211_shutdown_all_interfaces(local->hw.wiphy); -+} -+ - static void ieee80211_assign_chanctx(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata) - { -@@ -1520,9 +1558,11 @@ int ieee80211_reconfig(struct ieee80211_ - */ - res = drv_start(local); - if (res) { -- WARN(local->suspended, "Hardware became unavailable " -- "upon resume. This could be a software issue " -- "prior to suspend or a hardware issue.\n"); -+ if (local->suspended) -+ WARN(1, "Hardware became unavailable upon resume. This could be a software issue prior to suspend or a hardware issue.\n"); -+ else -+ WARN(1, "Hardware became unavailable during restart.\n"); -+ ieee80211_handle_reconfig_failure(local); - return res; - } - ---- a/net/wireless/ap.c -+++ b/net/wireless/ap.c -@@ -6,8 +6,8 @@ - #include "rdev-ops.h" - - --static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, -- struct net_device *dev, bool notify) -+int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, -+ struct net_device *dev, bool notify) - { - struct wireless_dev *wdev = dev->ieee80211_ptr; - int err; ---- a/net/wireless/chan.c -+++ b/net/wireless/chan.c -@@ -370,8 +370,8 @@ int cfg80211_chandef_dfs_required(struct - case NL80211_IFTYPE_AP_VLAN: - case NL80211_IFTYPE_WDS: - case NL80211_IFTYPE_P2P_DEVICE: -- case NL80211_IFTYPE_UNSPECIFIED: - break; -+ case NL80211_IFTYPE_UNSPECIFIED: - case NUM_NL80211_IFTYPES: - WARN_ON(1); - } -@@ -796,8 +796,7 @@ bool cfg80211_reg_can_beacon(struct wiph - !cfg80211_go_permissive_chan(rdev, chandef->chan)) - prohibited_flags |= IEEE80211_CHAN_NO_IR; - -- if (cfg80211_chandef_dfs_required(wiphy, chandef, -- NL80211_IFTYPE_UNSPECIFIED) > 0 && -+ if (cfg80211_chandef_dfs_required(wiphy, chandef, iftype) > 0 && - cfg80211_chandef_dfs_available(wiphy, chandef)) { - /* We can skip IEEE80211_CHAN_NO_IR if chandef dfs available */ - prohibited_flags = IEEE80211_CHAN_DISABLED; ---- a/net/wireless/core.c -+++ b/net/wireless/core.c -@@ -210,15 +210,12 @@ void cfg80211_stop_p2p_device(struct cfg - } - } - --static int cfg80211_rfkill_set_block(void *data, bool blocked) -+void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy) - { -- struct cfg80211_registered_device *rdev = data; -+ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); - struct wireless_dev *wdev; - -- if (!blocked) -- return 0; -- -- rtnl_lock(); -+ ASSERT_RTNL(); - - list_for_each_entry(wdev, &rdev->wdev_list, list) { - if (wdev->netdev) { -@@ -234,7 +231,18 @@ static int cfg80211_rfkill_set_block(voi - break; - } - } -+} -+EXPORT_SYMBOL_GPL(cfg80211_shutdown_all_interfaces); - -+static int cfg80211_rfkill_set_block(void *data, bool blocked) -+{ -+ struct cfg80211_registered_device *rdev = data; -+ -+ if (!blocked) -+ return 0; -+ -+ rtnl_lock(); -+ cfg80211_shutdown_all_interfaces(&rdev->wiphy); - rtnl_unlock(); - - return 0; -@@ -401,6 +409,8 @@ struct wiphy *wiphy_new(const struct cfg - rdev->wiphy.rts_threshold = (u32) -1; - rdev->wiphy.coverage_class = 0; - -+ rdev->wiphy.max_num_csa_counters = 1; -+ - return &rdev->wiphy; - } - EXPORT_SYMBOL(wiphy_new); -@@ -697,7 +707,7 @@ void wiphy_unregister(struct wiphy *wiph - rtnl_lock(); - rdev->wiphy.registered = false; - -- BUG_ON(!list_empty(&rdev->wdev_list)); -+ WARN_ON(!list_empty(&rdev->wdev_list)); - - /* - * First remove the hardware from everywhere, this makes -@@ -799,23 +809,23 @@ void cfg80211_update_iface_num(struct cf - rdev->num_running_monitor_ifaces += num; - } - --void cfg80211_leave(struct cfg80211_registered_device *rdev, -- struct wireless_dev *wdev) -+void __cfg80211_leave(struct cfg80211_registered_device *rdev, -+ struct wireless_dev *wdev) - { - struct net_device *dev = wdev->netdev; - - ASSERT_RTNL(); -+ ASSERT_WDEV_LOCK(wdev); - - switch (wdev->iftype) { - case NL80211_IFTYPE_ADHOC: -- cfg80211_leave_ibss(rdev, dev, true); -+ __cfg80211_leave_ibss(rdev, dev, true); - break; - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_STATION: - if (rdev->sched_scan_req && dev == rdev->sched_scan_req->dev) - __cfg80211_stop_sched_scan(rdev, false); - -- wdev_lock(wdev); - #ifdef CPTCFG_CFG80211_WEXT - kfree(wdev->wext.ie); - wdev->wext.ie = NULL; -@@ -824,20 +834,49 @@ void cfg80211_leave(struct cfg80211_regi - #endif - cfg80211_disconnect(rdev, dev, - WLAN_REASON_DEAUTH_LEAVING, true); -- wdev_unlock(wdev); - break; - case NL80211_IFTYPE_MESH_POINT: -- cfg80211_leave_mesh(rdev, dev); -+ __cfg80211_leave_mesh(rdev, dev); - break; - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_P2P_GO: -- cfg80211_stop_ap(rdev, dev, true); -+ __cfg80211_stop_ap(rdev, dev, true); - break; - default: - break; - } - } - -+void cfg80211_leave(struct cfg80211_registered_device *rdev, -+ struct wireless_dev *wdev) -+{ -+ wdev_lock(wdev); -+ __cfg80211_leave(rdev, wdev); -+ wdev_unlock(wdev); -+} -+ -+void cfg80211_stop_iface(struct wiphy *wiphy, struct wireless_dev *wdev, -+ gfp_t gfp) -+{ -+ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); -+ struct cfg80211_event *ev; -+ unsigned long flags; -+ -+ trace_cfg80211_stop_iface(wiphy, wdev); -+ -+ ev = kzalloc(sizeof(*ev), gfp); -+ if (!ev) -+ return; -+ -+ ev->type = EVENT_STOPPED; -+ -+ spin_lock_irqsave(&wdev->event_lock, flags); -+ list_add_tail(&ev->list, &wdev->event_list); -+ spin_unlock_irqrestore(&wdev->event_lock, flags); -+ queue_work(cfg80211_wq, &rdev->event_work); -+} -+EXPORT_SYMBOL(cfg80211_stop_iface); -+ - static int cfg80211_netdev_notifier_call(struct notifier_block *nb, - unsigned long state, void *ptr) - { ---- a/net/wireless/core.h -+++ b/net/wireless/core.h -@@ -185,6 +185,7 @@ enum cfg80211_event_type { - EVENT_ROAMED, - EVENT_DISCONNECTED, - EVENT_IBSS_JOINED, -+ EVENT_STOPPED, - }; - - struct cfg80211_event { -@@ -281,6 +282,8 @@ int cfg80211_join_mesh(struct cfg80211_r - struct net_device *dev, - struct mesh_setup *setup, - const struct mesh_config *conf); -+int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, -+ struct net_device *dev); - int cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, - struct net_device *dev); - int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev, -@@ -288,6 +291,8 @@ int cfg80211_set_mesh_channel(struct cfg - struct cfg80211_chan_def *chandef); - - /* AP */ -+int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, -+ struct net_device *dev, bool notify); - int cfg80211_stop_ap(struct cfg80211_registered_device *rdev, - struct net_device *dev, bool notify); - -@@ -441,6 +446,8 @@ int cfg80211_validate_beacon_int(struct - void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, - enum nl80211_iftype iftype, int num); - -+void __cfg80211_leave(struct cfg80211_registered_device *rdev, -+ struct wireless_dev *wdev); - void cfg80211_leave(struct cfg80211_registered_device *rdev, - struct wireless_dev *wdev); - ---- a/net/wireless/ibss.c -+++ b/net/wireless/ibss.c -@@ -420,8 +420,8 @@ int cfg80211_ibss_wext_siwessid(struct n - if (len > 0 && ssid[len - 1] == '\0') - len--; - -+ memcpy(wdev->ssid, ssid, len); - wdev->wext.ibss.ssid = wdev->ssid; -- memcpy(wdev->wext.ibss.ssid, ssid, len); - wdev->wext.ibss.ssid_len = len; - - wdev_lock(wdev); ---- a/net/wireless/mesh.c -+++ b/net/wireless/mesh.c -@@ -238,8 +238,8 @@ int cfg80211_set_mesh_channel(struct cfg - return 0; - } - --static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, -- struct net_device *dev) -+int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, -+ struct net_device *dev) - { - struct wireless_dev *wdev = dev->ieee80211_ptr; - int err; ---- a/net/wireless/nl80211.c -+++ b/net/wireless/nl80211.c -@@ -371,8 +371,8 @@ static const struct nla_policy nl80211_p - [NL80211_ATTR_CH_SWITCH_COUNT] = { .type = NLA_U32 }, - [NL80211_ATTR_CH_SWITCH_BLOCK_TX] = { .type = NLA_FLAG }, - [NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED }, -- [NL80211_ATTR_CSA_C_OFF_BEACON] = { .type = NLA_U16 }, -- [NL80211_ATTR_CSA_C_OFF_PRESP] = { .type = NLA_U16 }, -+ [NL80211_ATTR_CSA_C_OFF_BEACON] = { .type = NLA_BINARY }, -+ [NL80211_ATTR_CSA_C_OFF_PRESP] = { .type = NLA_BINARY }, - [NL80211_ATTR_STA_SUPPORTED_CHANNELS] = { .type = NLA_BINARY }, - [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] = { .type = NLA_BINARY }, - [NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG }, -@@ -386,6 +386,7 @@ static const struct nla_policy nl80211_p - [NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 }, - [NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 }, - [NL80211_ATTR_IFACE_SOCKET_OWNER] = { .type = NLA_FLAG }, -+ [NL80211_ATTR_CSA_C_OFFSETS_TX] = { .type = NLA_BINARY }, - }; - - /* policy for the key attributes */ -@@ -970,8 +971,10 @@ static int nl80211_put_iface_combination - c->max_interfaces)) - goto nla_put_failure; - if (large && -- nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS, -- c->radar_detect_widths)) -+ (nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS, -+ c->radar_detect_widths) || -+ nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_REGIONS, -+ c->radar_detect_regions))) - goto nla_put_failure; - - nla_nest_end(msg, nl_combi); -@@ -1667,6 +1670,13 @@ static int nl80211_send_wiphy(struct cfg - } - nla_nest_end(msg, nested); - } -+ state->split_start++; -+ break; -+ case 12: -+ if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH && -+ nla_put_u8(msg, NL80211_ATTR_MAX_CSA_COUNTERS, -+ rdev->wiphy.max_num_csa_counters)) -+ goto nla_put_failure; - - /* done */ - state->split_start = 0; -@@ -5825,7 +5835,7 @@ static int nl80211_start_radar_detection - return -EBUSY; - - err = cfg80211_chandef_dfs_required(wdev->wiphy, &chandef, -- NL80211_IFTYPE_UNSPECIFIED); -+ wdev->iftype); - if (err < 0) - return err; - -@@ -5866,6 +5876,7 @@ static int nl80211_channel_switch(struct - u8 radar_detect_width = 0; - int err; - bool need_new_beacon = false; -+ int len, i; - - if (!rdev->ops->channel_switch || - !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)) -@@ -5924,26 +5935,55 @@ static int nl80211_channel_switch(struct - if (!csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]) - return -EINVAL; - -- params.counter_offset_beacon = -- nla_get_u16(csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]); -- if (params.counter_offset_beacon >= params.beacon_csa.tail_len) -+ len = nla_len(csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]); -+ if (!len || (len % sizeof(u16))) - return -EINVAL; - -- /* sanity check - counters should be the same */ -- if (params.beacon_csa.tail[params.counter_offset_beacon] != -- params.count) -+ params.n_counter_offsets_beacon = len / sizeof(u16); -+ if (rdev->wiphy.max_num_csa_counters && -+ (params.n_counter_offsets_beacon > -+ rdev->wiphy.max_num_csa_counters)) - return -EINVAL; - -+ params.counter_offsets_beacon = -+ nla_data(csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]); -+ -+ /* sanity checks - counters should fit and be the same */ -+ for (i = 0; i < params.n_counter_offsets_beacon; i++) { -+ u16 offset = params.counter_offsets_beacon[i]; -+ -+ if (offset >= params.beacon_csa.tail_len) -+ return -EINVAL; -+ -+ if (params.beacon_csa.tail[offset] != params.count) -+ return -EINVAL; -+ } -+ - if (csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]) { -- params.counter_offset_presp = -- nla_get_u16(csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]); -- if (params.counter_offset_presp >= -- params.beacon_csa.probe_resp_len) -+ len = nla_len(csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]); -+ if (!len || (len % sizeof(u16))) - return -EINVAL; - -- if (params.beacon_csa.probe_resp[params.counter_offset_presp] != -- params.count) -+ params.n_counter_offsets_presp = len / sizeof(u16); -+ if (rdev->wiphy.max_num_csa_counters && -+ (params.n_counter_offsets_beacon > -+ rdev->wiphy.max_num_csa_counters)) - return -EINVAL; -+ -+ params.counter_offsets_presp = -+ nla_data(csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]); -+ -+ /* sanity checks - counters should fit and be the same */ -+ for (i = 0; i < params.n_counter_offsets_presp; i++) { -+ u16 offset = params.counter_offsets_presp[i]; -+ -+ if (offset >= params.beacon_csa.probe_resp_len) -+ return -EINVAL; -+ -+ if (params.beacon_csa.probe_resp[offset] != -+ params.count) -+ return -EINVAL; -+ } - } - - skip_beacons: -@@ -7793,6 +7833,27 @@ static int nl80211_tx_mgmt(struct sk_buf - if (!chandef.chan && params.offchan) - return -EINVAL; - -+ params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]); -+ params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]); -+ -+ if (info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]) { -+ int len = nla_len(info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]); -+ int i; -+ -+ if (len % sizeof(u16)) -+ return -EINVAL; -+ -+ params.n_csa_offsets = len / sizeof(u16); -+ params.csa_offsets = -+ nla_data(info->attrs[NL80211_ATTR_CSA_C_OFFSETS_TX]); -+ -+ /* check that all the offsets fit the frame */ -+ for (i = 0; i < params.n_csa_offsets; i++) { -+ if (params.csa_offsets[i] >= params.len) -+ return -EINVAL; -+ } -+ } -+ - if (!params.dont_wait_for_ack) { - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); - if (!msg) -@@ -7807,8 +7868,6 @@ static int nl80211_tx_mgmt(struct sk_buf - } - } - -- params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]); -- params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]); - params.chan = chandef.chan; - err = cfg80211_mlme_mgmt_tx(rdev, wdev, ¶ms, &cookie); - if (err) -@@ -8507,6 +8566,8 @@ static int nl80211_set_wowlan(struct sk_ - - nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN], - rem) { -+ u8 *mask_pat; -+ - nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat), - nla_len(pat), NULL); - err = -EINVAL; -@@ -8530,19 +8591,18 @@ static int nl80211_set_wowlan(struct sk_ - goto error; - new_triggers.patterns[i].pkt_offset = pkt_offset; - -- new_triggers.patterns[i].mask = -- kmalloc(mask_len + pat_len, GFP_KERNEL); -- if (!new_triggers.patterns[i].mask) { -+ mask_pat = kmalloc(mask_len + pat_len, GFP_KERNEL); -+ if (!mask_pat) { - err = -ENOMEM; - goto error; - } -- new_triggers.patterns[i].pattern = -- new_triggers.patterns[i].mask + mask_len; -- memcpy(new_triggers.patterns[i].mask, -- nla_data(pat_tb[NL80211_PKTPAT_MASK]), -+ new_triggers.patterns[i].mask = mask_pat; -+ memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_MASK]), - mask_len); -+ mask_pat += mask_len; -+ new_triggers.patterns[i].pattern = mask_pat; - new_triggers.patterns[i].pattern_len = pat_len; -- memcpy(new_triggers.patterns[i].pattern, -+ memcpy(mask_pat, - nla_data(pat_tb[NL80211_PKTPAT_PATTERN]), - pat_len); - i++; -@@ -8735,6 +8795,8 @@ static int nl80211_parse_coalesce_rule(s - - nla_for_each_nested(pat, tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN], - rem) { -+ u8 *mask_pat; -+ - nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat), - nla_len(pat), NULL); - if (!pat_tb[NL80211_PKTPAT_MASK] || -@@ -8756,17 +8818,19 @@ static int nl80211_parse_coalesce_rule(s - return -EINVAL; - new_rule->patterns[i].pkt_offset = pkt_offset; - -- new_rule->patterns[i].mask = -- kmalloc(mask_len + pat_len, GFP_KERNEL); -- if (!new_rule->patterns[i].mask) -+ mask_pat = kmalloc(mask_len + pat_len, GFP_KERNEL); -+ if (!mask_pat) - return -ENOMEM; -- new_rule->patterns[i].pattern = -- new_rule->patterns[i].mask + mask_len; -- memcpy(new_rule->patterns[i].mask, -- nla_data(pat_tb[NL80211_PKTPAT_MASK]), mask_len); -+ -+ new_rule->patterns[i].mask = mask_pat; -+ memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_MASK]), -+ mask_len); -+ -+ mask_pat += mask_len; -+ new_rule->patterns[i].pattern = mask_pat; - new_rule->patterns[i].pattern_len = pat_len; -- memcpy(new_rule->patterns[i].pattern, -- nla_data(pat_tb[NL80211_PKTPAT_PATTERN]), pat_len); -+ memcpy(mask_pat, nla_data(pat_tb[NL80211_PKTPAT_PATTERN]), -+ pat_len); - i++; - } - ---- a/net/wireless/sme.c -+++ b/net/wireless/sme.c -@@ -149,7 +149,8 @@ static int cfg80211_conn_do_work(struct - case CFG80211_CONN_SCAN_AGAIN: - return cfg80211_conn_scan(wdev); - case CFG80211_CONN_AUTHENTICATE_NEXT: -- BUG_ON(!rdev->ops->auth); -+ if (WARN_ON(!rdev->ops->auth)) -+ return -EOPNOTSUPP; - wdev->conn->state = CFG80211_CONN_AUTHENTICATING; - return cfg80211_mlme_auth(rdev, wdev->netdev, - params->channel, params->auth_type, -@@ -161,7 +162,8 @@ static int cfg80211_conn_do_work(struct - case CFG80211_CONN_AUTH_FAILED: - return -ENOTCONN; - case CFG80211_CONN_ASSOCIATE_NEXT: -- BUG_ON(!rdev->ops->assoc); -+ if (WARN_ON(!rdev->ops->assoc)) -+ return -EOPNOTSUPP; - wdev->conn->state = CFG80211_CONN_ASSOCIATING; - if (wdev->conn->prev_bssid_valid) - req.prev_bssid = wdev->conn->prev_bssid; -@@ -877,7 +879,7 @@ void __cfg80211_disconnected(struct net_ - } - - void cfg80211_disconnected(struct net_device *dev, u16 reason, -- u8 *ie, size_t ie_len, gfp_t gfp) -+ const u8 *ie, size_t ie_len, gfp_t gfp) - { - struct wireless_dev *wdev = dev->ieee80211_ptr; - struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); ---- a/net/wireless/trace.h -+++ b/net/wireless/trace.h -@@ -1876,29 +1876,33 @@ TRACE_EVENT(rdev_channel_switch, - WIPHY_ENTRY - NETDEV_ENTRY - CHAN_DEF_ENTRY -- __field(u16, counter_offset_beacon) -- __field(u16, counter_offset_presp) - __field(bool, radar_required) - __field(bool, block_tx) - __field(u8, count) -+ __dynamic_array(u16, bcn_ofs, params->n_counter_offsets_beacon) -+ __dynamic_array(u16, pres_ofs, params->n_counter_offsets_presp) - ), - TP_fast_assign( - WIPHY_ASSIGN; - NETDEV_ASSIGN; - CHAN_DEF_ASSIGN(¶ms->chandef); -- __entry->counter_offset_beacon = params->counter_offset_beacon; -- __entry->counter_offset_presp = params->counter_offset_presp; - __entry->radar_required = params->radar_required; - __entry->block_tx = params->block_tx; - __entry->count = params->count; -+ memcpy(__get_dynamic_array(bcn_ofs), -+ params->counter_offsets_beacon, -+ params->n_counter_offsets_beacon * sizeof(u16)); -+ -+ /* probe response offsets are optional */ -+ if (params->n_counter_offsets_presp) -+ memcpy(__get_dynamic_array(pres_ofs), -+ params->counter_offsets_presp, -+ params->n_counter_offsets_presp * sizeof(u16)); - ), - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT -- ", block_tx: %d, count: %u, radar_required: %d" -- ", counter offsets (beacon/presp): %u/%u", -+ ", block_tx: %d, count: %u, radar_required: %d", - WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_DEF_PR_ARG, -- __entry->block_tx, __entry->count, __entry->radar_required, -- __entry->counter_offset_beacon, -- __entry->counter_offset_presp) -+ __entry->block_tx, __entry->count, __entry->radar_required) - ); - - TRACE_EVENT(rdev_set_qos_map, -@@ -2636,6 +2640,21 @@ TRACE_EVENT(cfg80211_ft_event, - WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(target_ap)) - ); - -+TRACE_EVENT(cfg80211_stop_iface, -+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev), -+ TP_ARGS(wiphy, wdev), -+ TP_STRUCT__entry( -+ WIPHY_ENTRY -+ WDEV_ENTRY -+ ), -+ TP_fast_assign( -+ WIPHY_ASSIGN; -+ WDEV_ASSIGN; -+ ), -+ TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT, -+ WIPHY_PR_ARG, WDEV_PR_ARG) -+); -+ - #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */ - - #undef TRACE_INCLUDE_PATH ---- a/net/wireless/util.c -+++ b/net/wireless/util.c -@@ -476,7 +476,8 @@ int ieee80211_data_to_8023(struct sk_buf - EXPORT_SYMBOL(ieee80211_data_to_8023); - - int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr, -- enum nl80211_iftype iftype, u8 *bssid, bool qos) -+ enum nl80211_iftype iftype, -+ const u8 *bssid, bool qos) - { - struct ieee80211_hdr hdr; - u16 hdrlen, ethertype; -@@ -839,6 +840,9 @@ void cfg80211_process_wdev_events(struct - __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid, - ev->ij.channel); - break; -+ case EVENT_STOPPED: -+ __cfg80211_leave(wiphy_to_rdev(wdev->wiphy), wdev); -+ break; - } - wdev_unlock(wdev); - -@@ -1271,10 +1275,20 @@ int cfg80211_iter_combinations(struct wi - void *data), - void *data) - { -+ const struct ieee80211_regdomain *regdom; -+ enum nl80211_dfs_regions region = 0; - int i, j, iftype; - int num_interfaces = 0; - u32 used_iftypes = 0; - -+ if (radar_detect) { -+ rcu_read_lock(); -+ regdom = rcu_dereference(cfg80211_regdomain); -+ if (regdom) -+ region = regdom->dfs_region; -+ rcu_read_unlock(); -+ } -+ - for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) { - num_interfaces += iftype_num[iftype]; - if (iftype_num[iftype] > 0 && -@@ -1315,6 +1329,10 @@ int cfg80211_iter_combinations(struct wi - if (radar_detect != (c->radar_detect_widths & radar_detect)) - goto cont; - -+ if (radar_detect && c->radar_detect_regions && -+ !(c->radar_detect_regions & BIT(region))) -+ goto cont; -+ - /* Finally check that all iftypes that we're currently - * using are actually part of this combination. If they - * aren't then we can't use this combination and have --- 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 @@ -4381,3 +99,65 @@ Date: Tue Apr 29 17:52:36 2014 +0200 } if (!budget--) +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -227,6 +227,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 +239,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); +--- 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) ++{ ++ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); ++ ++ /* This packet was aggregated but doesn't carry status info */ ++ if ((info->flags & IEEE80211_TX_CTL_AMPDU) && ++ !(info->flags & IEEE80211_TX_STAT_AMPDU)) ++ return; ++ ++ if (++sta->lost_packets < STA_LOST_PKT_THRESHOLD) ++ return; ++ ++ cfg80211_cqm_pktloss_notify(sta->sdata->dev, sta->sta.addr, ++ sta->lost_packets, GFP_ATOMIC); ++ sta->lost_packets = 0; ++} ++ + void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) + { + struct sk_buff *skb2; +@@ -680,12 +697,8 @@ void ieee80211_tx_status(struct ieee8021 + if (info->flags & IEEE80211_TX_STAT_ACK) { + if (sta->lost_packets) + sta->lost_packets = 0; +- } else if (++sta->lost_packets >= STA_LOST_PKT_THRESHOLD) { +- cfg80211_cqm_pktloss_notify(sta->sdata->dev, +- sta->sta.addr, +- sta->lost_packets, +- GFP_ATOMIC); +- sta->lost_packets = 0; ++ } else { ++ ieee80211_lost_packet(sta, skb); + } + } + |