aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/cfg80211.h24
-rw-r--r--net/mac80211/cfg.c12
-rw-r--r--net/mac80211/ieee80211_i.h6
-rw-r--r--net/mac80211/mlme.c25
-rw-r--r--net/wireless/core.c92
-rw-r--r--net/wireless/core.h100
-rw-r--r--net/wireless/ibss.c133
-rw-r--r--net/wireless/mlme.c214
-rw-r--r--net/wireless/nl80211.c8
-rw-r--r--net/wireless/nl80211.h2
-rw-r--r--net/wireless/scan.c30
-rw-r--r--net/wireless/sme.c252
-rw-r--r--net/wireless/wext-sme.c125
13 files changed, 823 insertions, 200 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 60c1f11da45f..83c2c727d71e 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -555,6 +555,7 @@ struct cfg80211_scan_request {
555 /* internal */ 555 /* internal */
556 struct wiphy *wiphy; 556 struct wiphy *wiphy;
557 int ifidx; 557 int ifidx;
558 bool aborted;
558}; 559};
559 560
560/** 561/**
@@ -998,9 +999,11 @@ struct cfg80211_ops {
998 int (*assoc)(struct wiphy *wiphy, struct net_device *dev, 999 int (*assoc)(struct wiphy *wiphy, struct net_device *dev,
999 struct cfg80211_assoc_request *req); 1000 struct cfg80211_assoc_request *req);
1000 int (*deauth)(struct wiphy *wiphy, struct net_device *dev, 1001 int (*deauth)(struct wiphy *wiphy, struct net_device *dev,
1001 struct cfg80211_deauth_request *req); 1002 struct cfg80211_deauth_request *req,
1003 void *cookie);
1002 int (*disassoc)(struct wiphy *wiphy, struct net_device *dev, 1004 int (*disassoc)(struct wiphy *wiphy, struct net_device *dev,
1003 struct cfg80211_disassoc_request *req); 1005 struct cfg80211_disassoc_request *req,
1006 void *cookie);
1004 1007
1005 int (*connect)(struct wiphy *wiphy, struct net_device *dev, 1008 int (*connect)(struct wiphy *wiphy, struct net_device *dev,
1006 struct cfg80211_connect_params *sme); 1009 struct cfg80211_connect_params *sme);
@@ -1249,10 +1252,12 @@ struct wireless_dev {
1249 struct wiphy *wiphy; 1252 struct wiphy *wiphy;
1250 enum nl80211_iftype iftype; 1253 enum nl80211_iftype iftype;
1251 1254
1252 /* private to the generic wireless code */ 1255 /* the remainder of this struct should be private to cfg80211 */
1253 struct list_head list; 1256 struct list_head list;
1254 struct net_device *netdev; 1257 struct net_device *netdev;
1255 1258
1259 struct mutex mtx;
1260
1256 /* currently used for IBSS and SME - might be rearranged later */ 1261 /* currently used for IBSS and SME - might be rearranged later */
1257 u8 ssid[IEEE80211_MAX_SSID_LEN]; 1262 u8 ssid[IEEE80211_MAX_SSID_LEN];
1258 u8 ssid_len; 1263 u8 ssid_len;
@@ -1263,6 +1268,9 @@ struct wireless_dev {
1263 } sme_state; 1268 } sme_state;
1264 struct cfg80211_conn *conn; 1269 struct cfg80211_conn *conn;
1265 1270
1271 struct list_head event_list;
1272 spinlock_t event_lock;
1273
1266 struct cfg80211_internal_bss *authtry_bsses[MAX_AUTH_BSSES]; 1274 struct cfg80211_internal_bss *authtry_bsses[MAX_AUTH_BSSES];
1267 struct cfg80211_internal_bss *auth_bsses[MAX_AUTH_BSSES]; 1275 struct cfg80211_internal_bss *auth_bsses[MAX_AUTH_BSSES];
1268 struct cfg80211_internal_bss *current_bss; /* associated / joined */ 1276 struct cfg80211_internal_bss *current_bss; /* associated / joined */
@@ -1765,24 +1773,30 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr);
1765 * @dev: network device 1773 * @dev: network device
1766 * @buf: deauthentication frame (header + body) 1774 * @buf: deauthentication frame (header + body)
1767 * @len: length of the frame data 1775 * @len: length of the frame data
1776 * @cookie: cookie from ->deauth if called within that callback,
1777 * %NULL otherwise
1768 * 1778 *
1769 * This function is called whenever deauthentication has been processed in 1779 * This function is called whenever deauthentication has been processed in
1770 * station mode. This includes both received deauthentication frames and 1780 * station mode. This includes both received deauthentication frames and
1771 * locally generated ones. This function may sleep. 1781 * locally generated ones. This function may sleep.
1772 */ 1782 */
1773void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len); 1783void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len,
1784 void *cookie);
1774 1785
1775/** 1786/**
1776 * cfg80211_send_disassoc - notification of processed disassociation 1787 * cfg80211_send_disassoc - notification of processed disassociation
1777 * @dev: network device 1788 * @dev: network device
1778 * @buf: disassociation response frame (header + body) 1789 * @buf: disassociation response frame (header + body)
1779 * @len: length of the frame data 1790 * @len: length of the frame data
1791 * @cookie: cookie from ->disassoc if called within that callback,
1792 * %NULL otherwise
1780 * 1793 *
1781 * This function is called whenever disassociation has been processed in 1794 * This function is called whenever disassociation has been processed in
1782 * station mode. This includes both received disassociation frames and locally 1795 * station mode. This includes both received disassociation frames and locally
1783 * generated ones. This function may sleep. 1796 * generated ones. This function may sleep.
1784 */ 1797 */
1785void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len); 1798void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len,
1799 void *cookie);
1786 1800
1787/** 1801/**
1788 * cfg80211_michael_mic_failure - notification of Michael MIC failure (TKIP) 1802 * cfg80211_michael_mic_failure - notification of Michael MIC failure (TKIP)
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7cfc14e4ca07..36f8f245fa4c 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1182,15 +1182,19 @@ static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev,
1182} 1182}
1183 1183
1184static int ieee80211_deauth(struct wiphy *wiphy, struct net_device *dev, 1184static int ieee80211_deauth(struct wiphy *wiphy, struct net_device *dev,
1185 struct cfg80211_deauth_request *req) 1185 struct cfg80211_deauth_request *req,
1186 void *cookie)
1186{ 1187{
1187 return ieee80211_mgd_deauth(IEEE80211_DEV_TO_SUB_IF(dev), req); 1188 return ieee80211_mgd_deauth(IEEE80211_DEV_TO_SUB_IF(dev),
1189 req, cookie);
1188} 1190}
1189 1191
1190static int ieee80211_disassoc(struct wiphy *wiphy, struct net_device *dev, 1192static int ieee80211_disassoc(struct wiphy *wiphy, struct net_device *dev,
1191 struct cfg80211_disassoc_request *req) 1193 struct cfg80211_disassoc_request *req,
1194 void *cookie)
1192{ 1195{
1193 return ieee80211_mgd_disassoc(IEEE80211_DEV_TO_SUB_IF(dev), req); 1196 return ieee80211_mgd_disassoc(IEEE80211_DEV_TO_SUB_IF(dev),
1197 req, cookie);
1194} 1198}
1195 1199
1196static int ieee80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, 1200static int ieee80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 2e92bbd9b2d0..327aabc07abe 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -918,9 +918,11 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
918int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, 918int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
919 struct cfg80211_assoc_request *req); 919 struct cfg80211_assoc_request *req);
920int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, 920int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
921 struct cfg80211_deauth_request *req); 921 struct cfg80211_deauth_request *req,
922 void *cookie);
922int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, 923int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
923 struct cfg80211_disassoc_request *req); 924 struct cfg80211_disassoc_request *req,
925 void *cookie);
924ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, 926ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata,
925 struct sk_buff *skb); 927 struct sk_buff *skb);
926void ieee80211_send_pspoll(struct ieee80211_local *local, 928void ieee80211_send_pspoll(struct ieee80211_local *local,
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 15dbb57ab55e..c9db9646025b 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -386,7 +386,8 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
386 386
387 387
388static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, 388static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
389 const u8 *bssid, u16 stype, u16 reason) 389 const u8 *bssid, u16 stype, u16 reason,
390 void *cookie)
390{ 391{
391 struct ieee80211_local *local = sdata->local; 392 struct ieee80211_local *local = sdata->local;
392 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 393 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
@@ -412,9 +413,9 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
412 mgmt->u.deauth.reason_code = cpu_to_le16(reason); 413 mgmt->u.deauth.reason_code = cpu_to_le16(reason);
413 414
414 if (stype == IEEE80211_STYPE_DEAUTH) 415 if (stype == IEEE80211_STYPE_DEAUTH)
415 cfg80211_send_deauth(sdata->dev, (u8 *) mgmt, skb->len); 416 cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len, cookie);
416 else 417 else
417 cfg80211_send_disassoc(sdata->dev, (u8 *) mgmt, skb->len); 418 cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len, cookie);
418 ieee80211_tx_skb(sdata, skb, ifmgd->flags & IEEE80211_STA_MFP_ENABLED); 419 ieee80211_tx_skb(sdata, skb, ifmgd->flags & IEEE80211_STA_MFP_ENABLED);
419} 420}
420 421
@@ -1837,10 +1838,12 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
1837 /* no action */ 1838 /* no action */
1838 break; 1839 break;
1839 case RX_MGMT_CFG80211_DEAUTH: 1840 case RX_MGMT_CFG80211_DEAUTH:
1840 cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); 1841 cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len,
1842 NULL);
1841 break; 1843 break;
1842 case RX_MGMT_CFG80211_DISASSOC: 1844 case RX_MGMT_CFG80211_DISASSOC:
1843 cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len); 1845 cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len,
1846 NULL);
1844 break; 1847 break;
1845 default: 1848 default:
1846 WARN(1, "unexpected: %d", rma); 1849 WARN(1, "unexpected: %d", rma);
@@ -2273,7 +2276,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
2273} 2276}
2274 2277
2275int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, 2278int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
2276 struct cfg80211_deauth_request *req) 2279 struct cfg80211_deauth_request *req,
2280 void *cookie)
2277{ 2281{
2278 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 2282 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2279 struct ieee80211_mgd_work *wk; 2283 struct ieee80211_mgd_work *wk;
@@ -2305,13 +2309,15 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
2305 mutex_unlock(&ifmgd->mtx); 2309 mutex_unlock(&ifmgd->mtx);
2306 2310
2307 ieee80211_send_deauth_disassoc(sdata, bssid, 2311 ieee80211_send_deauth_disassoc(sdata, bssid,
2308 IEEE80211_STYPE_DEAUTH, req->reason_code); 2312 IEEE80211_STYPE_DEAUTH, req->reason_code,
2313 cookie);
2309 2314
2310 return 0; 2315 return 0;
2311} 2316}
2312 2317
2313int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, 2318int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
2314 struct cfg80211_disassoc_request *req) 2319 struct cfg80211_disassoc_request *req,
2320 void *cookie)
2315{ 2321{
2316 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 2322 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2317 2323
@@ -2331,6 +2337,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
2331 mutex_unlock(&ifmgd->mtx); 2337 mutex_unlock(&ifmgd->mtx);
2332 2338
2333 ieee80211_send_deauth_disassoc(sdata, req->bss->bssid, 2339 ieee80211_send_deauth_disassoc(sdata, req->bss->bssid,
2334 IEEE80211_STYPE_DISASSOC, req->reason_code); 2340 IEEE80211_STYPE_DISASSOC, req->reason_code,
2341 cookie);
2335 return 0; 2342 return 0;
2336} 2343}
diff --git a/net/wireless/core.c b/net/wireless/core.c
index c6813beded06..9c73769440a8 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -257,6 +257,71 @@ static void cfg80211_rfkill_sync_work(struct work_struct *work)
257 cfg80211_rfkill_set_block(drv, rfkill_blocked(drv->rfkill)); 257 cfg80211_rfkill_set_block(drv, rfkill_blocked(drv->rfkill));
258} 258}
259 259
260static void cfg80211_process_events(struct wireless_dev *wdev)
261{
262 struct cfg80211_event *ev;
263 unsigned long flags;
264
265 spin_lock_irqsave(&wdev->event_lock, flags);
266 while (!list_empty(&wdev->event_list)) {
267 ev = list_first_entry(&wdev->event_list,
268 struct cfg80211_event, list);
269 list_del(&ev->list);
270 spin_unlock_irqrestore(&wdev->event_lock, flags);
271
272 wdev_lock(wdev);
273 switch (ev->type) {
274 case EVENT_CONNECT_RESULT:
275 __cfg80211_connect_result(
276 wdev->netdev, ev->cr.bssid,
277 ev->cr.req_ie, ev->cr.req_ie_len,
278 ev->cr.resp_ie, ev->cr.resp_ie_len,
279 ev->cr.status,
280 ev->cr.status == WLAN_STATUS_SUCCESS);
281 break;
282 case EVENT_ROAMED:
283 __cfg80211_roamed(wdev, ev->rm.bssid,
284 ev->rm.req_ie, ev->rm.req_ie_len,
285 ev->rm.resp_ie, ev->rm.resp_ie_len);
286 break;
287 case EVENT_DISCONNECTED:
288 __cfg80211_disconnected(wdev->netdev,
289 ev->dc.ie, ev->dc.ie_len,
290 ev->dc.reason, true);
291 break;
292 case EVENT_IBSS_JOINED:
293 __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid);
294 break;
295 }
296 wdev_unlock(wdev);
297
298 kfree(ev);
299
300 spin_lock_irqsave(&wdev->event_lock, flags);
301 }
302 spin_unlock_irqrestore(&wdev->event_lock, flags);
303}
304
305static void cfg80211_event_work(struct work_struct *work)
306{
307 struct cfg80211_registered_device *rdev;
308 struct wireless_dev *wdev;
309
310 rdev = container_of(work, struct cfg80211_registered_device,
311 event_work);
312
313 rtnl_lock();
314 cfg80211_lock_rdev(rdev);
315 mutex_lock(&rdev->devlist_mtx);
316
317 list_for_each_entry(wdev, &rdev->netdev_list, list)
318 cfg80211_process_events(wdev);
319
320 mutex_unlock(&rdev->devlist_mtx);
321 cfg80211_unlock_rdev(rdev);
322 rtnl_unlock();
323}
324
260/* exported functions */ 325/* exported functions */
261 326
262struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) 327struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
@@ -299,6 +364,7 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
299 INIT_LIST_HEAD(&drv->netdev_list); 364 INIT_LIST_HEAD(&drv->netdev_list);
300 spin_lock_init(&drv->bss_lock); 365 spin_lock_init(&drv->bss_lock);
301 INIT_LIST_HEAD(&drv->bss_list); 366 INIT_LIST_HEAD(&drv->bss_list);
367 INIT_WORK(&drv->scan_done_wk, __cfg80211_scan_done);
302 368
303 device_initialize(&drv->wiphy.dev); 369 device_initialize(&drv->wiphy.dev);
304 drv->wiphy.dev.class = &ieee80211_class; 370 drv->wiphy.dev.class = &ieee80211_class;
@@ -316,6 +382,7 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
316 382
317 INIT_WORK(&drv->rfkill_sync, cfg80211_rfkill_sync_work); 383 INIT_WORK(&drv->rfkill_sync, cfg80211_rfkill_sync_work);
318 INIT_WORK(&drv->conn_work, cfg80211_conn_work); 384 INIT_WORK(&drv->conn_work, cfg80211_conn_work);
385 INIT_WORK(&drv->event_work, cfg80211_event_work);
319 386
320 /* 387 /*
321 * Initialize wiphy parameters to IEEE 802.11 MIB default values. 388 * Initialize wiphy parameters to IEEE 802.11 MIB default values.
@@ -477,6 +544,9 @@ void wiphy_unregister(struct wiphy *wiphy)
477 mutex_unlock(&drv->mtx); 544 mutex_unlock(&drv->mtx);
478 545
479 cancel_work_sync(&drv->conn_work); 546 cancel_work_sync(&drv->conn_work);
547 cancel_work_sync(&drv->scan_done_wk);
548 kfree(drv->scan_req);
549 flush_work(&drv->event_work);
480 550
481 cfg80211_debugfs_drv_del(drv); 551 cfg80211_debugfs_drv_del(drv);
482 552
@@ -535,6 +605,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
535 605
536 switch (state) { 606 switch (state) {
537 case NETDEV_REGISTER: 607 case NETDEV_REGISTER:
608 mutex_init(&wdev->mtx);
609 INIT_LIST_HEAD(&wdev->event_list);
610 spin_lock_init(&wdev->event_lock);
538 mutex_lock(&rdev->devlist_mtx); 611 mutex_lock(&rdev->devlist_mtx);
539 list_add(&wdev->list, &rdev->netdev_list); 612 list_add(&wdev->list, &rdev->netdev_list);
540 if (sysfs_create_link(&dev->dev.kobj, &rdev->wiphy.dev.kobj, 613 if (sysfs_create_link(&dev->dev.kobj, &rdev->wiphy.dev.kobj,
@@ -566,15 +639,17 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
566 cfg80211_leave_ibss(rdev, dev, true); 639 cfg80211_leave_ibss(rdev, dev, true);
567 break; 640 break;
568 case NL80211_IFTYPE_STATION: 641 case NL80211_IFTYPE_STATION:
642 wdev_lock(wdev);
569#ifdef CONFIG_WIRELESS_EXT 643#ifdef CONFIG_WIRELESS_EXT
570 kfree(wdev->wext.ie); 644 kfree(wdev->wext.ie);
571 wdev->wext.ie = NULL; 645 wdev->wext.ie = NULL;
572 wdev->wext.ie_len = 0; 646 wdev->wext.ie_len = 0;
573 wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; 647 wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
574#endif 648#endif
575 cfg80211_disconnect(rdev, dev, 649 __cfg80211_disconnect(rdev, dev,
576 WLAN_REASON_DEAUTH_LEAVING, true); 650 WLAN_REASON_DEAUTH_LEAVING, true);
577 cfg80211_mlme_down(rdev, dev); 651 cfg80211_mlme_down(rdev, dev);
652 wdev_unlock(wdev);
578 break; 653 break;
579 default: 654 default:
580 break; 655 break;
@@ -582,20 +657,24 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
582 break; 657 break;
583 case NETDEV_UP: 658 case NETDEV_UP:
584#ifdef CONFIG_WIRELESS_EXT 659#ifdef CONFIG_WIRELESS_EXT
660 cfg80211_lock_rdev(rdev);
661 wdev_lock(wdev);
585 switch (wdev->iftype) { 662 switch (wdev->iftype) {
586 case NL80211_IFTYPE_ADHOC: 663 case NL80211_IFTYPE_ADHOC:
587 if (wdev->wext.ibss.ssid_len) 664 if (wdev->wext.ibss.ssid_len)
588 cfg80211_join_ibss(rdev, dev, 665 __cfg80211_join_ibss(rdev, dev,
589 &wdev->wext.ibss); 666 &wdev->wext.ibss);
590 break; 667 break;
591 case NL80211_IFTYPE_STATION: 668 case NL80211_IFTYPE_STATION:
592 if (wdev->wext.connect.ssid_len) 669 if (wdev->wext.connect.ssid_len)
593 cfg80211_connect(rdev, dev, 670 __cfg80211_connect(rdev, dev,
594 &wdev->wext.connect); 671 &wdev->wext.connect);
595 break; 672 break;
596 default: 673 default:
597 break; 674 break;
598 } 675 }
676 wdev_unlock(wdev);
677 cfg80211_unlock_rdev(rdev);
599#endif 678#endif
600 break; 679 break;
601 case NETDEV_UNREGISTER: 680 case NETDEV_UNREGISTER:
@@ -605,6 +684,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
605 list_del_init(&wdev->list); 684 list_del_init(&wdev->list);
606 } 685 }
607 mutex_unlock(&rdev->devlist_mtx); 686 mutex_unlock(&rdev->devlist_mtx);
687 mutex_destroy(&wdev->mtx);
608 break; 688 break;
609 case NETDEV_PRE_UP: 689 case NETDEV_PRE_UP:
610 if (rfkill_blocked(rdev->rfkill)) 690 if (rfkill_blocked(rdev->rfkill))
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 92da612b3f9e..5ccd642e183b 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -57,12 +57,14 @@ struct cfg80211_registered_device {
57 u32 bss_generation; 57 u32 bss_generation;
58 struct cfg80211_scan_request *scan_req; /* protected by RTNL */ 58 struct cfg80211_scan_request *scan_req; /* protected by RTNL */
59 unsigned long suspend_at; 59 unsigned long suspend_at;
60 struct work_struct scan_done_wk;
60 61
61#ifdef CONFIG_NL80211_TESTMODE 62#ifdef CONFIG_NL80211_TESTMODE
62 struct genl_info *testmode_info; 63 struct genl_info *testmode_info;
63#endif 64#endif
64 65
65 struct work_struct conn_work; 66 struct work_struct conn_work;
67 struct work_struct event_work;
66 68
67#ifdef CONFIG_CFG80211_DEBUGFS 69#ifdef CONFIG_CFG80211_DEBUGFS
68 /* Debugfs entries */ 70 /* Debugfs entries */
@@ -170,12 +172,73 @@ struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx);
170extern struct cfg80211_registered_device * 172extern struct cfg80211_registered_device *
171cfg80211_get_dev_from_ifindex(int ifindex); 173cfg80211_get_dev_from_ifindex(int ifindex);
172 174
175static inline void cfg80211_lock_rdev(struct cfg80211_registered_device *drv)
176{
177 mutex_lock(&drv->mtx);
178}
179
173static inline void cfg80211_unlock_rdev(struct cfg80211_registered_device *drv) 180static inline void cfg80211_unlock_rdev(struct cfg80211_registered_device *drv)
174{ 181{
175 BUG_ON(IS_ERR(drv) || !drv); 182 BUG_ON(IS_ERR(drv) || !drv);
176 mutex_unlock(&drv->mtx); 183 mutex_unlock(&drv->mtx);
177} 184}
178 185
186static inline void wdev_lock(struct wireless_dev *wdev)
187 __acquires(wdev)
188{
189 mutex_lock(&wdev->mtx);
190 __acquire(wdev->mtx);
191}
192
193static inline void wdev_unlock(struct wireless_dev *wdev)
194 __releases(wdev)
195{
196 __release(wdev->mtx);
197 mutex_unlock(&wdev->mtx);
198}
199
200#define ASSERT_RDEV_LOCK(rdev) WARN_ON(!mutex_is_locked(&(rdev)->mtx));
201#define ASSERT_WDEV_LOCK(wdev) WARN_ON(!mutex_is_locked(&(wdev)->mtx));
202
203enum cfg80211_event_type {
204 EVENT_CONNECT_RESULT,
205 EVENT_ROAMED,
206 EVENT_DISCONNECTED,
207 EVENT_IBSS_JOINED,
208};
209
210struct cfg80211_event {
211 struct list_head list;
212 enum cfg80211_event_type type;
213
214 union {
215 struct {
216 u8 bssid[ETH_ALEN];
217 const u8 *req_ie;
218 const u8 *resp_ie;
219 size_t req_ie_len;
220 size_t resp_ie_len;
221 u16 status;
222 } cr;
223 struct {
224 u8 bssid[ETH_ALEN];
225 const u8 *req_ie;
226 const u8 *resp_ie;
227 size_t req_ie_len;
228 size_t resp_ie_len;
229 } rm;
230 struct {
231 const u8 *ie;
232 size_t ie_len;
233 u16 reason;
234 } dc;
235 struct {
236 u8 bssid[ETH_ALEN];
237 } ij;
238 };
239};
240
241
179/* free object */ 242/* free object */
180extern void cfg80211_dev_free(struct cfg80211_registered_device *drv); 243extern void cfg80211_dev_free(struct cfg80211_registered_device *drv);
181 244
@@ -191,25 +254,46 @@ void cfg80211_bss_age(struct cfg80211_registered_device *dev,
191 unsigned long age_secs); 254 unsigned long age_secs);
192 255
193/* IBSS */ 256/* IBSS */
257int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
258 struct net_device *dev,
259 struct cfg80211_ibss_params *params);
194int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, 260int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
195 struct net_device *dev, 261 struct net_device *dev,
196 struct cfg80211_ibss_params *params); 262 struct cfg80211_ibss_params *params);
197void cfg80211_clear_ibss(struct net_device *dev, bool nowext); 263void cfg80211_clear_ibss(struct net_device *dev, bool nowext);
198int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, 264int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
199 struct net_device *dev, bool nowext); 265 struct net_device *dev, bool nowext);
266void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid);
200 267
201/* MLME */ 268/* MLME */
269int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
270 struct net_device *dev,
271 struct ieee80211_channel *chan,
272 enum nl80211_auth_type auth_type,
273 const u8 *bssid,
274 const u8 *ssid, int ssid_len,
275 const u8 *ie, int ie_len);
202int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, 276int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
203 struct net_device *dev, struct ieee80211_channel *chan, 277 struct net_device *dev, struct ieee80211_channel *chan,
204 enum nl80211_auth_type auth_type, const u8 *bssid, 278 enum nl80211_auth_type auth_type, const u8 *bssid,
205 const u8 *ssid, int ssid_len, 279 const u8 *ssid, int ssid_len,
206 const u8 *ie, int ie_len); 280 const u8 *ie, int ie_len);
281int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
282 struct net_device *dev,
283 struct ieee80211_channel *chan,
284 const u8 *bssid, const u8 *prev_bssid,
285 const u8 *ssid, int ssid_len,
286 const u8 *ie, int ie_len, bool use_mfp,
287 struct cfg80211_crypto_settings *crypt);
207int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, 288int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
208 struct net_device *dev, struct ieee80211_channel *chan, 289 struct net_device *dev, struct ieee80211_channel *chan,
209 const u8 *bssid, const u8 *prev_bssid, 290 const u8 *bssid, const u8 *prev_bssid,
210 const u8 *ssid, int ssid_len, 291 const u8 *ssid, int ssid_len,
211 const u8 *ie, int ie_len, bool use_mfp, 292 const u8 *ie, int ie_len, bool use_mfp,
212 struct cfg80211_crypto_settings *crypt); 293 struct cfg80211_crypto_settings *crypt);
294int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
295 struct net_device *dev, const u8 *bssid,
296 const u8 *ie, int ie_len, u16 reason);
213int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, 297int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
214 struct net_device *dev, const u8 *bssid, 298 struct net_device *dev, const u8 *bssid,
215 const u8 *ie, int ie_len, u16 reason); 299 const u8 *ie, int ie_len, u16 reason);
@@ -218,24 +302,38 @@ int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
218 const u8 *ie, int ie_len, u16 reason); 302 const u8 *ie, int ie_len, u16 reason);
219void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, 303void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
220 struct net_device *dev); 304 struct net_device *dev);
305void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
306 const u8 *req_ie, size_t req_ie_len,
307 const u8 *resp_ie, size_t resp_ie_len,
308 u16 status, bool wextev);
221 309
222/* SME */ 310/* SME */
311int __cfg80211_connect(struct cfg80211_registered_device *rdev,
312 struct net_device *dev,
313 struct cfg80211_connect_params *connect);
223int cfg80211_connect(struct cfg80211_registered_device *rdev, 314int cfg80211_connect(struct cfg80211_registered_device *rdev,
224 struct net_device *dev, 315 struct net_device *dev,
225 struct cfg80211_connect_params *connect); 316 struct cfg80211_connect_params *connect);
317int __cfg80211_disconnect(struct cfg80211_registered_device *rdev,
318 struct net_device *dev, u16 reason,
319 bool wextev);
226int cfg80211_disconnect(struct cfg80211_registered_device *rdev, 320int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
227 struct net_device *dev, u16 reason, 321 struct net_device *dev, u16 reason,
228 bool wextev); 322 bool wextev);
323void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid,
324 const u8 *req_ie, size_t req_ie_len,
325 const u8 *resp_ie, size_t resp_ie_len);
229 326
230void cfg80211_conn_work(struct work_struct *work); 327void cfg80211_conn_work(struct work_struct *work);
231 328
232/* internal helpers */ 329/* internal helpers */
233int cfg80211_validate_key_settings(struct key_params *params, int key_idx, 330int cfg80211_validate_key_settings(struct key_params *params, int key_idx,
234 const u8 *mac_addr); 331 const u8 *mac_addr);
235void __cfg80211_disconnected(struct net_device *dev, gfp_t gfp, u8 *ie, 332void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
236 size_t ie_len, u16 reason, bool from_ap); 333 size_t ie_len, u16 reason, bool from_ap);
237void cfg80211_sme_scan_done(struct net_device *dev); 334void cfg80211_sme_scan_done(struct net_device *dev);
238void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len); 335void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
239void cfg80211_sme_disassoc(struct net_device *dev, int idx); 336void cfg80211_sme_disassoc(struct net_device *dev, int idx);
337void __cfg80211_scan_done(struct work_struct *wk);
240 338
241#endif /* __NET_WIRELESS_CORE_H */ 339#endif /* __NET_WIRELESS_CORE_H */
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index a5330c5a5477..99ef9364b7e8 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -10,7 +10,7 @@
10#include "nl80211.h" 10#include "nl80211.h"
11 11
12 12
13void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp) 13void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid)
14{ 14{
15 struct wireless_dev *wdev = dev->ieee80211_ptr; 15 struct wireless_dev *wdev = dev->ieee80211_ptr;
16 struct cfg80211_bss *bss; 16 struct cfg80211_bss *bss;
@@ -39,22 +39,45 @@ void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp)
39 cfg80211_hold_bss(bss_from_pub(bss)); 39 cfg80211_hold_bss(bss_from_pub(bss));
40 wdev->current_bss = bss_from_pub(bss); 40 wdev->current_bss = bss_from_pub(bss);
41 41
42 nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid, gfp); 42 nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid,
43 GFP_KERNEL);
43#ifdef CONFIG_WIRELESS_EXT 44#ifdef CONFIG_WIRELESS_EXT
44 memset(&wrqu, 0, sizeof(wrqu)); 45 memset(&wrqu, 0, sizeof(wrqu));
45 memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN); 46 memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
46 wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); 47 wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
47#endif 48#endif
48} 49}
50
51void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp)
52{
53 struct wireless_dev *wdev = dev->ieee80211_ptr;
54 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
55 struct cfg80211_event *ev;
56 unsigned long flags;
57
58 ev = kzalloc(sizeof(*ev), gfp);
59 if (!ev)
60 return;
61
62 ev->type = EVENT_IBSS_JOINED;
63 memcpy(ev->cr.bssid, bssid, ETH_ALEN);
64
65 spin_lock_irqsave(&wdev->event_lock, flags);
66 list_add_tail(&ev->list, &wdev->event_list);
67 spin_unlock_irqrestore(&wdev->event_lock, flags);
68 schedule_work(&rdev->event_work);
69}
49EXPORT_SYMBOL(cfg80211_ibss_joined); 70EXPORT_SYMBOL(cfg80211_ibss_joined);
50 71
51int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, 72int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
52 struct net_device *dev, 73 struct net_device *dev,
53 struct cfg80211_ibss_params *params) 74 struct cfg80211_ibss_params *params)
54{ 75{
55 struct wireless_dev *wdev = dev->ieee80211_ptr; 76 struct wireless_dev *wdev = dev->ieee80211_ptr;
56 int err; 77 int err;
57 78
79 ASSERT_WDEV_LOCK(wdev);
80
58 if (wdev->ssid_len) 81 if (wdev->ssid_len)
59 return -EALREADY; 82 return -EALREADY;
60 83
@@ -72,10 +95,26 @@ int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
72 return 0; 95 return 0;
73} 96}
74 97
75void cfg80211_clear_ibss(struct net_device *dev, bool nowext) 98int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
99 struct net_device *dev,
100 struct cfg80211_ibss_params *params)
101{
102 struct wireless_dev *wdev = dev->ieee80211_ptr;
103 int err;
104
105 wdev_lock(wdev);
106 err = __cfg80211_join_ibss(rdev, dev, params);
107 wdev_unlock(wdev);
108
109 return err;
110}
111
112static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext)
76{ 113{
77 struct wireless_dev *wdev = dev->ieee80211_ptr; 114 struct wireless_dev *wdev = dev->ieee80211_ptr;
78 115
116 ASSERT_WDEV_LOCK(wdev);
117
79 if (wdev->current_bss) { 118 if (wdev->current_bss) {
80 cfg80211_unhold_bss(wdev->current_bss); 119 cfg80211_unhold_bss(wdev->current_bss);
81 cfg80211_put_bss(&wdev->current_bss->pub); 120 cfg80211_put_bss(&wdev->current_bss->pub);
@@ -89,12 +128,23 @@ void cfg80211_clear_ibss(struct net_device *dev, bool nowext)
89#endif 128#endif
90} 129}
91 130
92int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, 131void cfg80211_clear_ibss(struct net_device *dev, bool nowext)
93 struct net_device *dev, bool nowext) 132{
133 struct wireless_dev *wdev = dev->ieee80211_ptr;
134
135 wdev_lock(wdev);
136 __cfg80211_clear_ibss(dev, nowext);
137 wdev_unlock(wdev);
138}
139
140static int __cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
141 struct net_device *dev, bool nowext)
94{ 142{
95 struct wireless_dev *wdev = dev->ieee80211_ptr; 143 struct wireless_dev *wdev = dev->ieee80211_ptr;
96 int err; 144 int err;
97 145
146 ASSERT_WDEV_LOCK(wdev);
147
98 if (!wdev->ssid_len) 148 if (!wdev->ssid_len)
99 return -ENOLINK; 149 return -ENOLINK;
100 150
@@ -103,11 +153,24 @@ int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
103 if (err) 153 if (err)
104 return err; 154 return err;
105 155
106 cfg80211_clear_ibss(dev, nowext); 156 __cfg80211_clear_ibss(dev, nowext);
107 157
108 return 0; 158 return 0;
109} 159}
110 160
161int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
162 struct net_device *dev, bool nowext)
163{
164 struct wireless_dev *wdev = dev->ieee80211_ptr;
165 int err;
166
167 wdev_lock(wdev);
168 err = __cfg80211_leave_ibss(rdev, dev, nowext);
169 wdev_unlock(wdev);
170
171 return err;
172}
173
111#ifdef CONFIG_WIRELESS_EXT 174#ifdef CONFIG_WIRELESS_EXT
112static int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, 175static int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
113 struct wireless_dev *wdev) 176 struct wireless_dev *wdev)
@@ -184,12 +247,15 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
184 if (wdev->wext.ibss.channel == chan) 247 if (wdev->wext.ibss.channel == chan)
185 return 0; 248 return 0;
186 249
187 if (wdev->ssid_len) { 250 wdev_lock(wdev);
188 err = cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy), 251 err = 0;
189 dev, true); 252 if (wdev->ssid_len)
190 if (err) 253 err = __cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy),
191 return err; 254 dev, true);
192 } 255 wdev_unlock(wdev);
256
257 if (err)
258 return err;
193 259
194 if (chan) { 260 if (chan) {
195 wdev->wext.ibss.channel = chan; 261 wdev->wext.ibss.channel = chan;
@@ -215,10 +281,12 @@ int cfg80211_ibss_wext_giwfreq(struct net_device *dev,
215 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) 281 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
216 return -EINVAL; 282 return -EINVAL;
217 283
284 wdev_lock(wdev);
218 if (wdev->current_bss) 285 if (wdev->current_bss)
219 chan = wdev->current_bss->pub.channel; 286 chan = wdev->current_bss->pub.channel;
220 else if (wdev->wext.ibss.channel) 287 else if (wdev->wext.ibss.channel)
221 chan = wdev->wext.ibss.channel; 288 chan = wdev->wext.ibss.channel;
289 wdev_unlock(wdev);
222 290
223 if (chan) { 291 if (chan) {
224 freq->m = chan->center_freq; 292 freq->m = chan->center_freq;
@@ -247,12 +315,15 @@ int cfg80211_ibss_wext_siwessid(struct net_device *dev,
247 if (!wiphy_to_dev(wdev->wiphy)->ops->join_ibss) 315 if (!wiphy_to_dev(wdev->wiphy)->ops->join_ibss)
248 return -EOPNOTSUPP; 316 return -EOPNOTSUPP;
249 317
250 if (wdev->ssid_len) { 318 wdev_lock(wdev);
251 err = cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy), 319 err = 0;
252 dev, true); 320 if (wdev->ssid_len)
253 if (err) 321 err = __cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy),
254 return err; 322 dev, true);
255 } 323 wdev_unlock(wdev);
324
325 if (err)
326 return err;
256 327
257 /* iwconfig uses nul termination in SSID.. */ 328 /* iwconfig uses nul termination in SSID.. */
258 if (len > 0 && ssid[len - 1] == '\0') 329 if (len > 0 && ssid[len - 1] == '\0')
@@ -279,6 +350,7 @@ int cfg80211_ibss_wext_giwessid(struct net_device *dev,
279 350
280 data->flags = 0; 351 data->flags = 0;
281 352
353 wdev_lock(wdev);
282 if (wdev->ssid_len) { 354 if (wdev->ssid_len) {
283 data->flags = 1; 355 data->flags = 1;
284 data->length = wdev->ssid_len; 356 data->length = wdev->ssid_len;
@@ -288,6 +360,7 @@ int cfg80211_ibss_wext_giwessid(struct net_device *dev,
288 data->length = wdev->wext.ibss.ssid_len; 360 data->length = wdev->wext.ibss.ssid_len;
289 memcpy(ssid, wdev->wext.ibss.ssid, data->length); 361 memcpy(ssid, wdev->wext.ibss.ssid, data->length);
290 } 362 }
363 wdev_unlock(wdev);
291 364
292 return 0; 365 return 0;
293} 366}
@@ -325,12 +398,15 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev,
325 compare_ether_addr(bssid, wdev->wext.ibss.bssid) == 0) 398 compare_ether_addr(bssid, wdev->wext.ibss.bssid) == 0)
326 return 0; 399 return 0;
327 400
328 if (wdev->ssid_len) { 401 wdev_lock(wdev);
329 err = cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy), 402 err = 0;
330 dev, true); 403 if (wdev->ssid_len)
331 if (err) 404 err = __cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy),
332 return err; 405 dev, true);
333 } 406 wdev_unlock(wdev);
407
408 if (err)
409 return err;
334 410
335 if (bssid) { 411 if (bssid) {
336 memcpy(wdev->wext.bssid, bssid, ETH_ALEN); 412 memcpy(wdev->wext.bssid, bssid, ETH_ALEN);
@@ -355,10 +431,13 @@ int cfg80211_ibss_wext_giwap(struct net_device *dev,
355 431
356 ap_addr->sa_family = ARPHRD_ETHER; 432 ap_addr->sa_family = ARPHRD_ETHER;
357 433
434 wdev_lock(wdev);
358 if (wdev->current_bss) 435 if (wdev->current_bss)
359 memcpy(ap_addr->sa_data, wdev->current_bss->pub.bssid, ETH_ALEN); 436 memcpy(ap_addr->sa_data, wdev->current_bss->pub.bssid, ETH_ALEN);
360 else 437 else
361 memcpy(ap_addr->sa_data, wdev->wext.ibss.bssid, ETH_ALEN); 438 memcpy(ap_addr->sa_data, wdev->wext.ibss.bssid, ETH_ALEN);
439 wdev_unlock(wdev);
440
362 return 0; 441 return 0;
363} 442}
364/* temporary symbol - mark GPL - in the future the handler won't be */ 443/* temporary symbol - mark GPL - in the future the handler won't be */
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);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 4976eac888a3..cf4ac786b20a 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -4029,6 +4029,8 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
4029 struct nlattr *nest; 4029 struct nlattr *nest;
4030 int i; 4030 int i;
4031 4031
4032 ASSERT_RDEV_LOCK(rdev);
4033
4032 if (WARN_ON(!req)) 4034 if (WARN_ON(!req))
4033 return 0; 4035 return 0;
4034 4036
@@ -4391,12 +4393,12 @@ void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
4391 4393
4392void nl80211_send_disconnected(struct cfg80211_registered_device *rdev, 4394void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
4393 struct net_device *netdev, u16 reason, 4395 struct net_device *netdev, u16 reason,
4394 u8 *ie, size_t ie_len, bool from_ap, gfp_t gfp) 4396 const u8 *ie, size_t ie_len, bool from_ap)
4395{ 4397{
4396 struct sk_buff *msg; 4398 struct sk_buff *msg;
4397 void *hdr; 4399 void *hdr;
4398 4400
4399 msg = nlmsg_new(NLMSG_GOODSIZE, gfp); 4401 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
4400 if (!msg) 4402 if (!msg)
4401 return; 4403 return;
4402 4404
@@ -4420,7 +4422,7 @@ void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
4420 return; 4422 return;
4421 } 4423 }
4422 4424
4423 genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp); 4425 genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, GFP_KERNEL);
4424 return; 4426 return;
4425 4427
4426 nla_put_failure: 4428 nla_put_failure:
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index cf3708b48c29..44cc2a76a1b0 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -42,7 +42,7 @@ void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
42 const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp); 42 const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp);
43void nl80211_send_disconnected(struct cfg80211_registered_device *rdev, 43void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
44 struct net_device *netdev, u16 reason, 44 struct net_device *netdev, u16 reason,
45 u8 *ie, size_t ie_len, bool from_ap, gfp_t gfp); 45 const u8 *ie, size_t ie_len, bool from_ap);
46 46
47void 47void
48nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev, 48nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 1625faf1de57..4f552c3f29a3 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -17,13 +17,21 @@
17 17
18#define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ) 18#define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ)
19 19
20void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) 20void __cfg80211_scan_done(struct work_struct *wk)
21{ 21{
22 struct cfg80211_registered_device *rdev;
23 struct cfg80211_scan_request *request;
22 struct net_device *dev; 24 struct net_device *dev;
23#ifdef CONFIG_WIRELESS_EXT 25#ifdef CONFIG_WIRELESS_EXT
24 union iwreq_data wrqu; 26 union iwreq_data wrqu;
25#endif 27#endif
26 28
29 rdev = container_of(wk, struct cfg80211_registered_device,
30 scan_done_wk);
31
32 mutex_lock(&rdev->mtx);
33 request = rdev->scan_req;
34
27 dev = dev_get_by_index(&init_net, request->ifidx); 35 dev = dev_get_by_index(&init_net, request->ifidx);
28 if (!dev) 36 if (!dev)
29 goto out; 37 goto out;
@@ -35,7 +43,7 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
35 */ 43 */
36 cfg80211_sme_scan_done(dev); 44 cfg80211_sme_scan_done(dev);
37 45
38 if (aborted) 46 if (request->aborted)
39 nl80211_send_scan_aborted(wiphy_to_dev(request->wiphy), dev); 47 nl80211_send_scan_aborted(wiphy_to_dev(request->wiphy), dev);
40 else 48 else
41 nl80211_send_scan_done(wiphy_to_dev(request->wiphy), dev); 49 nl80211_send_scan_done(wiphy_to_dev(request->wiphy), dev);
@@ -43,7 +51,7 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
43 wiphy_to_dev(request->wiphy)->scan_req = NULL; 51 wiphy_to_dev(request->wiphy)->scan_req = NULL;
44 52
45#ifdef CONFIG_WIRELESS_EXT 53#ifdef CONFIG_WIRELESS_EXT
46 if (!aborted) { 54 if (!request->aborted) {
47 memset(&wrqu, 0, sizeof(wrqu)); 55 memset(&wrqu, 0, sizeof(wrqu));
48 56
49 wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL); 57 wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
@@ -53,8 +61,24 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
53 dev_put(dev); 61 dev_put(dev);
54 62
55 out: 63 out:
64 cfg80211_unlock_rdev(rdev);
56 kfree(request); 65 kfree(request);
57} 66}
67
68void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
69{
70 struct net_device *dev = dev_get_by_index(&init_net, request->ifidx);
71 if (WARN_ON(!dev)) {
72 kfree(request);
73 return;
74 }
75
76 WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req);
77
78 request->aborted = aborted;
79 schedule_work(&wiphy_to_dev(request->wiphy)->scan_done_wk);
80 dev_put(dev);
81}
58EXPORT_SYMBOL(cfg80211_scan_done); 82EXPORT_SYMBOL(cfg80211_scan_done);
59 83
60static void bss_release(struct kref *ref) 84static void bss_release(struct kref *ref)
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
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c
index fe1987acb891..6f75aaa7f795 100644
--- a/net/wireless/wext-sme.c
+++ b/net/wireless/wext-sme.c
@@ -15,6 +15,9 @@ static int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
15{ 15{
16 int err; 16 int err;
17 17
18 ASSERT_RDEV_LOCK(rdev);
19 ASSERT_WDEV_LOCK(wdev);
20
18 if (!netif_running(wdev->netdev)) 21 if (!netif_running(wdev->netdev))
19 return 0; 22 return 0;
20 23
@@ -24,8 +27,8 @@ static int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
24 27
25 err = 0; 28 err = 0;
26 if (wdev->wext.connect.ssid_len != 0) 29 if (wdev->wext.connect.ssid_len != 0)
27 err = cfg80211_connect(rdev, wdev->netdev, 30 err = __cfg80211_connect(rdev, wdev->netdev,
28 &wdev->wext.connect); 31 &wdev->wext.connect);
29 32
30 return err; 33 return err;
31} 34}
@@ -50,33 +53,43 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
50 if (chan && (chan->flags & IEEE80211_CHAN_DISABLED)) 53 if (chan && (chan->flags & IEEE80211_CHAN_DISABLED))
51 return -EINVAL; 54 return -EINVAL;
52 55
53 if (wdev->wext.connect.channel == chan) 56 cfg80211_lock_rdev(rdev);
54 return 0; 57 wdev_lock(wdev);
58
59 if (wdev->wext.connect.channel == chan) {
60 err = 0;
61 goto out;
62 }
55 63
56 if (wdev->sme_state != CFG80211_SME_IDLE) { 64 if (wdev->sme_state != CFG80211_SME_IDLE) {
57 bool event = true; 65 bool event = true;
58 /* if SSID set, we'll try right again, avoid event */ 66 /* if SSID set, we'll try right again, avoid event */
59 if (wdev->wext.connect.ssid_len) 67 if (wdev->wext.connect.ssid_len)
60 event = false; 68 event = false;
61 err = cfg80211_disconnect(wiphy_to_dev(wdev->wiphy), 69 err = __cfg80211_disconnect(wiphy_to_dev(wdev->wiphy),
62 dev, WLAN_REASON_DEAUTH_LEAVING, 70 dev, WLAN_REASON_DEAUTH_LEAVING,
63 event); 71 event);
64 if (err) 72 if (err)
65 return err; 73 goto out;
66 } 74 }
67 75
76
68 wdev->wext.connect.channel = chan; 77 wdev->wext.connect.channel = chan;
69 78
70 /* SSID is not set, we just want to switch channel */ 79 /* SSID is not set, we just want to switch channel */
71 if (wdev->wext.connect.ssid_len && chan) { 80 if (wdev->wext.connect.ssid_len && chan) {
72 if (!rdev->ops->set_channel) 81 err = -EOPNOTSUPP;
73 return -EOPNOTSUPP; 82 if (rdev->ops->set_channel)
74 83 err = rdev->ops->set_channel(wdev->wiphy, chan,
75 return rdev->ops->set_channel(wdev->wiphy, chan, 84 NL80211_CHAN_NO_HT);
76 NL80211_CHAN_NO_HT); 85 goto out;
77 } 86 }
78 87
79 return cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev); 88 err = cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev);
89 out:
90 wdev_unlock(wdev);
91 cfg80211_unlock_rdev(rdev);
92 return err;
80} 93}
81/* temporary symbol - mark GPL - in the future the handler won't be */ 94/* temporary symbol - mark GPL - in the future the handler won't be */
82EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwfreq); 95EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwfreq);
@@ -92,10 +105,12 @@ int cfg80211_mgd_wext_giwfreq(struct net_device *dev,
92 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION)) 105 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
93 return -EINVAL; 106 return -EINVAL;
94 107
108 wdev_lock(wdev);
95 if (wdev->current_bss) 109 if (wdev->current_bss)
96 chan = wdev->current_bss->pub.channel; 110 chan = wdev->current_bss->pub.channel;
97 else if (wdev->wext.connect.channel) 111 else if (wdev->wext.connect.channel)
98 chan = wdev->wext.connect.channel; 112 chan = wdev->wext.connect.channel;
113 wdev_unlock(wdev);
99 114
100 if (chan) { 115 if (chan) {
101 freq->m = chan->center_freq; 116 freq->m = chan->center_freq;
@@ -128,21 +143,26 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
128 if (len > 0 && ssid[len - 1] == '\0') 143 if (len > 0 && ssid[len - 1] == '\0')
129 len--; 144 len--;
130 145
146 cfg80211_lock_rdev(wiphy_to_dev(wdev->wiphy));
147 wdev_lock(wdev);
148
149 err = 0;
150
131 if (wdev->wext.connect.ssid && len && 151 if (wdev->wext.connect.ssid && len &&
132 len == wdev->wext.connect.ssid_len && 152 len == wdev->wext.connect.ssid_len &&
133 memcmp(wdev->wext.connect.ssid, ssid, len)) 153 memcmp(wdev->wext.connect.ssid, ssid, len))
134 return 0; 154 goto out;
135 155
136 if (wdev->sme_state != CFG80211_SME_IDLE) { 156 if (wdev->sme_state != CFG80211_SME_IDLE) {
137 bool event = true; 157 bool event = true;
138 /* if SSID set now, we'll try to connect, avoid event */ 158 /* if SSID set now, we'll try to connect, avoid event */
139 if (len) 159 if (len)
140 event = false; 160 event = false;
141 err = cfg80211_disconnect(wiphy_to_dev(wdev->wiphy), 161 err = __cfg80211_disconnect(wiphy_to_dev(wdev->wiphy),
142 dev, WLAN_REASON_DEAUTH_LEAVING, 162 dev, WLAN_REASON_DEAUTH_LEAVING,
143 event); 163 event);
144 if (err) 164 if (err)
145 return err; 165 goto out;
146 } 166 }
147 167
148 wdev->wext.connect.ssid = wdev->wext.ssid; 168 wdev->wext.connect.ssid = wdev->wext.ssid;
@@ -151,7 +171,11 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
151 171
152 wdev->wext.connect.crypto.control_port = false; 172 wdev->wext.connect.crypto.control_port = false;
153 173
154 return cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev); 174 err = cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev);
175 out:
176 wdev_unlock(wdev);
177 cfg80211_unlock_rdev(wiphy_to_dev(wdev->wiphy));
178 return err;
155} 179}
156/* temporary symbol - mark GPL - in the future the handler won't be */ 180/* temporary symbol - mark GPL - in the future the handler won't be */
157EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwessid); 181EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwessid);
@@ -168,6 +192,7 @@ int cfg80211_mgd_wext_giwessid(struct net_device *dev,
168 192
169 data->flags = 0; 193 data->flags = 0;
170 194
195 wdev_lock(wdev);
171 if (wdev->ssid_len) { 196 if (wdev->ssid_len) {
172 data->flags = 1; 197 data->flags = 1;
173 data->length = wdev->ssid_len; 198 data->length = wdev->ssid_len;
@@ -178,6 +203,7 @@ int cfg80211_mgd_wext_giwessid(struct net_device *dev,
178 memcpy(ssid, wdev->wext.connect.ssid, data->length); 203 memcpy(ssid, wdev->wext.connect.ssid, data->length);
179 } else 204 } else
180 data->flags = 0; 205 data->flags = 0;
206 wdev_unlock(wdev);
181 207
182 return 0; 208 return 0;
183} 209}
@@ -203,21 +229,25 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
203 if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid)) 229 if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid))
204 bssid = NULL; 230 bssid = NULL;
205 231
232 cfg80211_lock_rdev(wiphy_to_dev(wdev->wiphy));
233 wdev_lock(wdev);
234
235 err = 0;
206 /* both automatic */ 236 /* both automatic */
207 if (!bssid && !wdev->wext.connect.bssid) 237 if (!bssid && !wdev->wext.connect.bssid)
208 return 0; 238 goto out;
209 239
210 /* fixed already - and no change */ 240 /* fixed already - and no change */
211 if (wdev->wext.connect.bssid && bssid && 241 if (wdev->wext.connect.bssid && bssid &&
212 compare_ether_addr(bssid, wdev->wext.connect.bssid) == 0) 242 compare_ether_addr(bssid, wdev->wext.connect.bssid) == 0)
213 return 0; 243 goto out;
214 244
215 if (wdev->sme_state != CFG80211_SME_IDLE) { 245 if (wdev->sme_state != CFG80211_SME_IDLE) {
216 err = cfg80211_disconnect(wiphy_to_dev(wdev->wiphy), 246 err = __cfg80211_disconnect(wiphy_to_dev(wdev->wiphy),
217 dev, WLAN_REASON_DEAUTH_LEAVING, 247 dev, WLAN_REASON_DEAUTH_LEAVING,
218 false); 248 false);
219 if (err) 249 if (err)
220 return err; 250 goto out;
221 } 251 }
222 252
223 if (bssid) { 253 if (bssid) {
@@ -226,7 +256,11 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
226 } else 256 } else
227 wdev->wext.connect.bssid = NULL; 257 wdev->wext.connect.bssid = NULL;
228 258
229 return cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev); 259 err = cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev);
260 out:
261 wdev_unlock(wdev);
262 cfg80211_unlock_rdev(wiphy_to_dev(wdev->wiphy));
263 return err;
230} 264}
231/* temporary symbol - mark GPL - in the future the handler won't be */ 265/* temporary symbol - mark GPL - in the future the handler won't be */
232EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwap); 266EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwap);
@@ -243,12 +277,14 @@ int cfg80211_mgd_wext_giwap(struct net_device *dev,
243 277
244 ap_addr->sa_family = ARPHRD_ETHER; 278 ap_addr->sa_family = ARPHRD_ETHER;
245 279
280 wdev_lock(wdev);
246 if (wdev->current_bss) 281 if (wdev->current_bss)
247 memcpy(ap_addr->sa_data, wdev->current_bss->pub.bssid, ETH_ALEN); 282 memcpy(ap_addr->sa_data, wdev->current_bss->pub.bssid, ETH_ALEN);
248 else if (wdev->wext.connect.bssid) 283 else if (wdev->wext.connect.bssid)
249 memcpy(ap_addr->sa_data, wdev->wext.connect.bssid, ETH_ALEN); 284 memcpy(ap_addr->sa_data, wdev->wext.connect.bssid, ETH_ALEN);
250 else 285 else
251 memset(ap_addr->sa_data, 0, ETH_ALEN); 286 memset(ap_addr->sa_data, 0, ETH_ALEN);
287 wdev_unlock(wdev);
252 288
253 return 0; 289 return 0;
254} 290}
@@ -270,15 +306,20 @@ int cfg80211_wext_siwgenie(struct net_device *dev,
270 if (!ie_len) 306 if (!ie_len)
271 ie = NULL; 307 ie = NULL;
272 308
309 wdev_lock(wdev);
310
273 /* no change */ 311 /* no change */
312 err = 0;
274 if (wdev->wext.ie_len == ie_len && 313 if (wdev->wext.ie_len == ie_len &&
275 memcmp(wdev->wext.ie, ie, ie_len) == 0) 314 memcmp(wdev->wext.ie, ie, ie_len) == 0)
276 return 0; 315 goto out;
277 316
278 if (ie_len) { 317 if (ie_len) {
279 ie = kmemdup(extra, ie_len, GFP_KERNEL); 318 ie = kmemdup(extra, ie_len, GFP_KERNEL);
280 if (!ie) 319 if (!ie) {
281 return -ENOMEM; 320 err = -ENOMEM;
321 goto out;
322 }
282 } else 323 } else
283 ie = NULL; 324 ie = NULL;
284 325
@@ -287,14 +328,17 @@ int cfg80211_wext_siwgenie(struct net_device *dev,
287 wdev->wext.ie_len = ie_len; 328 wdev->wext.ie_len = ie_len;
288 329
289 if (wdev->sme_state != CFG80211_SME_IDLE) { 330 if (wdev->sme_state != CFG80211_SME_IDLE) {
290 err = cfg80211_disconnect(rdev, dev, 331 err = __cfg80211_disconnect(rdev, dev,
291 WLAN_REASON_DEAUTH_LEAVING, false); 332 WLAN_REASON_DEAUTH_LEAVING, false);
292 if (err) 333 if (err)
293 return err; 334 goto out;
294 } 335 }
295 336
296 /* userspace better not think we'll reconnect */ 337 /* userspace better not think we'll reconnect */
297 return 0; 338 err = 0;
339 out:
340 wdev_unlock(wdev);
341 return err;
298} 342}
299EXPORT_SYMBOL_GPL(cfg80211_wext_siwgenie); 343EXPORT_SYMBOL_GPL(cfg80211_wext_siwgenie);
300 344
@@ -305,6 +349,7 @@ int cfg80211_wext_siwmlme(struct net_device *dev,
305 struct wireless_dev *wdev = dev->ieee80211_ptr; 349 struct wireless_dev *wdev = dev->ieee80211_ptr;
306 struct iw_mlme *mlme = (struct iw_mlme *)extra; 350 struct iw_mlme *mlme = (struct iw_mlme *)extra;
307 struct cfg80211_registered_device *rdev; 351 struct cfg80211_registered_device *rdev;
352 int err;
308 353
309 if (!wdev) 354 if (!wdev)
310 return -EOPNOTSUPP; 355 return -EOPNOTSUPP;
@@ -317,13 +362,19 @@ int cfg80211_wext_siwmlme(struct net_device *dev,
317 if (mlme->addr.sa_family != ARPHRD_ETHER) 362 if (mlme->addr.sa_family != ARPHRD_ETHER)
318 return -EINVAL; 363 return -EINVAL;
319 364
365 wdev_lock(wdev);
320 switch (mlme->cmd) { 366 switch (mlme->cmd) {
321 case IW_MLME_DEAUTH: 367 case IW_MLME_DEAUTH:
322 case IW_MLME_DISASSOC: 368 case IW_MLME_DISASSOC:
323 return cfg80211_disconnect(rdev, dev, mlme->reason_code, 369 err = __cfg80211_disconnect(rdev, dev, mlme->reason_code,
324 true); 370 true);
371 break;
325 default: 372 default:
326 return -EOPNOTSUPP; 373 err = -EOPNOTSUPP;
374 break;
327 } 375 }
376 wdev_unlock(wdev);
377
378 return err;
328} 379}
329EXPORT_SYMBOL_GPL(cfg80211_wext_siwmlme); 380EXPORT_SYMBOL_GPL(cfg80211_wext_siwmlme);