summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-05-08 15:45:15 -0400
committerJohannes Berg <johannes.berg@intel.com>2013-05-24 18:02:15 -0400
commit5fe231e873729fa2f57cdc417d5c1f80871e2d7d (patch)
tree48810991fa4cf4faa69c0a992fdaf962feb6edda /net
parent73810b77def898b43a97638478692922b7f820eb (diff)
cfg80211: vastly simplify locking
Virtually all code paths in cfg80211 already (need to) hold the RTNL. As such, there's little point in having another four mutexes for various parts of the code, they just cause lock ordering issues (and much of the time, the RTNL and a few of the others need thus be held.) Simplify all this by getting rid of the extra four mutexes and just use the RTNL throughout. Only a few code changes were needed to do this and we can get rid of a work struct for bonus points. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net')
-rw-r--r--net/wireless/core.c166
-rw-r--r--net/wireless/core.h32
-rw-r--r--net/wireless/debugfs.c4
-rw-r--r--net/wireless/ibss.c10
-rw-r--r--net/wireless/mesh.c2
-rw-r--r--net/wireless/mlme.c12
-rw-r--r--net/wireless/nl80211.c178
-rw-r--r--net/wireless/reg.c36
-rw-r--r--net/wireless/scan.c42
-rw-r--r--net/wireless/sme.c26
-rw-r--r--net/wireless/util.c11
-rw-r--r--net/wireless/wext-compat.c22
-rw-r--r--net/wireless/wext-sme.c18
13 files changed, 115 insertions, 444 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 9416b8f55f50..5fc642d4071b 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -36,12 +36,10 @@ MODULE_LICENSE("GPL");
36MODULE_DESCRIPTION("wireless configuration support"); 36MODULE_DESCRIPTION("wireless configuration support");
37MODULE_ALIAS_GENL_FAMILY(NL80211_GENL_NAME); 37MODULE_ALIAS_GENL_FAMILY(NL80211_GENL_NAME);
38 38
39/* RCU-protected (and cfg80211_mutex for writers) */ 39/* RCU-protected (and RTNL for writers) */
40LIST_HEAD(cfg80211_rdev_list); 40LIST_HEAD(cfg80211_rdev_list);
41int cfg80211_rdev_list_generation; 41int cfg80211_rdev_list_generation;
42 42
43DEFINE_MUTEX(cfg80211_mutex);
44
45/* for debugfs */ 43/* for debugfs */
46static struct dentry *ieee80211_debugfs_dir; 44static struct dentry *ieee80211_debugfs_dir;
47 45
@@ -53,12 +51,11 @@ module_param(cfg80211_disable_40mhz_24ghz, bool, 0644);
53MODULE_PARM_DESC(cfg80211_disable_40mhz_24ghz, 51MODULE_PARM_DESC(cfg80211_disable_40mhz_24ghz,
54 "Disable 40MHz support in the 2.4GHz band"); 52 "Disable 40MHz support in the 2.4GHz band");
55 53
56/* requires cfg80211_mutex to be held! */
57struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx) 54struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx)
58{ 55{
59 struct cfg80211_registered_device *result = NULL, *rdev; 56 struct cfg80211_registered_device *result = NULL, *rdev;
60 57
61 assert_cfg80211_lock(); 58 ASSERT_RTNL();
62 59
63 list_for_each_entry(rdev, &cfg80211_rdev_list, list) { 60 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
64 if (rdev->wiphy_idx == wiphy_idx) { 61 if (rdev->wiphy_idx == wiphy_idx) {
@@ -77,12 +74,11 @@ int get_wiphy_idx(struct wiphy *wiphy)
77 return rdev->wiphy_idx; 74 return rdev->wiphy_idx;
78} 75}
79 76
80/* requires cfg80211_rdev_mutex to be held! */
81struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx) 77struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx)
82{ 78{
83 struct cfg80211_registered_device *rdev; 79 struct cfg80211_registered_device *rdev;
84 80
85 assert_cfg80211_lock(); 81 ASSERT_RTNL();
86 82
87 rdev = cfg80211_rdev_by_wiphy_idx(wiphy_idx); 83 rdev = cfg80211_rdev_by_wiphy_idx(wiphy_idx);
88 if (!rdev) 84 if (!rdev)
@@ -90,14 +86,13 @@ struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx)
90 return &rdev->wiphy; 86 return &rdev->wiphy;
91} 87}
92 88
93/* requires cfg80211_mutex to be held */
94int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, 89int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
95 char *newname) 90 char *newname)
96{ 91{
97 struct cfg80211_registered_device *rdev2; 92 struct cfg80211_registered_device *rdev2;
98 int wiphy_idx, taken = -1, result, digits; 93 int wiphy_idx, taken = -1, result, digits;
99 94
100 assert_cfg80211_lock(); 95 ASSERT_RTNL();
101 96
102 /* prohibit calling the thing phy%d when %d is not its number */ 97 /* prohibit calling the thing phy%d when %d is not its number */
103 sscanf(newname, PHY_NAME "%d%n", &wiphy_idx, &taken); 98 sscanf(newname, PHY_NAME "%d%n", &wiphy_idx, &taken);
@@ -195,8 +190,7 @@ static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data)
195void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, 190void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
196 struct wireless_dev *wdev) 191 struct wireless_dev *wdev)
197{ 192{
198 lockdep_assert_held(&rdev->devlist_mtx); 193 ASSERT_RTNL();
199 lockdep_assert_held(&rdev->sched_scan_mtx);
200 194
201 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)) 195 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_P2P_DEVICE))
202 return; 196 return;
@@ -235,8 +229,6 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked)
235 229
236 rtnl_lock(); 230 rtnl_lock();
237 231
238 /* read-only iteration need not hold the devlist_mtx */
239
240 list_for_each_entry(wdev, &rdev->wdev_list, list) { 232 list_for_each_entry(wdev, &rdev->wdev_list, list) {
241 if (wdev->netdev) { 233 if (wdev->netdev) {
242 dev_close(wdev->netdev); 234 dev_close(wdev->netdev);
@@ -245,12 +237,7 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked)
245 /* otherwise, check iftype */ 237 /* otherwise, check iftype */
246 switch (wdev->iftype) { 238 switch (wdev->iftype) {
247 case NL80211_IFTYPE_P2P_DEVICE: 239 case NL80211_IFTYPE_P2P_DEVICE:
248 /* but this requires it */
249 mutex_lock(&rdev->devlist_mtx);
250 mutex_lock(&rdev->sched_scan_mtx);
251 cfg80211_stop_p2p_device(rdev, wdev); 240 cfg80211_stop_p2p_device(rdev, wdev);
252 mutex_unlock(&rdev->sched_scan_mtx);
253 mutex_unlock(&rdev->devlist_mtx);
254 break; 241 break;
255 default: 242 default:
256 break; 243 break;
@@ -278,10 +265,7 @@ static void cfg80211_event_work(struct work_struct *work)
278 event_work); 265 event_work);
279 266
280 rtnl_lock(); 267 rtnl_lock();
281 cfg80211_lock_rdev(rdev);
282
283 cfg80211_process_rdev_events(rdev); 268 cfg80211_process_rdev_events(rdev);
284 cfg80211_unlock_rdev(rdev);
285 rtnl_unlock(); 269 rtnl_unlock();
286} 270}
287 271
@@ -323,9 +307,6 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
323 /* give it a proper name */ 307 /* give it a proper name */
324 dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx); 308 dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx);
325 309
326 mutex_init(&rdev->mtx);
327 mutex_init(&rdev->devlist_mtx);
328 mutex_init(&rdev->sched_scan_mtx);
329 INIT_LIST_HEAD(&rdev->wdev_list); 310 INIT_LIST_HEAD(&rdev->wdev_list);
330 INIT_LIST_HEAD(&rdev->beacon_registrations); 311 INIT_LIST_HEAD(&rdev->beacon_registrations);
331 spin_lock_init(&rdev->beacon_registrations_lock); 312 spin_lock_init(&rdev->beacon_registrations_lock);
@@ -573,11 +554,11 @@ int wiphy_register(struct wiphy *wiphy)
573 /* check and set up bitrates */ 554 /* check and set up bitrates */
574 ieee80211_set_bitrate_flags(wiphy); 555 ieee80211_set_bitrate_flags(wiphy);
575 556
576 mutex_lock(&cfg80211_mutex); 557 rtnl_lock();
577 558
578 res = device_add(&rdev->wiphy.dev); 559 res = device_add(&rdev->wiphy.dev);
579 if (res) { 560 if (res) {
580 mutex_unlock(&cfg80211_mutex); 561 rtnl_unlock();
581 return res; 562 return res;
582 } 563 }
583 564
@@ -606,25 +587,18 @@ int wiphy_register(struct wiphy *wiphy)
606 } 587 }
607 588
608 cfg80211_debugfs_rdev_add(rdev); 589 cfg80211_debugfs_rdev_add(rdev);
609 mutex_unlock(&cfg80211_mutex);
610 590
611 /*
612 * due to a locking dependency this has to be outside of the
613 * cfg80211_mutex lock
614 */
615 res = rfkill_register(rdev->rfkill); 591 res = rfkill_register(rdev->rfkill);
616 if (res) { 592 if (res) {
617 device_del(&rdev->wiphy.dev); 593 device_del(&rdev->wiphy.dev);
618 594
619 mutex_lock(&cfg80211_mutex);
620 debugfs_remove_recursive(rdev->wiphy.debugfsdir); 595 debugfs_remove_recursive(rdev->wiphy.debugfsdir);
621 list_del_rcu(&rdev->list); 596 list_del_rcu(&rdev->list);
622 wiphy_regulatory_deregister(wiphy); 597 wiphy_regulatory_deregister(wiphy);
623 mutex_unlock(&cfg80211_mutex); 598 rtnl_unlock();
624 return res; 599 return res;
625 } 600 }
626 601
627 rtnl_lock();
628 rdev->wiphy.registered = true; 602 rdev->wiphy.registered = true;
629 rtnl_unlock(); 603 rtnl_unlock();
630 return 0; 604 return 0;
@@ -654,25 +628,19 @@ void wiphy_unregister(struct wiphy *wiphy)
654{ 628{
655 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); 629 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
656 630
657 rtnl_lock();
658 rdev->wiphy.registered = false;
659 rtnl_unlock();
660
661 rfkill_unregister(rdev->rfkill);
662
663 /* protect the device list */
664 mutex_lock(&cfg80211_mutex);
665
666 wait_event(rdev->dev_wait, ({ 631 wait_event(rdev->dev_wait, ({
667 int __count; 632 int __count;
668 mutex_lock(&rdev->devlist_mtx); 633 rtnl_lock();
669 __count = rdev->opencount; 634 __count = rdev->opencount;
670 mutex_unlock(&rdev->devlist_mtx); 635 rtnl_unlock();
671 __count == 0; })); 636 __count == 0; }));
672 637
673 mutex_lock(&rdev->devlist_mtx); 638 rtnl_lock();
639 rdev->wiphy.registered = false;
640
641 rfkill_unregister(rdev->rfkill);
642
674 BUG_ON(!list_empty(&rdev->wdev_list)); 643 BUG_ON(!list_empty(&rdev->wdev_list));
675 mutex_unlock(&rdev->devlist_mtx);
676 644
677 /* 645 /*
678 * First remove the hardware from everywhere, this makes 646 * First remove the hardware from everywhere, this makes
@@ -683,20 +651,6 @@ void wiphy_unregister(struct wiphy *wiphy)
683 synchronize_rcu(); 651 synchronize_rcu();
684 652
685 /* 653 /*
686 * Try to grab rdev->mtx. If a command is still in progress,
687 * hopefully the driver will refuse it since it's tearing
688 * down the device already. We wait for this command to complete
689 * before unlinking the item from the list.
690 * Note: as codified by the BUG_ON above we cannot get here if
691 * a virtual interface is still present. Hence, we can only get
692 * to lock contention here if userspace issues a command that
693 * identified the hardware by wiphy index.
694 */
695 cfg80211_lock_rdev(rdev);
696 /* nothing */
697 cfg80211_unlock_rdev(rdev);
698
699 /*
700 * If this device got a regulatory hint tell core its 654 * If this device got a regulatory hint tell core its
701 * free to listen now to a new shiny device regulatory hint 655 * free to listen now to a new shiny device regulatory hint
702 */ 656 */
@@ -705,7 +659,7 @@ void wiphy_unregister(struct wiphy *wiphy)
705 cfg80211_rdev_list_generation++; 659 cfg80211_rdev_list_generation++;
706 device_del(&rdev->wiphy.dev); 660 device_del(&rdev->wiphy.dev);
707 661
708 mutex_unlock(&cfg80211_mutex); 662 rtnl_unlock();
709 663
710 flush_work(&rdev->scan_done_wk); 664 flush_work(&rdev->scan_done_wk);
711 cancel_work_sync(&rdev->conn_work); 665 cancel_work_sync(&rdev->conn_work);
@@ -723,9 +677,6 @@ void cfg80211_dev_free(struct cfg80211_registered_device *rdev)
723 struct cfg80211_internal_bss *scan, *tmp; 677 struct cfg80211_internal_bss *scan, *tmp;
724 struct cfg80211_beacon_registration *reg, *treg; 678 struct cfg80211_beacon_registration *reg, *treg;
725 rfkill_destroy(rdev->rfkill); 679 rfkill_destroy(rdev->rfkill);
726 mutex_destroy(&rdev->mtx);
727 mutex_destroy(&rdev->devlist_mtx);
728 mutex_destroy(&rdev->sched_scan_mtx);
729 list_for_each_entry_safe(reg, treg, &rdev->beacon_registrations, list) { 680 list_for_each_entry_safe(reg, treg, &rdev->beacon_registrations, list) {
730 list_del(&reg->list); 681 list_del(&reg->list);
731 kfree(reg); 682 kfree(reg);
@@ -750,36 +701,6 @@ void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked)
750} 701}
751EXPORT_SYMBOL(wiphy_rfkill_set_hw_state); 702EXPORT_SYMBOL(wiphy_rfkill_set_hw_state);
752 703
753static void wdev_cleanup_work(struct work_struct *work)
754{
755 struct wireless_dev *wdev;
756 struct cfg80211_registered_device *rdev;
757
758 wdev = container_of(work, struct wireless_dev, cleanup_work);
759 rdev = wiphy_to_dev(wdev->wiphy);
760
761 mutex_lock(&rdev->sched_scan_mtx);
762
763 if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) {
764 rdev->scan_req->aborted = true;
765 ___cfg80211_scan_done(rdev, true);
766 }
767
768 if (WARN_ON(rdev->sched_scan_req &&
769 rdev->sched_scan_req->dev == wdev->netdev)) {
770 __cfg80211_stop_sched_scan(rdev, false);
771 }
772
773 mutex_unlock(&rdev->sched_scan_mtx);
774
775 mutex_lock(&rdev->devlist_mtx);
776 rdev->opencount--;
777 mutex_unlock(&rdev->devlist_mtx);
778 wake_up(&rdev->dev_wait);
779
780 dev_put(wdev->netdev);
781}
782
783void cfg80211_unregister_wdev(struct wireless_dev *wdev) 704void cfg80211_unregister_wdev(struct wireless_dev *wdev)
784{ 705{
785 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 706 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
@@ -789,8 +710,6 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev)
789 if (WARN_ON(wdev->netdev)) 710 if (WARN_ON(wdev->netdev))
790 return; 711 return;
791 712
792 mutex_lock(&rdev->devlist_mtx);
793 mutex_lock(&rdev->sched_scan_mtx);
794 list_del_rcu(&wdev->list); 713 list_del_rcu(&wdev->list);
795 rdev->devlist_generation++; 714 rdev->devlist_generation++;
796 715
@@ -802,8 +721,6 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev)
802 WARN_ON_ONCE(1); 721 WARN_ON_ONCE(1);
803 break; 722 break;
804 } 723 }
805 mutex_unlock(&rdev->sched_scan_mtx);
806 mutex_unlock(&rdev->devlist_mtx);
807} 724}
808EXPORT_SYMBOL(cfg80211_unregister_wdev); 725EXPORT_SYMBOL(cfg80211_unregister_wdev);
809 726
@@ -822,7 +739,7 @@ void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
822} 739}
823 740
824void cfg80211_leave(struct cfg80211_registered_device *rdev, 741void cfg80211_leave(struct cfg80211_registered_device *rdev,
825 struct wireless_dev *wdev) 742 struct wireless_dev *wdev)
826{ 743{
827 struct net_device *dev = wdev->netdev; 744 struct net_device *dev = wdev->netdev;
828 745
@@ -832,9 +749,7 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev,
832 break; 749 break;
833 case NL80211_IFTYPE_P2P_CLIENT: 750 case NL80211_IFTYPE_P2P_CLIENT:
834 case NL80211_IFTYPE_STATION: 751 case NL80211_IFTYPE_STATION:
835 mutex_lock(&rdev->sched_scan_mtx);
836 __cfg80211_stop_sched_scan(rdev, false); 752 __cfg80211_stop_sched_scan(rdev, false);
837 mutex_unlock(&rdev->sched_scan_mtx);
838 753
839 wdev_lock(wdev); 754 wdev_lock(wdev);
840#ifdef CONFIG_CFG80211_WEXT 755#ifdef CONFIG_CFG80211_WEXT
@@ -887,13 +802,11 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
887 * are added with nl80211. 802 * are added with nl80211.
888 */ 803 */
889 mutex_init(&wdev->mtx); 804 mutex_init(&wdev->mtx);
890 INIT_WORK(&wdev->cleanup_work, wdev_cleanup_work);
891 INIT_LIST_HEAD(&wdev->event_list); 805 INIT_LIST_HEAD(&wdev->event_list);
892 spin_lock_init(&wdev->event_lock); 806 spin_lock_init(&wdev->event_lock);
893 INIT_LIST_HEAD(&wdev->mgmt_registrations); 807 INIT_LIST_HEAD(&wdev->mgmt_registrations);
894 spin_lock_init(&wdev->mgmt_registrations_lock); 808 spin_lock_init(&wdev->mgmt_registrations_lock);
895 809
896 mutex_lock(&rdev->devlist_mtx);
897 wdev->identifier = ++rdev->wdev_id; 810 wdev->identifier = ++rdev->wdev_id;
898 list_add_rcu(&wdev->list, &rdev->wdev_list); 811 list_add_rcu(&wdev->list, &rdev->wdev_list);
899 rdev->devlist_generation++; 812 rdev->devlist_generation++;
@@ -906,7 +819,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
906 } 819 }
907 wdev->netdev = dev; 820 wdev->netdev = dev;
908 wdev->sme_state = CFG80211_SME_IDLE; 821 wdev->sme_state = CFG80211_SME_IDLE;
909 mutex_unlock(&rdev->devlist_mtx);
910#ifdef CONFIG_CFG80211_WEXT 822#ifdef CONFIG_CFG80211_WEXT
911 wdev->wext.default_key = -1; 823 wdev->wext.default_key = -1;
912 wdev->wext.default_mgmt_key = -1; 824 wdev->wext.default_mgmt_key = -1;
@@ -932,26 +844,22 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
932 break; 844 break;
933 case NETDEV_DOWN: 845 case NETDEV_DOWN:
934 cfg80211_update_iface_num(rdev, wdev->iftype, -1); 846 cfg80211_update_iface_num(rdev, wdev->iftype, -1);
935 dev_hold(dev); 847 if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
936 queue_work(cfg80211_wq, &wdev->cleanup_work); 848 if (WARN_ON(!rdev->scan_req->notified))
849 rdev->scan_req->aborted = true;
850 ___cfg80211_scan_done(rdev, true);
851 }
852
853 if (WARN_ON(rdev->sched_scan_req &&
854 rdev->sched_scan_req->dev == wdev->netdev)) {
855 __cfg80211_stop_sched_scan(rdev, false);
856 }
857
858 rdev->opencount--;
859 wake_up(&rdev->dev_wait);
937 break; 860 break;
938 case NETDEV_UP: 861 case NETDEV_UP:
939 /*
940 * If we have a really quick DOWN/UP succession we may
941 * have this work still pending ... cancel it and see
942 * if it was pending, in which case we need to account
943 * for some of the work it would have done.
944 */
945 if (cancel_work_sync(&wdev->cleanup_work)) {
946 mutex_lock(&rdev->devlist_mtx);
947 rdev->opencount--;
948 mutex_unlock(&rdev->devlist_mtx);
949 dev_put(dev);
950 }
951 cfg80211_update_iface_num(rdev, wdev->iftype, 1); 862 cfg80211_update_iface_num(rdev, wdev->iftype, 1);
952 cfg80211_lock_rdev(rdev);
953 mutex_lock(&rdev->devlist_mtx);
954 mutex_lock(&rdev->sched_scan_mtx);
955 wdev_lock(wdev); 863 wdev_lock(wdev);
956 switch (wdev->iftype) { 864 switch (wdev->iftype) {
957#ifdef CONFIG_CFG80211_WEXT 865#ifdef CONFIG_CFG80211_WEXT
@@ -983,10 +891,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
983 break; 891 break;
984 } 892 }
985 wdev_unlock(wdev); 893 wdev_unlock(wdev);
986 mutex_unlock(&rdev->sched_scan_mtx);
987 rdev->opencount++; 894 rdev->opencount++;
988 mutex_unlock(&rdev->devlist_mtx);
989 cfg80211_unlock_rdev(rdev);
990 895
991 /* 896 /*
992 * Configure power management to the driver here so that its 897 * Configure power management to the driver here so that its
@@ -1003,12 +908,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
1003 break; 908 break;
1004 case NETDEV_UNREGISTER: 909 case NETDEV_UNREGISTER:
1005 /* 910 /*
1006 * NB: cannot take rdev->mtx here because this may be
1007 * called within code protected by it when interfaces
1008 * are removed with nl80211.
1009 */
1010 mutex_lock(&rdev->devlist_mtx);
1011 /*
1012 * It is possible to get NETDEV_UNREGISTER 911 * It is possible to get NETDEV_UNREGISTER
1013 * multiple times. To detect that, check 912 * multiple times. To detect that, check
1014 * that the interface is still on the list 913 * that the interface is still on the list
@@ -1024,7 +923,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
1024 kfree(wdev->wext.keys); 923 kfree(wdev->wext.keys);
1025#endif 924#endif
1026 } 925 }
1027 mutex_unlock(&rdev->devlist_mtx);
1028 /* 926 /*
1029 * synchronise (so that we won't find this netdev 927 * synchronise (so that we won't find this netdev
1030 * from other code any more) and then clear the list 928 * from other code any more) and then clear the list
@@ -1044,9 +942,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
1044 return notifier_from_errno(-EOPNOTSUPP); 942 return notifier_from_errno(-EOPNOTSUPP);
1045 if (rfkill_blocked(rdev->rfkill)) 943 if (rfkill_blocked(rdev->rfkill))
1046 return notifier_from_errno(-ERFKILL); 944 return notifier_from_errno(-ERFKILL);
1047 mutex_lock(&rdev->devlist_mtx);
1048 ret = cfg80211_can_add_interface(rdev, wdev->iftype); 945 ret = cfg80211_can_add_interface(rdev, wdev->iftype);
1049 mutex_unlock(&rdev->devlist_mtx);
1050 if (ret) 946 if (ret)
1051 return notifier_from_errno(ret); 947 return notifier_from_errno(ret);
1052 break; 948 break;
@@ -1064,12 +960,10 @@ static void __net_exit cfg80211_pernet_exit(struct net *net)
1064 struct cfg80211_registered_device *rdev; 960 struct cfg80211_registered_device *rdev;
1065 961
1066 rtnl_lock(); 962 rtnl_lock();
1067 mutex_lock(&cfg80211_mutex);
1068 list_for_each_entry(rdev, &cfg80211_rdev_list, list) { 963 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
1069 if (net_eq(wiphy_net(&rdev->wiphy), net)) 964 if (net_eq(wiphy_net(&rdev->wiphy), net))
1070 WARN_ON(cfg80211_switch_netns(rdev, &init_net)); 965 WARN_ON(cfg80211_switch_netns(rdev, &init_net));
1071 } 966 }
1072 mutex_unlock(&cfg80211_mutex);
1073 rtnl_unlock(); 967 rtnl_unlock();
1074} 968}
1075 969
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 95b29075a9c8..d21a0fc01401 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -5,7 +5,6 @@
5 */ 5 */
6#ifndef __NET_WIRELESS_CORE_H 6#ifndef __NET_WIRELESS_CORE_H
7#define __NET_WIRELESS_CORE_H 7#define __NET_WIRELESS_CORE_H
8#include <linux/mutex.h>
9#include <linux/list.h> 8#include <linux/list.h>
10#include <linux/netdevice.h> 9#include <linux/netdevice.h>
11#include <linux/rbtree.h> 10#include <linux/rbtree.h>
@@ -23,11 +22,6 @@
23struct cfg80211_registered_device { 22struct cfg80211_registered_device {
24 const struct cfg80211_ops *ops; 23 const struct cfg80211_ops *ops;
25 struct list_head list; 24 struct list_head list;
26 /* we hold this mutex during any call so that
27 * we cannot do multiple calls at once, and also
28 * to avoid the deregister call to proceed while
29 * any call is in progress */
30 struct mutex mtx;
31 25
32 /* rfkill support */ 26 /* rfkill support */
33 struct rfkill_ops rfkill_ops; 27 struct rfkill_ops rfkill_ops;
@@ -49,9 +43,7 @@ struct cfg80211_registered_device {
49 /* wiphy index, internal only */ 43 /* wiphy index, internal only */
50 int wiphy_idx; 44 int wiphy_idx;
51 45
52 /* associated wireless interfaces */ 46 /* associated wireless interfaces, protected by rtnl or RCU */
53 struct mutex devlist_mtx;
54 /* protected by devlist_mtx or RCU */
55 struct list_head wdev_list; 47 struct list_head wdev_list;
56 int devlist_generation, wdev_id; 48 int devlist_generation, wdev_id;
57 int opencount; /* also protected by devlist_mtx */ 49 int opencount; /* also protected by devlist_mtx */
@@ -75,8 +67,6 @@ struct cfg80211_registered_device {
75 struct work_struct scan_done_wk; 67 struct work_struct scan_done_wk;
76 struct work_struct sched_scan_results_wk; 68 struct work_struct sched_scan_results_wk;
77 69
78 struct mutex sched_scan_mtx;
79
80#ifdef CONFIG_NL80211_TESTMODE 70#ifdef CONFIG_NL80211_TESTMODE
81 struct genl_info *testmode_info; 71 struct genl_info *testmode_info;
82#endif 72#endif
@@ -120,15 +110,9 @@ cfg80211_rdev_free_wowlan(struct cfg80211_registered_device *rdev)
120} 110}
121 111
122extern struct workqueue_struct *cfg80211_wq; 112extern struct workqueue_struct *cfg80211_wq;
123extern struct mutex cfg80211_mutex;
124extern struct list_head cfg80211_rdev_list; 113extern struct list_head cfg80211_rdev_list;
125extern int cfg80211_rdev_list_generation; 114extern int cfg80211_rdev_list_generation;
126 115
127static inline void assert_cfg80211_lock(void)
128{
129 lockdep_assert_held(&cfg80211_mutex);
130}
131
132struct cfg80211_internal_bss { 116struct cfg80211_internal_bss {
133 struct list_head list; 117 struct list_head list;
134 struct list_head hidden_list; 118 struct list_head hidden_list;
@@ -161,23 +145,11 @@ static inline void cfg80211_unhold_bss(struct cfg80211_internal_bss *bss)
161struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx); 145struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx);
162int get_wiphy_idx(struct wiphy *wiphy); 146int get_wiphy_idx(struct wiphy *wiphy);
163 147
164/* requires cfg80211_rdev_mutex to be held! */
165struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx); 148struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx);
166 149
167int cfg80211_switch_netns(struct cfg80211_registered_device *rdev, 150int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
168 struct net *net); 151 struct net *net);
169 152
170static inline void cfg80211_lock_rdev(struct cfg80211_registered_device *rdev)
171{
172 mutex_lock(&rdev->mtx);
173}
174
175static inline void cfg80211_unlock_rdev(struct cfg80211_registered_device *rdev)
176{
177 BUG_ON(IS_ERR(rdev) || !rdev);
178 mutex_unlock(&rdev->mtx);
179}
180
181static inline void wdev_lock(struct wireless_dev *wdev) 153static inline void wdev_lock(struct wireless_dev *wdev)
182 __acquires(wdev) 154 __acquires(wdev)
183{ 155{
@@ -192,7 +164,7 @@ static inline void wdev_unlock(struct wireless_dev *wdev)
192 mutex_unlock(&wdev->mtx); 164 mutex_unlock(&wdev->mtx);
193} 165}
194 166
195#define ASSERT_RDEV_LOCK(rdev) lockdep_assert_held(&(rdev)->mtx) 167#define ASSERT_RDEV_LOCK(rdev) ASSERT_RTNL()
196#define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx) 168#define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx)
197 169
198static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev) 170static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev)
diff --git a/net/wireless/debugfs.c b/net/wireless/debugfs.c
index 920cabe0461b..90d050036624 100644
--- a/net/wireless/debugfs.c
+++ b/net/wireless/debugfs.c
@@ -74,7 +74,7 @@ static ssize_t ht40allow_map_read(struct file *file,
74 if (!buf) 74 if (!buf)
75 return -ENOMEM; 75 return -ENOMEM;
76 76
77 mutex_lock(&cfg80211_mutex); 77 rtnl_lock();
78 78
79 for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 79 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
80 sband = wiphy->bands[band]; 80 sband = wiphy->bands[band];
@@ -85,7 +85,7 @@ static ssize_t ht40allow_map_read(struct file *file,
85 buf, buf_size, offset); 85 buf, buf_size, offset);
86 } 86 }
87 87
88 mutex_unlock(&cfg80211_mutex); 88 rtnl_unlock();
89 89
90 r = simple_read_from_buffer(user_buf, count, ppos, buf, offset); 90 r = simple_read_from_buffer(user_buf, count, ppos, buf, offset);
91 91
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index d80e47194d49..5449c5a6de84 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -152,11 +152,11 @@ int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
152 struct wireless_dev *wdev = dev->ieee80211_ptr; 152 struct wireless_dev *wdev = dev->ieee80211_ptr;
153 int err; 153 int err;
154 154
155 mutex_lock(&rdev->devlist_mtx); 155 ASSERT_RTNL();
156
156 wdev_lock(wdev); 157 wdev_lock(wdev);
157 err = __cfg80211_join_ibss(rdev, dev, params, connkeys); 158 err = __cfg80211_join_ibss(rdev, dev, params, connkeys);
158 wdev_unlock(wdev); 159 wdev_unlock(wdev);
159 mutex_unlock(&rdev->devlist_mtx);
160 160
161 return err; 161 return err;
162} 162}
@@ -359,11 +359,9 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
359 wdev->wext.ibss.channel_fixed = false; 359 wdev->wext.ibss.channel_fixed = false;
360 } 360 }
361 361
362 mutex_lock(&rdev->devlist_mtx);
363 wdev_lock(wdev); 362 wdev_lock(wdev);
364 err = cfg80211_ibss_wext_join(rdev, wdev); 363 err = cfg80211_ibss_wext_join(rdev, wdev);
365 wdev_unlock(wdev); 364 wdev_unlock(wdev);
366 mutex_unlock(&rdev->devlist_mtx);
367 365
368 return err; 366 return err;
369} 367}
@@ -429,11 +427,9 @@ int cfg80211_ibss_wext_siwessid(struct net_device *dev,
429 memcpy(wdev->wext.ibss.ssid, ssid, len); 427 memcpy(wdev->wext.ibss.ssid, ssid, len);
430 wdev->wext.ibss.ssid_len = len; 428 wdev->wext.ibss.ssid_len = len;
431 429
432 mutex_lock(&rdev->devlist_mtx);
433 wdev_lock(wdev); 430 wdev_lock(wdev);
434 err = cfg80211_ibss_wext_join(rdev, wdev); 431 err = cfg80211_ibss_wext_join(rdev, wdev);
435 wdev_unlock(wdev); 432 wdev_unlock(wdev);
436 mutex_unlock(&rdev->devlist_mtx);
437 433
438 return err; 434 return err;
439} 435}
@@ -512,11 +508,9 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev,
512 } else 508 } else
513 wdev->wext.ibss.bssid = NULL; 509 wdev->wext.ibss.bssid = NULL;
514 510
515 mutex_lock(&rdev->devlist_mtx);
516 wdev_lock(wdev); 511 wdev_lock(wdev);
517 err = cfg80211_ibss_wext_join(rdev, wdev); 512 err = cfg80211_ibss_wext_join(rdev, wdev);
518 wdev_unlock(wdev); 513 wdev_unlock(wdev);
519 mutex_unlock(&rdev->devlist_mtx);
520 514
521 return err; 515 return err;
522} 516}
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
index 9546ad210550..5dfb289ab761 100644
--- a/net/wireless/mesh.c
+++ b/net/wireless/mesh.c
@@ -186,11 +186,9 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
186 struct wireless_dev *wdev = dev->ieee80211_ptr; 186 struct wireless_dev *wdev = dev->ieee80211_ptr;
187 int err; 187 int err;
188 188
189 mutex_lock(&rdev->devlist_mtx);
190 wdev_lock(wdev); 189 wdev_lock(wdev);
191 err = __cfg80211_join_mesh(rdev, dev, setup, conf); 190 err = __cfg80211_join_mesh(rdev, dev, setup, conf);
192 wdev_unlock(wdev); 191 wdev_unlock(wdev);
193 mutex_unlock(&rdev->devlist_mtx);
194 192
195 return err; 193 return err;
196} 194}
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index c21e32f9549c..68b40f21bc38 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -313,14 +313,14 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
313{ 313{
314 int err; 314 int err;
315 315
316 mutex_lock(&rdev->devlist_mtx); 316 ASSERT_RTNL();
317
317 wdev_lock(dev->ieee80211_ptr); 318 wdev_lock(dev->ieee80211_ptr);
318 err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, 319 err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
319 ssid, ssid_len, ie, ie_len, 320 ssid, ssid_len, ie, ie_len,
320 key, key_len, key_idx, 321 key, key_len, key_idx,
321 sae_data, sae_data_len); 322 sae_data, sae_data_len);
322 wdev_unlock(dev->ieee80211_ptr); 323 wdev_unlock(dev->ieee80211_ptr);
323 mutex_unlock(&rdev->devlist_mtx);
324 324
325 return err; 325 return err;
326} 326}
@@ -424,12 +424,12 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
424 struct wireless_dev *wdev = dev->ieee80211_ptr; 424 struct wireless_dev *wdev = dev->ieee80211_ptr;
425 int err; 425 int err;
426 426
427 mutex_lock(&rdev->devlist_mtx); 427 ASSERT_RTNL();
428
428 wdev_lock(wdev); 429 wdev_lock(wdev);
429 err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, 430 err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid,
430 ssid, ssid_len, req); 431 ssid, ssid_len, req);
431 wdev_unlock(wdev); 432 wdev_unlock(wdev);
432 mutex_unlock(&rdev->devlist_mtx);
433 433
434 return err; 434 return err;
435} 435}
@@ -844,7 +844,7 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work)
844 dfs_update_channels_wk); 844 dfs_update_channels_wk);
845 wiphy = &rdev->wiphy; 845 wiphy = &rdev->wiphy;
846 846
847 mutex_lock(&cfg80211_mutex); 847 rtnl_lock();
848 for (bandid = 0; bandid < IEEE80211_NUM_BANDS; bandid++) { 848 for (bandid = 0; bandid < IEEE80211_NUM_BANDS; bandid++) {
849 sband = wiphy->bands[bandid]; 849 sband = wiphy->bands[bandid];
850 if (!sband) 850 if (!sband)
@@ -877,7 +877,7 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work)
877 check_again = true; 877 check_again = true;
878 } 878 }
879 } 879 }
880 mutex_unlock(&cfg80211_mutex); 880 rtnl_unlock();
881 881
882 /* reschedule if there are other channels waiting to be cleared again */ 882 /* reschedule if there are other channels waiting to be cleared again */
883 if (check_again) 883 if (check_again)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 5bcf3a5b6465..74cdb1a0cf31 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -59,7 +59,7 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
59 int wiphy_idx = -1; 59 int wiphy_idx = -1;
60 int ifidx = -1; 60 int ifidx = -1;
61 61
62 assert_cfg80211_lock(); 62 ASSERT_RTNL();
63 63
64 if (!have_ifidx && !have_wdev_id) 64 if (!have_ifidx && !have_wdev_id)
65 return ERR_PTR(-EINVAL); 65 return ERR_PTR(-EINVAL);
@@ -80,7 +80,6 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
80 if (have_wdev_id && rdev->wiphy_idx != wiphy_idx) 80 if (have_wdev_id && rdev->wiphy_idx != wiphy_idx)
81 continue; 81 continue;
82 82
83 mutex_lock(&rdev->devlist_mtx);
84 list_for_each_entry(wdev, &rdev->wdev_list, list) { 83 list_for_each_entry(wdev, &rdev->wdev_list, list) {
85 if (have_ifidx && wdev->netdev && 84 if (have_ifidx && wdev->netdev &&
86 wdev->netdev->ifindex == ifidx) { 85 wdev->netdev->ifindex == ifidx) {
@@ -92,7 +91,6 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
92 break; 91 break;
93 } 92 }
94 } 93 }
95 mutex_unlock(&rdev->devlist_mtx);
96 94
97 if (result) 95 if (result)
98 break; 96 break;
@@ -109,7 +107,7 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
109 struct cfg80211_registered_device *rdev = NULL, *tmp; 107 struct cfg80211_registered_device *rdev = NULL, *tmp;
110 struct net_device *netdev; 108 struct net_device *netdev;
111 109
112 assert_cfg80211_lock(); 110 ASSERT_RTNL();
113 111
114 if (!attrs[NL80211_ATTR_WIPHY] && 112 if (!attrs[NL80211_ATTR_WIPHY] &&
115 !attrs[NL80211_ATTR_IFINDEX] && 113 !attrs[NL80211_ATTR_IFINDEX] &&
@@ -128,14 +126,12 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
128 tmp = cfg80211_rdev_by_wiphy_idx(wdev_id >> 32); 126 tmp = cfg80211_rdev_by_wiphy_idx(wdev_id >> 32);
129 if (tmp) { 127 if (tmp) {
130 /* make sure wdev exists */ 128 /* make sure wdev exists */
131 mutex_lock(&tmp->devlist_mtx);
132 list_for_each_entry(wdev, &tmp->wdev_list, list) { 129 list_for_each_entry(wdev, &tmp->wdev_list, list) {
133 if (wdev->identifier != (u32)wdev_id) 130 if (wdev->identifier != (u32)wdev_id)
134 continue; 131 continue;
135 found = true; 132 found = true;
136 break; 133 break;
137 } 134 }
138 mutex_unlock(&tmp->devlist_mtx);
139 135
140 if (!found) 136 if (!found)
141 tmp = NULL; 137 tmp = NULL;
@@ -182,19 +178,6 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
182/* 178/*
183 * This function returns a pointer to the driver 179 * This function returns a pointer to the driver
184 * that the genl_info item that is passed refers to. 180 * that the genl_info item that is passed refers to.
185 * If successful, it returns non-NULL and also locks
186 * the driver's mutex!
187 *
188 * This means that you need to call cfg80211_unlock_rdev()
189 * before being allowed to acquire &cfg80211_mutex!
190 *
191 * This is necessary because we need to lock the global
192 * mutex to get an item off the list safely, and then
193 * we lock the rdev mutex so it doesn't go away under us.
194 *
195 * We don't want to keep cfg80211_mutex locked
196 * for all the time in order to allow requests on
197 * other interfaces to go through at the same time.
198 * 181 *
199 * The result of this can be a PTR_ERR and hence must 182 * The result of this can be a PTR_ERR and hence must
200 * be checked with IS_ERR() for errors. 183 * be checked with IS_ERR() for errors.
@@ -202,20 +185,7 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
202static struct cfg80211_registered_device * 185static struct cfg80211_registered_device *
203cfg80211_get_dev_from_info(struct net *netns, struct genl_info *info) 186cfg80211_get_dev_from_info(struct net *netns, struct genl_info *info)
204{ 187{
205 struct cfg80211_registered_device *rdev; 188 return __cfg80211_rdev_from_attrs(netns, info->attrs);
206
207 mutex_lock(&cfg80211_mutex);
208 rdev = __cfg80211_rdev_from_attrs(netns, info->attrs);
209
210 /* if it is not an error we grab the lock on
211 * it to assure it won't be going away while
212 * we operate on it */
213 if (!IS_ERR(rdev))
214 mutex_lock(&rdev->mtx);
215
216 mutex_unlock(&cfg80211_mutex);
217
218 return rdev;
219} 189}
220 190
221/* policy for the attributes */ 191/* policy for the attributes */
@@ -456,7 +426,6 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
456 int err; 426 int err;
457 427
458 rtnl_lock(); 428 rtnl_lock();
459 mutex_lock(&cfg80211_mutex);
460 429
461 if (!cb->args[0]) { 430 if (!cb->args[0]) {
462 err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, 431 err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
@@ -485,14 +454,12 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
485 *rdev = wiphy_to_dev(wiphy); 454 *rdev = wiphy_to_dev(wiphy);
486 *wdev = NULL; 455 *wdev = NULL;
487 456
488 mutex_lock(&(*rdev)->devlist_mtx);
489 list_for_each_entry(tmp, &(*rdev)->wdev_list, list) { 457 list_for_each_entry(tmp, &(*rdev)->wdev_list, list) {
490 if (tmp->identifier == cb->args[1]) { 458 if (tmp->identifier == cb->args[1]) {
491 *wdev = tmp; 459 *wdev = tmp;
492 break; 460 break;
493 } 461 }
494 } 462 }
495 mutex_unlock(&(*rdev)->devlist_mtx);
496 463
497 if (!*wdev) { 464 if (!*wdev) {
498 err = -ENODEV; 465 err = -ENODEV;
@@ -500,19 +467,14 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
500 } 467 }
501 } 468 }
502 469
503 cfg80211_lock_rdev(*rdev);
504
505 mutex_unlock(&cfg80211_mutex);
506 return 0; 470 return 0;
507 out_unlock: 471 out_unlock:
508 mutex_unlock(&cfg80211_mutex);
509 rtnl_unlock(); 472 rtnl_unlock();
510 return err; 473 return err;
511} 474}
512 475
513static void nl80211_finish_wdev_dump(struct cfg80211_registered_device *rdev) 476static void nl80211_finish_wdev_dump(struct cfg80211_registered_device *rdev)
514{ 477{
515 cfg80211_unlock_rdev(rdev);
516 rtnl_unlock(); 478 rtnl_unlock();
517} 479}
518 480
@@ -1568,7 +1530,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
1568 struct nlattr **tb = nl80211_fam.attrbuf; 1530 struct nlattr **tb = nl80211_fam.attrbuf;
1569 int res; 1531 int res;
1570 1532
1571 mutex_lock(&cfg80211_mutex); 1533 rtnl_lock();
1572 res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, 1534 res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
1573 tb, nl80211_fam.maxattr, nl80211_policy); 1535 tb, nl80211_fam.maxattr, nl80211_policy);
1574 if (res == 0) { 1536 if (res == 0) {
@@ -1582,10 +1544,8 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
1582 int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]); 1544 int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
1583 1545
1584 netdev = dev_get_by_index(sock_net(skb->sk), ifidx); 1546 netdev = dev_get_by_index(sock_net(skb->sk), ifidx);
1585 if (!netdev) { 1547 if (!netdev)
1586 mutex_unlock(&cfg80211_mutex);
1587 return -ENODEV; 1548 return -ENODEV;
1588 }
1589 if (netdev->ieee80211_ptr) { 1549 if (netdev->ieee80211_ptr) {
1590 dev = wiphy_to_dev( 1550 dev = wiphy_to_dev(
1591 netdev->ieee80211_ptr->wiphy); 1551 netdev->ieee80211_ptr->wiphy);
@@ -1629,7 +1589,6 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
1629 !skb->len && 1589 !skb->len &&
1630 cb->min_dump_alloc < 4096) { 1590 cb->min_dump_alloc < 4096) {
1631 cb->min_dump_alloc = 4096; 1591 cb->min_dump_alloc = 4096;
1632 mutex_unlock(&cfg80211_mutex);
1633 return 1; 1592 return 1;
1634 } 1593 }
1635 idx--; 1594 idx--;
@@ -1638,7 +1597,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
1638 } while (cb->args[1] > 0); 1597 } while (cb->args[1] > 0);
1639 break; 1598 break;
1640 } 1599 }
1641 mutex_unlock(&cfg80211_mutex); 1600 rtnl_unlock();
1642 1601
1643 cb->args[0] = idx; 1602 cb->args[0] = idx;
1644 1603
@@ -1793,7 +1752,6 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
1793 if (result) 1752 if (result)
1794 return result; 1753 return result;
1795 1754
1796 mutex_lock(&rdev->devlist_mtx);
1797 switch (iftype) { 1755 switch (iftype) {
1798 case NL80211_IFTYPE_AP: 1756 case NL80211_IFTYPE_AP:
1799 case NL80211_IFTYPE_P2P_GO: 1757 case NL80211_IFTYPE_P2P_GO:
@@ -1817,7 +1775,6 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
1817 default: 1775 default:
1818 result = -EINVAL; 1776 result = -EINVAL;
1819 } 1777 }
1820 mutex_unlock(&rdev->devlist_mtx);
1821 1778
1822 return result; 1779 return result;
1823} 1780}
@@ -1866,6 +1823,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
1866 u32 frag_threshold = 0, rts_threshold = 0; 1823 u32 frag_threshold = 0, rts_threshold = 0;
1867 u8 coverage_class = 0; 1824 u8 coverage_class = 0;
1868 1825
1826 ASSERT_RTNL();
1827
1869 /* 1828 /*
1870 * Try to find the wiphy and netdev. Normally this 1829 * Try to find the wiphy and netdev. Normally this
1871 * function shouldn't need the netdev, but this is 1830 * function shouldn't need the netdev, but this is
@@ -1875,31 +1834,25 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
1875 * also passed a netdev to set_wiphy, so that it is 1834 * also passed a netdev to set_wiphy, so that it is
1876 * possible to let that go to the right netdev! 1835 * possible to let that go to the right netdev!
1877 */ 1836 */
1878 mutex_lock(&cfg80211_mutex);
1879 1837
1880 if (info->attrs[NL80211_ATTR_IFINDEX]) { 1838 if (info->attrs[NL80211_ATTR_IFINDEX]) {
1881 int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]); 1839 int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
1882 1840
1883 netdev = dev_get_by_index(genl_info_net(info), ifindex); 1841 netdev = dev_get_by_index(genl_info_net(info), ifindex);
1884 if (netdev && netdev->ieee80211_ptr) { 1842 if (netdev && netdev->ieee80211_ptr)
1885 rdev = wiphy_to_dev(netdev->ieee80211_ptr->wiphy); 1843 rdev = wiphy_to_dev(netdev->ieee80211_ptr->wiphy);
1886 mutex_lock(&rdev->mtx); 1844 else
1887 } else
1888 netdev = NULL; 1845 netdev = NULL;
1889 } 1846 }
1890 1847
1891 if (!netdev) { 1848 if (!netdev) {
1892 rdev = __cfg80211_rdev_from_attrs(genl_info_net(info), 1849 rdev = __cfg80211_rdev_from_attrs(genl_info_net(info),
1893 info->attrs); 1850 info->attrs);
1894 if (IS_ERR(rdev)) { 1851 if (IS_ERR(rdev))
1895 mutex_unlock(&cfg80211_mutex);
1896 return PTR_ERR(rdev); 1852 return PTR_ERR(rdev);
1897 }
1898 wdev = NULL; 1853 wdev = NULL;
1899 netdev = NULL; 1854 netdev = NULL;
1900 result = 0; 1855 result = 0;
1901
1902 mutex_lock(&rdev->mtx);
1903 } else 1856 } else
1904 wdev = netdev->ieee80211_ptr; 1857 wdev = netdev->ieee80211_ptr;
1905 1858
@@ -1912,8 +1865,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
1912 result = cfg80211_dev_rename( 1865 result = cfg80211_dev_rename(
1913 rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME])); 1866 rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
1914 1867
1915 mutex_unlock(&cfg80211_mutex);
1916
1917 if (result) 1868 if (result)
1918 goto bad_res; 1869 goto bad_res;
1919 1870
@@ -2120,7 +2071,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
2120 } 2071 }
2121 2072
2122 bad_res: 2073 bad_res:
2123 mutex_unlock(&rdev->mtx);
2124 if (netdev) 2074 if (netdev)
2125 dev_put(netdev); 2075 dev_put(netdev);
2126 return result; 2076 return result;
@@ -2218,7 +2168,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
2218 struct cfg80211_registered_device *rdev; 2168 struct cfg80211_registered_device *rdev;
2219 struct wireless_dev *wdev; 2169 struct wireless_dev *wdev;
2220 2170
2221 mutex_lock(&cfg80211_mutex); 2171 rtnl_lock();
2222 list_for_each_entry(rdev, &cfg80211_rdev_list, list) { 2172 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
2223 if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk))) 2173 if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
2224 continue; 2174 continue;
@@ -2228,7 +2178,6 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
2228 } 2178 }
2229 if_idx = 0; 2179 if_idx = 0;
2230 2180
2231 mutex_lock(&rdev->devlist_mtx);
2232 list_for_each_entry(wdev, &rdev->wdev_list, list) { 2181 list_for_each_entry(wdev, &rdev->wdev_list, list) {
2233 if (if_idx < if_start) { 2182 if (if_idx < if_start) {
2234 if_idx++; 2183 if_idx++;
@@ -2237,17 +2186,15 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
2237 if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).portid, 2186 if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).portid,
2238 cb->nlh->nlmsg_seq, NLM_F_MULTI, 2187 cb->nlh->nlmsg_seq, NLM_F_MULTI,
2239 rdev, wdev) < 0) { 2188 rdev, wdev) < 0) {
2240 mutex_unlock(&rdev->devlist_mtx);
2241 goto out; 2189 goto out;
2242 } 2190 }
2243 if_idx++; 2191 if_idx++;
2244 } 2192 }
2245 mutex_unlock(&rdev->devlist_mtx);
2246 2193
2247 wp_idx++; 2194 wp_idx++;
2248 } 2195 }
2249 out: 2196 out:
2250 mutex_unlock(&cfg80211_mutex); 2197 rtnl_unlock();
2251 2198
2252 cb->args[0] = wp_idx; 2199 cb->args[0] = wp_idx;
2253 cb->args[1] = if_idx; 2200 cb->args[1] = if_idx;
@@ -2480,11 +2427,9 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
2480 INIT_LIST_HEAD(&wdev->mgmt_registrations); 2427 INIT_LIST_HEAD(&wdev->mgmt_registrations);
2481 spin_lock_init(&wdev->mgmt_registrations_lock); 2428 spin_lock_init(&wdev->mgmt_registrations_lock);
2482 2429
2483 mutex_lock(&rdev->devlist_mtx);
2484 wdev->identifier = ++rdev->wdev_id; 2430 wdev->identifier = ++rdev->wdev_id;
2485 list_add_rcu(&wdev->list, &rdev->wdev_list); 2431 list_add_rcu(&wdev->list, &rdev->wdev_list);
2486 rdev->devlist_generation++; 2432 rdev->devlist_generation++;
2487 mutex_unlock(&rdev->devlist_mtx);
2488 break; 2433 break;
2489 default: 2434 default:
2490 break; 2435 break;
@@ -2993,8 +2938,6 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
2993 struct wireless_dev *wdev; 2938 struct wireless_dev *wdev;
2994 bool ret = false; 2939 bool ret = false;
2995 2940
2996 mutex_lock(&rdev->devlist_mtx);
2997
2998 list_for_each_entry(wdev, &rdev->wdev_list, list) { 2941 list_for_each_entry(wdev, &rdev->wdev_list, list) {
2999 if (wdev->iftype != NL80211_IFTYPE_AP && 2942 if (wdev->iftype != NL80211_IFTYPE_AP &&
3000 wdev->iftype != NL80211_IFTYPE_P2P_GO) 2943 wdev->iftype != NL80211_IFTYPE_P2P_GO)
@@ -3008,8 +2951,6 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
3008 break; 2951 break;
3009 } 2952 }
3010 2953
3011 mutex_unlock(&rdev->devlist_mtx);
3012
3013 return ret; 2954 return ret;
3014} 2955}
3015 2956
@@ -3171,13 +3112,10 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
3171 params.radar_required = true; 3112 params.radar_required = true;
3172 } 3113 }
3173 3114
3174 mutex_lock(&rdev->devlist_mtx);
3175 err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, 3115 err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
3176 params.chandef.chan, 3116 params.chandef.chan,
3177 CHAN_MODE_SHARED, 3117 CHAN_MODE_SHARED,
3178 radar_detect_width); 3118 radar_detect_width);
3179 mutex_unlock(&rdev->devlist_mtx);
3180
3181 if (err) 3119 if (err)
3182 return err; 3120 return err;
3183 3121
@@ -4914,18 +4852,13 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
4914 void *hdr = NULL; 4852 void *hdr = NULL;
4915 struct nlattr *nl_reg_rules; 4853 struct nlattr *nl_reg_rules;
4916 unsigned int i; 4854 unsigned int i;
4917 int err = -EINVAL;
4918
4919 mutex_lock(&cfg80211_mutex);
4920 4855
4921 if (!cfg80211_regdomain) 4856 if (!cfg80211_regdomain)
4922 goto out; 4857 return -EINVAL;
4923 4858
4924 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 4859 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4925 if (!msg) { 4860 if (!msg)
4926 err = -ENOBUFS; 4861 return -ENOBUFS;
4927 goto out;
4928 }
4929 4862
4930 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0, 4863 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
4931 NL80211_CMD_GET_REG); 4864 NL80211_CMD_GET_REG);
@@ -4984,8 +4917,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
4984 nla_nest_end(msg, nl_reg_rules); 4917 nla_nest_end(msg, nl_reg_rules);
4985 4918
4986 genlmsg_end(msg, hdr); 4919 genlmsg_end(msg, hdr);
4987 err = genlmsg_reply(msg, info); 4920 return genlmsg_reply(msg, info);
4988 goto out;
4989 4921
4990nla_put_failure_rcu: 4922nla_put_failure_rcu:
4991 rcu_read_unlock(); 4923 rcu_read_unlock();
@@ -4993,10 +4925,7 @@ nla_put_failure:
4993 genlmsg_cancel(msg, hdr); 4925 genlmsg_cancel(msg, hdr);
4994put_failure: 4926put_failure:
4995 nlmsg_free(msg); 4927 nlmsg_free(msg);
4996 err = -EMSGSIZE; 4928 return -EMSGSIZE;
4997out:
4998 mutex_unlock(&cfg80211_mutex);
4999 return err;
5000} 4929}
5001 4930
5002static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) 4931static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
@@ -5062,12 +4991,9 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
5062 } 4991 }
5063 } 4992 }
5064 4993
5065 mutex_lock(&cfg80211_mutex);
5066
5067 r = set_regdom(rd); 4994 r = set_regdom(rd);
5068 /* set_regdom took ownership */ 4995 /* set_regdom took ownership */
5069 rd = NULL; 4996 rd = NULL;
5070 mutex_unlock(&cfg80211_mutex);
5071 4997
5072 bad_reg: 4998 bad_reg:
5073 kfree(rd); 4999 kfree(rd);
@@ -5117,7 +5043,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
5117 if (!rdev->ops->scan) 5043 if (!rdev->ops->scan)
5118 return -EOPNOTSUPP; 5044 return -EOPNOTSUPP;
5119 5045
5120 mutex_lock(&rdev->sched_scan_mtx);
5121 if (rdev->scan_req) { 5046 if (rdev->scan_req) {
5122 err = -EBUSY; 5047 err = -EBUSY;
5123 goto unlock; 5048 goto unlock;
@@ -5303,7 +5228,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
5303 } 5228 }
5304 5229
5305 unlock: 5230 unlock:
5306 mutex_unlock(&rdev->sched_scan_mtx);
5307 return err; 5231 return err;
5308} 5232}
5309 5233
@@ -5375,8 +5299,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
5375 if (ie_len > wiphy->max_sched_scan_ie_len) 5299 if (ie_len > wiphy->max_sched_scan_ie_len)
5376 return -EINVAL; 5300 return -EINVAL;
5377 5301
5378 mutex_lock(&rdev->sched_scan_mtx);
5379
5380 if (rdev->sched_scan_req) { 5302 if (rdev->sched_scan_req) {
5381 err = -EINPROGRESS; 5303 err = -EINPROGRESS;
5382 goto out; 5304 goto out;
@@ -5544,7 +5466,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
5544out_free: 5466out_free:
5545 kfree(request); 5467 kfree(request);
5546out: 5468out:
5547 mutex_unlock(&rdev->sched_scan_mtx);
5548 return err; 5469 return err;
5549} 5470}
5550 5471
@@ -5552,17 +5473,12 @@ static int nl80211_stop_sched_scan(struct sk_buff *skb,
5552 struct genl_info *info) 5473 struct genl_info *info)
5553{ 5474{
5554 struct cfg80211_registered_device *rdev = info->user_ptr[0]; 5475 struct cfg80211_registered_device *rdev = info->user_ptr[0];
5555 int err;
5556 5476
5557 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) || 5477 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
5558 !rdev->ops->sched_scan_stop) 5478 !rdev->ops->sched_scan_stop)
5559 return -EOPNOTSUPP; 5479 return -EOPNOTSUPP;
5560 5480
5561 mutex_lock(&rdev->sched_scan_mtx); 5481 return __cfg80211_stop_sched_scan(rdev, false);
5562 err = __cfg80211_stop_sched_scan(rdev, false);
5563 mutex_unlock(&rdev->sched_scan_mtx);
5564
5565 return err;
5566} 5482}
5567 5483
5568static int nl80211_start_radar_detection(struct sk_buff *skb, 5484static int nl80211_start_radar_detection(struct sk_buff *skb,
@@ -5594,12 +5510,11 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
5594 if (!rdev->ops->start_radar_detection) 5510 if (!rdev->ops->start_radar_detection)
5595 return -EOPNOTSUPP; 5511 return -EOPNOTSUPP;
5596 5512
5597 mutex_lock(&rdev->devlist_mtx);
5598 err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, 5513 err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
5599 chandef.chan, CHAN_MODE_SHARED, 5514 chandef.chan, CHAN_MODE_SHARED,
5600 BIT(chandef.width)); 5515 BIT(chandef.width));
5601 if (err) 5516 if (err)
5602 goto err_locked; 5517 return err;
5603 5518
5604 err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef); 5519 err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef);
5605 if (!err) { 5520 if (!err) {
@@ -5607,9 +5522,6 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
5607 wdev->cac_started = true; 5522 wdev->cac_started = true;
5608 wdev->cac_start_time = jiffies; 5523 wdev->cac_start_time = jiffies;
5609 } 5524 }
5610err_locked:
5611 mutex_unlock(&rdev->devlist_mtx);
5612
5613 return err; 5525 return err;
5614} 5526}
5615 5527
@@ -6472,6 +6384,8 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
6472 void *data = NULL; 6384 void *data = NULL;
6473 int data_len = 0; 6385 int data_len = 0;
6474 6386
6387 rtnl_lock();
6388
6475 if (cb->args[0]) { 6389 if (cb->args[0]) {
6476 /* 6390 /*
6477 * 0 is a valid index, but not valid for args[0], 6391 * 0 is a valid index, but not valid for args[0],
@@ -6483,18 +6397,16 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
6483 nl80211_fam.attrbuf, nl80211_fam.maxattr, 6397 nl80211_fam.attrbuf, nl80211_fam.maxattr,
6484 nl80211_policy); 6398 nl80211_policy);
6485 if (err) 6399 if (err)
6486 return err; 6400 goto out_err;
6487 6401
6488 mutex_lock(&cfg80211_mutex);
6489 rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), 6402 rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk),
6490 nl80211_fam.attrbuf); 6403 nl80211_fam.attrbuf);
6491 if (IS_ERR(rdev)) { 6404 if (IS_ERR(rdev)) {
6492 mutex_unlock(&cfg80211_mutex); 6405 err = PTR_ERR(rdev);
6493 return PTR_ERR(rdev); 6406 goto out_err;
6494 } 6407 }
6495 phy_idx = rdev->wiphy_idx; 6408 phy_idx = rdev->wiphy_idx;
6496 rdev = NULL; 6409 rdev = NULL;
6497 mutex_unlock(&cfg80211_mutex);
6498 6410
6499 if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA]) 6411 if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA])
6500 cb->args[1] = 6412 cb->args[1] =
@@ -6506,14 +6418,11 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
6506 data_len = nla_len((void *)cb->args[1]); 6418 data_len = nla_len((void *)cb->args[1]);
6507 } 6419 }
6508 6420
6509 mutex_lock(&cfg80211_mutex);
6510 rdev = cfg80211_rdev_by_wiphy_idx(phy_idx); 6421 rdev = cfg80211_rdev_by_wiphy_idx(phy_idx);
6511 if (!rdev) { 6422 if (!rdev) {
6512 mutex_unlock(&cfg80211_mutex); 6423 err = -ENOENT;
6513 return -ENOENT; 6424 goto out_err;
6514 } 6425 }
6515 cfg80211_lock_rdev(rdev);
6516 mutex_unlock(&cfg80211_mutex);
6517 6426
6518 if (!rdev->ops->testmode_dump) { 6427 if (!rdev->ops->testmode_dump) {
6519 err = -EOPNOTSUPP; 6428 err = -EOPNOTSUPP;
@@ -6554,7 +6463,7 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
6554 /* see above */ 6463 /* see above */
6555 cb->args[0] = phy_idx + 1; 6464 cb->args[0] = phy_idx + 1;
6556 out_err: 6465 out_err:
6557 cfg80211_unlock_rdev(rdev); 6466 rtnl_unlock();
6558 return err; 6467 return err;
6559} 6468}
6560 6469
@@ -8189,9 +8098,7 @@ static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
8189 if (wdev->p2p_started) 8098 if (wdev->p2p_started)
8190 return 0; 8099 return 0;
8191 8100
8192 mutex_lock(&rdev->devlist_mtx);
8193 err = cfg80211_can_add_interface(rdev, wdev->iftype); 8101 err = cfg80211_can_add_interface(rdev, wdev->iftype);
8194 mutex_unlock(&rdev->devlist_mtx);
8195 if (err) 8102 if (err)
8196 return err; 8103 return err;
8197 8104
@@ -8200,9 +8107,7 @@ static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
8200 return err; 8107 return err;
8201 8108
8202 wdev->p2p_started = true; 8109 wdev->p2p_started = true;
8203 mutex_lock(&rdev->devlist_mtx);
8204 rdev->opencount++; 8110 rdev->opencount++;
8205 mutex_unlock(&rdev->devlist_mtx);
8206 8111
8207 return 0; 8112 return 0;
8208} 8113}
@@ -8218,11 +8123,7 @@ static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info)
8218 if (!rdev->ops->stop_p2p_device) 8123 if (!rdev->ops->stop_p2p_device)
8219 return -EOPNOTSUPP; 8124 return -EOPNOTSUPP;
8220 8125
8221 mutex_lock(&rdev->devlist_mtx);
8222 mutex_lock(&rdev->sched_scan_mtx);
8223 cfg80211_stop_p2p_device(rdev, wdev); 8126 cfg80211_stop_p2p_device(rdev, wdev);
8224 mutex_unlock(&rdev->sched_scan_mtx);
8225 mutex_unlock(&rdev->devlist_mtx);
8226 8127
8227 return 0; 8128 return 0;
8228} 8129}
@@ -8365,11 +8266,11 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
8365 info->user_ptr[0] = rdev; 8266 info->user_ptr[0] = rdev;
8366 } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV || 8267 } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV ||
8367 ops->internal_flags & NL80211_FLAG_NEED_WDEV) { 8268 ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
8368 mutex_lock(&cfg80211_mutex); 8269 ASSERT_RTNL();
8270
8369 wdev = __cfg80211_wdev_from_attrs(genl_info_net(info), 8271 wdev = __cfg80211_wdev_from_attrs(genl_info_net(info),
8370 info->attrs); 8272 info->attrs);
8371 if (IS_ERR(wdev)) { 8273 if (IS_ERR(wdev)) {
8372 mutex_unlock(&cfg80211_mutex);
8373 if (rtnl) 8274 if (rtnl)
8374 rtnl_unlock(); 8275 rtnl_unlock();
8375 return PTR_ERR(wdev); 8276 return PTR_ERR(wdev);
@@ -8380,7 +8281,6 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
8380 8281
8381 if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) { 8282 if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) {
8382 if (!dev) { 8283 if (!dev) {
8383 mutex_unlock(&cfg80211_mutex);
8384 if (rtnl) 8284 if (rtnl)
8385 rtnl_unlock(); 8285 rtnl_unlock();
8386 return -EINVAL; 8286 return -EINVAL;
@@ -8394,7 +8294,6 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
8394 if (dev) { 8294 if (dev) {
8395 if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP && 8295 if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
8396 !netif_running(dev)) { 8296 !netif_running(dev)) {
8397 mutex_unlock(&cfg80211_mutex);
8398 if (rtnl) 8297 if (rtnl)
8399 rtnl_unlock(); 8298 rtnl_unlock();
8400 return -ENETDOWN; 8299 return -ENETDOWN;
@@ -8403,17 +8302,12 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
8403 dev_hold(dev); 8302 dev_hold(dev);
8404 } else if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP) { 8303 } else if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP) {
8405 if (!wdev->p2p_started) { 8304 if (!wdev->p2p_started) {
8406 mutex_unlock(&cfg80211_mutex);
8407 if (rtnl) 8305 if (rtnl)
8408 rtnl_unlock(); 8306 rtnl_unlock();
8409 return -ENETDOWN; 8307 return -ENETDOWN;
8410 } 8308 }
8411 } 8309 }
8412 8310
8413 cfg80211_lock_rdev(rdev);
8414
8415 mutex_unlock(&cfg80211_mutex);
8416
8417 info->user_ptr[0] = rdev; 8311 info->user_ptr[0] = rdev;
8418 } 8312 }
8419 8313
@@ -8423,8 +8317,6 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
8423static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb, 8317static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb,
8424 struct genl_info *info) 8318 struct genl_info *info)
8425{ 8319{
8426 if (info->user_ptr[0])
8427 cfg80211_unlock_rdev(info->user_ptr[0]);
8428 if (info->user_ptr[1]) { 8320 if (info->user_ptr[1]) {
8429 if (ops->internal_flags & NL80211_FLAG_NEED_WDEV) { 8321 if (ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
8430 struct wireless_dev *wdev = info->user_ptr[1]; 8322 struct wireless_dev *wdev = info->user_ptr[1];
@@ -8446,7 +8338,8 @@ static struct genl_ops nl80211_ops[] = {
8446 .dumpit = nl80211_dump_wiphy, 8338 .dumpit = nl80211_dump_wiphy,
8447 .policy = nl80211_policy, 8339 .policy = nl80211_policy,
8448 /* can be retrieved by unprivileged users */ 8340 /* can be retrieved by unprivileged users */
8449 .internal_flags = NL80211_FLAG_NEED_WIPHY, 8341 .internal_flags = NL80211_FLAG_NEED_WIPHY |
8342 NL80211_FLAG_NEED_RTNL,
8450 }, 8343 },
8451 { 8344 {
8452 .cmd = NL80211_CMD_SET_WIPHY, 8345 .cmd = NL80211_CMD_SET_WIPHY,
@@ -8461,7 +8354,8 @@ static struct genl_ops nl80211_ops[] = {
8461 .dumpit = nl80211_dump_interface, 8354 .dumpit = nl80211_dump_interface,
8462 .policy = nl80211_policy, 8355 .policy = nl80211_policy,
8463 /* can be retrieved by unprivileged users */ 8356 /* can be retrieved by unprivileged users */
8464 .internal_flags = NL80211_FLAG_NEED_WDEV, 8357 .internal_flags = NL80211_FLAG_NEED_WDEV |
8358 NL80211_FLAG_NEED_RTNL,
8465 }, 8359 },
8466 { 8360 {
8467 .cmd = NL80211_CMD_SET_INTERFACE, 8361 .cmd = NL80211_CMD_SET_INTERFACE,
@@ -8620,6 +8514,7 @@ static struct genl_ops nl80211_ops[] = {
8620 .cmd = NL80211_CMD_GET_REG, 8514 .cmd = NL80211_CMD_GET_REG,
8621 .doit = nl80211_get_reg, 8515 .doit = nl80211_get_reg,
8622 .policy = nl80211_policy, 8516 .policy = nl80211_policy,
8517 .internal_flags = NL80211_FLAG_NEED_RTNL,
8623 /* can be retrieved by unprivileged users */ 8518 /* can be retrieved by unprivileged users */
8624 }, 8519 },
8625 { 8520 {
@@ -8627,6 +8522,7 @@ static struct genl_ops nl80211_ops[] = {
8627 .doit = nl80211_set_reg, 8522 .doit = nl80211_set_reg,
8628 .policy = nl80211_policy, 8523 .policy = nl80211_policy,
8629 .flags = GENL_ADMIN_PERM, 8524 .flags = GENL_ADMIN_PERM,
8525 .internal_flags = NL80211_FLAG_NEED_RTNL,
8630 }, 8526 },
8631 { 8527 {
8632 .cmd = NL80211_CMD_REQ_SET_REG, 8528 .cmd = NL80211_CMD_REQ_SET_REG,
@@ -9082,8 +8978,6 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
9082 struct nlattr *nest; 8978 struct nlattr *nest;
9083 int i; 8979 int i;
9084 8980
9085 lockdep_assert_held(&rdev->sched_scan_mtx);
9086
9087 if (WARN_ON(!req)) 8981 if (WARN_ON(!req))
9088 return 0; 8982 return 0;
9089 8983
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index cc35fbaa4578..e76559618588 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -377,7 +377,7 @@ static void reg_regdb_search(struct work_struct *work)
377 const struct ieee80211_regdomain *curdom, *regdom = NULL; 377 const struct ieee80211_regdomain *curdom, *regdom = NULL;
378 int i; 378 int i;
379 379
380 mutex_lock(&cfg80211_mutex); 380 rtnl_lock();
381 381
382 mutex_lock(&reg_regdb_search_mutex); 382 mutex_lock(&reg_regdb_search_mutex);
383 while (!list_empty(&reg_regdb_search_list)) { 383 while (!list_empty(&reg_regdb_search_list)) {
@@ -402,7 +402,7 @@ static void reg_regdb_search(struct work_struct *work)
402 if (!IS_ERR_OR_NULL(regdom)) 402 if (!IS_ERR_OR_NULL(regdom))
403 set_regdom(regdom); 403 set_regdom(regdom);
404 404
405 mutex_unlock(&cfg80211_mutex); 405 rtnl_unlock();
406} 406}
407 407
408static DECLARE_WORK(reg_regdb_work, reg_regdb_search); 408static DECLARE_WORK(reg_regdb_work, reg_regdb_search);
@@ -1225,7 +1225,7 @@ static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator)
1225 struct cfg80211_registered_device *rdev; 1225 struct cfg80211_registered_device *rdev;
1226 struct wiphy *wiphy; 1226 struct wiphy *wiphy;
1227 1227
1228 assert_cfg80211_lock(); 1228 ASSERT_RTNL();
1229 1229
1230 list_for_each_entry(rdev, &cfg80211_rdev_list, list) { 1230 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
1231 wiphy = &rdev->wiphy; 1231 wiphy = &rdev->wiphy;
@@ -1570,21 +1570,19 @@ static void reg_process_pending_hints(void)
1570{ 1570{
1571 struct regulatory_request *reg_request, *lr; 1571 struct regulatory_request *reg_request, *lr;
1572 1572
1573 mutex_lock(&cfg80211_mutex);
1574 mutex_lock(&reg_mutex);
1575 lr = get_last_request(); 1573 lr = get_last_request();
1576 1574
1577 /* When last_request->processed becomes true this will be rescheduled */ 1575 /* When last_request->processed becomes true this will be rescheduled */
1578 if (lr && !lr->processed) { 1576 if (lr && !lr->processed) {
1579 REG_DBG_PRINT("Pending regulatory request, waiting for it to be processed...\n"); 1577 REG_DBG_PRINT("Pending regulatory request, waiting for it to be processed...\n");
1580 goto out; 1578 return;
1581 } 1579 }
1582 1580
1583 spin_lock(&reg_requests_lock); 1581 spin_lock(&reg_requests_lock);
1584 1582
1585 if (list_empty(&reg_requests_list)) { 1583 if (list_empty(&reg_requests_list)) {
1586 spin_unlock(&reg_requests_lock); 1584 spin_unlock(&reg_requests_lock);
1587 goto out; 1585 return;
1588 } 1586 }
1589 1587
1590 reg_request = list_first_entry(&reg_requests_list, 1588 reg_request = list_first_entry(&reg_requests_list,
@@ -1595,10 +1593,6 @@ static void reg_process_pending_hints(void)
1595 spin_unlock(&reg_requests_lock); 1593 spin_unlock(&reg_requests_lock);
1596 1594
1597 reg_process_hint(reg_request, reg_request->initiator); 1595 reg_process_hint(reg_request, reg_request->initiator);
1598
1599out:
1600 mutex_unlock(&reg_mutex);
1601 mutex_unlock(&cfg80211_mutex);
1602} 1596}
1603 1597
1604/* Processes beacon hints -- this has nothing to do with country IEs */ 1598/* Processes beacon hints -- this has nothing to do with country IEs */
@@ -1607,9 +1601,6 @@ static void reg_process_pending_beacon_hints(void)
1607 struct cfg80211_registered_device *rdev; 1601 struct cfg80211_registered_device *rdev;
1608 struct reg_beacon *pending_beacon, *tmp; 1602 struct reg_beacon *pending_beacon, *tmp;
1609 1603
1610 mutex_lock(&cfg80211_mutex);
1611 mutex_lock(&reg_mutex);
1612
1613 /* This goes through the _pending_ beacon list */ 1604 /* This goes through the _pending_ beacon list */
1614 spin_lock_bh(&reg_pending_beacons_lock); 1605 spin_lock_bh(&reg_pending_beacons_lock);
1615 1606
@@ -1626,14 +1617,16 @@ static void reg_process_pending_beacon_hints(void)
1626 } 1617 }
1627 1618
1628 spin_unlock_bh(&reg_pending_beacons_lock); 1619 spin_unlock_bh(&reg_pending_beacons_lock);
1629 mutex_unlock(&reg_mutex);
1630 mutex_unlock(&cfg80211_mutex);
1631} 1620}
1632 1621
1633static void reg_todo(struct work_struct *work) 1622static void reg_todo(struct work_struct *work)
1634{ 1623{
1624 rtnl_lock();
1625 mutex_lock(&reg_mutex);
1635 reg_process_pending_hints(); 1626 reg_process_pending_hints();
1636 reg_process_pending_beacon_hints(); 1627 reg_process_pending_beacon_hints();
1628 mutex_unlock(&reg_mutex);
1629 rtnl_unlock();
1637} 1630}
1638 1631
1639static void queue_regulatory_request(struct regulatory_request *request) 1632static void queue_regulatory_request(struct regulatory_request *request)
@@ -1717,10 +1710,6 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2)
1717} 1710}
1718EXPORT_SYMBOL(regulatory_hint); 1711EXPORT_SYMBOL(regulatory_hint);
1719 1712
1720/*
1721 * We hold wdev_lock() here so we cannot hold cfg80211_mutex() and
1722 * therefore cannot iterate over the rdev list here.
1723 */
1724void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band, 1713void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band,
1725 const u8 *country_ie, u8 country_ie_len) 1714 const u8 *country_ie, u8 country_ie_len)
1726{ 1715{
@@ -1752,7 +1741,7 @@ void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band,
1752 /* 1741 /*
1753 * We will run this only upon a successful connection on cfg80211. 1742 * We will run this only upon a successful connection on cfg80211.
1754 * We leave conflict resolution to the workqueue, where can hold 1743 * We leave conflict resolution to the workqueue, where can hold
1755 * cfg80211_mutex. 1744 * the RTNL.
1756 */ 1745 */
1757 if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE && 1746 if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE &&
1758 lr->wiphy_idx != WIPHY_IDX_INVALID) 1747 lr->wiphy_idx != WIPHY_IDX_INVALID)
@@ -1858,7 +1847,8 @@ static void restore_regulatory_settings(bool reset_user)
1858 LIST_HEAD(tmp_reg_req_list); 1847 LIST_HEAD(tmp_reg_req_list);
1859 struct cfg80211_registered_device *rdev; 1848 struct cfg80211_registered_device *rdev;
1860 1849
1861 mutex_lock(&cfg80211_mutex); 1850 ASSERT_RTNL();
1851
1862 mutex_lock(&reg_mutex); 1852 mutex_lock(&reg_mutex);
1863 1853
1864 reset_regdomains(true, &world_regdom); 1854 reset_regdomains(true, &world_regdom);
@@ -1915,7 +1905,6 @@ static void restore_regulatory_settings(bool reset_user)
1915 spin_unlock(&reg_requests_lock); 1905 spin_unlock(&reg_requests_lock);
1916 1906
1917 mutex_unlock(&reg_mutex); 1907 mutex_unlock(&reg_mutex);
1918 mutex_unlock(&cfg80211_mutex);
1919 1908
1920 REG_DBG_PRINT("Kicking the queue\n"); 1909 REG_DBG_PRINT("Kicking the queue\n");
1921 1910
@@ -2297,7 +2286,6 @@ void wiphy_regulatory_register(struct wiphy *wiphy)
2297 mutex_unlock(&reg_mutex); 2286 mutex_unlock(&reg_mutex);
2298} 2287}
2299 2288
2300/* Caller must hold cfg80211_mutex */
2301void wiphy_regulatory_deregister(struct wiphy *wiphy) 2289void wiphy_regulatory_deregister(struct wiphy *wiphy)
2302{ 2290{
2303 struct wiphy *request_wiphy = NULL; 2291 struct wiphy *request_wiphy = NULL;
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 2ce44a712f13..dd01b58fa78c 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -169,7 +169,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
169 union iwreq_data wrqu; 169 union iwreq_data wrqu;
170#endif 170#endif
171 171
172 lockdep_assert_held(&rdev->sched_scan_mtx); 172 ASSERT_RTNL();
173 173
174 request = rdev->scan_req; 174 request = rdev->scan_req;
175 175
@@ -230,9 +230,9 @@ void __cfg80211_scan_done(struct work_struct *wk)
230 rdev = container_of(wk, struct cfg80211_registered_device, 230 rdev = container_of(wk, struct cfg80211_registered_device,
231 scan_done_wk); 231 scan_done_wk);
232 232
233 mutex_lock(&rdev->sched_scan_mtx); 233 rtnl_lock();
234 ___cfg80211_scan_done(rdev, false); 234 ___cfg80211_scan_done(rdev, false);
235 mutex_unlock(&rdev->sched_scan_mtx); 235 rtnl_unlock();
236} 236}
237 237
238void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) 238void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
@@ -241,6 +241,7 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
241 WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req); 241 WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req);
242 242
243 request->aborted = aborted; 243 request->aborted = aborted;
244 request->notified = true;
244 queue_work(cfg80211_wq, &wiphy_to_dev(request->wiphy)->scan_done_wk); 245 queue_work(cfg80211_wq, &wiphy_to_dev(request->wiphy)->scan_done_wk);
245} 246}
246EXPORT_SYMBOL(cfg80211_scan_done); 247EXPORT_SYMBOL(cfg80211_scan_done);
@@ -255,7 +256,7 @@ void __cfg80211_sched_scan_results(struct work_struct *wk)
255 256
256 request = rdev->sched_scan_req; 257 request = rdev->sched_scan_req;
257 258
258 mutex_lock(&rdev->sched_scan_mtx); 259 rtnl_lock();
259 260
260 /* we don't have sched_scan_req anymore if the scan is stopping */ 261 /* we don't have sched_scan_req anymore if the scan is stopping */
261 if (request) { 262 if (request) {
@@ -270,7 +271,7 @@ void __cfg80211_sched_scan_results(struct work_struct *wk)
270 nl80211_send_sched_scan_results(rdev, request->dev); 271 nl80211_send_sched_scan_results(rdev, request->dev);
271 } 272 }
272 273
273 mutex_unlock(&rdev->sched_scan_mtx); 274 rtnl_unlock();
274} 275}
275 276
276void cfg80211_sched_scan_results(struct wiphy *wiphy) 277void cfg80211_sched_scan_results(struct wiphy *wiphy)
@@ -289,9 +290,9 @@ void cfg80211_sched_scan_stopped(struct wiphy *wiphy)
289 290
290 trace_cfg80211_sched_scan_stopped(wiphy); 291 trace_cfg80211_sched_scan_stopped(wiphy);
291 292
292 mutex_lock(&rdev->sched_scan_mtx); 293 rtnl_lock();
293 __cfg80211_stop_sched_scan(rdev, true); 294 __cfg80211_stop_sched_scan(rdev, true);
294 mutex_unlock(&rdev->sched_scan_mtx); 295 rtnl_unlock();
295} 296}
296EXPORT_SYMBOL(cfg80211_sched_scan_stopped); 297EXPORT_SYMBOL(cfg80211_sched_scan_stopped);
297 298
@@ -300,7 +301,7 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
300{ 301{
301 struct net_device *dev; 302 struct net_device *dev;
302 303
303 lockdep_assert_held(&rdev->sched_scan_mtx); 304 ASSERT_RTNL();
304 305
305 if (!rdev->sched_scan_req) 306 if (!rdev->sched_scan_req)
306 return -ENOENT; 307 return -ENOENT;
@@ -1043,21 +1044,19 @@ EXPORT_SYMBOL(cfg80211_unlink_bss);
1043static struct cfg80211_registered_device * 1044static struct cfg80211_registered_device *
1044cfg80211_get_dev_from_ifindex(struct net *net, int ifindex) 1045cfg80211_get_dev_from_ifindex(struct net *net, int ifindex)
1045{ 1046{
1046 struct cfg80211_registered_device *rdev = ERR_PTR(-ENODEV); 1047 struct cfg80211_registered_device *rdev;
1047 struct net_device *dev; 1048 struct net_device *dev;
1048 1049
1049 mutex_lock(&cfg80211_mutex); 1050 ASSERT_RTNL();
1051
1050 dev = dev_get_by_index(net, ifindex); 1052 dev = dev_get_by_index(net, ifindex);
1051 if (!dev) 1053 if (!dev)
1052 goto out; 1054 return ERR_PTR(-ENODEV);
1053 if (dev->ieee80211_ptr) { 1055 if (dev->ieee80211_ptr)
1054 rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy); 1056 rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
1055 mutex_lock(&rdev->mtx); 1057 else
1056 } else
1057 rdev = ERR_PTR(-ENODEV); 1058 rdev = ERR_PTR(-ENODEV);
1058 dev_put(dev); 1059 dev_put(dev);
1059 out:
1060 mutex_unlock(&cfg80211_mutex);
1061 return rdev; 1060 return rdev;
1062} 1061}
1063 1062
@@ -1083,7 +1082,6 @@ int cfg80211_wext_siwscan(struct net_device *dev,
1083 if (IS_ERR(rdev)) 1082 if (IS_ERR(rdev))
1084 return PTR_ERR(rdev); 1083 return PTR_ERR(rdev);
1085 1084
1086 mutex_lock(&rdev->sched_scan_mtx);
1087 if (rdev->scan_req) { 1085 if (rdev->scan_req) {
1088 err = -EBUSY; 1086 err = -EBUSY;
1089 goto out; 1087 goto out;
@@ -1190,9 +1188,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
1190 dev_hold(dev); 1188 dev_hold(dev);
1191 } 1189 }
1192 out: 1190 out:
1193 mutex_unlock(&rdev->sched_scan_mtx);
1194 kfree(creq); 1191 kfree(creq);
1195 cfg80211_unlock_rdev(rdev);
1196 return err; 1192 return err;
1197} 1193}
1198EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan); 1194EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan);
@@ -1491,10 +1487,8 @@ int cfg80211_wext_giwscan(struct net_device *dev,
1491 if (IS_ERR(rdev)) 1487 if (IS_ERR(rdev))
1492 return PTR_ERR(rdev); 1488 return PTR_ERR(rdev);
1493 1489
1494 if (rdev->scan_req) { 1490 if (rdev->scan_req)
1495 res = -EAGAIN; 1491 return -EAGAIN;
1496 goto out;
1497 }
1498 1492
1499 res = ieee80211_scan_results(rdev, info, extra, data->length); 1493 res = ieee80211_scan_results(rdev, info, extra, data->length);
1500 data->length = 0; 1494 data->length = 0;
@@ -1503,8 +1497,6 @@ int cfg80211_wext_giwscan(struct net_device *dev,
1503 res = 0; 1497 res = 0;
1504 } 1498 }
1505 1499
1506 out:
1507 cfg80211_unlock_rdev(rdev);
1508 return res; 1500 return res;
1509} 1501}
1510EXPORT_SYMBOL_GPL(cfg80211_wext_giwscan); 1502EXPORT_SYMBOL_GPL(cfg80211_wext_giwscan);
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 3ed35c345cae..4dbf31407a56 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -43,35 +43,29 @@ static bool cfg80211_is_all_idle(void)
43 struct wireless_dev *wdev; 43 struct wireless_dev *wdev;
44 bool is_all_idle = true; 44 bool is_all_idle = true;
45 45
46 mutex_lock(&cfg80211_mutex);
47
48 /* 46 /*
49 * All devices must be idle as otherwise if you are actively 47 * All devices must be idle as otherwise if you are actively
50 * scanning some new beacon hints could be learned and would 48 * scanning some new beacon hints could be learned and would
51 * count as new regulatory hints. 49 * count as new regulatory hints.
52 */ 50 */
53 list_for_each_entry(rdev, &cfg80211_rdev_list, list) { 51 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
54 cfg80211_lock_rdev(rdev);
55 list_for_each_entry(wdev, &rdev->wdev_list, list) { 52 list_for_each_entry(wdev, &rdev->wdev_list, list) {
56 wdev_lock(wdev); 53 wdev_lock(wdev);
57 if (wdev->sme_state != CFG80211_SME_IDLE) 54 if (wdev->sme_state != CFG80211_SME_IDLE)
58 is_all_idle = false; 55 is_all_idle = false;
59 wdev_unlock(wdev); 56 wdev_unlock(wdev);
60 } 57 }
61 cfg80211_unlock_rdev(rdev);
62 } 58 }
63 59
64 mutex_unlock(&cfg80211_mutex);
65
66 return is_all_idle; 60 return is_all_idle;
67} 61}
68 62
69static void disconnect_work(struct work_struct *work) 63static void disconnect_work(struct work_struct *work)
70{ 64{
71 if (!cfg80211_is_all_idle()) 65 rtnl_lock();
72 return; 66 if (cfg80211_is_all_idle())
73 67 regulatory_hint_disconnect();
74 regulatory_hint_disconnect(); 68 rtnl_unlock();
75} 69}
76 70
77static DECLARE_WORK(cfg80211_disconnect_work, disconnect_work); 71static DECLARE_WORK(cfg80211_disconnect_work, disconnect_work);
@@ -85,7 +79,6 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
85 ASSERT_RTNL(); 79 ASSERT_RTNL();
86 ASSERT_RDEV_LOCK(rdev); 80 ASSERT_RDEV_LOCK(rdev);
87 ASSERT_WDEV_LOCK(wdev); 81 ASSERT_WDEV_LOCK(wdev);
88 lockdep_assert_held(&rdev->sched_scan_mtx);
89 82
90 if (rdev->scan_req) 83 if (rdev->scan_req)
91 return -EBUSY; 84 return -EBUSY;
@@ -226,9 +219,6 @@ void cfg80211_conn_work(struct work_struct *work)
226 u8 bssid_buf[ETH_ALEN], *bssid = NULL; 219 u8 bssid_buf[ETH_ALEN], *bssid = NULL;
227 220
228 rtnl_lock(); 221 rtnl_lock();
229 cfg80211_lock_rdev(rdev);
230 mutex_lock(&rdev->devlist_mtx);
231 mutex_lock(&rdev->sched_scan_mtx);
232 222
233 list_for_each_entry(wdev, &rdev->wdev_list, list) { 223 list_for_each_entry(wdev, &rdev->wdev_list, list) {
234 if (!wdev->netdev) 224 if (!wdev->netdev)
@@ -256,9 +246,6 @@ void cfg80211_conn_work(struct work_struct *work)
256 wdev_unlock(wdev); 246 wdev_unlock(wdev);
257 } 247 }
258 248
259 mutex_unlock(&rdev->sched_scan_mtx);
260 mutex_unlock(&rdev->devlist_mtx);
261 cfg80211_unlock_rdev(rdev);
262 rtnl_unlock(); 249 rtnl_unlock();
263} 250}
264 251
@@ -931,14 +918,9 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
931{ 918{
932 int err; 919 int err;
933 920
934 mutex_lock(&rdev->devlist_mtx);
935 /* might request scan - scan_mtx -> wdev_mtx dependency */
936 mutex_lock(&rdev->sched_scan_mtx);
937 wdev_lock(dev->ieee80211_ptr); 921 wdev_lock(dev->ieee80211_ptr);
938 err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL); 922 err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL);
939 wdev_unlock(dev->ieee80211_ptr); 923 wdev_unlock(dev->ieee80211_ptr);
940 mutex_unlock(&rdev->sched_scan_mtx);
941 mutex_unlock(&rdev->devlist_mtx);
942 924
943 return err; 925 return err;
944} 926}
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 0962f107f57f..501724257af5 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -808,12 +808,8 @@ void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev)
808 ASSERT_RTNL(); 808 ASSERT_RTNL();
809 ASSERT_RDEV_LOCK(rdev); 809 ASSERT_RDEV_LOCK(rdev);
810 810
811 mutex_lock(&rdev->devlist_mtx);
812
813 list_for_each_entry(wdev, &rdev->wdev_list, list) 811 list_for_each_entry(wdev, &rdev->wdev_list, list)
814 cfg80211_process_wdev_events(wdev); 812 cfg80211_process_wdev_events(wdev);
815
816 mutex_unlock(&rdev->devlist_mtx);
817} 813}
818 814
819int cfg80211_change_iface(struct cfg80211_registered_device *rdev, 815int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
@@ -845,10 +841,8 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
845 return -EBUSY; 841 return -EBUSY;
846 842
847 if (ntype != otype && netif_running(dev)) { 843 if (ntype != otype && netif_running(dev)) {
848 mutex_lock(&rdev->devlist_mtx);
849 err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr, 844 err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr,
850 ntype); 845 ntype);
851 mutex_unlock(&rdev->devlist_mtx);
852 if (err) 846 if (err)
853 return err; 847 return err;
854 848
@@ -1210,8 +1204,6 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
1210 if (!beacon_int) 1204 if (!beacon_int)
1211 return -EINVAL; 1205 return -EINVAL;
1212 1206
1213 mutex_lock(&rdev->devlist_mtx);
1214
1215 list_for_each_entry(wdev, &rdev->wdev_list, list) { 1207 list_for_each_entry(wdev, &rdev->wdev_list, list) {
1216 if (!wdev->beacon_interval) 1208 if (!wdev->beacon_interval)
1217 continue; 1209 continue;
@@ -1221,8 +1213,6 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
1221 } 1213 }
1222 } 1214 }
1223 1215
1224 mutex_unlock(&rdev->devlist_mtx);
1225
1226 return res; 1216 return res;
1227} 1217}
1228 1218
@@ -1246,7 +1236,6 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
1246 int i, j; 1236 int i, j;
1247 1237
1248 ASSERT_RTNL(); 1238 ASSERT_RTNL();
1249 lockdep_assert_held(&rdev->devlist_mtx);
1250 1239
1251 if (WARN_ON(hweight32(radar_detect) > 1)) 1240 if (WARN_ON(hweight32(radar_detect) > 1))
1252 return -EINVAL; 1241 return -EINVAL;
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index d997d0f0c54a..e7c6e862580d 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -72,7 +72,6 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
72 struct cfg80211_registered_device *rdev; 72 struct cfg80211_registered_device *rdev;
73 struct vif_params vifparams; 73 struct vif_params vifparams;
74 enum nl80211_iftype type; 74 enum nl80211_iftype type;
75 int ret;
76 75
77 rdev = wiphy_to_dev(wdev->wiphy); 76 rdev = wiphy_to_dev(wdev->wiphy);
78 77
@@ -98,11 +97,7 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
98 97
99 memset(&vifparams, 0, sizeof(vifparams)); 98 memset(&vifparams, 0, sizeof(vifparams));
100 99
101 cfg80211_lock_rdev(rdev); 100 return cfg80211_change_iface(rdev, dev, type, NULL, &vifparams);
102 ret = cfg80211_change_iface(rdev, dev, type, NULL, &vifparams);
103 cfg80211_unlock_rdev(rdev);
104
105 return ret;
106} 101}
107EXPORT_SYMBOL_GPL(cfg80211_wext_siwmode); 102EXPORT_SYMBOL_GPL(cfg80211_wext_siwmode);
108 103
@@ -579,13 +574,10 @@ static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
579{ 574{
580 int err; 575 int err;
581 576
582 /* devlist mutex needed for possible IBSS re-join */
583 mutex_lock(&rdev->devlist_mtx);
584 wdev_lock(dev->ieee80211_ptr); 577 wdev_lock(dev->ieee80211_ptr);
585 err = __cfg80211_set_encryption(rdev, dev, pairwise, addr, 578 err = __cfg80211_set_encryption(rdev, dev, pairwise, addr,
586 remove, tx_key, idx, params); 579 remove, tx_key, idx, params);
587 wdev_unlock(dev->ieee80211_ptr); 580 wdev_unlock(dev->ieee80211_ptr);
588 mutex_unlock(&rdev->devlist_mtx);
589 581
590 return err; 582 return err;
591} 583}
@@ -787,7 +779,7 @@ static int cfg80211_wext_siwfreq(struct net_device *dev,
787 struct cfg80211_chan_def chandef = { 779 struct cfg80211_chan_def chandef = {
788 .width = NL80211_CHAN_WIDTH_20_NOHT, 780 .width = NL80211_CHAN_WIDTH_20_NOHT,
789 }; 781 };
790 int freq, err; 782 int freq;
791 783
792 switch (wdev->iftype) { 784 switch (wdev->iftype) {
793 case NL80211_IFTYPE_STATION: 785 case NL80211_IFTYPE_STATION:
@@ -804,10 +796,7 @@ static int cfg80211_wext_siwfreq(struct net_device *dev,
804 chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq); 796 chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq);
805 if (!chandef.chan) 797 if (!chandef.chan)
806 return -EINVAL; 798 return -EINVAL;
807 mutex_lock(&rdev->devlist_mtx); 799 return cfg80211_set_monitor_channel(rdev, &chandef);
808 err = cfg80211_set_monitor_channel(rdev, &chandef);
809 mutex_unlock(&rdev->devlist_mtx);
810 return err;
811 case NL80211_IFTYPE_MESH_POINT: 800 case NL80211_IFTYPE_MESH_POINT:
812 freq = cfg80211_wext_freq(wdev->wiphy, wextfreq); 801 freq = cfg80211_wext_freq(wdev->wiphy, wextfreq);
813 if (freq < 0) 802 if (freq < 0)
@@ -818,10 +807,7 @@ static int cfg80211_wext_siwfreq(struct net_device *dev,
818 chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq); 807 chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq);
819 if (!chandef.chan) 808 if (!chandef.chan)
820 return -EINVAL; 809 return -EINVAL;
821 mutex_lock(&rdev->devlist_mtx); 810 return cfg80211_set_mesh_channel(rdev, wdev, &chandef);
822 err = cfg80211_set_mesh_channel(rdev, wdev, &chandef);
823 mutex_unlock(&rdev->devlist_mtx);
824 return err;
825 default: 811 default:
826 return -EOPNOTSUPP; 812 return -EOPNOTSUPP;
827 } 813 }
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c
index e79cb5c0655a..aeefd6817189 100644
--- a/net/wireless/wext-sme.c
+++ b/net/wireless/wext-sme.c
@@ -87,9 +87,6 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
87 return -EINVAL; 87 return -EINVAL;
88 } 88 }
89 89
90 cfg80211_lock_rdev(rdev);
91 mutex_lock(&rdev->devlist_mtx);
92 mutex_lock(&rdev->sched_scan_mtx);
93 wdev_lock(wdev); 90 wdev_lock(wdev);
94 91
95 if (wdev->sme_state != CFG80211_SME_IDLE) { 92 if (wdev->sme_state != CFG80211_SME_IDLE) {
@@ -136,9 +133,6 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
136 err = cfg80211_mgd_wext_connect(rdev, wdev); 133 err = cfg80211_mgd_wext_connect(rdev, wdev);
137 out: 134 out:
138 wdev_unlock(wdev); 135 wdev_unlock(wdev);
139 mutex_unlock(&rdev->sched_scan_mtx);
140 mutex_unlock(&rdev->devlist_mtx);
141 cfg80211_unlock_rdev(rdev);
142 return err; 136 return err;
143} 137}
144 138
@@ -190,9 +184,6 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
190 if (len > 0 && ssid[len - 1] == '\0') 184 if (len > 0 && ssid[len - 1] == '\0')
191 len--; 185 len--;
192 186
193 cfg80211_lock_rdev(rdev);
194 mutex_lock(&rdev->devlist_mtx);
195 mutex_lock(&rdev->sched_scan_mtx);
196 wdev_lock(wdev); 187 wdev_lock(wdev);
197 188
198 err = 0; 189 err = 0;
@@ -226,9 +217,6 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
226 err = cfg80211_mgd_wext_connect(rdev, wdev); 217 err = cfg80211_mgd_wext_connect(rdev, wdev);
227 out: 218 out:
228 wdev_unlock(wdev); 219 wdev_unlock(wdev);
229 mutex_unlock(&rdev->sched_scan_mtx);
230 mutex_unlock(&rdev->devlist_mtx);
231 cfg80211_unlock_rdev(rdev);
232 return err; 220 return err;
233} 221}
234 222
@@ -287,9 +275,6 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
287 if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid)) 275 if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid))
288 bssid = NULL; 276 bssid = NULL;
289 277
290 cfg80211_lock_rdev(rdev);
291 mutex_lock(&rdev->devlist_mtx);
292 mutex_lock(&rdev->sched_scan_mtx);
293 wdev_lock(wdev); 278 wdev_lock(wdev);
294 279
295 if (wdev->sme_state != CFG80211_SME_IDLE) { 280 if (wdev->sme_state != CFG80211_SME_IDLE) {
@@ -318,9 +303,6 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
318 err = cfg80211_mgd_wext_connect(rdev, wdev); 303 err = cfg80211_mgd_wext_connect(rdev, wdev);
319 out: 304 out:
320 wdev_unlock(wdev); 305 wdev_unlock(wdev);
321 mutex_unlock(&rdev->sched_scan_mtx);
322 mutex_unlock(&rdev->devlist_mtx);
323 cfg80211_unlock_rdev(rdev);
324 return err; 306 return err;
325} 307}
326 308