aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/sme.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/sme.c')
-rw-r--r--net/wireless/sme.c252
1 files changed, 196 insertions, 56 deletions
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 066a19ef9d73..472e2412c781 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -38,6 +38,8 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
38 int n_channels, err; 38 int n_channels, err;
39 39
40 ASSERT_RTNL(); 40 ASSERT_RTNL();
41 ASSERT_RDEV_LOCK(drv);
42 ASSERT_WDEV_LOCK(wdev);
41 43
42 if (drv->scan_req) 44 if (drv->scan_req)
43 return -EBUSY; 45 return -EBUSY;
@@ -106,6 +108,8 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
106 struct cfg80211_connect_params *params; 108 struct cfg80211_connect_params *params;
107 int err; 109 int err;
108 110
111 ASSERT_WDEV_LOCK(wdev);
112
109 if (!wdev->conn) 113 if (!wdev->conn)
110 return 0; 114 return 0;
111 115
@@ -117,11 +121,11 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
117 case CFG80211_CONN_AUTHENTICATE_NEXT: 121 case CFG80211_CONN_AUTHENTICATE_NEXT:
118 BUG_ON(!drv->ops->auth); 122 BUG_ON(!drv->ops->auth);
119 wdev->conn->state = CFG80211_CONN_AUTHENTICATING; 123 wdev->conn->state = CFG80211_CONN_AUTHENTICATING;
120 return cfg80211_mlme_auth(drv, wdev->netdev, 124 return __cfg80211_mlme_auth(drv, wdev->netdev,
121 params->channel, params->auth_type, 125 params->channel, params->auth_type,
122 params->bssid, 126 params->bssid,
123 params->ssid, params->ssid_len, 127 params->ssid, params->ssid_len,
124 NULL, 0); 128 NULL, 0);
125 case CFG80211_CONN_ASSOCIATE_NEXT: 129 case CFG80211_CONN_ASSOCIATE_NEXT:
126 BUG_ON(!drv->ops->assoc); 130 BUG_ON(!drv->ops->assoc);
127 wdev->conn->state = CFG80211_CONN_ASSOCIATING; 131 wdev->conn->state = CFG80211_CONN_ASSOCIATING;
@@ -131,14 +135,16 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
131 * that some APs don't like that -- so we'd need to retry 135 * that some APs don't like that -- so we'd need to retry
132 * the association. 136 * the association.
133 */ 137 */
134 err = cfg80211_mlme_assoc(drv, wdev->netdev, 138 err = __cfg80211_mlme_assoc(drv, wdev->netdev,
135 params->channel, params->bssid, NULL, 139 params->channel, params->bssid,
136 params->ssid, params->ssid_len, 140 NULL,
137 params->ie, params->ie_len, 141 params->ssid, params->ssid_len,
138 false, &params->crypto); 142 params->ie, params->ie_len,
143 false, &params->crypto);
139 if (err) 144 if (err)
140 cfg80211_mlme_deauth(drv, wdev->netdev, params->bssid, 145 __cfg80211_mlme_deauth(drv, wdev->netdev, params->bssid,
141 NULL, 0, WLAN_REASON_DEAUTH_LEAVING); 146 NULL, 0,
147 WLAN_REASON_DEAUTH_LEAVING);
142 return err; 148 return err;
143 default: 149 default:
144 return 0; 150 return 0;
@@ -152,22 +158,31 @@ void cfg80211_conn_work(struct work_struct *work)
152 struct wireless_dev *wdev; 158 struct wireless_dev *wdev;
153 159
154 rtnl_lock(); 160 rtnl_lock();
161 cfg80211_lock_rdev(drv);
155 mutex_lock(&drv->devlist_mtx); 162 mutex_lock(&drv->devlist_mtx);
156 163
157 list_for_each_entry(wdev, &drv->netdev_list, list) { 164 list_for_each_entry(wdev, &drv->netdev_list, list) {
158 if (!netif_running(wdev->netdev)) 165 wdev_lock(wdev);
166 if (!netif_running(wdev->netdev)) {
167 wdev_unlock(wdev);
159 continue; 168 continue;
160 if (wdev->sme_state != CFG80211_SME_CONNECTING) 169 }
170 if (wdev->sme_state != CFG80211_SME_CONNECTING) {
171 wdev_unlock(wdev);
161 continue; 172 continue;
173 }
162 if (cfg80211_conn_do_work(wdev)) 174 if (cfg80211_conn_do_work(wdev))
163 cfg80211_connect_result(wdev->netdev, 175 __cfg80211_connect_result(
164 wdev->conn->params.bssid, 176 wdev->netdev,
165 NULL, 0, NULL, 0, 177 wdev->conn->params.bssid,
166 WLAN_STATUS_UNSPECIFIED_FAILURE, 178 NULL, 0, NULL, 0,
167 GFP_ATOMIC); 179 WLAN_STATUS_UNSPECIFIED_FAILURE,
180 false);
181 wdev_unlock(wdev);
168 } 182 }
169 183
170 mutex_unlock(&drv->devlist_mtx); 184 mutex_unlock(&drv->devlist_mtx);
185 cfg80211_unlock_rdev(drv);
171 rtnl_unlock(); 186 rtnl_unlock();
172} 187}
173 188
@@ -177,6 +192,8 @@ static bool cfg80211_get_conn_bss(struct wireless_dev *wdev)
177 struct cfg80211_bss *bss; 192 struct cfg80211_bss *bss;
178 u16 capa = WLAN_CAPABILITY_ESS; 193 u16 capa = WLAN_CAPABILITY_ESS;
179 194
195 ASSERT_WDEV_LOCK(wdev);
196
180 if (wdev->conn->params.privacy) 197 if (wdev->conn->params.privacy)
181 capa |= WLAN_CAPABILITY_PRIVACY; 198 capa |= WLAN_CAPABILITY_PRIVACY;
182 199
@@ -198,11 +215,13 @@ static bool cfg80211_get_conn_bss(struct wireless_dev *wdev)
198 return true; 215 return true;
199} 216}
200 217
201void cfg80211_sme_scan_done(struct net_device *dev) 218static void __cfg80211_sme_scan_done(struct net_device *dev)
202{ 219{
203 struct wireless_dev *wdev = dev->ieee80211_ptr; 220 struct wireless_dev *wdev = dev->ieee80211_ptr;
204 struct cfg80211_registered_device *drv = wiphy_to_dev(wdev->wiphy); 221 struct cfg80211_registered_device *drv = wiphy_to_dev(wdev->wiphy);
205 222
223 ASSERT_WDEV_LOCK(wdev);
224
206 if (wdev->sme_state != CFG80211_SME_CONNECTING) 225 if (wdev->sme_state != CFG80211_SME_CONNECTING)
207 return; 226 return;
208 227
@@ -218,15 +237,26 @@ void cfg80211_sme_scan_done(struct net_device *dev)
218 if (wdev->conn->state == CFG80211_CONN_SCAN_AGAIN) 237 if (wdev->conn->state == CFG80211_CONN_SCAN_AGAIN)
219 schedule_work(&drv->conn_work); 238 schedule_work(&drv->conn_work);
220 else 239 else
221 cfg80211_connect_result(dev, wdev->conn->params.bssid, 240 __cfg80211_connect_result(
222 NULL, 0, NULL, 0, 241 wdev->netdev,
223 WLAN_STATUS_UNSPECIFIED_FAILURE, 242 wdev->conn->params.bssid,
224 GFP_ATOMIC); 243 NULL, 0, NULL, 0,
225 return; 244 WLAN_STATUS_UNSPECIFIED_FAILURE,
245 false);
226 } 246 }
227} 247}
228 248
229void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len) 249void cfg80211_sme_scan_done(struct net_device *dev)
250{
251 struct wireless_dev *wdev = dev->ieee80211_ptr;
252
253 wdev_lock(wdev);
254 __cfg80211_sme_scan_done(dev);
255 wdev_unlock(wdev);
256}
257
258void cfg80211_sme_rx_auth(struct net_device *dev,
259 const u8 *buf, size_t len)
230{ 260{
231 struct wireless_dev *wdev = dev->ieee80211_ptr; 261 struct wireless_dev *wdev = dev->ieee80211_ptr;
232 struct wiphy *wiphy = wdev->wiphy; 262 struct wiphy *wiphy = wdev->wiphy;
@@ -234,6 +264,8 @@ void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len)
234 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; 264 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
235 u16 status_code = le16_to_cpu(mgmt->u.auth.status_code); 265 u16 status_code = le16_to_cpu(mgmt->u.auth.status_code);
236 266
267 ASSERT_WDEV_LOCK(wdev);
268
237 /* should only RX auth frames when connecting */ 269 /* should only RX auth frames when connecting */
238 if (wdev->sme_state != CFG80211_SME_CONNECTING) 270 if (wdev->sme_state != CFG80211_SME_CONNECTING)
239 return; 271 return;
@@ -273,10 +305,10 @@ void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len)
273 } 305 }
274} 306}
275 307
276static void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, 308void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
277 const u8 *req_ie, size_t req_ie_len, 309 const u8 *req_ie, size_t req_ie_len,
278 const u8 *resp_ie, size_t resp_ie_len, 310 const u8 *resp_ie, size_t resp_ie_len,
279 u16 status, bool wextev, gfp_t gfp) 311 u16 status, bool wextev)
280{ 312{
281 struct wireless_dev *wdev = dev->ieee80211_ptr; 313 struct wireless_dev *wdev = dev->ieee80211_ptr;
282 struct cfg80211_bss *bss; 314 struct cfg80211_bss *bss;
@@ -284,18 +316,20 @@ static void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
284 union iwreq_data wrqu; 316 union iwreq_data wrqu;
285#endif 317#endif
286 318
319 ASSERT_WDEV_LOCK(wdev);
320
287 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION)) 321 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
288 return; 322 return;
289 323
290 if (wdev->sme_state == CFG80211_SME_CONNECTED) 324 if (wdev->sme_state == CFG80211_SME_CONNECTED)
291 nl80211_send_roamed(wiphy_to_dev(wdev->wiphy), dev, 325 nl80211_send_roamed(wiphy_to_dev(wdev->wiphy), dev,
292 bssid, req_ie, req_ie_len, 326 bssid, req_ie, req_ie_len,
293 resp_ie, resp_ie_len, gfp); 327 resp_ie, resp_ie_len, GFP_KERNEL);
294 else 328 else
295 nl80211_send_connect_result(wiphy_to_dev(wdev->wiphy), dev, 329 nl80211_send_connect_result(wiphy_to_dev(wdev->wiphy), dev,
296 bssid, req_ie, req_ie_len, 330 bssid, req_ie, req_ie_len,
297 resp_ie, resp_ie_len, 331 resp_ie, resp_ie_len,
298 status, gfp); 332 status, GFP_KERNEL);
299 333
300#ifdef CONFIG_WIRELESS_EXT 334#ifdef CONFIG_WIRELESS_EXT
301 if (wextev) { 335 if (wextev) {
@@ -362,21 +396,43 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
362 const u8 *resp_ie, size_t resp_ie_len, 396 const u8 *resp_ie, size_t resp_ie_len,
363 u16 status, gfp_t gfp) 397 u16 status, gfp_t gfp)
364{ 398{
365 bool wextev = status == WLAN_STATUS_SUCCESS; 399 struct wireless_dev *wdev = dev->ieee80211_ptr;
366 __cfg80211_connect_result(dev, bssid, req_ie, req_ie_len, resp_ie, resp_ie_len, status, wextev, gfp); 400 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
401 struct cfg80211_event *ev;
402 unsigned long flags;
403
404 ev = kzalloc(sizeof(*ev) + req_ie_len + resp_ie_len, gfp);
405 if (!ev)
406 return;
407
408 ev->type = EVENT_CONNECT_RESULT;
409 memcpy(ev->cr.bssid, bssid, ETH_ALEN);
410 ev->cr.req_ie = ((u8 *)ev) + sizeof(*ev);
411 ev->cr.req_ie_len = req_ie_len;
412 memcpy((void *)ev->cr.req_ie, req_ie, req_ie_len);
413 ev->cr.resp_ie = ((u8 *)ev) + sizeof(*ev) + req_ie_len;
414 ev->cr.resp_ie_len = resp_ie_len;
415 memcpy((void *)ev->cr.resp_ie, resp_ie, resp_ie_len);
416 ev->cr.status = status;
417
418 spin_lock_irqsave(&wdev->event_lock, flags);
419 list_add_tail(&ev->list, &wdev->event_list);
420 spin_unlock_irqrestore(&wdev->event_lock, flags);
421 schedule_work(&rdev->event_work);
367} 422}
368EXPORT_SYMBOL(cfg80211_connect_result); 423EXPORT_SYMBOL(cfg80211_connect_result);
369 424
370void cfg80211_roamed(struct net_device *dev, const u8 *bssid, 425void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid,
371 const u8 *req_ie, size_t req_ie_len, 426 const u8 *req_ie, size_t req_ie_len,
372 const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp) 427 const u8 *resp_ie, size_t resp_ie_len)
373{ 428{
374 struct wireless_dev *wdev = dev->ieee80211_ptr;
375 struct cfg80211_bss *bss; 429 struct cfg80211_bss *bss;
376#ifdef CONFIG_WIRELESS_EXT 430#ifdef CONFIG_WIRELESS_EXT
377 union iwreq_data wrqu; 431 union iwreq_data wrqu;
378#endif 432#endif
379 433
434 ASSERT_WDEV_LOCK(wdev);
435
380 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION)) 436 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
381 return; 437 return;
382 438
@@ -402,31 +458,62 @@ void cfg80211_roamed(struct net_device *dev, const u8 *bssid,
402 cfg80211_hold_bss(bss_from_pub(bss)); 458 cfg80211_hold_bss(bss_from_pub(bss));
403 wdev->current_bss = bss_from_pub(bss); 459 wdev->current_bss = bss_from_pub(bss);
404 460
405 nl80211_send_roamed(wiphy_to_dev(wdev->wiphy), dev, bssid, 461 nl80211_send_roamed(wiphy_to_dev(wdev->wiphy), wdev->netdev, bssid,
406 req_ie, req_ie_len, resp_ie, resp_ie_len, gfp); 462 req_ie, req_ie_len, resp_ie, resp_ie_len,
463 GFP_KERNEL);
407 464
408#ifdef CONFIG_WIRELESS_EXT 465#ifdef CONFIG_WIRELESS_EXT
409 if (req_ie) { 466 if (req_ie) {
410 memset(&wrqu, 0, sizeof(wrqu)); 467 memset(&wrqu, 0, sizeof(wrqu));
411 wrqu.data.length = req_ie_len; 468 wrqu.data.length = req_ie_len;
412 wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, req_ie); 469 wireless_send_event(wdev->netdev, IWEVASSOCRESPIE,
470 &wrqu, req_ie);
413 } 471 }
414 472
415 if (resp_ie) { 473 if (resp_ie) {
416 memset(&wrqu, 0, sizeof(wrqu)); 474 memset(&wrqu, 0, sizeof(wrqu));
417 wrqu.data.length = resp_ie_len; 475 wrqu.data.length = resp_ie_len;
418 wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, resp_ie); 476 wireless_send_event(wdev->netdev, IWEVASSOCRESPIE,
477 &wrqu, resp_ie);
419 } 478 }
420 479
421 memset(&wrqu, 0, sizeof(wrqu)); 480 memset(&wrqu, 0, sizeof(wrqu));
422 wrqu.ap_addr.sa_family = ARPHRD_ETHER; 481 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
423 memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN); 482 memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
424 wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); 483 wireless_send_event(wdev->netdev, SIOCGIWAP, &wrqu, NULL);
425#endif 484#endif
426} 485}
486
487void cfg80211_roamed(struct net_device *dev, const u8 *bssid,
488 const u8 *req_ie, size_t req_ie_len,
489 const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp)
490{
491 struct wireless_dev *wdev = dev->ieee80211_ptr;
492 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
493 struct cfg80211_event *ev;
494 unsigned long flags;
495
496 ev = kzalloc(sizeof(*ev) + req_ie_len + resp_ie_len, gfp);
497 if (!ev)
498 return;
499
500 ev->type = EVENT_ROAMED;
501 memcpy(ev->rm.bssid, bssid, ETH_ALEN);
502 ev->rm.req_ie = ((u8 *)ev) + sizeof(*ev);
503 ev->rm.req_ie_len = req_ie_len;
504 memcpy((void *)ev->rm.req_ie, req_ie, req_ie_len);
505 ev->rm.resp_ie = ((u8 *)ev) + sizeof(*ev) + req_ie_len;
506 ev->rm.resp_ie_len = resp_ie_len;
507 memcpy((void *)ev->rm.resp_ie, resp_ie, resp_ie_len);
508
509 spin_lock_irqsave(&wdev->event_lock, flags);
510 list_add_tail(&ev->list, &wdev->event_list);
511 spin_unlock_irqrestore(&wdev->event_lock, flags);
512 schedule_work(&rdev->event_work);
513}
427EXPORT_SYMBOL(cfg80211_roamed); 514EXPORT_SYMBOL(cfg80211_roamed);
428 515
429void __cfg80211_disconnected(struct net_device *dev, gfp_t gfp, u8 *ie, 516void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
430 size_t ie_len, u16 reason, bool from_ap) 517 size_t ie_len, u16 reason, bool from_ap)
431{ 518{
432 struct wireless_dev *wdev = dev->ieee80211_ptr; 519 struct wireless_dev *wdev = dev->ieee80211_ptr;
@@ -434,6 +521,8 @@ void __cfg80211_disconnected(struct net_device *dev, gfp_t gfp, u8 *ie,
434 union iwreq_data wrqu; 521 union iwreq_data wrqu;
435#endif 522#endif
436 523
524 ASSERT_WDEV_LOCK(wdev);
525
437 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION)) 526 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
438 return; 527 return;
439 528
@@ -456,7 +545,7 @@ void __cfg80211_disconnected(struct net_device *dev, gfp_t gfp, u8 *ie,
456 } 545 }
457 546
458 nl80211_send_disconnected(wiphy_to_dev(wdev->wiphy), dev, 547 nl80211_send_disconnected(wiphy_to_dev(wdev->wiphy), dev,
459 reason, ie, ie_len, from_ap, gfp); 548 reason, ie, ie_len, from_ap);
460 549
461#ifdef CONFIG_WIRELESS_EXT 550#ifdef CONFIG_WIRELESS_EXT
462 memset(&wrqu, 0, sizeof(wrqu)); 551 memset(&wrqu, 0, sizeof(wrqu));
@@ -468,16 +557,36 @@ void __cfg80211_disconnected(struct net_device *dev, gfp_t gfp, u8 *ie,
468void cfg80211_disconnected(struct net_device *dev, u16 reason, 557void cfg80211_disconnected(struct net_device *dev, u16 reason,
469 u8 *ie, size_t ie_len, gfp_t gfp) 558 u8 *ie, size_t ie_len, gfp_t gfp)
470{ 559{
471 __cfg80211_disconnected(dev, gfp, ie, ie_len, reason, true); 560 struct wireless_dev *wdev = dev->ieee80211_ptr;
561 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
562 struct cfg80211_event *ev;
563 unsigned long flags;
564
565 ev = kzalloc(sizeof(*ev) + ie_len, gfp);
566 if (!ev)
567 return;
568
569 ev->type = EVENT_DISCONNECTED;
570 ev->dc.ie = ((u8 *)ev) + sizeof(*ev);
571 ev->dc.ie_len = ie_len;
572 memcpy((void *)ev->dc.ie, ie, ie_len);
573 ev->dc.reason = reason;
574
575 spin_lock_irqsave(&wdev->event_lock, flags);
576 list_add_tail(&ev->list, &wdev->event_list);
577 spin_unlock_irqrestore(&wdev->event_lock, flags);
578 schedule_work(&rdev->event_work);
472} 579}
473EXPORT_SYMBOL(cfg80211_disconnected); 580EXPORT_SYMBOL(cfg80211_disconnected);
474 581
475int cfg80211_connect(struct cfg80211_registered_device *rdev, 582int __cfg80211_connect(struct cfg80211_registered_device *rdev,
476 struct net_device *dev, 583 struct net_device *dev,
477 struct cfg80211_connect_params *connect) 584 struct cfg80211_connect_params *connect)
478{ 585{
479 int err;
480 struct wireless_dev *wdev = dev->ieee80211_ptr; 586 struct wireless_dev *wdev = dev->ieee80211_ptr;
587 int err;
588
589 ASSERT_WDEV_LOCK(wdev);
481 590
482 if (wdev->sme_state != CFG80211_SME_IDLE) 591 if (wdev->sme_state != CFG80211_SME_IDLE)
483 return -EALREADY; 592 return -EALREADY;
@@ -572,12 +681,27 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
572 } 681 }
573} 682}
574 683
575int cfg80211_disconnect(struct cfg80211_registered_device *rdev, 684int cfg80211_connect(struct cfg80211_registered_device *rdev,
576 struct net_device *dev, u16 reason, bool wextev) 685 struct net_device *dev,
686 struct cfg80211_connect_params *connect)
687{
688 int err;
689
690 wdev_lock(dev->ieee80211_ptr);
691 err = __cfg80211_connect(rdev, dev, connect);
692 wdev_unlock(dev->ieee80211_ptr);
693
694 return err;
695}
696
697int __cfg80211_disconnect(struct cfg80211_registered_device *rdev,
698 struct net_device *dev, u16 reason, bool wextev)
577{ 699{
578 struct wireless_dev *wdev = dev->ieee80211_ptr; 700 struct wireless_dev *wdev = dev->ieee80211_ptr;
579 int err; 701 int err;
580 702
703 ASSERT_WDEV_LOCK(wdev);
704
581 if (wdev->sme_state == CFG80211_SME_IDLE) 705 if (wdev->sme_state == CFG80211_SME_IDLE)
582 return -EINVAL; 706 return -EINVAL;
583 707
@@ -601,8 +725,9 @@ int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
601 } 725 }
602 726
603 /* wdev->conn->params.bssid must be set if > SCANNING */ 727 /* wdev->conn->params.bssid must be set if > SCANNING */
604 err = cfg80211_mlme_deauth(rdev, dev, wdev->conn->params.bssid, 728 err = __cfg80211_mlme_deauth(rdev, dev,
605 NULL, 0, reason); 729 wdev->conn->params.bssid,
730 NULL, 0, reason);
606 if (err) 731 if (err)
607 return err; 732 return err;
608 } else { 733 } else {
@@ -612,21 +737,36 @@ int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
612 } 737 }
613 738
614 if (wdev->sme_state == CFG80211_SME_CONNECTED) 739 if (wdev->sme_state == CFG80211_SME_CONNECTED)
615 __cfg80211_disconnected(dev, GFP_KERNEL, NULL, 0, 0, false); 740 __cfg80211_disconnected(dev, NULL, 0, 0, false);
616 else if (wdev->sme_state == CFG80211_SME_CONNECTING) 741 else if (wdev->sme_state == CFG80211_SME_CONNECTING)
617 __cfg80211_connect_result(dev, NULL, NULL, 0, NULL, 0, 742 __cfg80211_connect_result(dev, NULL, NULL, 0, NULL, 0,
618 WLAN_STATUS_UNSPECIFIED_FAILURE, 743 WLAN_STATUS_UNSPECIFIED_FAILURE,
619 wextev, GFP_KERNEL); 744 wextev);
620 745
621 return 0; 746 return 0;
622} 747}
623 748
749int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
750 struct net_device *dev,
751 u16 reason, bool wextev)
752{
753 int err;
754
755 wdev_lock(dev->ieee80211_ptr);
756 err = __cfg80211_disconnect(rdev, dev, reason, wextev);
757 wdev_unlock(dev->ieee80211_ptr);
758
759 return err;
760}
761
624void cfg80211_sme_disassoc(struct net_device *dev, int idx) 762void cfg80211_sme_disassoc(struct net_device *dev, int idx)
625{ 763{
626 struct wireless_dev *wdev = dev->ieee80211_ptr; 764 struct wireless_dev *wdev = dev->ieee80211_ptr;
627 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 765 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
628 u8 bssid[ETH_ALEN]; 766 u8 bssid[ETH_ALEN];
629 767
768 ASSERT_WDEV_LOCK(wdev);
769
630 if (!wdev->conn) 770 if (!wdev->conn)
631 return; 771 return;
632 772