aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/core.c54
-rw-r--r--net/wireless/core.h4
-rw-r--r--net/wireless/nl80211.c16
-rw-r--r--net/wireless/util.c108
-rw-r--r--net/wireless/wext-compat.c16
5 files changed, 117 insertions, 81 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 9b157caa74fd..45b2be3274db 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -294,69 +294,17 @@ static void cfg80211_rfkill_sync_work(struct work_struct *work)
294 cfg80211_rfkill_set_block(rdev, rfkill_blocked(rdev->rfkill)); 294 cfg80211_rfkill_set_block(rdev, rfkill_blocked(rdev->rfkill));
295} 295}
296 296
297static void cfg80211_process_events(struct wireless_dev *wdev)
298{
299 struct cfg80211_event *ev;
300 unsigned long flags;
301
302 spin_lock_irqsave(&wdev->event_lock, flags);
303 while (!list_empty(&wdev->event_list)) {
304 ev = list_first_entry(&wdev->event_list,
305 struct cfg80211_event, list);
306 list_del(&ev->list);
307 spin_unlock_irqrestore(&wdev->event_lock, flags);
308
309 wdev_lock(wdev);
310 switch (ev->type) {
311 case EVENT_CONNECT_RESULT:
312 __cfg80211_connect_result(
313 wdev->netdev, is_zero_ether_addr(ev->cr.bssid) ?
314 NULL : ev->cr.bssid,
315 ev->cr.req_ie, ev->cr.req_ie_len,
316 ev->cr.resp_ie, ev->cr.resp_ie_len,
317 ev->cr.status,
318 ev->cr.status == WLAN_STATUS_SUCCESS,
319 NULL);
320 break;
321 case EVENT_ROAMED:
322 __cfg80211_roamed(wdev, ev->rm.bssid,
323 ev->rm.req_ie, ev->rm.req_ie_len,
324 ev->rm.resp_ie, ev->rm.resp_ie_len);
325 break;
326 case EVENT_DISCONNECTED:
327 __cfg80211_disconnected(wdev->netdev,
328 ev->dc.ie, ev->dc.ie_len,
329 ev->dc.reason, true);
330 break;
331 case EVENT_IBSS_JOINED:
332 __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid);
333 break;
334 }
335 wdev_unlock(wdev);
336
337 kfree(ev);
338
339 spin_lock_irqsave(&wdev->event_lock, flags);
340 }
341 spin_unlock_irqrestore(&wdev->event_lock, flags);
342}
343
344static void cfg80211_event_work(struct work_struct *work) 297static void cfg80211_event_work(struct work_struct *work)
345{ 298{
346 struct cfg80211_registered_device *rdev; 299 struct cfg80211_registered_device *rdev;
347 struct wireless_dev *wdev;
348 300
349 rdev = container_of(work, struct cfg80211_registered_device, 301 rdev = container_of(work, struct cfg80211_registered_device,
350 event_work); 302 event_work);
351 303
352 rtnl_lock(); 304 rtnl_lock();
353 cfg80211_lock_rdev(rdev); 305 cfg80211_lock_rdev(rdev);
354 mutex_lock(&rdev->devlist_mtx);
355 306
356 list_for_each_entry(wdev, &rdev->netdev_list, list) 307 cfg80211_process_rdev_events(rdev);
357 cfg80211_process_events(wdev);
358
359 mutex_unlock(&rdev->devlist_mtx);
360 cfg80211_unlock_rdev(rdev); 308 cfg80211_unlock_rdev(rdev);
361 rtnl_unlock(); 309 rtnl_unlock();
362} 310}
diff --git a/net/wireless/core.h b/net/wireless/core.h
index d262d42cbd5e..2a33d8bc886b 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -372,6 +372,10 @@ void cfg80211_sme_disassoc(struct net_device *dev, int idx);
372void __cfg80211_scan_done(struct work_struct *wk); 372void __cfg80211_scan_done(struct work_struct *wk);
373void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak); 373void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak);
374void cfg80211_upload_connect_keys(struct wireless_dev *wdev); 374void cfg80211_upload_connect_keys(struct wireless_dev *wdev);
375int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
376 struct net_device *dev, enum nl80211_iftype ntype,
377 u32 *flags, struct vif_params *params);
378void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev);
375 379
376struct ieee80211_channel * 380struct ieee80211_channel *
377rdev_fixed_channel(struct cfg80211_registered_device *rdev, 381rdev_fixed_channel(struct cfg80211_registered_device *rdev,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index a8aaadeb6773..71bfc044a939 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -977,12 +977,6 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
977 } 977 }
978 } 978 }
979 979
980 if (!rdev->ops->change_virtual_intf ||
981 !(rdev->wiphy.interface_modes & (1 << ntype))) {
982 err = -EOPNOTSUPP;
983 goto unlock;
984 }
985
986 if (info->attrs[NL80211_ATTR_MESH_ID]) { 980 if (info->attrs[NL80211_ATTR_MESH_ID]) {
987 if (ntype != NL80211_IFTYPE_MESH_POINT) { 981 if (ntype != NL80211_IFTYPE_MESH_POINT) {
988 err = -EINVAL; 982 err = -EINVAL;
@@ -1008,18 +1002,10 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
1008 } 1002 }
1009 1003
1010 if (change) 1004 if (change)
1011 err = rdev->ops->change_virtual_intf(&rdev->wiphy, dev, 1005 err = cfg80211_change_iface(rdev, dev, ntype, flags, &params);
1012 ntype, flags, &params);
1013 else 1006 else
1014 err = 0; 1007 err = 0;
1015 1008
1016 WARN_ON(!err && dev->ieee80211_ptr->iftype != ntype);
1017
1018 if (!err && (ntype != otype)) {
1019 if (otype == NL80211_IFTYPE_ADHOC)
1020 cfg80211_clear_ibss(dev, false);
1021 }
1022
1023 unlock: 1009 unlock:
1024 dev_put(dev); 1010 dev_put(dev);
1025 cfg80211_unlock_rdev(rdev); 1011 cfg80211_unlock_rdev(rdev);
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 693275a16a26..3fc2df86278f 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -574,3 +574,111 @@ void cfg80211_upload_connect_keys(struct wireless_dev *wdev)
574 kfree(wdev->connect_keys); 574 kfree(wdev->connect_keys);
575 wdev->connect_keys = NULL; 575 wdev->connect_keys = NULL;
576} 576}
577
578static void cfg80211_process_wdev_events(struct wireless_dev *wdev)
579{
580 struct cfg80211_event *ev;
581 unsigned long flags;
582 const u8 *bssid = NULL;
583
584 spin_lock_irqsave(&wdev->event_lock, flags);
585 while (!list_empty(&wdev->event_list)) {
586 ev = list_first_entry(&wdev->event_list,
587 struct cfg80211_event, list);
588 list_del(&ev->list);
589 spin_unlock_irqrestore(&wdev->event_lock, flags);
590
591 wdev_lock(wdev);
592 switch (ev->type) {
593 case EVENT_CONNECT_RESULT:
594 if (!is_zero_ether_addr(ev->cr.bssid))
595 bssid = ev->cr.bssid;
596 __cfg80211_connect_result(
597 wdev->netdev, bssid,
598 ev->cr.req_ie, ev->cr.req_ie_len,
599 ev->cr.resp_ie, ev->cr.resp_ie_len,
600 ev->cr.status,
601 ev->cr.status == WLAN_STATUS_SUCCESS,
602 NULL);
603 break;
604 case EVENT_ROAMED:
605 __cfg80211_roamed(wdev, ev->rm.bssid,
606 ev->rm.req_ie, ev->rm.req_ie_len,
607 ev->rm.resp_ie, ev->rm.resp_ie_len);
608 break;
609 case EVENT_DISCONNECTED:
610 __cfg80211_disconnected(wdev->netdev,
611 ev->dc.ie, ev->dc.ie_len,
612 ev->dc.reason, true);
613 break;
614 case EVENT_IBSS_JOINED:
615 __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid);
616 break;
617 }
618 wdev_unlock(wdev);
619
620 kfree(ev);
621
622 spin_lock_irqsave(&wdev->event_lock, flags);
623 }
624 spin_unlock_irqrestore(&wdev->event_lock, flags);
625}
626
627void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev)
628{
629 struct wireless_dev *wdev;
630
631 ASSERT_RTNL();
632 ASSERT_RDEV_LOCK(rdev);
633
634 mutex_lock(&rdev->devlist_mtx);
635
636 list_for_each_entry(wdev, &rdev->netdev_list, list)
637 cfg80211_process_wdev_events(wdev);
638
639 mutex_unlock(&rdev->devlist_mtx);
640}
641
642int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
643 struct net_device *dev, enum nl80211_iftype ntype,
644 u32 *flags, struct vif_params *params)
645{
646 int err;
647 enum nl80211_iftype otype = dev->ieee80211_ptr->iftype;
648
649 ASSERT_RDEV_LOCK(rdev);
650
651 /* don't support changing VLANs, you just re-create them */
652 if (otype == NL80211_IFTYPE_AP_VLAN)
653 return -EOPNOTSUPP;
654
655 if (!rdev->ops->change_virtual_intf ||
656 !(rdev->wiphy.interface_modes & (1 << ntype)))
657 return -EOPNOTSUPP;
658
659 if (ntype != otype) {
660 switch (otype) {
661 case NL80211_IFTYPE_ADHOC:
662 cfg80211_leave_ibss(rdev, dev, false);
663 break;
664 case NL80211_IFTYPE_STATION:
665 cfg80211_disconnect(rdev, dev,
666 WLAN_REASON_DEAUTH_LEAVING, true);
667 break;
668 case NL80211_IFTYPE_MESH_POINT:
669 /* mesh should be handled? */
670 break;
671 default:
672 break;
673 }
674
675 cfg80211_process_rdev_events(rdev);
676 }
677
678 err = rdev->ops->change_virtual_intf(&rdev->wiphy, dev,
679 ntype, flags, params);
680
681 WARN_ON(!err && dev->ieee80211_ptr->iftype != ntype);
682
683 return err;
684}
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index c12029b1def0..429dd06a4ecc 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -70,18 +70,8 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
70 enum nl80211_iftype type; 70 enum nl80211_iftype type;
71 int ret; 71 int ret;
72 72
73 if (!wdev)
74 return -EOPNOTSUPP;
75
76 rdev = wiphy_to_dev(wdev->wiphy); 73 rdev = wiphy_to_dev(wdev->wiphy);
77 74
78 if (!rdev->ops->change_virtual_intf)
79 return -EOPNOTSUPP;
80
81 /* don't support changing VLANs, you just re-create them */
82 if (wdev->iftype == NL80211_IFTYPE_AP_VLAN)
83 return -EOPNOTSUPP;
84
85 switch (*mode) { 75 switch (*mode) {
86 case IW_MODE_INFRA: 76 case IW_MODE_INFRA:
87 type = NL80211_IFTYPE_STATION; 77 type = NL80211_IFTYPE_STATION;
@@ -104,9 +94,9 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
104 94
105 memset(&vifparams, 0, sizeof(vifparams)); 95 memset(&vifparams, 0, sizeof(vifparams));
106 96
107 ret = rdev->ops->change_virtual_intf(wdev->wiphy, dev, type, 97 cfg80211_lock_rdev(rdev);
108 NULL, &vifparams); 98 ret = cfg80211_change_iface(rdev, dev, type, NULL, &vifparams);
109 WARN_ON(!ret && wdev->iftype != type); 99 cfg80211_unlock_rdev(rdev);
110 100
111 return ret; 101 return ret;
112} 102}