mac80211: update to wireless-testing 2014-01-23
[openwrt/staging/mkresin.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)