aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/util.c')
-rw-r--r--net/wireless/util.c108
1 files changed, 108 insertions, 0 deletions
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}