8513629e3e
Signed-off-by: Felix Fietkau <nbd@openwrt.org> SVN-Revision: 40800
4446 lines
143 KiB
Diff
4446 lines
143 KiB
Diff
commit 230ab8c1880266c9cfceac962e2d48309dea79a7
|
||
Author: Felix Fietkau <nbd@openwrt.org>
|
||
Date: Mon May 19 21:48:56 2014 +0200
|
||
|
||
ath9k: re-schedule rx processing after budget exceeded
|
||
|
||
Should improve rx stability under load
|
||
|
||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||
|
||
commit ff9655bebd25d35ab13c2515a029723b69949720
|
||
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>
|
||
|
||
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.
|
||
|
||
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.
|
||
|
||
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
|
||
|
||
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>
|
||
|
||
commit 4f46eb8b28f96aca212a364e0fa847eb5333df67
|
||
Author: Felix Fietkau <nbd@openwrt.org>
|
||
Date: Mon May 5 11:48:40 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.
|
||
|
||
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
|
||
|
||
cfg80211: remove BUG_ON usage
|
||
|
||
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().
|
||
|
||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||
|
||
--- 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/main.c
|
||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||
@@ -444,6 +444,8 @@ void ath9k_tasklet(unsigned long data)
|
||
ath9k_ps_wakeup(sc);
|
||
spin_lock(&sc->sc_pcu_lock);
|
||
|
||
+ sc->intrstatus = 0;
|
||
+
|
||
if (status & ATH9K_INT_FATAL) {
|
||
type = RESET_TYPE_FATAL_INT;
|
||
ath9k_queue_reset(sc, type);
|
||
@@ -512,10 +514,12 @@ void ath9k_tasklet(unsigned long data)
|
||
if (status & rxmask) {
|
||
/* Check for high priority Rx first */
|
||
if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
|
||
- (status & ATH9K_INT_RXHP))
|
||
- ath_rx_tasklet(sc, 0, true);
|
||
+ (status & ATH9K_INT_RXHP) &&
|
||
+ ath_rx_tasklet(sc, 0, true))
|
||
+ sc->intrstatus |= ATH9K_INT_RXHP;
|
||
|
||
- ath_rx_tasklet(sc, 0, false);
|
||
+ if (ath_rx_tasklet(sc, 0, false))
|
||
+ sc->intrstatus |= ATH9K_INT_RXLP;
|
||
}
|
||
|
||
if (status & ATH9K_INT_TX) {
|
||
@@ -543,6 +547,9 @@ void ath9k_tasklet(unsigned long data)
|
||
|
||
/* re-enable hardware interrupt */
|
||
ath9k_hw_enable_interrupts(ah);
|
||
+ if (sc->intrstatus)
|
||
+ tasklet_schedule(&sc->intr_tq);
|
||
+
|
||
out:
|
||
spin_unlock(&sc->sc_pcu_lock);
|
||
ath9k_ps_restore(sc);
|
||
@@ -609,7 +616,7 @@ irqreturn_t ath_isr(int irq, void *dev)
|
||
return IRQ_NONE;
|
||
|
||
/* Cache the status */
|
||
- sc->intrstatus = status;
|
||
+ sc->intrstatus |= status;
|
||
|
||
if (status & SCHED_INTR)
|
||
sched = true;
|
||
--- a/drivers/net/wireless/ath/ath9k/recv.c
|
||
+++ b/drivers/net/wireless/ath/ath9k/recv.c
|
||
@@ -34,7 +34,8 @@ static inline bool ath9k_check_auto_slee
|
||
* buffer (or rx fifo). This can incorrectly acknowledge packets
|
||
* to a sender if last desc is self-linked.
|
||
*/
|
||
-static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf)
|
||
+static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf,
|
||
+ bool flush)
|
||
{
|
||
struct ath_hw *ah = sc->sc_ah;
|
||
struct ath_common *common = ath9k_hw_common(ah);
|
||
@@ -59,18 +60,19 @@ static void ath_rx_buf_link(struct ath_s
|
||
common->rx_bufsize,
|
||
0);
|
||
|
||
- if (sc->rx.rxlink == NULL)
|
||
- ath9k_hw_putrxbuf(ah, bf->bf_daddr);
|
||
- else
|
||
+ if (sc->rx.rxlink)
|
||
*sc->rx.rxlink = bf->bf_daddr;
|
||
+ else if (!flush)
|
||
+ ath9k_hw_putrxbuf(ah, bf->bf_daddr);
|
||
|
||
sc->rx.rxlink = &ds->ds_link;
|
||
}
|
||
|
||
-static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf)
|
||
+static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf,
|
||
+ bool flush)
|
||
{
|
||
if (sc->rx.buf_hold)
|
||
- ath_rx_buf_link(sc, sc->rx.buf_hold);
|
||
+ ath_rx_buf_link(sc, sc->rx.buf_hold, flush);
|
||
|
||
sc->rx.buf_hold = bf;
|
||
}
|
||
@@ -442,7 +444,7 @@ int ath_startrecv(struct ath_softc *sc)
|
||
sc->rx.buf_hold = NULL;
|
||
sc->rx.rxlink = NULL;
|
||
list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) {
|
||
- ath_rx_buf_link(sc, bf);
|
||
+ ath_rx_buf_link(sc, bf, false);
|
||
}
|
||
|
||
/* We could have deleted elements so the list may be empty now */
|
||
@@ -1118,12 +1120,12 @@ requeue_drop_frag:
|
||
requeue:
|
||
list_add_tail(&bf->list, &sc->rx.rxbuf);
|
||
|
||
- if (edma) {
|
||
- ath_rx_edma_buf_link(sc, qtype);
|
||
- } else {
|
||
- ath_rx_buf_relink(sc, bf);
|
||
+ if (!edma) {
|
||
+ ath_rx_buf_relink(sc, bf, flush);
|
||
if (!flush)
|
||
ath9k_hw_rxena(ah);
|
||
+ } else if (!flush) {
|
||
+ ath_rx_edma_buf_link(sc, qtype);
|
||
}
|
||
|
||
if (!budget--)
|
||
@@ -1135,5 +1137,5 @@ requeue:
|
||
ath9k_hw_set_interrupts(ah);
|
||
}
|
||
|
||
- return 0;
|
||
+ return !budget;
|
||
}
|