diff options
Diffstat (limited to 'net/wireless/mlme.c')
-rw-r--r-- | net/wireless/mlme.c | 214 |
1 files changed, 168 insertions, 46 deletions
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 960bf60e44e5..1b2ca1fea7a1 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -23,7 +23,7 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len) | |||
23 | u16 status = le16_to_cpu(mgmt->u.auth.status_code); | 23 | u16 status = le16_to_cpu(mgmt->u.auth.status_code); |
24 | bool done = false; | 24 | bool done = false; |
25 | 25 | ||
26 | might_sleep(); | 26 | wdev_lock(wdev); |
27 | 27 | ||
28 | for (i = 0; i < MAX_AUTH_BSSES; i++) { | 28 | for (i = 0; i < MAX_AUTH_BSSES; i++) { |
29 | if (wdev->authtry_bsses[i] && | 29 | if (wdev->authtry_bsses[i] && |
@@ -45,6 +45,8 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len) | |||
45 | 45 | ||
46 | nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL); | 46 | nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL); |
47 | cfg80211_sme_rx_auth(dev, buf, len); | 47 | cfg80211_sme_rx_auth(dev, buf, len); |
48 | |||
49 | wdev_unlock(wdev); | ||
48 | } | 50 | } |
49 | EXPORT_SYMBOL(cfg80211_send_rx_auth); | 51 | EXPORT_SYMBOL(cfg80211_send_rx_auth); |
50 | 52 | ||
@@ -59,14 +61,15 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len) | |||
59 | int i, ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); | 61 | int i, ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); |
60 | bool done; | 62 | bool done; |
61 | 63 | ||
62 | might_sleep(); | 64 | wdev_lock(wdev); |
63 | 65 | ||
64 | status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); | 66 | status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); |
65 | 67 | ||
66 | nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL); | 68 | nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL); |
67 | 69 | ||
68 | cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs, | 70 | __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs, |
69 | status_code, GFP_KERNEL); | 71 | status_code, |
72 | status_code == WLAN_STATUS_SUCCESS); | ||
70 | 73 | ||
71 | if (status_code == WLAN_STATUS_SUCCESS) { | 74 | if (status_code == WLAN_STATUS_SUCCESS) { |
72 | for (i = 0; wdev->current_bss && i < MAX_AUTH_BSSES; i++) { | 75 | for (i = 0; wdev->current_bss && i < MAX_AUTH_BSSES; i++) { |
@@ -81,10 +84,13 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len) | |||
81 | 84 | ||
82 | WARN_ON(!done); | 85 | WARN_ON(!done); |
83 | } | 86 | } |
87 | |||
88 | wdev_unlock(wdev); | ||
84 | } | 89 | } |
85 | EXPORT_SYMBOL(cfg80211_send_rx_assoc); | 90 | EXPORT_SYMBOL(cfg80211_send_rx_assoc); |
86 | 91 | ||
87 | void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len) | 92 | static void __cfg80211_send_deauth(struct net_device *dev, |
93 | const u8 *buf, size_t len) | ||
88 | { | 94 | { |
89 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 95 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
90 | struct wiphy *wiphy = wdev->wiphy; | 96 | struct wiphy *wiphy = wdev->wiphy; |
@@ -94,7 +100,7 @@ void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len) | |||
94 | int i; | 100 | int i; |
95 | bool done = false; | 101 | bool done = false; |
96 | 102 | ||
97 | might_sleep(); | 103 | ASSERT_WDEV_LOCK(wdev); |
98 | 104 | ||
99 | nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL); | 105 | nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL); |
100 | 106 | ||
@@ -132,17 +138,35 @@ void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len) | |||
132 | reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); | 138 | reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); |
133 | 139 | ||
134 | from_ap = memcmp(mgmt->da, dev->dev_addr, ETH_ALEN) == 0; | 140 | from_ap = memcmp(mgmt->da, dev->dev_addr, ETH_ALEN) == 0; |
135 | __cfg80211_disconnected(dev, GFP_KERNEL, NULL, 0, | 141 | __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap); |
136 | reason_code, from_ap); | ||
137 | } else if (wdev->sme_state == CFG80211_SME_CONNECTING) { | 142 | } else if (wdev->sme_state == CFG80211_SME_CONNECTING) { |
138 | cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0, | 143 | __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0, |
139 | WLAN_STATUS_UNSPECIFIED_FAILURE, | 144 | WLAN_STATUS_UNSPECIFIED_FAILURE, |
140 | GFP_KERNEL); | 145 | false); |
146 | } | ||
147 | } | ||
148 | |||
149 | |||
150 | void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len, | ||
151 | void *cookie) | ||
152 | { | ||
153 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
154 | |||
155 | BUG_ON(cookie && wdev != cookie); | ||
156 | |||
157 | if (cookie) { | ||
158 | /* called within callback */ | ||
159 | __cfg80211_send_deauth(dev, buf, len); | ||
160 | } else { | ||
161 | wdev_lock(wdev); | ||
162 | __cfg80211_send_deauth(dev, buf, len); | ||
163 | wdev_unlock(wdev); | ||
141 | } | 164 | } |
142 | } | 165 | } |
143 | EXPORT_SYMBOL(cfg80211_send_deauth); | 166 | EXPORT_SYMBOL(cfg80211_send_deauth); |
144 | 167 | ||
145 | void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len) | 168 | static void __cfg80211_send_disassoc(struct net_device *dev, |
169 | const u8 *buf, size_t len) | ||
146 | { | 170 | { |
147 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 171 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
148 | struct wiphy *wiphy = wdev->wiphy; | 172 | struct wiphy *wiphy = wdev->wiphy; |
@@ -154,12 +178,12 @@ void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len) | |||
154 | bool from_ap; | 178 | bool from_ap; |
155 | bool done = false; | 179 | bool done = false; |
156 | 180 | ||
157 | might_sleep(); | 181 | wdev_lock(wdev); |
158 | 182 | ||
159 | nl80211_send_disassoc(rdev, dev, buf, len, GFP_KERNEL); | 183 | nl80211_send_disassoc(rdev, dev, buf, len, GFP_KERNEL); |
160 | 184 | ||
161 | if (!wdev->sme_state == CFG80211_SME_CONNECTED) | 185 | if (!wdev->sme_state == CFG80211_SME_CONNECTED) |
162 | return; | 186 | goto out; |
163 | 187 | ||
164 | if (wdev->current_bss && | 188 | if (wdev->current_bss && |
165 | memcmp(wdev->current_bss, bssid, ETH_ALEN) == 0) { | 189 | memcmp(wdev->current_bss, bssid, ETH_ALEN) == 0) { |
@@ -180,8 +204,26 @@ void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len) | |||
180 | reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); | 204 | reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); |
181 | 205 | ||
182 | from_ap = memcmp(mgmt->da, dev->dev_addr, ETH_ALEN) == 0; | 206 | from_ap = memcmp(mgmt->da, dev->dev_addr, ETH_ALEN) == 0; |
183 | __cfg80211_disconnected(dev, GFP_KERNEL, NULL, 0, | 207 | __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap); |
184 | reason_code, from_ap); | 208 | out: |
209 | wdev_unlock(wdev); | ||
210 | } | ||
211 | |||
212 | void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len, | ||
213 | void *cookie) | ||
214 | { | ||
215 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
216 | |||
217 | BUG_ON(cookie && wdev != cookie); | ||
218 | |||
219 | if (cookie) { | ||
220 | /* called within callback */ | ||
221 | __cfg80211_send_disassoc(dev, buf, len); | ||
222 | } else { | ||
223 | wdev_lock(wdev); | ||
224 | __cfg80211_send_disassoc(dev, buf, len); | ||
225 | wdev_unlock(wdev); | ||
226 | } | ||
185 | } | 227 | } |
186 | EXPORT_SYMBOL(cfg80211_send_disassoc); | 228 | EXPORT_SYMBOL(cfg80211_send_disassoc); |
187 | 229 | ||
@@ -193,13 +235,13 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) | |||
193 | int i; | 235 | int i; |
194 | bool done = false; | 236 | bool done = false; |
195 | 237 | ||
196 | might_sleep(); | 238 | wdev_lock(wdev); |
197 | 239 | ||
198 | nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL); | 240 | nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL); |
199 | if (wdev->sme_state == CFG80211_SME_CONNECTING) | 241 | if (wdev->sme_state == CFG80211_SME_CONNECTING) |
200 | cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0, | 242 | __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0, |
201 | WLAN_STATUS_UNSPECIFIED_FAILURE, | 243 | WLAN_STATUS_UNSPECIFIED_FAILURE, |
202 | GFP_KERNEL); | 244 | false); |
203 | 245 | ||
204 | for (i = 0; addr && i < MAX_AUTH_BSSES; i++) { | 246 | for (i = 0; addr && i < MAX_AUTH_BSSES; i++) { |
205 | if (wdev->authtry_bsses[i] && | 247 | if (wdev->authtry_bsses[i] && |
@@ -214,6 +256,8 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) | |||
214 | } | 256 | } |
215 | 257 | ||
216 | WARN_ON(!done); | 258 | WARN_ON(!done); |
259 | |||
260 | wdev_unlock(wdev); | ||
217 | } | 261 | } |
218 | EXPORT_SYMBOL(cfg80211_send_auth_timeout); | 262 | EXPORT_SYMBOL(cfg80211_send_auth_timeout); |
219 | 263 | ||
@@ -225,13 +269,13 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr) | |||
225 | int i; | 269 | int i; |
226 | bool done = false; | 270 | bool done = false; |
227 | 271 | ||
228 | might_sleep(); | 272 | wdev_lock(wdev); |
229 | 273 | ||
230 | nl80211_send_assoc_timeout(rdev, dev, addr, GFP_KERNEL); | 274 | nl80211_send_assoc_timeout(rdev, dev, addr, GFP_KERNEL); |
231 | if (wdev->sme_state == CFG80211_SME_CONNECTING) | 275 | if (wdev->sme_state == CFG80211_SME_CONNECTING) |
232 | cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0, | 276 | __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0, |
233 | WLAN_STATUS_UNSPECIFIED_FAILURE, | 277 | WLAN_STATUS_UNSPECIFIED_FAILURE, |
234 | GFP_KERNEL); | 278 | false); |
235 | 279 | ||
236 | for (i = 0; addr && i < MAX_AUTH_BSSES; i++) { | 280 | for (i = 0; addr && i < MAX_AUTH_BSSES; i++) { |
237 | if (wdev->auth_bsses[i] && | 281 | if (wdev->auth_bsses[i] && |
@@ -246,6 +290,8 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr) | |||
246 | } | 290 | } |
247 | 291 | ||
248 | WARN_ON(!done); | 292 | WARN_ON(!done); |
293 | |||
294 | wdev_unlock(wdev); | ||
249 | } | 295 | } |
250 | EXPORT_SYMBOL(cfg80211_send_assoc_timeout); | 296 | EXPORT_SYMBOL(cfg80211_send_assoc_timeout); |
251 | 297 | ||
@@ -276,17 +322,21 @@ void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr, | |||
276 | EXPORT_SYMBOL(cfg80211_michael_mic_failure); | 322 | EXPORT_SYMBOL(cfg80211_michael_mic_failure); |
277 | 323 | ||
278 | /* some MLME handling for userspace SME */ | 324 | /* some MLME handling for userspace SME */ |
279 | int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | 325 | int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, |
280 | struct net_device *dev, struct ieee80211_channel *chan, | 326 | struct net_device *dev, |
281 | enum nl80211_auth_type auth_type, const u8 *bssid, | 327 | struct ieee80211_channel *chan, |
282 | const u8 *ssid, int ssid_len, | 328 | enum nl80211_auth_type auth_type, |
283 | const u8 *ie, int ie_len) | 329 | const u8 *bssid, |
330 | const u8 *ssid, int ssid_len, | ||
331 | const u8 *ie, int ie_len) | ||
284 | { | 332 | { |
285 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 333 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
286 | struct cfg80211_auth_request req; | 334 | struct cfg80211_auth_request req; |
287 | struct cfg80211_internal_bss *bss; | 335 | struct cfg80211_internal_bss *bss; |
288 | int i, err, slot = -1, nfree = 0; | 336 | int i, err, slot = -1, nfree = 0; |
289 | 337 | ||
338 | ASSERT_WDEV_LOCK(wdev); | ||
339 | |||
290 | if (wdev->current_bss && | 340 | if (wdev->current_bss && |
291 | memcmp(bssid, wdev->current_bss->pub.bssid, ETH_ALEN) == 0) | 341 | memcmp(bssid, wdev->current_bss->pub.bssid, ETH_ALEN) == 0) |
292 | return -EALREADY; | 342 | return -EALREADY; |
@@ -342,18 +392,37 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
342 | return err; | 392 | return err; |
343 | } | 393 | } |
344 | 394 | ||
345 | int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | 395 | int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, |
346 | struct net_device *dev, struct ieee80211_channel *chan, | 396 | struct net_device *dev, struct ieee80211_channel *chan, |
347 | const u8 *bssid, const u8 *prev_bssid, | 397 | enum nl80211_auth_type auth_type, const u8 *bssid, |
348 | const u8 *ssid, int ssid_len, | 398 | const u8 *ssid, int ssid_len, |
349 | const u8 *ie, int ie_len, bool use_mfp, | 399 | const u8 *ie, int ie_len) |
350 | struct cfg80211_crypto_settings *crypt) | 400 | { |
401 | int err; | ||
402 | |||
403 | wdev_lock(dev->ieee80211_ptr); | ||
404 | err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, | ||
405 | ssid, ssid_len, ie, ie_len); | ||
406 | wdev_unlock(dev->ieee80211_ptr); | ||
407 | |||
408 | return err; | ||
409 | } | ||
410 | |||
411 | int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | ||
412 | struct net_device *dev, | ||
413 | struct ieee80211_channel *chan, | ||
414 | const u8 *bssid, const u8 *prev_bssid, | ||
415 | const u8 *ssid, int ssid_len, | ||
416 | const u8 *ie, int ie_len, bool use_mfp, | ||
417 | struct cfg80211_crypto_settings *crypt) | ||
351 | { | 418 | { |
352 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 419 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
353 | struct cfg80211_assoc_request req; | 420 | struct cfg80211_assoc_request req; |
354 | struct cfg80211_internal_bss *bss; | 421 | struct cfg80211_internal_bss *bss; |
355 | int i, err, slot = -1; | 422 | int i, err, slot = -1; |
356 | 423 | ||
424 | ASSERT_WDEV_LOCK(wdev); | ||
425 | |||
357 | memset(&req, 0, sizeof(req)); | 426 | memset(&req, 0, sizeof(req)); |
358 | 427 | ||
359 | if (wdev->current_bss) | 428 | if (wdev->current_bss) |
@@ -390,14 +459,35 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | |||
390 | return err; | 459 | return err; |
391 | } | 460 | } |
392 | 461 | ||
393 | int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | 462 | int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, |
394 | struct net_device *dev, const u8 *bssid, | 463 | struct net_device *dev, |
395 | const u8 *ie, int ie_len, u16 reason) | 464 | struct ieee80211_channel *chan, |
465 | const u8 *bssid, const u8 *prev_bssid, | ||
466 | const u8 *ssid, int ssid_len, | ||
467 | const u8 *ie, int ie_len, bool use_mfp, | ||
468 | struct cfg80211_crypto_settings *crypt) | ||
469 | { | ||
470 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
471 | int err; | ||
472 | |||
473 | wdev_lock(wdev); | ||
474 | err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid, | ||
475 | ssid, ssid_len, ie, ie_len, use_mfp, crypt); | ||
476 | wdev_unlock(wdev); | ||
477 | |||
478 | return err; | ||
479 | } | ||
480 | |||
481 | int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | ||
482 | struct net_device *dev, const u8 *bssid, | ||
483 | const u8 *ie, int ie_len, u16 reason) | ||
396 | { | 484 | { |
397 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 485 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
398 | struct cfg80211_deauth_request req; | 486 | struct cfg80211_deauth_request req; |
399 | int i; | 487 | int i; |
400 | 488 | ||
489 | ASSERT_WDEV_LOCK(wdev); | ||
490 | |||
401 | memset(&req, 0, sizeof(req)); | 491 | memset(&req, 0, sizeof(req)); |
402 | req.reason_code = reason; | 492 | req.reason_code = reason; |
403 | req.ie = ie; | 493 | req.ie = ie; |
@@ -421,16 +511,32 @@ int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | |||
421 | if (!req.bss) | 511 | if (!req.bss) |
422 | return -ENOTCONN; | 512 | return -ENOTCONN; |
423 | 513 | ||
424 | return rdev->ops->deauth(&rdev->wiphy, dev, &req); | 514 | return rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev); |
425 | } | 515 | } |
426 | 516 | ||
427 | int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, | 517 | int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, |
428 | struct net_device *dev, const u8 *bssid, | 518 | struct net_device *dev, const u8 *bssid, |
429 | const u8 *ie, int ie_len, u16 reason) | 519 | const u8 *ie, int ie_len, u16 reason) |
520 | { | ||
521 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
522 | int err; | ||
523 | |||
524 | wdev_lock(wdev); | ||
525 | err = __cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason); | ||
526 | wdev_unlock(wdev); | ||
527 | |||
528 | return err; | ||
529 | } | ||
530 | |||
531 | static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, | ||
532 | struct net_device *dev, const u8 *bssid, | ||
533 | const u8 *ie, int ie_len, u16 reason) | ||
430 | { | 534 | { |
431 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 535 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
432 | struct cfg80211_disassoc_request req; | 536 | struct cfg80211_disassoc_request req; |
433 | 537 | ||
538 | ASSERT_WDEV_LOCK(wdev); | ||
539 | |||
434 | memset(&req, 0, sizeof(req)); | 540 | memset(&req, 0, sizeof(req)); |
435 | req.reason_code = reason; | 541 | req.reason_code = reason; |
436 | req.ie = ie; | 542 | req.ie = ie; |
@@ -440,7 +546,21 @@ int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, | |||
440 | else | 546 | else |
441 | return -ENOTCONN; | 547 | return -ENOTCONN; |
442 | 548 | ||
443 | return rdev->ops->disassoc(&rdev->wiphy, dev, &req); | 549 | return rdev->ops->disassoc(&rdev->wiphy, dev, &req, wdev); |
550 | } | ||
551 | |||
552 | int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, | ||
553 | struct net_device *dev, const u8 *bssid, | ||
554 | const u8 *ie, int ie_len, u16 reason) | ||
555 | { | ||
556 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
557 | int err; | ||
558 | |||
559 | wdev_lock(wdev); | ||
560 | err = __cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason); | ||
561 | wdev_unlock(wdev); | ||
562 | |||
563 | return err; | ||
444 | } | 564 | } |
445 | 565 | ||
446 | void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, | 566 | void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, |
@@ -450,6 +570,8 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, | |||
450 | struct cfg80211_deauth_request req; | 570 | struct cfg80211_deauth_request req; |
451 | int i; | 571 | int i; |
452 | 572 | ||
573 | ASSERT_WDEV_LOCK(wdev); | ||
574 | |||
453 | if (!rdev->ops->deauth) | 575 | if (!rdev->ops->deauth) |
454 | return; | 576 | return; |
455 | 577 | ||
@@ -460,7 +582,7 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, | |||
460 | 582 | ||
461 | if (wdev->current_bss) { | 583 | if (wdev->current_bss) { |
462 | req.bss = &wdev->current_bss->pub; | 584 | req.bss = &wdev->current_bss->pub; |
463 | rdev->ops->deauth(&rdev->wiphy, dev, &req); | 585 | rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev); |
464 | if (wdev->current_bss) { | 586 | if (wdev->current_bss) { |
465 | cfg80211_unhold_bss(wdev->current_bss); | 587 | cfg80211_unhold_bss(wdev->current_bss); |
466 | cfg80211_put_bss(&wdev->current_bss->pub); | 588 | cfg80211_put_bss(&wdev->current_bss->pub); |
@@ -471,7 +593,7 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, | |||
471 | for (i = 0; i < MAX_AUTH_BSSES; i++) { | 593 | for (i = 0; i < MAX_AUTH_BSSES; i++) { |
472 | if (wdev->auth_bsses[i]) { | 594 | if (wdev->auth_bsses[i]) { |
473 | req.bss = &wdev->auth_bsses[i]->pub; | 595 | req.bss = &wdev->auth_bsses[i]->pub; |
474 | rdev->ops->deauth(&rdev->wiphy, dev, &req); | 596 | rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev); |
475 | if (wdev->auth_bsses[i]) { | 597 | if (wdev->auth_bsses[i]) { |
476 | cfg80211_unhold_bss(wdev->auth_bsses[i]); | 598 | cfg80211_unhold_bss(wdev->auth_bsses[i]); |
477 | cfg80211_put_bss(&wdev->auth_bsses[i]->pub); | 599 | cfg80211_put_bss(&wdev->auth_bsses[i]->pub); |
@@ -480,7 +602,7 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, | |||
480 | } | 602 | } |
481 | if (wdev->authtry_bsses[i]) { | 603 | if (wdev->authtry_bsses[i]) { |
482 | req.bss = &wdev->authtry_bsses[i]->pub; | 604 | req.bss = &wdev->authtry_bsses[i]->pub; |
483 | rdev->ops->deauth(&rdev->wiphy, dev, &req); | 605 | rdev->ops->deauth(&rdev->wiphy, dev, &req, wdev); |
484 | if (wdev->authtry_bsses[i]) { | 606 | if (wdev->authtry_bsses[i]) { |
485 | cfg80211_unhold_bss(wdev->authtry_bsses[i]); | 607 | cfg80211_unhold_bss(wdev->authtry_bsses[i]); |
486 | cfg80211_put_bss(&wdev->authtry_bsses[i]->pub); | 608 | cfg80211_put_bss(&wdev->authtry_bsses[i]->pub); |