d78f97f200301f91bde877dff1a1ad1c1f8c8bb7
[openwrt.git] / package / kernel / mac80211 / patches / 300-pending_work.patch
1 commit de5f242e0c10e841017e37eb8c38974a642dbca8
2 Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
3 Date:   Tue Jan 28 06:21:59 2014 +0530
4
5     ath9k: Fix build error on ARM
6     
7     Use mdelay instead of udelay to fix this error:
8     
9     ERROR: "__bad_udelay" [drivers/net/wireless/ath/ath9k/ath9k_hw.ko] undefined!
10     make[1]: *** [__modpost] Error 1
11     make: *** [modules] Error 2
12     
13     Reported-by: Josh Boyer <jwboyer@fedoraproject.org>
14     Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
15
16 commit 8e3ea7a51dfc61810fcefd947f6edcf61125252a
17 Author: Geert Uytterhoeven <geert@linux-m68k.org>
18 Date:   Sun Jan 26 11:53:21 2014 +0100
19
20     ath9k: Fix uninitialized variable in ath9k_has_tx_pending()
21     
22     drivers/net/wireless/ath/ath9k/main.c: In function ‘ath9k_has_tx_pending’:
23     drivers/net/wireless/ath/ath9k/main.c:1869: warning: ‘npend’ may be used uninitialized in this function
24     
25     Introduced by commit 10e2318103f5941aa70c318afe34bc41f1b98529 ("ath9k:
26     optimize ath9k_flush").
27     
28     Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
29
30 commit a4a634a6937ebdd827fa58e8fcdb8ca49a3769f6
31 Author: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
32 Date:   Mon Jan 27 11:07:42 2014 +0200
33
34     mac80211: release the channel in error path in start_ap
35     
36     When the driver cannot start the AP or when the assignement
37     of the beacon goes wrong, we need to unassign the vif.
38     
39     Cc: stable@vger.kernel.org
40     Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
41     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
42
43 commit dfb6889a75c601aedb7450b7e606668e77da6679
44 Author: Johannes Berg <johannes.berg@intel.com>
45 Date:   Wed Jan 22 11:14:19 2014 +0200
46
47     cfg80211: send scan results from work queue
48     
49     Due to the previous commit, when a scan finishes, it is in theory
50     possible to hit the following sequence:
51      1. interface starts being removed
52      2. scan is cancelled by driver and cfg80211 is notified
53      3. scan done work is scheduled
54      4. interface is removed completely, rdev->scan_req is freed,
55         event sent to userspace but scan done work remains pending
56      5. new scan is requested on another virtual interface
57      6. scan done work runs, freeing the still-running scan
58     
59     To fix this situation, hang on to the scan done message and block
60     new scans while that is the case, and only send the message from
61     the work function, regardless of whether the scan_req is already
62     freed from interface removal. This makes step 5 above impossible
63     and changes step 6 to be
64      5. scan done work runs, sending the scan done message
65     
66     As this can't work for wext, so we send the message immediately,
67     but this shouldn't be an issue since we still return -EBUSY.
68     
69     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
70
71 commit 45b7ab41fc08627d9a8428cb413d5d84662a9707
72 Author: Johannes Berg <johannes.berg@intel.com>
73 Date:   Wed Jan 22 11:14:18 2014 +0200
74
75     cfg80211: fix scan done race
76     
77     When an interface/wdev is removed, any ongoing scan should be
78     cancelled by the driver. This will make it call cfg80211, which
79     only queues a work struct. If interface/wdev removal is quick
80     enough, this can leave the scan request pending and processed
81     only after the interface is gone, causing a use-after-free.
82     
83     Fix this by making sure the scan request is not pending after
84     the interface is destroyed. We can't flush or cancel the work
85     item due to locking concerns, but when it'll run it shouldn't
86     find anything to do. This leaves a potential issue, if a new
87     scan gets requested before the work runs, it prematurely stops
88     the running scan, potentially causing another crash. I'll fix
89     that in the next patch.
90     
91     This was particularly observed with P2P_DEVICE wdevs, likely
92     because freeing them is quicker than freeing netdevs.
93     
94     Reported-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
95     Fixes: 4a58e7c38443 ("cfg80211: don't "leak" uncompleted scans")
96     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
97
98 commit ae04fa489ab31b5a10d3cc8399f52761175d4321
99 Author: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
100 Date:   Thu Jan 23 14:28:16 2014 +0200
101
102     mac80211: avoid deadlock revealed by lockdep
103     
104     sdata->u.ap.request_smps_work can’t be flushed synchronously
105     under wdev_lock(wdev) since ieee80211_request_smps_ap_work
106     itself locks the same lock.
107     While at it, reset the driver_smps_mode when the ap is
108     stopped to its default: OFF.
109     
110     This solves:
111     
112     ======================================================
113     [ INFO: possible circular locking dependency detected ]
114     3.12.0-ipeer+ #2 Tainted: G           O
115     -------------------------------------------------------
116     rmmod/2867 is trying to acquire lock:
117       ((&sdata->u.ap.request_smps_work)){+.+...}, at: [<c105b8d0>] flush_work+0x0/0x90
118     
119     but task is already holding lock:
120       (&wdev->mtx){+.+.+.}, at: [<f9b32626>] cfg80211_stop_ap+0x26/0x230 [cfg80211]
121     
122     which lock already depends on the new lock.
123     
124     the existing dependency chain (in reverse order) is:
125     
126     -> #1 (&wdev->mtx){+.+.+.}:
127             [<c10aefa9>] lock_acquire+0x79/0xe0
128             [<c1607a1a>] mutex_lock_nested+0x4a/0x360
129             [<fb06288b>] ieee80211_request_smps_ap_work+0x2b/0x50 [mac80211]
130             [<c105cdd8>] process_one_work+0x198/0x450
131             [<c105d469>] worker_thread+0xf9/0x320
132             [<c10669ff>] kthread+0x9f/0xb0
133             [<c1613397>] ret_from_kernel_thread+0x1b/0x28
134     
135     -> #0 ((&sdata->u.ap.request_smps_work)){+.+...}:
136             [<c10ae9df>] __lock_acquire+0x183f/0x1910
137             [<c10aefa9>] lock_acquire+0x79/0xe0
138             [<c105b917>] flush_work+0x47/0x90
139             [<c105d867>] __cancel_work_timer+0x67/0xe0
140             [<c105d90f>] cancel_work_sync+0xf/0x20
141             [<fb0765cc>] ieee80211_stop_ap+0x8c/0x340 [mac80211]
142             [<f9b3268c>] cfg80211_stop_ap+0x8c/0x230 [cfg80211]
143             [<f9b0d8f9>] cfg80211_leave+0x79/0x100 [cfg80211]
144             [<f9b0da72>] cfg80211_netdev_notifier_call+0xf2/0x4f0 [cfg80211]
145             [<c160f2c9>] notifier_call_chain+0x59/0x130
146             [<c106c6de>] __raw_notifier_call_chain+0x1e/0x30
147             [<c106c70f>] raw_notifier_call_chain+0x1f/0x30
148             [<c14f8213>] call_netdevice_notifiers_info+0x33/0x70
149             [<c14f8263>] call_netdevice_notifiers+0x13/0x20
150             [<c14f82a4>] __dev_close_many+0x34/0xb0
151             [<c14f83fe>] dev_close_many+0x6e/0xc0
152             [<c14f9c77>] rollback_registered_many+0xa7/0x1f0
153             [<c14f9dd4>] unregister_netdevice_many+0x14/0x60
154             [<fb06f4d9>] ieee80211_remove_interfaces+0xe9/0x170 [mac80211]
155             [<fb055116>] ieee80211_unregister_hw+0x56/0x110 [mac80211]
156             [<fa3e9396>] iwl_op_mode_mvm_stop+0x26/0xe0 [iwlmvm]
157             [<f9b9d8ca>] _iwl_op_mode_stop+0x3a/0x70 [iwlwifi]
158             [<f9b9d96f>] iwl_opmode_deregister+0x6f/0x90 [iwlwifi]
159             [<fa405179>] __exit_compat+0xd/0x19 [iwlmvm]
160             [<c10b8bf9>] SyS_delete_module+0x179/0x2b0
161             [<c1613421>] sysenter_do_call+0x12/0x32
162     
163     Fixes: 687da132234f ("mac80211: implement SMPS for AP")
164     Cc: <stable@vger.kernel.org> [3.13]
165     Reported-by: Ilan Peer <ilan.peer@intel.com>
166     Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
167     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
168
169 commit 178b205e96217164fd7c30113464250d0b6f5eca
170 Author: Johannes Berg <johannes.berg@intel.com>
171 Date:   Thu Jan 23 16:32:29 2014 +0100
172
173     cfg80211: re-enable 5/10 MHz support
174     
175     Unfortunately I forgot this during the merge window, but the
176     patch seems small enough to go in as a fix. The userspace API
177     bug that was the reason for disabling it has long been fixed.
178     
179     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
180
181 commit 110a1c79acda14edc83b7c8dc5af9c7ddd23eb61
182 Author: Pontus Fuchs <pontus.fuchs@gmail.com>
183 Date:   Thu Jan 16 15:00:40 2014 +0100
184
185     nl80211: Reset split_start when netlink skb is exhausted
186     
187     When the netlink skb is exhausted split_start is left set. In the
188     subsequent retry, with a larger buffer, the dump is continued from the
189     failing point instead of from the beginning.
190     
191     This was causing my rt28xx based USB dongle to now show up when
192     running "iw list" with an old iw version without split dump support.
193     
194     Cc: stable@vger.kernel.org
195     Fixes: 3713b4e364ef ("nl80211: allow splitting wiphy information in dumps")
196     Signed-off-by: Pontus Fuchs <pontus.fuchs@gmail.com>
197     [avoid the entire workaround when state->split is set]
198     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
199
200 commit b4c31b45ffc7ef110fa9ecc34d7878fe7c5b9da4
201 Author: Eliad Peller <eliad@wizery.com>
202 Date:   Sun Jan 12 11:06:37 2014 +0200
203
204     mac80211: move roc cookie assignment earlier
205     
206     ieee80211_start_roc_work() might add a new roc
207     to existing roc, and tell cfg80211 it has already
208     started.
209     
210     However, this might happen before the roc cookie
211     was set, resulting in REMAIN_ON_CHANNEL (started)
212     event with null cookie. Consequently, it can make
213     wpa_supplicant go out of sync.
214     
215     Fix it by setting the roc cookie earlier.
216     
217     Cc: stable@vger.kernel.org
218     Signed-off-by: Eliad Peller <eliad@wizery.com>
219     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
220
221 commit cfdc9157bfd7bcf88ab4dae08873a9907eba984c
222 Author: Johannes Berg <johannes.berg@intel.com>
223 Date:   Fri Jan 24 14:06:29 2014 +0100
224
225     nl80211: send event when AP operation is stopped
226     
227     There are a few cases, e.g. suspend, where an AP interface is
228     stopped by the kernel rather than by userspace request, most
229     commonly when suspending. To let userspace know about this,
230     send the NL80211_CMD_STOP_AP command as an event every time
231     an AP interface is stopped. This also happens when userspace
232     did in fact request the AP stop, but that's not a problem.
233     
234     For full-MAC drivers this may need to be extended to also
235     cover cases where the device stopped the AP operation for
236     some reason, this a bit more complicated because then all
237     cfg80211 state also needs to be reset; such API is not part
238     of this patch.
239     
240     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
241
242 commit d5d567eda7704f190379ca852a8f9a4112e3eee3
243 Author: Johannes Berg <johannes.berg@intel.com>
244 Date:   Thu Jan 23 16:20:29 2014 +0100
245
246     mac80211: add length check in ieee80211_is_robust_mgmt_frame()
247     
248     A few places weren't checking that the frame passed to the
249     function actually has enough data even though the function
250     clearly documents it must have a payload byte. Make this
251     safer by changing the function to take an skb and checking
252     the length inside. The old version is preserved for now as
253     the rtl* drivers use it and don't have a correct skb.
254     
255     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
256
257 commit f8f6d212a047fc65c7d3442dfc038f65517236fc
258 Author: Johannes Berg <johannes.berg@intel.com>
259 Date:   Fri Jan 24 10:53:53 2014 +0100
260
261     nl80211: fix scheduled scan RSSI matchset attribute confusion
262     
263     The scheduled scan matchsets were intended to be a list of filters,
264     with the found BSS having to pass at least one of them to be passed
265     to the host. When the RSSI attribute was added, however, this was
266     broken and currently wpa_supplicant adds that attribute in its own
267     matchset; however, it doesn't intend that to mean that anything
268     that passes the RSSI filter should be passed to the host, instead
269     it wants it to mean that everything needs to also have higher RSSI.
270     
271     This is semantically problematic because we have a list of filters
272     like [ SSID1, SSID2, SSID3, RSSI ] with no real indication which
273     one should be OR'ed and which one AND'ed.
274     
275     To fix this, move the RSSI filter attribute into each matchset. As
276     we need to stay backward compatible, treat a matchset with only the
277     RSSI attribute as a "default RSSI filter" for all other matchsets,
278     but only if there are other matchsets (an RSSI-only matchset by
279     itself is still desirable.)
280     
281     To make driver implementation easier, keep a global min_rssi_thold
282     for the entire request as well. The only affected driver is ath6kl.
283     
284     I found this when I looked into the code after Raja Mani submitted
285     a patch fixing the n_match_sets calculation to disregard the RSSI,
286     but that patch didn't address the semantic issue.
287     
288     Reported-by: Raja Mani <rmani@qti.qualcomm.com>
289     Acked-by: Luciano Coelho <luciano.coelho@intel.com>
290     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
291
292 commit de553e8545e65a6dc4e45f43df7e1443d4291922
293 Author: Johannes Berg <johannes.berg@intel.com>
294 Date:   Fri Jan 24 10:17:47 2014 +0100
295
296     nl80211: check nla_parse() return values
297     
298     If there's a policy, then nla_parse() return values must be
299     checked, otherwise the policy is useless and there's nothing
300     that ensures the attributes are actually what we expect them
301     to be.
302     
303     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
304
305 commit 652204a0733e9e1c54661d6f9d36e2e1e3b22bb1
306 Author: Karl Beldan <karl.beldan@rivierawaves.com>
307 Date:   Thu Jan 23 20:06:34 2014 +0100
308
309     mac80211: send {ADD,DEL}BA on AC_VO like other mgmt frames, as per spec
310     
311     ATM, {ADD,DEL}BA and BAR frames are sent on the AC matching the TID of
312     the BA parameters. In the discussion [1] about this patch, Johannes
313     recalled that it fixed some races with the DELBA and indeed this
314     behavior was introduced in [2].
315     While [2] is right for the BARs, the part queueing the {ADD,DEL}BAs on
316     their BA params TID AC violates the spec and is more a workaround for
317     some drivers. Helmut expressed some concerns wrt such drivers, in
318     particular DELBAs in rt2x00.
319     
320     ATM, DELBAs are sent after a driver has called (hence "purposely")
321     ieee80211_start_tx_ba_cb_irqsafe and Johannes and Emmanuel gave some
322     details wrt intentions behind the split of the IEEE80211_AMPDU_TX_STOP_*
323     given to the driver ampdu_action supposed to call this function, which
324     could prove handy to people trying to do the right thing in faulty
325     drivers (if their fw/hw don't get in their way).
326     
327     [1] http://mid.gmane.org/1390391564-18481-1-git-send-email-karl.beldan@gmail.com
328     [2] Commit: cf6bb79ad828 ("mac80211: Use appropriate TID for sending BAR, ADDBA and DELBA frames")
329     
330     Signed-off-by: Karl Beldan <karl.beldan@rivierawaves.com>
331     Cc: Helmut Schaa <helmut.schaa@googlemail.com>
332     Cc: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
333     Signed-off-by: Johannes Berg <johannes.berg@intel.com>
334 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
335 +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
336 @@ -3256,6 +3256,15 @@ static int ath6kl_cfg80211_sscan_start(s
337         struct ath6kl_vif *vif = netdev_priv(dev);
338         u16 interval;
339         int ret, rssi_thold;
340 +       int n_match_sets = request->n_match_sets;
341 +
342 +       /*
343 +        * If there's a matchset w/o an SSID, then assume it's just for
344 +        * the RSSI (nothing else is currently supported) and ignore it.
345 +        * The device only supports a global RSSI filter that we set below.
346 +        */
347 +       if (n_match_sets == 1 && !request->match_sets[0].ssid.ssid_len)
348 +               n_match_sets = 0;
349  
350         if (ar->state != ATH6KL_STATE_ON)
351                 return -EIO;
352 @@ -3268,11 +3277,11 @@ static int ath6kl_cfg80211_sscan_start(s
353         ret = ath6kl_set_probed_ssids(ar, vif, request->ssids,
354                                       request->n_ssids,
355                                       request->match_sets,
356 -                                     request->n_match_sets);
357 +                                     n_match_sets);
358         if (ret < 0)
359                 return ret;
360  
361 -       if (!request->n_match_sets) {
362 +       if (!n_match_sets) {
363                 ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
364                                                ALL_BSS_FILTER, 0);
365                 if (ret < 0)
366 @@ -3286,12 +3295,12 @@ static int ath6kl_cfg80211_sscan_start(s
367  
368         if (test_bit(ATH6KL_FW_CAPABILITY_RSSI_SCAN_THOLD,
369                      ar->fw_capabilities)) {
370 -               if (request->rssi_thold <= NL80211_SCAN_RSSI_THOLD_OFF)
371 +               if (request->min_rssi_thold <= NL80211_SCAN_RSSI_THOLD_OFF)
372                         rssi_thold = 0;
373 -               else if (request->rssi_thold < -127)
374 +               else if (request->min_rssi_thold < -127)
375                         rssi_thold = -127;
376                 else
377 -                       rssi_thold = request->rssi_thold;
378 +                       rssi_thold = request->min_rssi_thold;
379  
380                 ret = ath6kl_wmi_set_rssi_filter_cmd(ar->wmi, vif->fw_vif_idx,
381                                                      rssi_thold);
382 --- a/drivers/net/wireless/ath/ath9k/hw.c
383 +++ b/drivers/net/wireless/ath/ath9k/hw.c
384 @@ -1316,7 +1316,7 @@ static bool ath9k_hw_set_reset(struct at
385         if (AR_SREV_9300_20_OR_LATER(ah))
386                 udelay(50);
387         else if (AR_SREV_9100(ah))
388 -               udelay(10000);
389 +               mdelay(10);
390         else
391                 udelay(100);
392  
393 @@ -2051,9 +2051,8 @@ static bool ath9k_hw_set_power_awake(str
394  
395         REG_SET_BIT(ah, AR_RTC_FORCE_WAKE,
396                     AR_RTC_FORCE_WAKE_EN);
397 -
398         if (AR_SREV_9100(ah))
399 -               udelay(10000);
400 +               mdelay(10);
401         else
402                 udelay(50);
403  
404 --- a/drivers/net/wireless/ath/ath9k/main.c
405 +++ b/drivers/net/wireless/ath/ath9k/main.c
406 @@ -1866,7 +1866,7 @@ static void ath9k_set_coverage_class(str
407  
408  static bool ath9k_has_tx_pending(struct ath_softc *sc)
409  {
410 -       int i, npend;
411 +       int i, npend = 0;
412  
413         for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
414                 if (!ATH_TXQ_SETUP(sc, i))
415 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c
416 +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c
417 @@ -595,6 +595,9 @@ static void iwl_scan_offload_build_ssid(
418          * config match list.
419          */
420         for (i = 0; i < req->n_match_sets && i < PROBE_OPTION_MAX; i++) {
421 +               /* skip empty SSID matchsets */
422 +               if (!req->match_sets[i].ssid.ssid_len)
423 +                       continue;
424                 scan->direct_scan[i].id = WLAN_EID_SSID;
425                 scan->direct_scan[i].len = req->match_sets[i].ssid.ssid_len;
426                 memcpy(scan->direct_scan[i].ssid, req->match_sets[i].ssid.ssid,
427 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
428 +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
429 @@ -452,7 +452,7 @@ bool rtl88ee_rx_query_desc(struct ieee80
430                         /* During testing, hdr was NULL */
431                         return false;
432                 }
433 -               if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
434 +               if ((_ieee80211_is_robust_mgmt_frame(hdr)) &&
435                     (ieee80211_has_protected(hdr->frame_control)))
436                         rx_status->flag &= ~RX_FLAG_DECRYPTED;
437                 else
438 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
439 +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
440 @@ -393,7 +393,7 @@ bool rtl92ce_rx_query_desc(struct ieee80
441                         /* In testing, hdr was NULL here */
442                         return false;
443                 }
444 -               if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
445 +               if ((_ieee80211_is_robust_mgmt_frame(hdr)) &&
446                     (ieee80211_has_protected(hdr->frame_control)))
447                         rx_status->flag &= ~RX_FLAG_DECRYPTED;
448                 else
449 --- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
450 +++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
451 @@ -310,7 +310,7 @@ bool rtl92se_rx_query_desc(struct ieee80
452                         /* during testing, hdr was NULL here */
453                         return false;
454                 }
455 -               if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
456 +               if ((_ieee80211_is_robust_mgmt_frame(hdr)) &&
457                         (ieee80211_has_protected(hdr->frame_control)))
458                         rx_status->flag &= ~RX_FLAG_DECRYPTED;
459                 else
460 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c
461 +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c
462 @@ -334,7 +334,7 @@ bool rtl8723ae_rx_query_desc(struct ieee
463                         /* during testing, hdr could be NULL here */
464                         return false;
465                 }
466 -               if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
467 +               if ((_ieee80211_is_robust_mgmt_frame(hdr)) &&
468                         (ieee80211_has_protected(hdr->frame_control)))
469                         rx_status->flag &= ~RX_FLAG_DECRYPTED;
470                 else
471 --- a/include/linux/ieee80211.h
472 +++ b/include/linux/ieee80211.h
473 @@ -2192,10 +2192,10 @@ static inline u8 *ieee80211_get_DA(struc
474  }
475  
476  /**
477 - * ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame
478 + * _ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame
479   * @hdr: the frame (buffer must include at least the first octet of payload)
480   */
481 -static inline bool ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr)
482 +static inline bool _ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr)
483  {
484         if (ieee80211_is_disassoc(hdr->frame_control) ||
485             ieee80211_is_deauth(hdr->frame_control))
486 @@ -2224,6 +2224,17 @@ static inline bool ieee80211_is_robust_m
487  }
488  
489  /**
490 + * ieee80211_is_robust_mgmt_frame - check if skb contains a robust mgmt frame
491 + * @skb: the skb containing the frame, length will be checked
492 + */
493 +static inline bool ieee80211_is_robust_mgmt_frame(struct sk_buff *skb)
494 +{
495 +       if (skb->len < 25)
496 +               return false;
497 +       return _ieee80211_is_robust_mgmt_frame((void *)skb->data);
498 +}
499 +
500 +/**
501   * ieee80211_is_public_action - check if frame is a public action frame
502   * @hdr: the frame
503   * @len: length of the frame
504 --- a/include/net/cfg80211.h
505 +++ b/include/net/cfg80211.h
506 @@ -1395,9 +1395,11 @@ struct cfg80211_scan_request {
507   * struct cfg80211_match_set - sets of attributes to match
508   *
509   * @ssid: SSID to be matched
510 + * @rssi_thold: don't report scan results below this threshold (in s32 dBm)
511   */
512  struct cfg80211_match_set {
513         struct cfg80211_ssid ssid;
514 +       s32 rssi_thold;
515  };
516  
517  /**
518 @@ -1420,7 +1422,8 @@ struct cfg80211_match_set {
519   * @dev: the interface
520   * @scan_start: start time of the scheduled scan
521   * @channels: channels to scan
522 - * @rssi_thold: don't report scan results below this threshold (in s32 dBm)
523 + * @min_rssi_thold: for drivers only supporting a single threshold, this
524 + *     contains the minimum over all matchsets
525   */
526  struct cfg80211_sched_scan_request {
527         struct cfg80211_ssid *ssids;
528 @@ -1433,7 +1436,7 @@ struct cfg80211_sched_scan_request {
529         u32 flags;
530         struct cfg80211_match_set *match_sets;
531         int n_match_sets;
532 -       s32 rssi_thold;
533 +       s32 min_rssi_thold;
534  
535         /* internal */
536         struct wiphy *wiphy;
537 --- a/include/uapi/linux/nl80211.h
538 +++ b/include/uapi/linux/nl80211.h
539 @@ -2442,9 +2442,15 @@ enum nl80211_reg_rule_attr {
540   * enum nl80211_sched_scan_match_attr - scheduled scan match attributes
541   * @__NL80211_SCHED_SCAN_MATCH_ATTR_INVALID: attribute number 0 is reserved
542   * @NL80211_SCHED_SCAN_MATCH_ATTR_SSID: SSID to be used for matching,
543 - * only report BSS with matching SSID.
544 + *     only report BSS with matching SSID.
545   * @NL80211_SCHED_SCAN_MATCH_ATTR_RSSI: RSSI threshold (in dBm) for reporting a
546 - *     BSS in scan results. Filtering is turned off if not specified.
547 + *     BSS in scan results. Filtering is turned off if not specified. Note that
548 + *     if this attribute is in a match set of its own, then it is treated as
549 + *     the default value for all matchsets with an SSID, rather than being a
550 + *     matchset of its own without an RSSI filter. This is due to problems with
551 + *     how this API was implemented in the past. Also, due to the same problem,
552 + *     the only way to create a matchset with only an RSSI filter (with this
553 + *     attribute) is if there's only a single matchset with the RSSI attribute.
554   * @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter
555   *     attribute number currently defined
556   * @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use
557 --- a/net/mac80211/agg-tx.c
558 +++ b/net/mac80211/agg-tx.c
559 @@ -107,7 +107,7 @@ static void ieee80211_send_addba_request
560         mgmt->u.action.u.addba_req.start_seq_num =
561                                         cpu_to_le16(start_seq_num << 4);
562  
563 -       ieee80211_tx_skb_tid(sdata, skb, tid);
564 +       ieee80211_tx_skb(sdata, skb);
565  }
566  
567  void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn)
568 --- a/net/mac80211/cfg.c
569 +++ b/net/mac80211/cfg.c
570 @@ -1021,8 +1021,10 @@ static int ieee80211_start_ap(struct wip
571                                         IEEE80211_P2P_OPPPS_ENABLE_BIT;
572  
573         err = ieee80211_assign_beacon(sdata, &params->beacon);
574 -       if (err < 0)
575 +       if (err < 0) {
576 +               ieee80211_vif_release_channel(sdata);
577                 return err;
578 +       }
579         changed |= err;
580  
581         err = drv_start_ap(sdata->local, sdata);
582 @@ -1032,6 +1034,7 @@ static int ieee80211_start_ap(struct wip
583                 if (old)
584                         kfree_rcu(old, rcu_head);
585                 RCU_INIT_POINTER(sdata->u.ap.beacon, NULL);
586 +               ieee80211_vif_release_channel(sdata);
587                 return err;
588         }
589  
590 @@ -1090,8 +1093,6 @@ static int ieee80211_stop_ap(struct wiph
591         kfree(sdata->u.ap.next_beacon);
592         sdata->u.ap.next_beacon = NULL;
593  
594 -       cancel_work_sync(&sdata->u.ap.request_smps_work);
595 -
596         /* turn off carrier for this interface and dependent VLANs */
597         list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
598                 netif_carrier_off(vlan->dev);
599 @@ -1103,6 +1104,7 @@ static int ieee80211_stop_ap(struct wiph
600         kfree_rcu(old_beacon, rcu_head);
601         if (old_probe_resp)
602                 kfree_rcu(old_probe_resp, rcu_head);
603 +       sdata->u.ap.driver_smps_mode = IEEE80211_SMPS_OFF;
604  
605         __sta_info_flush(sdata, true);
606         ieee80211_free_keys(sdata, true);
607 @@ -2638,6 +2640,24 @@ static int ieee80211_start_roc_work(stru
608         INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work);
609         INIT_LIST_HEAD(&roc->dependents);
610  
611 +       /*
612 +        * cookie is either the roc cookie (for normal roc)
613 +        * or the SKB (for mgmt TX)
614 +        */
615 +       if (!txskb) {
616 +               /* local->mtx protects this */
617 +               local->roc_cookie_counter++;
618 +               roc->cookie = local->roc_cookie_counter;
619 +               /* wow, you wrapped 64 bits ... more likely a bug */
620 +               if (WARN_ON(roc->cookie == 0)) {
621 +                       roc->cookie = 1;
622 +                       local->roc_cookie_counter++;
623 +               }
624 +               *cookie = roc->cookie;
625 +       } else {
626 +               *cookie = (unsigned long)txskb;
627 +       }
628 +
629         /* if there's one pending or we're scanning, queue this one */
630         if (!list_empty(&local->roc_list) ||
631             local->scanning || local->radar_detect_enabled)
632 @@ -2772,24 +2792,6 @@ static int ieee80211_start_roc_work(stru
633         if (!queued)
634                 list_add_tail(&roc->list, &local->roc_list);
635  
636 -       /*
637 -        * cookie is either the roc cookie (for normal roc)
638 -        * or the SKB (for mgmt TX)
639 -        */
640 -       if (!txskb) {
641 -               /* local->mtx protects this */
642 -               local->roc_cookie_counter++;
643 -               roc->cookie = local->roc_cookie_counter;
644 -               /* wow, you wrapped 64 bits ... more likely a bug */
645 -               if (WARN_ON(roc->cookie == 0)) {
646 -                       roc->cookie = 1;
647 -                       local->roc_cookie_counter++;
648 -               }
649 -               *cookie = roc->cookie;
650 -       } else {
651 -               *cookie = (unsigned long)txskb;
652 -       }
653 -
654         return 0;
655  }
656  
657 --- a/net/mac80211/ht.c
658 +++ b/net/mac80211/ht.c
659 @@ -375,7 +375,7 @@ void ieee80211_send_delba(struct ieee802
660         mgmt->u.action.u.delba.params = cpu_to_le16(params);
661         mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code);
662  
663 -       ieee80211_tx_skb_tid(sdata, skb, tid);
664 +       ieee80211_tx_skb(sdata, skb);
665  }
666  
667  void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,
668 @@ -466,7 +466,9 @@ void ieee80211_request_smps_ap_work(stru
669                              u.ap.request_smps_work);
670  
671         sdata_lock(sdata);
672 -       __ieee80211_request_smps_ap(sdata, sdata->u.ap.driver_smps_mode);
673 +       if (sdata_dereference(sdata->u.ap.beacon, sdata))
674 +               __ieee80211_request_smps_ap(sdata,
675 +                                           sdata->u.ap.driver_smps_mode);
676         sdata_unlock(sdata);
677  }
678  
679 --- a/net/mac80211/iface.c
680 +++ b/net/mac80211/iface.c
681 @@ -770,12 +770,19 @@ static void ieee80211_do_stop(struct iee
682  
683         ieee80211_roc_purge(local, sdata);
684  
685 -       if (sdata->vif.type == NL80211_IFTYPE_STATION)
686 +       switch (sdata->vif.type) {
687 +       case NL80211_IFTYPE_STATION:
688                 ieee80211_mgd_stop(sdata);
689 -
690 -       if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
691 +               break;
692 +       case NL80211_IFTYPE_ADHOC:
693                 ieee80211_ibss_stop(sdata);
694 -
695 +               break;
696 +       case NL80211_IFTYPE_AP:
697 +               cancel_work_sync(&sdata->u.ap.request_smps_work);
698 +               break;
699 +       default:
700 +               break;
701 +       }
702  
703         /*
704          * Remove all stations associated with this interface.
705 --- a/net/mac80211/rx.c
706 +++ b/net/mac80211/rx.c
707 @@ -599,10 +599,10 @@ static int ieee80211_is_unicast_robust_m
708  {
709         struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
710  
711 -       if (skb->len < 24 || is_multicast_ether_addr(hdr->addr1))
712 +       if (is_multicast_ether_addr(hdr->addr1))
713                 return 0;
714  
715 -       return ieee80211_is_robust_mgmt_frame(hdr);
716 +       return ieee80211_is_robust_mgmt_frame(skb);
717  }
718  
719  
720 @@ -610,10 +610,10 @@ static int ieee80211_is_multicast_robust
721  {
722         struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
723  
724 -       if (skb->len < 24 || !is_multicast_ether_addr(hdr->addr1))
725 +       if (!is_multicast_ether_addr(hdr->addr1))
726                 return 0;
727  
728 -       return ieee80211_is_robust_mgmt_frame(hdr);
729 +       return ieee80211_is_robust_mgmt_frame(skb);
730  }
731  
732  
733 @@ -626,7 +626,7 @@ static int ieee80211_get_mmie_keyidx(str
734         if (skb->len < 24 + sizeof(*mmie) || !is_multicast_ether_addr(hdr->da))
735                 return -1;
736  
737 -       if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) hdr))
738 +       if (!ieee80211_is_robust_mgmt_frame(skb))
739                 return -1; /* not a robust management frame */
740  
741         mmie = (struct ieee80211_mmie *)
742 @@ -1845,8 +1845,7 @@ static int ieee80211_drop_unencrypted_mg
743                  * having configured keys.
744                  */
745                 if (unlikely(ieee80211_is_action(fc) && !rx->key &&
746 -                            ieee80211_is_robust_mgmt_frame(
747 -                                    (struct ieee80211_hdr *) rx->skb->data)))
748 +                            ieee80211_is_robust_mgmt_frame(rx->skb)))
749                         return -EACCES;
750         }
751  
752 --- a/net/mac80211/tx.c
753 +++ b/net/mac80211/tx.c
754 @@ -452,8 +452,7 @@ static int ieee80211_use_mfp(__le16 fc, 
755         if (sta == NULL || !test_sta_flag(sta, WLAN_STA_MFP))
756                 return 0;
757  
758 -       if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *)
759 -                                           skb->data))
760 +       if (!ieee80211_is_robust_mgmt_frame(skb))
761                 return 0;
762  
763         return 1;
764 @@ -567,7 +566,7 @@ ieee80211_tx_h_select_key(struct ieee802
765                 tx->key = key;
766         else if (ieee80211_is_mgmt(hdr->frame_control) &&
767                  is_multicast_ether_addr(hdr->addr1) &&
768 -                ieee80211_is_robust_mgmt_frame(hdr) &&
769 +                ieee80211_is_robust_mgmt_frame(tx->skb) &&
770                  (key = rcu_dereference(tx->sdata->default_mgmt_key)))
771                 tx->key = key;
772         else if (is_multicast_ether_addr(hdr->addr1) &&
773 @@ -582,12 +581,12 @@ ieee80211_tx_h_select_key(struct ieee802
774                 tx->key = NULL;
775         else if (tx->skb->protocol == tx->sdata->control_port_protocol)
776                 tx->key = NULL;
777 -       else if (ieee80211_is_robust_mgmt_frame(hdr) &&
778 +       else if (ieee80211_is_robust_mgmt_frame(tx->skb) &&
779                  !(ieee80211_is_action(hdr->frame_control) &&
780                    tx->sta && test_sta_flag(tx->sta, WLAN_STA_MFP)))
781                 tx->key = NULL;
782         else if (ieee80211_is_mgmt(hdr->frame_control) &&
783 -                !ieee80211_is_robust_mgmt_frame(hdr))
784 +                !ieee80211_is_robust_mgmt_frame(tx->skb))
785                 tx->key = NULL;
786         else {
787                 I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted);
788 --- a/net/mac80211/wpa.c
789 +++ b/net/mac80211/wpa.c
790 @@ -499,7 +499,7 @@ ieee80211_crypto_ccmp_decrypt(struct iee
791         hdrlen = ieee80211_hdrlen(hdr->frame_control);
792  
793         if (!ieee80211_is_data(hdr->frame_control) &&
794 -           !ieee80211_is_robust_mgmt_frame(hdr))
795 +           !ieee80211_is_robust_mgmt_frame(skb))
796                 return RX_CONTINUE;
797  
798         data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN -
799 --- a/net/wireless/ap.c
800 +++ b/net/wireless/ap.c
801 @@ -30,6 +30,7 @@ static int __cfg80211_stop_ap(struct cfg
802                 wdev->channel = NULL;
803                 wdev->ssid_len = 0;
804                 rdev_set_qos_map(rdev, dev, NULL);
805 +               nl80211_send_ap_stopped(wdev);
806         }
807  
808         return err;
809 --- a/net/wireless/core.c
810 +++ b/net/wireless/core.c
811 @@ -203,8 +203,11 @@ void cfg80211_stop_p2p_device(struct cfg
812  
813         rdev->opencount--;
814  
815 -       WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev &&
816 -               !rdev->scan_req->notified);
817 +       if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
818 +               if (WARN_ON(!rdev->scan_req->notified))
819 +                       rdev->scan_req->aborted = true;
820 +               ___cfg80211_scan_done(rdev, false);
821 +       }
822  }
823  
824  static int cfg80211_rfkill_set_block(void *data, bool blocked)
825 @@ -447,9 +450,6 @@ int wiphy_register(struct wiphy *wiphy)
826         int i;
827         u16 ifmodes = wiphy->interface_modes;
828  
829 -       /* support for 5/10 MHz is broken due to nl80211 API mess - disable */
830 -       wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_5_10_MHZ;
831 -
832         /*
833          * There are major locking problems in nl80211/mac80211 for CSA,
834          * disable for all drivers until this has been reworked.
835 @@ -875,8 +875,11 @@ static int cfg80211_netdev_notifier_call
836                 break;
837         case NETDEV_DOWN:
838                 cfg80211_update_iface_num(rdev, wdev->iftype, -1);
839 -               WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev &&
840 -                       !rdev->scan_req->notified);
841 +               if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
842 +                       if (WARN_ON(!rdev->scan_req->notified))
843 +                               rdev->scan_req->aborted = true;
844 +                       ___cfg80211_scan_done(rdev, false);
845 +               }
846  
847                 if (WARN_ON(rdev->sched_scan_req &&
848                             rdev->sched_scan_req->dev == wdev->netdev)) {
849 --- a/net/wireless/core.h
850 +++ b/net/wireless/core.h
851 @@ -62,6 +62,7 @@ struct cfg80211_registered_device {
852         struct rb_root bss_tree;
853         u32 bss_generation;
854         struct cfg80211_scan_request *scan_req; /* protected by RTNL */
855 +       struct sk_buff *scan_msg;
856         struct cfg80211_sched_scan_request *sched_scan_req;
857         unsigned long suspend_at;
858         struct work_struct scan_done_wk;
859 @@ -361,7 +362,8 @@ int cfg80211_validate_key_settings(struc
860                                    struct key_params *params, int key_idx,
861                                    bool pairwise, const u8 *mac_addr);
862  void __cfg80211_scan_done(struct work_struct *wk);
863 -void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev);
864 +void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
865 +                          bool send_message);
866  void __cfg80211_sched_scan_results(struct work_struct *wk);
867  int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
868                                bool driver_initiated);
869 --- a/net/wireless/nl80211.c
870 +++ b/net/wireless/nl80211.c
871 @@ -1723,9 +1723,10 @@ static int nl80211_dump_wiphy(struct sk_
872                                  * We can then retry with the larger buffer.
873                                  */
874                                 if ((ret == -ENOBUFS || ret == -EMSGSIZE) &&
875 -                                   !skb->len &&
876 +                                   !skb->len && !state->split &&
877                                     cb->min_dump_alloc < 4096) {
878                                         cb->min_dump_alloc = 4096;
879 +                                       state->split_start = 0;
880                                         rtnl_unlock();
881                                         return 1;
882                                 }
883 @@ -2047,10 +2048,12 @@ static int nl80211_set_wiphy(struct sk_b
884                 nla_for_each_nested(nl_txq_params,
885                                     info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
886                                     rem_txq_params) {
887 -                       nla_parse(tb, NL80211_TXQ_ATTR_MAX,
888 -                                 nla_data(nl_txq_params),
889 -                                 nla_len(nl_txq_params),
890 -                                 txq_params_policy);
891 +                       result = nla_parse(tb, NL80211_TXQ_ATTR_MAX,
892 +                                          nla_data(nl_txq_params),
893 +                                          nla_len(nl_txq_params),
894 +                                          txq_params_policy);
895 +                       if (result)
896 +                               goto bad_res;
897                         result = parse_txq_params(tb, &txq_params);
898                         if (result)
899                                 goto bad_res;
900 @@ -5210,9 +5213,11 @@ static int nl80211_set_reg(struct sk_buf
901  
902         nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
903                             rem_reg_rules) {
904 -               nla_parse(tb, NL80211_REG_RULE_ATTR_MAX,
905 -                         nla_data(nl_reg_rule), nla_len(nl_reg_rule),
906 -                         reg_rule_policy);
907 +               r = nla_parse(tb, NL80211_REG_RULE_ATTR_MAX,
908 +                             nla_data(nl_reg_rule), nla_len(nl_reg_rule),
909 +                             reg_rule_policy);
910 +               if (r)
911 +                       goto bad_reg;
912                 r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]);
913                 if (r)
914                         goto bad_reg;
915 @@ -5277,7 +5282,7 @@ static int nl80211_trigger_scan(struct s
916         if (!rdev->ops->scan)
917                 return -EOPNOTSUPP;
918  
919 -       if (rdev->scan_req) {
920 +       if (rdev->scan_req || rdev->scan_msg) {
921                 err = -EBUSY;
922                 goto unlock;
923         }
924 @@ -5475,6 +5480,7 @@ static int nl80211_start_sched_scan(stru
925         enum ieee80211_band band;
926         size_t ie_len;
927         struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1];
928 +       s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF;
929  
930         if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
931             !rdev->ops->sched_scan_start)
932 @@ -5509,11 +5515,40 @@ static int nl80211_start_sched_scan(stru
933         if (n_ssids > wiphy->max_sched_scan_ssids)
934                 return -EINVAL;
935  
936 -       if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH])
937 +       /*
938 +        * First, count the number of 'real' matchsets. Due to an issue with
939 +        * the old implementation, matchsets containing only the RSSI attribute
940 +        * (NL80211_SCHED_SCAN_MATCH_ATTR_RSSI) are considered as the 'default'
941 +        * RSSI for all matchsets, rather than their own matchset for reporting
942 +        * all APs with a strong RSSI. This is needed to be compatible with
943 +        * older userspace that treated a matchset with only the RSSI as the
944 +        * global RSSI for all other matchsets - if there are other matchsets.
945 +        */
946 +       if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
947                 nla_for_each_nested(attr,
948                                     info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
949 -                                   tmp)
950 -                       n_match_sets++;
951 +                                   tmp) {
952 +                       struct nlattr *rssi;
953 +
954 +                       err = nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
955 +                                       nla_data(attr), nla_len(attr),
956 +                                       nl80211_match_policy);
957 +                       if (err)
958 +                               return err;
959 +                       /* add other standalone attributes here */
960 +                       if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID]) {
961 +                               n_match_sets++;
962 +                               continue;
963 +                       }
964 +                       rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
965 +                       if (rssi)
966 +                               default_match_rssi = nla_get_s32(rssi);
967 +               }
968 +       }
969 +
970 +       /* However, if there's no other matchset, add the RSSI one */
971 +       if (!n_match_sets && default_match_rssi != NL80211_SCAN_RSSI_THOLD_OFF)
972 +               n_match_sets = 1;
973  
974         if (n_match_sets > wiphy->max_match_sets)
975                 return -EINVAL;
976 @@ -5634,11 +5669,22 @@ static int nl80211_start_sched_scan(stru
977                                     tmp) {
978                         struct nlattr *ssid, *rssi;
979  
980 -                       nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
981 -                                 nla_data(attr), nla_len(attr),
982 -                                 nl80211_match_policy);
983 +                       err = nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
984 +                                       nla_data(attr), nla_len(attr),
985 +                                       nl80211_match_policy);
986 +                       if (err)
987 +                               goto out_free;
988                         ssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID];
989                         if (ssid) {
990 +                               if (WARN_ON(i >= n_match_sets)) {
991 +                                       /* this indicates a programming error,
992 +                                        * the loop above should have verified
993 +                                        * things properly
994 +                                        */
995 +                                       err = -EINVAL;
996 +                                       goto out_free;
997 +                               }
998 +
999                                 if (nla_len(ssid) > IEEE80211_MAX_SSID_LEN) {
1000                                         err = -EINVAL;
1001                                         goto out_free;
1002 @@ -5647,15 +5693,28 @@ static int nl80211_start_sched_scan(stru
1003                                        nla_data(ssid), nla_len(ssid));
1004                                 request->match_sets[i].ssid.ssid_len =
1005                                         nla_len(ssid);
1006 +                               /* special attribute - old implemenation w/a */
1007 +                               request->match_sets[i].rssi_thold =
1008 +                                       default_match_rssi;
1009 +                               rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
1010 +                               if (rssi)
1011 +                                       request->match_sets[i].rssi_thold =
1012 +                                               nla_get_s32(rssi);
1013                         }
1014 -                       rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
1015 -                       if (rssi)
1016 -                               request->rssi_thold = nla_get_u32(rssi);
1017 -                       else
1018 -                               request->rssi_thold =
1019 -                                                  NL80211_SCAN_RSSI_THOLD_OFF;
1020                         i++;
1021                 }
1022 +
1023 +               /* there was no other matchset, so the RSSI one is alone */
1024 +               if (i == 0)
1025 +                       request->match_sets[0].rssi_thold = default_match_rssi;
1026 +
1027 +               request->min_rssi_thold = INT_MAX;
1028 +               for (i = 0; i < n_match_sets; i++)
1029 +                       request->min_rssi_thold =
1030 +                               min(request->match_sets[i].rssi_thold,
1031 +                                   request->min_rssi_thold);
1032 +       } else {
1033 +               request->min_rssi_thold = NL80211_SCAN_RSSI_THOLD_OFF;
1034         }
1035  
1036         if (info->attrs[NL80211_ATTR_IE]) {
1037 @@ -7502,16 +7561,19 @@ static int nl80211_set_tx_bitrate_mask(s
1038          * directly to the enum ieee80211_band values used in cfg80211.
1039          */
1040         BUILD_BUG_ON(NL80211_MAX_SUPP_HT_RATES > IEEE80211_HT_MCS_MASK_LEN * 8);
1041 -       nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem)
1042 -       {
1043 +       nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem) {
1044                 enum ieee80211_band band = nla_type(tx_rates);
1045 +               int err;
1046 +
1047                 if (band < 0 || band >= IEEE80211_NUM_BANDS)
1048                         return -EINVAL;
1049                 sband = rdev->wiphy.bands[band];
1050                 if (sband == NULL)
1051                         return -EINVAL;
1052 -               nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates),
1053 -                         nla_len(tx_rates), nl80211_txattr_policy);
1054 +               err = nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates),
1055 +                               nla_len(tx_rates), nl80211_txattr_policy);
1056 +               if (err)
1057 +                       return err;
1058                 if (tb[NL80211_TXRATE_LEGACY]) {
1059                         mask.control[band].legacy = rateset_to_mask(
1060                                 sband,
1061 @@ -10054,40 +10116,31 @@ void nl80211_send_scan_start(struct cfg8
1062                                 NL80211_MCGRP_SCAN, GFP_KERNEL);
1063  }
1064  
1065 -void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
1066 -                           struct wireless_dev *wdev)
1067 +struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev,
1068 +                                      struct wireless_dev *wdev, bool aborted)
1069  {
1070         struct sk_buff *msg;
1071  
1072         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1073         if (!msg)
1074 -               return;
1075 +               return NULL;
1076  
1077         if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0,
1078 -                                 NL80211_CMD_NEW_SCAN_RESULTS) < 0) {
1079 +                                 aborted ? NL80211_CMD_SCAN_ABORTED :
1080 +                                           NL80211_CMD_NEW_SCAN_RESULTS) < 0) {
1081                 nlmsg_free(msg);
1082 -               return;
1083 +               return NULL;
1084         }
1085  
1086 -       genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
1087 -                               NL80211_MCGRP_SCAN, GFP_KERNEL);
1088 +       return msg;
1089  }
1090  
1091 -void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
1092 -                              struct wireless_dev *wdev)
1093 +void nl80211_send_scan_result(struct cfg80211_registered_device *rdev,
1094 +                             struct sk_buff *msg)
1095  {
1096 -       struct sk_buff *msg;
1097 -
1098 -       msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1099         if (!msg)
1100                 return;
1101  
1102 -       if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0,
1103 -                                 NL80211_CMD_SCAN_ABORTED) < 0) {
1104 -               nlmsg_free(msg);
1105 -               return;
1106 -       }
1107 -
1108         genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
1109                                 NL80211_MCGRP_SCAN, GFP_KERNEL);
1110  }
1111 @@ -11673,6 +11726,35 @@ void cfg80211_crit_proto_stopped(struct 
1112  }
1113  EXPORT_SYMBOL(cfg80211_crit_proto_stopped);
1114  
1115 +void nl80211_send_ap_stopped(struct wireless_dev *wdev)
1116 +{
1117 +       struct wiphy *wiphy = wdev->wiphy;
1118 +       struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
1119 +       struct sk_buff *msg;
1120 +       void *hdr;
1121 +
1122 +       msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1123 +       if (!msg)
1124 +               return;
1125 +
1126 +       hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_STOP_AP);
1127 +       if (!hdr)
1128 +               goto out;
1129 +
1130 +       if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
1131 +           nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex) ||
1132 +           nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
1133 +               goto out;
1134 +
1135 +       genlmsg_end(msg, hdr);
1136 +
1137 +       genlmsg_multicast_netns(&nl80211_fam, wiphy_net(wiphy), msg, 0,
1138 +                               NL80211_MCGRP_MLME, GFP_KERNEL);
1139 +       return;
1140 + out:
1141 +       nlmsg_free(msg);
1142 +}
1143 +
1144  /* initialisation/exit functions */
1145  
1146  int nl80211_init(void)
1147 --- a/net/wireless/nl80211.h
1148 +++ b/net/wireless/nl80211.h
1149 @@ -8,10 +8,10 @@ void nl80211_exit(void);
1150  void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev);
1151  void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
1152                              struct wireless_dev *wdev);
1153 -void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
1154 -                           struct wireless_dev *wdev);
1155 -void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
1156 -                              struct wireless_dev *wdev);
1157 +struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev,
1158 +                                      struct wireless_dev *wdev, bool aborted);
1159 +void nl80211_send_scan_result(struct cfg80211_registered_device *rdev,
1160 +                             struct sk_buff *msg);
1161  void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev,
1162                              struct net_device *netdev, u32 cmd);
1163  void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev,
1164 @@ -74,6 +74,8 @@ nl80211_radar_notify(struct cfg80211_reg
1165                      enum nl80211_radar_event event,
1166                      struct net_device *netdev, gfp_t gfp);
1167  
1168 +void nl80211_send_ap_stopped(struct wireless_dev *wdev);
1169 +
1170  void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev);
1171  
1172  #endif /* __NET_WIRELESS_NL80211_H */
1173 --- a/net/wireless/scan.c
1174 +++ b/net/wireless/scan.c
1175 @@ -161,18 +161,25 @@ static void __cfg80211_bss_expire(struct
1176                 dev->bss_generation++;
1177  }
1178  
1179 -void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev)
1180 +void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
1181 +                          bool send_message)
1182  {
1183         struct cfg80211_scan_request *request;
1184         struct wireless_dev *wdev;
1185 +       struct sk_buff *msg;
1186  #ifdef CPTCFG_CFG80211_WEXT
1187         union iwreq_data wrqu;
1188  #endif
1189  
1190         ASSERT_RTNL();
1191  
1192 -       request = rdev->scan_req;
1193 +       if (rdev->scan_msg) {
1194 +               nl80211_send_scan_result(rdev, rdev->scan_msg);
1195 +               rdev->scan_msg = NULL;
1196 +               return;
1197 +       }
1198  
1199 +       request = rdev->scan_req;
1200         if (!request)
1201                 return;
1202  
1203 @@ -186,18 +193,16 @@ void ___cfg80211_scan_done(struct cfg802
1204         if (wdev->netdev)
1205                 cfg80211_sme_scan_done(wdev->netdev);
1206  
1207 -       if (request->aborted) {
1208 -               nl80211_send_scan_aborted(rdev, wdev);
1209 -       } else {
1210 -               if (request->flags & NL80211_SCAN_FLAG_FLUSH) {
1211 -                       /* flush entries from previous scans */
1212 -                       spin_lock_bh(&rdev->bss_lock);
1213 -                       __cfg80211_bss_expire(rdev, request->scan_start);
1214 -                       spin_unlock_bh(&rdev->bss_lock);
1215 -               }
1216 -               nl80211_send_scan_done(rdev, wdev);
1217 +       if (!request->aborted &&
1218 +           request->flags & NL80211_SCAN_FLAG_FLUSH) {
1219 +               /* flush entries from previous scans */
1220 +               spin_lock_bh(&rdev->bss_lock);
1221 +               __cfg80211_bss_expire(rdev, request->scan_start);
1222 +               spin_unlock_bh(&rdev->bss_lock);
1223         }
1224  
1225 +       msg = nl80211_build_scan_msg(rdev, wdev, request->aborted);
1226 +
1227  #ifdef CPTCFG_CFG80211_WEXT
1228         if (wdev->netdev && !request->aborted) {
1229                 memset(&wrqu, 0, sizeof(wrqu));
1230 @@ -211,6 +216,11 @@ void ___cfg80211_scan_done(struct cfg802
1231  
1232         rdev->scan_req = NULL;
1233         kfree(request);
1234 +
1235 +       if (!send_message)
1236 +               rdev->scan_msg = msg;
1237 +       else
1238 +               nl80211_send_scan_result(rdev, msg);
1239  }
1240  
1241  void __cfg80211_scan_done(struct work_struct *wk)
1242 @@ -221,7 +231,7 @@ void __cfg80211_scan_done(struct work_st
1243                             scan_done_wk);
1244  
1245         rtnl_lock();
1246 -       ___cfg80211_scan_done(rdev);
1247 +       ___cfg80211_scan_done(rdev, true);
1248         rtnl_unlock();
1249  }
1250  
1251 @@ -1079,7 +1089,7 @@ int cfg80211_wext_siwscan(struct net_dev
1252         if (IS_ERR(rdev))
1253                 return PTR_ERR(rdev);
1254  
1255 -       if (rdev->scan_req) {
1256 +       if (rdev->scan_req || rdev->scan_msg) {
1257                 err = -EBUSY;
1258                 goto out;
1259         }
1260 @@ -1481,7 +1491,7 @@ int cfg80211_wext_giwscan(struct net_dev
1261         if (IS_ERR(rdev))
1262                 return PTR_ERR(rdev);
1263  
1264 -       if (rdev->scan_req)
1265 +       if (rdev->scan_req || rdev->scan_msg)
1266                 return -EAGAIN;
1267  
1268         res = ieee80211_scan_results(rdev, info, extra, data->length);
1269 --- a/net/wireless/sme.c
1270 +++ b/net/wireless/sme.c
1271 @@ -67,7 +67,7 @@ static int cfg80211_conn_scan(struct wir
1272         ASSERT_RDEV_LOCK(rdev);
1273         ASSERT_WDEV_LOCK(wdev);
1274  
1275 -       if (rdev->scan_req)
1276 +       if (rdev->scan_req || rdev->scan_msg)
1277                 return -EBUSY;
1278  
1279         if (wdev->conn->params.channel)