aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/mlme.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-07-06 21:56:11 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-07-10 15:02:32 -0400
commit667503ddcb96f3b10211f997fe55907fa7509841 (patch)
tree5e2559e94a716bb81bfc7566e3e3a05267810c31 /net/wireless/mlme.c
parent4f5dadcebb55fccef34722bbbf6401d39124c8a4 (diff)
cfg80211: fix locking
Over time, a lot of locking issues have crept into the smarts of cfg80211, so e.g. scan completion can race against a new scan, IBSS join can race against leaving an IBSS, etc. Introduce a new per-interface lock that protects most of the per-interface data that we need to keep track of, and sprinkle assertions about that lock everywhere. Some things now need to be offloaded to work structs so that we don't require being able to sleep in functions the drivers call. The exception to that are the MLME callbacks (rx_auth etc.) that currently only mac80211 calls because it was easier to do that there instead of in cfg80211, and future drivers implementing those calls will, if they ever exist, probably need to use a similar scheme like mac80211 anyway... In order to be able to handle _deauth and _disassoc properly, introduce a cookie passed to it that will determine locking requirements. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless/mlme.c')
-rw-r--r--net/wireless/mlme.c214
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}
49EXPORT_SYMBOL(cfg80211_send_rx_auth); 51EXPORT_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}
85EXPORT_SYMBOL(cfg80211_send_rx_assoc); 90EXPORT_SYMBOL(cfg80211_send_rx_assoc);
86 91
87void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len) 92static 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
150void 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}
143EXPORT_SYMBOL(cfg80211_send_deauth); 166EXPORT_SYMBOL(cfg80211_send_deauth);
144 167
145void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len) 168static 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
212void 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}
186EXPORT_SYMBOL(cfg80211_send_disassoc); 228EXPORT_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}
218EXPORT_SYMBOL(cfg80211_send_auth_timeout); 262EXPORT_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}
250EXPORT_SYMBOL(cfg80211_send_assoc_timeout); 296EXPORT_SYMBOL(cfg80211_send_assoc_timeout);
251 297
@@ -276,17 +322,21 @@ void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
276EXPORT_SYMBOL(cfg80211_michael_mic_failure); 322EXPORT_SYMBOL(cfg80211_michael_mic_failure);
277 323
278/* some MLME handling for userspace SME */ 324/* some MLME handling for userspace SME */
279int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, 325int __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
345int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, 395int 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
411int __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
393int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, 462int 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
481int __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
427int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, 517int 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
531static 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
552int 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
446void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, 566void 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);