| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279 |
- commit de5f242e0c10e841017e37eb8c38974a642dbca8
- Author: Sujith Manoharan <[email protected]>
- Date: Tue Jan 28 06:21:59 2014 +0530
- ath9k: Fix build error on ARM
-
- Use mdelay instead of udelay to fix this error:
-
- ERROR: "__bad_udelay" [drivers/net/wireless/ath/ath9k/ath9k_hw.ko] undefined!
- make[1]: *** [__modpost] Error 1
- make: *** [modules] Error 2
-
- Reported-by: Josh Boyer <[email protected]>
- Signed-off-by: Sujith Manoharan <[email protected]>
- commit 8e3ea7a51dfc61810fcefd947f6edcf61125252a
- Author: Geert Uytterhoeven <[email protected]>
- Date: Sun Jan 26 11:53:21 2014 +0100
- ath9k: Fix uninitialized variable in ath9k_has_tx_pending()
-
- drivers/net/wireless/ath/ath9k/main.c: In function ‘ath9k_has_tx_pending’:
- drivers/net/wireless/ath/ath9k/main.c:1869: warning: ‘npend’ may be used uninitialized in this function
-
- Introduced by commit 10e2318103f5941aa70c318afe34bc41f1b98529 ("ath9k:
- optimize ath9k_flush").
-
- Signed-off-by: Geert Uytterhoeven <[email protected]>
- commit a4a634a6937ebdd827fa58e8fcdb8ca49a3769f6
- Author: Emmanuel Grumbach <[email protected]>
- Date: Mon Jan 27 11:07:42 2014 +0200
- mac80211: release the channel in error path in start_ap
-
- When the driver cannot start the AP or when the assignement
- of the beacon goes wrong, we need to unassign the vif.
-
- Cc: [email protected]
- Signed-off-by: Emmanuel Grumbach <[email protected]>
- Signed-off-by: Johannes Berg <[email protected]>
- commit dfb6889a75c601aedb7450b7e606668e77da6679
- Author: Johannes Berg <[email protected]>
- Date: Wed Jan 22 11:14:19 2014 +0200
- cfg80211: send scan results from work queue
-
- Due to the previous commit, when a scan finishes, it is in theory
- possible to hit the following sequence:
- 1. interface starts being removed
- 2. scan is cancelled by driver and cfg80211 is notified
- 3. scan done work is scheduled
- 4. interface is removed completely, rdev->scan_req is freed,
- event sent to userspace but scan done work remains pending
- 5. new scan is requested on another virtual interface
- 6. scan done work runs, freeing the still-running scan
-
- To fix this situation, hang on to the scan done message and block
- new scans while that is the case, and only send the message from
- the work function, regardless of whether the scan_req is already
- freed from interface removal. This makes step 5 above impossible
- and changes step 6 to be
- 5. scan done work runs, sending the scan done message
-
- As this can't work for wext, so we send the message immediately,
- but this shouldn't be an issue since we still return -EBUSY.
-
- Signed-off-by: Johannes Berg <[email protected]>
- commit 45b7ab41fc08627d9a8428cb413d5d84662a9707
- Author: Johannes Berg <[email protected]>
- Date: Wed Jan 22 11:14:18 2014 +0200
- cfg80211: fix scan done race
-
- When an interface/wdev is removed, any ongoing scan should be
- cancelled by the driver. This will make it call cfg80211, which
- only queues a work struct. If interface/wdev removal is quick
- enough, this can leave the scan request pending and processed
- only after the interface is gone, causing a use-after-free.
-
- Fix this by making sure the scan request is not pending after
- the interface is destroyed. We can't flush or cancel the work
- item due to locking concerns, but when it'll run it shouldn't
- find anything to do. This leaves a potential issue, if a new
- scan gets requested before the work runs, it prematurely stops
- the running scan, potentially causing another crash. I'll fix
- that in the next patch.
-
- This was particularly observed with P2P_DEVICE wdevs, likely
- because freeing them is quicker than freeing netdevs.
-
- Reported-by: Andrei Otcheretianski <[email protected]>
- Fixes: 4a58e7c38443 ("cfg80211: don't "leak" uncompleted scans")
- Signed-off-by: Johannes Berg <[email protected]>
- commit ae04fa489ab31b5a10d3cc8399f52761175d4321
- Author: Emmanuel Grumbach <[email protected]>
- Date: Thu Jan 23 14:28:16 2014 +0200
- mac80211: avoid deadlock revealed by lockdep
-
- sdata->u.ap.request_smps_work can’t be flushed synchronously
- under wdev_lock(wdev) since ieee80211_request_smps_ap_work
- itself locks the same lock.
- While at it, reset the driver_smps_mode when the ap is
- stopped to its default: OFF.
-
- This solves:
-
- ======================================================
- [ INFO: possible circular locking dependency detected ]
- 3.12.0-ipeer+ #2 Tainted: G O
- -------------------------------------------------------
- rmmod/2867 is trying to acquire lock:
- ((&sdata->u.ap.request_smps_work)){+.+...}, at: [<c105b8d0>] flush_work+0x0/0x90
-
- but task is already holding lock:
- (&wdev->mtx){+.+.+.}, at: [<f9b32626>] cfg80211_stop_ap+0x26/0x230 [cfg80211]
-
- which lock already depends on the new lock.
-
- the existing dependency chain (in reverse order) is:
-
- -> #1 (&wdev->mtx){+.+.+.}:
- [<c10aefa9>] lock_acquire+0x79/0xe0
- [<c1607a1a>] mutex_lock_nested+0x4a/0x360
- [<fb06288b>] ieee80211_request_smps_ap_work+0x2b/0x50 [mac80211]
- [<c105cdd8>] process_one_work+0x198/0x450
- [<c105d469>] worker_thread+0xf9/0x320
- [<c10669ff>] kthread+0x9f/0xb0
- [<c1613397>] ret_from_kernel_thread+0x1b/0x28
-
- -> #0 ((&sdata->u.ap.request_smps_work)){+.+...}:
- [<c10ae9df>] __lock_acquire+0x183f/0x1910
- [<c10aefa9>] lock_acquire+0x79/0xe0
- [<c105b917>] flush_work+0x47/0x90
- [<c105d867>] __cancel_work_timer+0x67/0xe0
- [<c105d90f>] cancel_work_sync+0xf/0x20
- [<fb0765cc>] ieee80211_stop_ap+0x8c/0x340 [mac80211]
- [<f9b3268c>] cfg80211_stop_ap+0x8c/0x230 [cfg80211]
- [<f9b0d8f9>] cfg80211_leave+0x79/0x100 [cfg80211]
- [<f9b0da72>] cfg80211_netdev_notifier_call+0xf2/0x4f0 [cfg80211]
- [<c160f2c9>] notifier_call_chain+0x59/0x130
- [<c106c6de>] __raw_notifier_call_chain+0x1e/0x30
- [<c106c70f>] raw_notifier_call_chain+0x1f/0x30
- [<c14f8213>] call_netdevice_notifiers_info+0x33/0x70
- [<c14f8263>] call_netdevice_notifiers+0x13/0x20
- [<c14f82a4>] __dev_close_many+0x34/0xb0
- [<c14f83fe>] dev_close_many+0x6e/0xc0
- [<c14f9c77>] rollback_registered_many+0xa7/0x1f0
- [<c14f9dd4>] unregister_netdevice_many+0x14/0x60
- [<fb06f4d9>] ieee80211_remove_interfaces+0xe9/0x170 [mac80211]
- [<fb055116>] ieee80211_unregister_hw+0x56/0x110 [mac80211]
- [<fa3e9396>] iwl_op_mode_mvm_stop+0x26/0xe0 [iwlmvm]
- [<f9b9d8ca>] _iwl_op_mode_stop+0x3a/0x70 [iwlwifi]
- [<f9b9d96f>] iwl_opmode_deregister+0x6f/0x90 [iwlwifi]
- [<fa405179>] __exit_compat+0xd/0x19 [iwlmvm]
- [<c10b8bf9>] SyS_delete_module+0x179/0x2b0
- [<c1613421>] sysenter_do_call+0x12/0x32
-
- Fixes: 687da132234f ("mac80211: implement SMPS for AP")
- Cc: <[email protected]> [3.13]
- Reported-by: Ilan Peer <[email protected]>
- Signed-off-by: Emmanuel Grumbach <[email protected]>
- Signed-off-by: Johannes Berg <[email protected]>
- commit 178b205e96217164fd7c30113464250d0b6f5eca
- Author: Johannes Berg <[email protected]>
- Date: Thu Jan 23 16:32:29 2014 +0100
- cfg80211: re-enable 5/10 MHz support
-
- Unfortunately I forgot this during the merge window, but the
- patch seems small enough to go in as a fix. The userspace API
- bug that was the reason for disabling it has long been fixed.
-
- Signed-off-by: Johannes Berg <[email protected]>
- commit 110a1c79acda14edc83b7c8dc5af9c7ddd23eb61
- Author: Pontus Fuchs <[email protected]>
- Date: Thu Jan 16 15:00:40 2014 +0100
- nl80211: Reset split_start when netlink skb is exhausted
-
- When the netlink skb is exhausted split_start is left set. In the
- subsequent retry, with a larger buffer, the dump is continued from the
- failing point instead of from the beginning.
-
- This was causing my rt28xx based USB dongle to now show up when
- running "iw list" with an old iw version without split dump support.
-
- Cc: [email protected]
- Fixes: 3713b4e364ef ("nl80211: allow splitting wiphy information in dumps")
- Signed-off-by: Pontus Fuchs <[email protected]>
- [avoid the entire workaround when state->split is set]
- Signed-off-by: Johannes Berg <[email protected]>
- commit b4c31b45ffc7ef110fa9ecc34d7878fe7c5b9da4
- Author: Eliad Peller <[email protected]>
- Date: Sun Jan 12 11:06:37 2014 +0200
- mac80211: move roc cookie assignment earlier
-
- ieee80211_start_roc_work() might add a new roc
- to existing roc, and tell cfg80211 it has already
- started.
-
- However, this might happen before the roc cookie
- was set, resulting in REMAIN_ON_CHANNEL (started)
- event with null cookie. Consequently, it can make
- wpa_supplicant go out of sync.
-
- Fix it by setting the roc cookie earlier.
-
- Cc: [email protected]
- Signed-off-by: Eliad Peller <[email protected]>
- Signed-off-by: Johannes Berg <[email protected]>
- commit cfdc9157bfd7bcf88ab4dae08873a9907eba984c
- Author: Johannes Berg <[email protected]>
- Date: Fri Jan 24 14:06:29 2014 +0100
- nl80211: send event when AP operation is stopped
-
- There are a few cases, e.g. suspend, where an AP interface is
- stopped by the kernel rather than by userspace request, most
- commonly when suspending. To let userspace know about this,
- send the NL80211_CMD_STOP_AP command as an event every time
- an AP interface is stopped. This also happens when userspace
- did in fact request the AP stop, but that's not a problem.
-
- For full-MAC drivers this may need to be extended to also
- cover cases where the device stopped the AP operation for
- some reason, this a bit more complicated because then all
- cfg80211 state also needs to be reset; such API is not part
- of this patch.
-
- Signed-off-by: Johannes Berg <[email protected]>
- commit d5d567eda7704f190379ca852a8f9a4112e3eee3
- Author: Johannes Berg <[email protected]>
- Date: Thu Jan 23 16:20:29 2014 +0100
- mac80211: add length check in ieee80211_is_robust_mgmt_frame()
-
- A few places weren't checking that the frame passed to the
- function actually has enough data even though the function
- clearly documents it must have a payload byte. Make this
- safer by changing the function to take an skb and checking
- the length inside. The old version is preserved for now as
- the rtl* drivers use it and don't have a correct skb.
-
- Signed-off-by: Johannes Berg <[email protected]>
- commit f8f6d212a047fc65c7d3442dfc038f65517236fc
- Author: Johannes Berg <[email protected]>
- Date: Fri Jan 24 10:53:53 2014 +0100
- nl80211: fix scheduled scan RSSI matchset attribute confusion
-
- The scheduled scan matchsets were intended to be a list of filters,
- with the found BSS having to pass at least one of them to be passed
- to the host. When the RSSI attribute was added, however, this was
- broken and currently wpa_supplicant adds that attribute in its own
- matchset; however, it doesn't intend that to mean that anything
- that passes the RSSI filter should be passed to the host, instead
- it wants it to mean that everything needs to also have higher RSSI.
-
- This is semantically problematic because we have a list of filters
- like [ SSID1, SSID2, SSID3, RSSI ] with no real indication which
- one should be OR'ed and which one AND'ed.
-
- To fix this, move the RSSI filter attribute into each matchset. As
- we need to stay backward compatible, treat a matchset with only the
- RSSI attribute as a "default RSSI filter" for all other matchsets,
- but only if there are other matchsets (an RSSI-only matchset by
- itself is still desirable.)
-
- To make driver implementation easier, keep a global min_rssi_thold
- for the entire request as well. The only affected driver is ath6kl.
-
- I found this when I looked into the code after Raja Mani submitted
- a patch fixing the n_match_sets calculation to disregard the RSSI,
- but that patch didn't address the semantic issue.
-
- Reported-by: Raja Mani <[email protected]>
- Acked-by: Luciano Coelho <[email protected]>
- Signed-off-by: Johannes Berg <[email protected]>
- commit de553e8545e65a6dc4e45f43df7e1443d4291922
- Author: Johannes Berg <[email protected]>
- Date: Fri Jan 24 10:17:47 2014 +0100
- nl80211: check nla_parse() return values
-
- If there's a policy, then nla_parse() return values must be
- checked, otherwise the policy is useless and there's nothing
- that ensures the attributes are actually what we expect them
- to be.
-
- Signed-off-by: Johannes Berg <[email protected]>
- commit 652204a0733e9e1c54661d6f9d36e2e1e3b22bb1
- Author: Karl Beldan <[email protected]>
- Date: Thu Jan 23 20:06:34 2014 +0100
- mac80211: send {ADD,DEL}BA on AC_VO like other mgmt frames, as per spec
-
- ATM, {ADD,DEL}BA and BAR frames are sent on the AC matching the TID of
- the BA parameters. In the discussion [1] about this patch, Johannes
- recalled that it fixed some races with the DELBA and indeed this
- behavior was introduced in [2].
- While [2] is right for the BARs, the part queueing the {ADD,DEL}BAs on
- their BA params TID AC violates the spec and is more a workaround for
- some drivers. Helmut expressed some concerns wrt such drivers, in
- particular DELBAs in rt2x00.
-
- ATM, DELBAs are sent after a driver has called (hence "purposely")
- ieee80211_start_tx_ba_cb_irqsafe and Johannes and Emmanuel gave some
- details wrt intentions behind the split of the IEEE80211_AMPDU_TX_STOP_*
- given to the driver ampdu_action supposed to call this function, which
- could prove handy to people trying to do the right thing in faulty
- drivers (if their fw/hw don't get in their way).
-
- [1] http://mid.gmane.org/[email protected]
- [2] Commit: cf6bb79ad828 ("mac80211: Use appropriate TID for sending BAR, ADDBA and DELBA frames")
-
- Signed-off-by: Karl Beldan <[email protected]>
- Cc: Helmut Schaa <[email protected]>
- Cc: Emmanuel Grumbach <[email protected]>
- Signed-off-by: Johannes Berg <[email protected]>
- --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
- +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
- @@ -3256,6 +3256,15 @@ static int ath6kl_cfg80211_sscan_start(s
- struct ath6kl_vif *vif = netdev_priv(dev);
- u16 interval;
- int ret, rssi_thold;
- + int n_match_sets = request->n_match_sets;
- +
- + /*
- + * If there's a matchset w/o an SSID, then assume it's just for
- + * the RSSI (nothing else is currently supported) and ignore it.
- + * The device only supports a global RSSI filter that we set below.
- + */
- + if (n_match_sets == 1 && !request->match_sets[0].ssid.ssid_len)
- + n_match_sets = 0;
-
- if (ar->state != ATH6KL_STATE_ON)
- return -EIO;
- @@ -3268,11 +3277,11 @@ static int ath6kl_cfg80211_sscan_start(s
- ret = ath6kl_set_probed_ssids(ar, vif, request->ssids,
- request->n_ssids,
- request->match_sets,
- - request->n_match_sets);
- + n_match_sets);
- if (ret < 0)
- return ret;
-
- - if (!request->n_match_sets) {
- + if (!n_match_sets) {
- ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
- ALL_BSS_FILTER, 0);
- if (ret < 0)
- @@ -3286,12 +3295,12 @@ static int ath6kl_cfg80211_sscan_start(s
-
- if (test_bit(ATH6KL_FW_CAPABILITY_RSSI_SCAN_THOLD,
- ar->fw_capabilities)) {
- - if (request->rssi_thold <= NL80211_SCAN_RSSI_THOLD_OFF)
- + if (request->min_rssi_thold <= NL80211_SCAN_RSSI_THOLD_OFF)
- rssi_thold = 0;
- - else if (request->rssi_thold < -127)
- + else if (request->min_rssi_thold < -127)
- rssi_thold = -127;
- else
- - rssi_thold = request->rssi_thold;
- + rssi_thold = request->min_rssi_thold;
-
- ret = ath6kl_wmi_set_rssi_filter_cmd(ar->wmi, vif->fw_vif_idx,
- rssi_thold);
- --- a/drivers/net/wireless/ath/ath9k/hw.c
- +++ b/drivers/net/wireless/ath/ath9k/hw.c
- @@ -1316,7 +1316,7 @@ static bool ath9k_hw_set_reset(struct at
- if (AR_SREV_9300_20_OR_LATER(ah))
- udelay(50);
- else if (AR_SREV_9100(ah))
- - udelay(10000);
- + mdelay(10);
- else
- udelay(100);
-
- @@ -2051,9 +2051,8 @@ static bool ath9k_hw_set_power_awake(str
-
- REG_SET_BIT(ah, AR_RTC_FORCE_WAKE,
- AR_RTC_FORCE_WAKE_EN);
- -
- if (AR_SREV_9100(ah))
- - udelay(10000);
- + mdelay(10);
- else
- udelay(50);
-
- --- a/drivers/net/wireless/ath/ath9k/main.c
- +++ b/drivers/net/wireless/ath/ath9k/main.c
- @@ -1866,7 +1866,7 @@ static void ath9k_set_coverage_class(str
-
- static bool ath9k_has_tx_pending(struct ath_softc *sc)
- {
- - int i, npend;
- + int i, npend = 0;
-
- for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
- if (!ATH_TXQ_SETUP(sc, i))
- --- a/drivers/net/wireless/iwlwifi/mvm/scan.c
- +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c
- @@ -595,6 +595,9 @@ static void iwl_scan_offload_build_ssid(
- * config match list.
- */
- for (i = 0; i < req->n_match_sets && i < PROBE_OPTION_MAX; i++) {
- + /* skip empty SSID matchsets */
- + if (!req->match_sets[i].ssid.ssid_len)
- + continue;
- scan->direct_scan[i].id = WLAN_EID_SSID;
- scan->direct_scan[i].len = req->match_sets[i].ssid.ssid_len;
- memcpy(scan->direct_scan[i].ssid, req->match_sets[i].ssid.ssid,
- --- a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
- +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
- @@ -452,7 +452,7 @@ bool rtl88ee_rx_query_desc(struct ieee80
- /* During testing, hdr was NULL */
- return false;
- }
- - if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
- + if ((_ieee80211_is_robust_mgmt_frame(hdr)) &&
- (ieee80211_has_protected(hdr->frame_control)))
- rx_status->flag &= ~RX_FLAG_DECRYPTED;
- else
- --- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
- +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
- @@ -393,7 +393,7 @@ bool rtl92ce_rx_query_desc(struct ieee80
- /* In testing, hdr was NULL here */
- return false;
- }
- - if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
- + if ((_ieee80211_is_robust_mgmt_frame(hdr)) &&
- (ieee80211_has_protected(hdr->frame_control)))
- rx_status->flag &= ~RX_FLAG_DECRYPTED;
- else
- --- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
- +++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
- @@ -310,7 +310,7 @@ bool rtl92se_rx_query_desc(struct ieee80
- /* during testing, hdr was NULL here */
- return false;
- }
- - if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
- + if ((_ieee80211_is_robust_mgmt_frame(hdr)) &&
- (ieee80211_has_protected(hdr->frame_control)))
- rx_status->flag &= ~RX_FLAG_DECRYPTED;
- else
- --- a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c
- +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c
- @@ -334,7 +334,7 @@ bool rtl8723ae_rx_query_desc(struct ieee
- /* during testing, hdr could be NULL here */
- return false;
- }
- - if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
- + if ((_ieee80211_is_robust_mgmt_frame(hdr)) &&
- (ieee80211_has_protected(hdr->frame_control)))
- rx_status->flag &= ~RX_FLAG_DECRYPTED;
- else
- --- a/include/linux/ieee80211.h
- +++ b/include/linux/ieee80211.h
- @@ -2192,10 +2192,10 @@ static inline u8 *ieee80211_get_DA(struc
- }
-
- /**
- - * ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame
- + * _ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame
- * @hdr: the frame (buffer must include at least the first octet of payload)
- */
- -static inline bool ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr)
- +static inline bool _ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr)
- {
- if (ieee80211_is_disassoc(hdr->frame_control) ||
- ieee80211_is_deauth(hdr->frame_control))
- @@ -2224,6 +2224,17 @@ static inline bool ieee80211_is_robust_m
- }
-
- /**
- + * ieee80211_is_robust_mgmt_frame - check if skb contains a robust mgmt frame
- + * @skb: the skb containing the frame, length will be checked
- + */
- +static inline bool ieee80211_is_robust_mgmt_frame(struct sk_buff *skb)
- +{
- + if (skb->len < 25)
- + return false;
- + return _ieee80211_is_robust_mgmt_frame((void *)skb->data);
- +}
- +
- +/**
- * ieee80211_is_public_action - check if frame is a public action frame
- * @hdr: the frame
- * @len: length of the frame
- --- a/include/net/cfg80211.h
- +++ b/include/net/cfg80211.h
- @@ -1395,9 +1395,11 @@ struct cfg80211_scan_request {
- * struct cfg80211_match_set - sets of attributes to match
- *
- * @ssid: SSID to be matched
- + * @rssi_thold: don't report scan results below this threshold (in s32 dBm)
- */
- struct cfg80211_match_set {
- struct cfg80211_ssid ssid;
- + s32 rssi_thold;
- };
-
- /**
- @@ -1420,7 +1422,8 @@ struct cfg80211_match_set {
- * @dev: the interface
- * @scan_start: start time of the scheduled scan
- * @channels: channels to scan
- - * @rssi_thold: don't report scan results below this threshold (in s32 dBm)
- + * @min_rssi_thold: for drivers only supporting a single threshold, this
- + * contains the minimum over all matchsets
- */
- struct cfg80211_sched_scan_request {
- struct cfg80211_ssid *ssids;
- @@ -1433,7 +1436,7 @@ struct cfg80211_sched_scan_request {
- u32 flags;
- struct cfg80211_match_set *match_sets;
- int n_match_sets;
- - s32 rssi_thold;
- + s32 min_rssi_thold;
-
- /* internal */
- struct wiphy *wiphy;
- --- a/include/uapi/linux/nl80211.h
- +++ b/include/uapi/linux/nl80211.h
- @@ -2442,9 +2442,15 @@ enum nl80211_reg_rule_attr {
- * enum nl80211_sched_scan_match_attr - scheduled scan match attributes
- * @__NL80211_SCHED_SCAN_MATCH_ATTR_INVALID: attribute number 0 is reserved
- * @NL80211_SCHED_SCAN_MATCH_ATTR_SSID: SSID to be used for matching,
- - * only report BSS with matching SSID.
- + * only report BSS with matching SSID.
- * @NL80211_SCHED_SCAN_MATCH_ATTR_RSSI: RSSI threshold (in dBm) for reporting a
- - * BSS in scan results. Filtering is turned off if not specified.
- + * BSS in scan results. Filtering is turned off if not specified. Note that
- + * if this attribute is in a match set of its own, then it is treated as
- + * the default value for all matchsets with an SSID, rather than being a
- + * matchset of its own without an RSSI filter. This is due to problems with
- + * how this API was implemented in the past. Also, due to the same problem,
- + * the only way to create a matchset with only an RSSI filter (with this
- + * attribute) is if there's only a single matchset with the RSSI attribute.
- * @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter
- * attribute number currently defined
- * @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use
- --- a/net/mac80211/agg-tx.c
- +++ b/net/mac80211/agg-tx.c
- @@ -107,7 +107,7 @@ static void ieee80211_send_addba_request
- mgmt->u.action.u.addba_req.start_seq_num =
- cpu_to_le16(start_seq_num << 4);
-
- - ieee80211_tx_skb_tid(sdata, skb, tid);
- + ieee80211_tx_skb(sdata, skb);
- }
-
- void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn)
- --- a/net/mac80211/cfg.c
- +++ b/net/mac80211/cfg.c
- @@ -1021,8 +1021,10 @@ static int ieee80211_start_ap(struct wip
- IEEE80211_P2P_OPPPS_ENABLE_BIT;
-
- err = ieee80211_assign_beacon(sdata, ¶ms->beacon);
- - if (err < 0)
- + if (err < 0) {
- + ieee80211_vif_release_channel(sdata);
- return err;
- + }
- changed |= err;
-
- err = drv_start_ap(sdata->local, sdata);
- @@ -1032,6 +1034,7 @@ static int ieee80211_start_ap(struct wip
- if (old)
- kfree_rcu(old, rcu_head);
- RCU_INIT_POINTER(sdata->u.ap.beacon, NULL);
- + ieee80211_vif_release_channel(sdata);
- return err;
- }
-
- @@ -1090,8 +1093,6 @@ static int ieee80211_stop_ap(struct wiph
- kfree(sdata->u.ap.next_beacon);
- sdata->u.ap.next_beacon = NULL;
-
- - cancel_work_sync(&sdata->u.ap.request_smps_work);
- -
- /* turn off carrier for this interface and dependent VLANs */
- list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
- netif_carrier_off(vlan->dev);
- @@ -1103,6 +1104,7 @@ static int ieee80211_stop_ap(struct wiph
- kfree_rcu(old_beacon, rcu_head);
- if (old_probe_resp)
- kfree_rcu(old_probe_resp, rcu_head);
- + sdata->u.ap.driver_smps_mode = IEEE80211_SMPS_OFF;
-
- __sta_info_flush(sdata, true);
- ieee80211_free_keys(sdata, true);
- @@ -2638,6 +2640,24 @@ static int ieee80211_start_roc_work(stru
- INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work);
- INIT_LIST_HEAD(&roc->dependents);
-
- + /*
- + * cookie is either the roc cookie (for normal roc)
- + * or the SKB (for mgmt TX)
- + */
- + if (!txskb) {
- + /* local->mtx protects this */
- + local->roc_cookie_counter++;
- + roc->cookie = local->roc_cookie_counter;
- + /* wow, you wrapped 64 bits ... more likely a bug */
- + if (WARN_ON(roc->cookie == 0)) {
- + roc->cookie = 1;
- + local->roc_cookie_counter++;
- + }
- + *cookie = roc->cookie;
- + } else {
- + *cookie = (unsigned long)txskb;
- + }
- +
- /* if there's one pending or we're scanning, queue this one */
- if (!list_empty(&local->roc_list) ||
- local->scanning || local->radar_detect_enabled)
- @@ -2772,24 +2792,6 @@ static int ieee80211_start_roc_work(stru
- if (!queued)
- list_add_tail(&roc->list, &local->roc_list);
-
- - /*
- - * cookie is either the roc cookie (for normal roc)
- - * or the SKB (for mgmt TX)
- - */
- - if (!txskb) {
- - /* local->mtx protects this */
- - local->roc_cookie_counter++;
- - roc->cookie = local->roc_cookie_counter;
- - /* wow, you wrapped 64 bits ... more likely a bug */
- - if (WARN_ON(roc->cookie == 0)) {
- - roc->cookie = 1;
- - local->roc_cookie_counter++;
- - }
- - *cookie = roc->cookie;
- - } else {
- - *cookie = (unsigned long)txskb;
- - }
- -
- return 0;
- }
-
- --- a/net/mac80211/ht.c
- +++ b/net/mac80211/ht.c
- @@ -375,7 +375,7 @@ void ieee80211_send_delba(struct ieee802
- mgmt->u.action.u.delba.params = cpu_to_le16(params);
- mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code);
-
- - ieee80211_tx_skb_tid(sdata, skb, tid);
- + ieee80211_tx_skb(sdata, skb);
- }
-
- void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,
- @@ -466,7 +466,9 @@ void ieee80211_request_smps_ap_work(stru
- u.ap.request_smps_work);
-
- sdata_lock(sdata);
- - __ieee80211_request_smps_ap(sdata, sdata->u.ap.driver_smps_mode);
- + if (sdata_dereference(sdata->u.ap.beacon, sdata))
- + __ieee80211_request_smps_ap(sdata,
- + sdata->u.ap.driver_smps_mode);
- sdata_unlock(sdata);
- }
-
- --- a/net/mac80211/iface.c
- +++ b/net/mac80211/iface.c
- @@ -770,12 +770,19 @@ static void ieee80211_do_stop(struct iee
-
- ieee80211_roc_purge(local, sdata);
-
- - if (sdata->vif.type == NL80211_IFTYPE_STATION)
- + switch (sdata->vif.type) {
- + case NL80211_IFTYPE_STATION:
- ieee80211_mgd_stop(sdata);
- -
- - if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
- + break;
- + case NL80211_IFTYPE_ADHOC:
- ieee80211_ibss_stop(sdata);
- -
- + break;
- + case NL80211_IFTYPE_AP:
- + cancel_work_sync(&sdata->u.ap.request_smps_work);
- + break;
- + default:
- + break;
- + }
-
- /*
- * Remove all stations associated with this interface.
- --- a/net/mac80211/rx.c
- +++ b/net/mac80211/rx.c
- @@ -599,10 +599,10 @@ static int ieee80211_is_unicast_robust_m
- {
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-
- - if (skb->len < 24 || is_multicast_ether_addr(hdr->addr1))
- + if (is_multicast_ether_addr(hdr->addr1))
- return 0;
-
- - return ieee80211_is_robust_mgmt_frame(hdr);
- + return ieee80211_is_robust_mgmt_frame(skb);
- }
-
-
- @@ -610,10 +610,10 @@ static int ieee80211_is_multicast_robust
- {
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-
- - if (skb->len < 24 || !is_multicast_ether_addr(hdr->addr1))
- + if (!is_multicast_ether_addr(hdr->addr1))
- return 0;
-
- - return ieee80211_is_robust_mgmt_frame(hdr);
- + return ieee80211_is_robust_mgmt_frame(skb);
- }
-
-
- @@ -626,7 +626,7 @@ static int ieee80211_get_mmie_keyidx(str
- if (skb->len < 24 + sizeof(*mmie) || !is_multicast_ether_addr(hdr->da))
- return -1;
-
- - if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) hdr))
- + if (!ieee80211_is_robust_mgmt_frame(skb))
- return -1; /* not a robust management frame */
-
- mmie = (struct ieee80211_mmie *)
- @@ -1845,8 +1845,7 @@ static int ieee80211_drop_unencrypted_mg
- * having configured keys.
- */
- if (unlikely(ieee80211_is_action(fc) && !rx->key &&
- - ieee80211_is_robust_mgmt_frame(
- - (struct ieee80211_hdr *) rx->skb->data)))
- + ieee80211_is_robust_mgmt_frame(rx->skb)))
- return -EACCES;
- }
-
- --- a/net/mac80211/tx.c
- +++ b/net/mac80211/tx.c
- @@ -452,8 +452,7 @@ static int ieee80211_use_mfp(__le16 fc,
- if (sta == NULL || !test_sta_flag(sta, WLAN_STA_MFP))
- return 0;
-
- - if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *)
- - skb->data))
- + if (!ieee80211_is_robust_mgmt_frame(skb))
- return 0;
-
- return 1;
- @@ -567,7 +566,7 @@ ieee80211_tx_h_select_key(struct ieee802
- tx->key = key;
- else if (ieee80211_is_mgmt(hdr->frame_control) &&
- is_multicast_ether_addr(hdr->addr1) &&
- - ieee80211_is_robust_mgmt_frame(hdr) &&
- + ieee80211_is_robust_mgmt_frame(tx->skb) &&
- (key = rcu_dereference(tx->sdata->default_mgmt_key)))
- tx->key = key;
- else if (is_multicast_ether_addr(hdr->addr1) &&
- @@ -582,12 +581,12 @@ ieee80211_tx_h_select_key(struct ieee802
- tx->key = NULL;
- else if (tx->skb->protocol == tx->sdata->control_port_protocol)
- tx->key = NULL;
- - else if (ieee80211_is_robust_mgmt_frame(hdr) &&
- + else if (ieee80211_is_robust_mgmt_frame(tx->skb) &&
- !(ieee80211_is_action(hdr->frame_control) &&
- tx->sta && test_sta_flag(tx->sta, WLAN_STA_MFP)))
- tx->key = NULL;
- else if (ieee80211_is_mgmt(hdr->frame_control) &&
- - !ieee80211_is_robust_mgmt_frame(hdr))
- + !ieee80211_is_robust_mgmt_frame(tx->skb))
- tx->key = NULL;
- else {
- I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted);
- --- a/net/mac80211/wpa.c
- +++ b/net/mac80211/wpa.c
- @@ -499,7 +499,7 @@ ieee80211_crypto_ccmp_decrypt(struct iee
- hdrlen = ieee80211_hdrlen(hdr->frame_control);
-
- if (!ieee80211_is_data(hdr->frame_control) &&
- - !ieee80211_is_robust_mgmt_frame(hdr))
- + !ieee80211_is_robust_mgmt_frame(skb))
- return RX_CONTINUE;
-
- data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN -
- --- a/net/wireless/ap.c
- +++ b/net/wireless/ap.c
- @@ -30,6 +30,7 @@ static int __cfg80211_stop_ap(struct cfg
- wdev->channel = NULL;
- wdev->ssid_len = 0;
- rdev_set_qos_map(rdev, dev, NULL);
- + nl80211_send_ap_stopped(wdev);
- }
-
- return err;
- --- a/net/wireless/core.c
- +++ b/net/wireless/core.c
- @@ -203,8 +203,11 @@ void cfg80211_stop_p2p_device(struct cfg
-
- rdev->opencount--;
-
- - WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev &&
- - !rdev->scan_req->notified);
- + if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
- + if (WARN_ON(!rdev->scan_req->notified))
- + rdev->scan_req->aborted = true;
- + ___cfg80211_scan_done(rdev, false);
- + }
- }
-
- static int cfg80211_rfkill_set_block(void *data, bool blocked)
- @@ -447,9 +450,6 @@ int wiphy_register(struct wiphy *wiphy)
- int i;
- u16 ifmodes = wiphy->interface_modes;
-
- - /* support for 5/10 MHz is broken due to nl80211 API mess - disable */
- - wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_5_10_MHZ;
- -
- /*
- * There are major locking problems in nl80211/mac80211 for CSA,
- * disable for all drivers until this has been reworked.
- @@ -875,8 +875,11 @@ static int cfg80211_netdev_notifier_call
- break;
- case NETDEV_DOWN:
- cfg80211_update_iface_num(rdev, wdev->iftype, -1);
- - WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev &&
- - !rdev->scan_req->notified);
- + if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
- + if (WARN_ON(!rdev->scan_req->notified))
- + rdev->scan_req->aborted = true;
- + ___cfg80211_scan_done(rdev, false);
- + }
-
- if (WARN_ON(rdev->sched_scan_req &&
- rdev->sched_scan_req->dev == wdev->netdev)) {
- --- a/net/wireless/core.h
- +++ b/net/wireless/core.h
- @@ -62,6 +62,7 @@ struct cfg80211_registered_device {
- struct rb_root bss_tree;
- u32 bss_generation;
- struct cfg80211_scan_request *scan_req; /* protected by RTNL */
- + struct sk_buff *scan_msg;
- struct cfg80211_sched_scan_request *sched_scan_req;
- unsigned long suspend_at;
- struct work_struct scan_done_wk;
- @@ -361,7 +362,8 @@ int cfg80211_validate_key_settings(struc
- struct key_params *params, int key_idx,
- bool pairwise, const u8 *mac_addr);
- void __cfg80211_scan_done(struct work_struct *wk);
- -void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev);
- +void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
- + bool send_message);
- void __cfg80211_sched_scan_results(struct work_struct *wk);
- int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
- bool driver_initiated);
- --- a/net/wireless/nl80211.c
- +++ b/net/wireless/nl80211.c
- @@ -1723,9 +1723,10 @@ static int nl80211_dump_wiphy(struct sk_
- * We can then retry with the larger buffer.
- */
- if ((ret == -ENOBUFS || ret == -EMSGSIZE) &&
- - !skb->len &&
- + !skb->len && !state->split &&
- cb->min_dump_alloc < 4096) {
- cb->min_dump_alloc = 4096;
- + state->split_start = 0;
- rtnl_unlock();
- return 1;
- }
- @@ -2047,10 +2048,12 @@ static int nl80211_set_wiphy(struct sk_b
- nla_for_each_nested(nl_txq_params,
- info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
- rem_txq_params) {
- - nla_parse(tb, NL80211_TXQ_ATTR_MAX,
- - nla_data(nl_txq_params),
- - nla_len(nl_txq_params),
- - txq_params_policy);
- + result = nla_parse(tb, NL80211_TXQ_ATTR_MAX,
- + nla_data(nl_txq_params),
- + nla_len(nl_txq_params),
- + txq_params_policy);
- + if (result)
- + goto bad_res;
- result = parse_txq_params(tb, &txq_params);
- if (result)
- goto bad_res;
- @@ -5210,9 +5213,11 @@ static int nl80211_set_reg(struct sk_buf
-
- nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
- rem_reg_rules) {
- - nla_parse(tb, NL80211_REG_RULE_ATTR_MAX,
- - nla_data(nl_reg_rule), nla_len(nl_reg_rule),
- - reg_rule_policy);
- + r = nla_parse(tb, NL80211_REG_RULE_ATTR_MAX,
- + nla_data(nl_reg_rule), nla_len(nl_reg_rule),
- + reg_rule_policy);
- + if (r)
- + goto bad_reg;
- r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]);
- if (r)
- goto bad_reg;
- @@ -5277,7 +5282,7 @@ static int nl80211_trigger_scan(struct s
- if (!rdev->ops->scan)
- return -EOPNOTSUPP;
-
- - if (rdev->scan_req) {
- + if (rdev->scan_req || rdev->scan_msg) {
- err = -EBUSY;
- goto unlock;
- }
- @@ -5475,6 +5480,7 @@ static int nl80211_start_sched_scan(stru
- enum ieee80211_band band;
- size_t ie_len;
- struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1];
- + s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF;
-
- if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
- !rdev->ops->sched_scan_start)
- @@ -5509,11 +5515,40 @@ static int nl80211_start_sched_scan(stru
- if (n_ssids > wiphy->max_sched_scan_ssids)
- return -EINVAL;
-
- - if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH])
- + /*
- + * First, count the number of 'real' matchsets. Due to an issue with
- + * the old implementation, matchsets containing only the RSSI attribute
- + * (NL80211_SCHED_SCAN_MATCH_ATTR_RSSI) are considered as the 'default'
- + * RSSI for all matchsets, rather than their own matchset for reporting
- + * all APs with a strong RSSI. This is needed to be compatible with
- + * older userspace that treated a matchset with only the RSSI as the
- + * global RSSI for all other matchsets - if there are other matchsets.
- + */
- + if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
- nla_for_each_nested(attr,
- info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
- - tmp)
- - n_match_sets++;
- + tmp) {
- + struct nlattr *rssi;
- +
- + err = nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
- + nla_data(attr), nla_len(attr),
- + nl80211_match_policy);
- + if (err)
- + return err;
- + /* add other standalone attributes here */
- + if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID]) {
- + n_match_sets++;
- + continue;
- + }
- + rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
- + if (rssi)
- + default_match_rssi = nla_get_s32(rssi);
- + }
- + }
- +
- + /* However, if there's no other matchset, add the RSSI one */
- + if (!n_match_sets && default_match_rssi != NL80211_SCAN_RSSI_THOLD_OFF)
- + n_match_sets = 1;
-
- if (n_match_sets > wiphy->max_match_sets)
- return -EINVAL;
- @@ -5634,11 +5669,22 @@ static int nl80211_start_sched_scan(stru
- tmp) {
- struct nlattr *ssid, *rssi;
-
- - nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
- - nla_data(attr), nla_len(attr),
- - nl80211_match_policy);
- + err = nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
- + nla_data(attr), nla_len(attr),
- + nl80211_match_policy);
- + if (err)
- + goto out_free;
- ssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID];
- if (ssid) {
- + if (WARN_ON(i >= n_match_sets)) {
- + /* this indicates a programming error,
- + * the loop above should have verified
- + * things properly
- + */
- + err = -EINVAL;
- + goto out_free;
- + }
- +
- if (nla_len(ssid) > IEEE80211_MAX_SSID_LEN) {
- err = -EINVAL;
- goto out_free;
- @@ -5647,15 +5693,28 @@ static int nl80211_start_sched_scan(stru
- nla_data(ssid), nla_len(ssid));
- request->match_sets[i].ssid.ssid_len =
- nla_len(ssid);
- + /* special attribute - old implemenation w/a */
- + request->match_sets[i].rssi_thold =
- + default_match_rssi;
- + rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
- + if (rssi)
- + request->match_sets[i].rssi_thold =
- + nla_get_s32(rssi);
- }
- - rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
- - if (rssi)
- - request->rssi_thold = nla_get_u32(rssi);
- - else
- - request->rssi_thold =
- - NL80211_SCAN_RSSI_THOLD_OFF;
- i++;
- }
- +
- + /* there was no other matchset, so the RSSI one is alone */
- + if (i == 0)
- + request->match_sets[0].rssi_thold = default_match_rssi;
- +
- + request->min_rssi_thold = INT_MAX;
- + for (i = 0; i < n_match_sets; i++)
- + request->min_rssi_thold =
- + min(request->match_sets[i].rssi_thold,
- + request->min_rssi_thold);
- + } else {
- + request->min_rssi_thold = NL80211_SCAN_RSSI_THOLD_OFF;
- }
-
- if (info->attrs[NL80211_ATTR_IE]) {
- @@ -7502,16 +7561,19 @@ static int nl80211_set_tx_bitrate_mask(s
- * directly to the enum ieee80211_band values used in cfg80211.
- */
- BUILD_BUG_ON(NL80211_MAX_SUPP_HT_RATES > IEEE80211_HT_MCS_MASK_LEN * 8);
- - nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem)
- - {
- + nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem) {
- enum ieee80211_band band = nla_type(tx_rates);
- + int err;
- +
- if (band < 0 || band >= IEEE80211_NUM_BANDS)
- return -EINVAL;
- sband = rdev->wiphy.bands[band];
- if (sband == NULL)
- return -EINVAL;
- - nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates),
- - nla_len(tx_rates), nl80211_txattr_policy);
- + err = nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates),
- + nla_len(tx_rates), nl80211_txattr_policy);
- + if (err)
- + return err;
- if (tb[NL80211_TXRATE_LEGACY]) {
- mask.control[band].legacy = rateset_to_mask(
- sband,
- @@ -10054,40 +10116,31 @@ void nl80211_send_scan_start(struct cfg8
- NL80211_MCGRP_SCAN, GFP_KERNEL);
- }
-
- -void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
- - struct wireless_dev *wdev)
- +struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev,
- + struct wireless_dev *wdev, bool aborted)
- {
- struct sk_buff *msg;
-
- msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
- if (!msg)
- - return;
- + return NULL;
-
- if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0,
- - NL80211_CMD_NEW_SCAN_RESULTS) < 0) {
- + aborted ? NL80211_CMD_SCAN_ABORTED :
- + NL80211_CMD_NEW_SCAN_RESULTS) < 0) {
- nlmsg_free(msg);
- - return;
- + return NULL;
- }
-
- - genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- - NL80211_MCGRP_SCAN, GFP_KERNEL);
- + return msg;
- }
-
- -void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
- - struct wireless_dev *wdev)
- +void nl80211_send_scan_result(struct cfg80211_registered_device *rdev,
- + struct sk_buff *msg)
- {
- - struct sk_buff *msg;
- -
- - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
- if (!msg)
- return;
-
- - if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0,
- - NL80211_CMD_SCAN_ABORTED) < 0) {
- - nlmsg_free(msg);
- - return;
- - }
- -
- genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- NL80211_MCGRP_SCAN, GFP_KERNEL);
- }
- @@ -11673,6 +11726,35 @@ void cfg80211_crit_proto_stopped(struct
- }
- EXPORT_SYMBOL(cfg80211_crit_proto_stopped);
-
- +void nl80211_send_ap_stopped(struct wireless_dev *wdev)
- +{
- + struct wiphy *wiphy = wdev->wiphy;
- + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
- + struct sk_buff *msg;
- + void *hdr;
- +
- + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
- + if (!msg)
- + return;
- +
- + hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_STOP_AP);
- + if (!hdr)
- + goto out;
- +
- + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
- + nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex) ||
- + nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
- + goto out;
- +
- + genlmsg_end(msg, hdr);
- +
- + genlmsg_multicast_netns(&nl80211_fam, wiphy_net(wiphy), msg, 0,
- + NL80211_MCGRP_MLME, GFP_KERNEL);
- + return;
- + out:
- + nlmsg_free(msg);
- +}
- +
- /* initialisation/exit functions */
-
- int nl80211_init(void)
- --- a/net/wireless/nl80211.h
- +++ b/net/wireless/nl80211.h
- @@ -8,10 +8,10 @@ void nl80211_exit(void);
- void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev);
- void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
- struct wireless_dev *wdev);
- -void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
- - struct wireless_dev *wdev);
- -void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
- - struct wireless_dev *wdev);
- +struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev,
- + struct wireless_dev *wdev, bool aborted);
- +void nl80211_send_scan_result(struct cfg80211_registered_device *rdev,
- + struct sk_buff *msg);
- void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev,
- struct net_device *netdev, u32 cmd);
- void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev,
- @@ -74,6 +74,8 @@ nl80211_radar_notify(struct cfg80211_reg
- enum nl80211_radar_event event,
- struct net_device *netdev, gfp_t gfp);
-
- +void nl80211_send_ap_stopped(struct wireless_dev *wdev);
- +
- void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev);
-
- #endif /* __NET_WIRELESS_NL80211_H */
- --- a/net/wireless/scan.c
- +++ b/net/wireless/scan.c
- @@ -161,18 +161,25 @@ static void __cfg80211_bss_expire(struct
- dev->bss_generation++;
- }
-
- -void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev)
- +void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
- + bool send_message)
- {
- struct cfg80211_scan_request *request;
- struct wireless_dev *wdev;
- + struct sk_buff *msg;
- #ifdef CPTCFG_CFG80211_WEXT
- union iwreq_data wrqu;
- #endif
-
- ASSERT_RTNL();
-
- - request = rdev->scan_req;
- + if (rdev->scan_msg) {
- + nl80211_send_scan_result(rdev, rdev->scan_msg);
- + rdev->scan_msg = NULL;
- + return;
- + }
-
- + request = rdev->scan_req;
- if (!request)
- return;
-
- @@ -186,18 +193,16 @@ void ___cfg80211_scan_done(struct cfg802
- if (wdev->netdev)
- cfg80211_sme_scan_done(wdev->netdev);
-
- - if (request->aborted) {
- - nl80211_send_scan_aborted(rdev, wdev);
- - } else {
- - if (request->flags & NL80211_SCAN_FLAG_FLUSH) {
- - /* flush entries from previous scans */
- - spin_lock_bh(&rdev->bss_lock);
- - __cfg80211_bss_expire(rdev, request->scan_start);
- - spin_unlock_bh(&rdev->bss_lock);
- - }
- - nl80211_send_scan_done(rdev, wdev);
- + if (!request->aborted &&
- + request->flags & NL80211_SCAN_FLAG_FLUSH) {
- + /* flush entries from previous scans */
- + spin_lock_bh(&rdev->bss_lock);
- + __cfg80211_bss_expire(rdev, request->scan_start);
- + spin_unlock_bh(&rdev->bss_lock);
- }
-
- + msg = nl80211_build_scan_msg(rdev, wdev, request->aborted);
- +
- #ifdef CPTCFG_CFG80211_WEXT
- if (wdev->netdev && !request->aborted) {
- memset(&wrqu, 0, sizeof(wrqu));
- @@ -211,6 +216,11 @@ void ___cfg80211_scan_done(struct cfg802
-
- rdev->scan_req = NULL;
- kfree(request);
- +
- + if (!send_message)
- + rdev->scan_msg = msg;
- + else
- + nl80211_send_scan_result(rdev, msg);
- }
-
- void __cfg80211_scan_done(struct work_struct *wk)
- @@ -221,7 +231,7 @@ void __cfg80211_scan_done(struct work_st
- scan_done_wk);
-
- rtnl_lock();
- - ___cfg80211_scan_done(rdev);
- + ___cfg80211_scan_done(rdev, true);
- rtnl_unlock();
- }
-
- @@ -1079,7 +1089,7 @@ int cfg80211_wext_siwscan(struct net_dev
- if (IS_ERR(rdev))
- return PTR_ERR(rdev);
-
- - if (rdev->scan_req) {
- + if (rdev->scan_req || rdev->scan_msg) {
- err = -EBUSY;
- goto out;
- }
- @@ -1481,7 +1491,7 @@ int cfg80211_wext_giwscan(struct net_dev
- if (IS_ERR(rdev))
- return PTR_ERR(rdev);
-
- - if (rdev->scan_req)
- + if (rdev->scan_req || rdev->scan_msg)
- return -EAGAIN;
-
- res = ieee80211_scan_results(rdev, info, extra, data->length);
- --- a/net/wireless/sme.c
- +++ b/net/wireless/sme.c
- @@ -67,7 +67,7 @@ static int cfg80211_conn_scan(struct wir
- ASSERT_RDEV_LOCK(rdev);
- ASSERT_WDEV_LOCK(wdev);
-
- - if (rdev->scan_req)
- + if (rdev->scan_req || rdev->scan_msg)
- return -EBUSY;
-
- if (wdev->conn->params.channel)
|