aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/sme.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/sme.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/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