diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/wireless/core.c | 166 | ||||
-rw-r--r-- | net/wireless/core.h | 32 | ||||
-rw-r--r-- | net/wireless/debugfs.c | 4 | ||||
-rw-r--r-- | net/wireless/ibss.c | 10 | ||||
-rw-r--r-- | net/wireless/mesh.c | 2 | ||||
-rw-r--r-- | net/wireless/mlme.c | 12 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 178 | ||||
-rw-r--r-- | net/wireless/reg.c | 36 | ||||
-rw-r--r-- | net/wireless/scan.c | 42 | ||||
-rw-r--r-- | net/wireless/sme.c | 26 | ||||
-rw-r--r-- | net/wireless/util.c | 11 | ||||
-rw-r--r-- | net/wireless/wext-compat.c | 22 | ||||
-rw-r--r-- | net/wireless/wext-sme.c | 18 |
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"); | |||
36 | MODULE_DESCRIPTION("wireless configuration support"); | 36 | MODULE_DESCRIPTION("wireless configuration support"); |
37 | MODULE_ALIAS_GENL_FAMILY(NL80211_GENL_NAME); | 37 | MODULE_ALIAS_GENL_FAMILY(NL80211_GENL_NAME); |
38 | 38 | ||
39 | /* RCU-protected (and cfg80211_mutex for writers) */ | 39 | /* RCU-protected (and RTNL for writers) */ |
40 | LIST_HEAD(cfg80211_rdev_list); | 40 | LIST_HEAD(cfg80211_rdev_list); |
41 | int cfg80211_rdev_list_generation; | 41 | int cfg80211_rdev_list_generation; |
42 | 42 | ||
43 | DEFINE_MUTEX(cfg80211_mutex); | ||
44 | |||
45 | /* for debugfs */ | 43 | /* for debugfs */ |
46 | static struct dentry *ieee80211_debugfs_dir; | 44 | static struct dentry *ieee80211_debugfs_dir; |
47 | 45 | ||
@@ -53,12 +51,11 @@ module_param(cfg80211_disable_40mhz_24ghz, bool, 0644); | |||
53 | MODULE_PARM_DESC(cfg80211_disable_40mhz_24ghz, | 51 | MODULE_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! */ | ||
57 | struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx) | 54 | struct 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! */ | ||
81 | struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx) | 77 | struct 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 */ | ||
94 | int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, | 89 | int 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) | |||
195 | void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, | 190 | void 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(®->list); | 681 | list_del(®->list); |
731 | kfree(reg); | 682 | kfree(reg); |
@@ -750,36 +701,6 @@ void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked) | |||
750 | } | 701 | } |
751 | EXPORT_SYMBOL(wiphy_rfkill_set_hw_state); | 702 | EXPORT_SYMBOL(wiphy_rfkill_set_hw_state); |
752 | 703 | ||
753 | static 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 | |||
783 | void cfg80211_unregister_wdev(struct wireless_dev *wdev) | 704 | void 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 | } |
808 | EXPORT_SYMBOL(cfg80211_unregister_wdev); | 725 | EXPORT_SYMBOL(cfg80211_unregister_wdev); |
809 | 726 | ||
@@ -822,7 +739,7 @@ void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, | |||
822 | } | 739 | } |
823 | 740 | ||
824 | void cfg80211_leave(struct cfg80211_registered_device *rdev, | 741 | void 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 @@ | |||
23 | struct cfg80211_registered_device { | 22 | struct 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 | ||
122 | extern struct workqueue_struct *cfg80211_wq; | 112 | extern struct workqueue_struct *cfg80211_wq; |
123 | extern struct mutex cfg80211_mutex; | ||
124 | extern struct list_head cfg80211_rdev_list; | 113 | extern struct list_head cfg80211_rdev_list; |
125 | extern int cfg80211_rdev_list_generation; | 114 | extern int cfg80211_rdev_list_generation; |
126 | 115 | ||
127 | static inline void assert_cfg80211_lock(void) | ||
128 | { | ||
129 | lockdep_assert_held(&cfg80211_mutex); | ||
130 | } | ||
131 | |||
132 | struct cfg80211_internal_bss { | 116 | struct 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) | |||
161 | struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx); | 145 | struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx); |
162 | int get_wiphy_idx(struct wiphy *wiphy); | 146 | int get_wiphy_idx(struct wiphy *wiphy); |
163 | 147 | ||
164 | /* requires cfg80211_rdev_mutex to be held! */ | ||
165 | struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx); | 148 | struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx); |
166 | 149 | ||
167 | int cfg80211_switch_netns(struct cfg80211_registered_device *rdev, | 150 | int cfg80211_switch_netns(struct cfg80211_registered_device *rdev, |
168 | struct net *net); | 151 | struct net *net); |
169 | 152 | ||
170 | static inline void cfg80211_lock_rdev(struct cfg80211_registered_device *rdev) | ||
171 | { | ||
172 | mutex_lock(&rdev->mtx); | ||
173 | } | ||
174 | |||
175 | static 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 | |||
181 | static inline void wdev_lock(struct wireless_dev *wdev) | 153 | static 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 | ||
198 | static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev) | 170 | static 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) | |||
202 | static struct cfg80211_registered_device * | 185 | static struct cfg80211_registered_device * |
203 | cfg80211_get_dev_from_info(struct net *netns, struct genl_info *info) | 186 | cfg80211_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 | ||
513 | static void nl80211_finish_wdev_dump(struct cfg80211_registered_device *rdev) | 476 | static 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 | ||
4990 | nla_put_failure_rcu: | 4922 | nla_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); |
4994 | put_failure: | 4926 | put_failure: |
4995 | nlmsg_free(msg); | 4927 | nlmsg_free(msg); |
4996 | err = -EMSGSIZE; | 4928 | return -EMSGSIZE; |
4997 | out: | ||
4998 | mutex_unlock(&cfg80211_mutex); | ||
4999 | return err; | ||
5000 | } | 4929 | } |
5001 | 4930 | ||
5002 | static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) | 4931 | static 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, | |||
5544 | out_free: | 5466 | out_free: |
5545 | kfree(request); | 5467 | kfree(request); |
5546 | out: | 5468 | out: |
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 | ||
5568 | static int nl80211_start_radar_detection(struct sk_buff *skb, | 5484 | static 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 | } |
5610 | err_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, | |||
8423 | static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb, | 8317 | static 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(®_regdb_search_mutex); | 382 | mutex_lock(®_regdb_search_mutex); |
383 | while (!list_empty(®_regdb_search_list)) { | 383 | while (!list_empty(®_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 | ||
408 | static DECLARE_WORK(reg_regdb_work, reg_regdb_search); | 408 | static 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(®_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(®_requests_lock); | 1581 | spin_lock(®_requests_lock); |
1584 | 1582 | ||
1585 | if (list_empty(®_requests_list)) { | 1583 | if (list_empty(®_requests_list)) { |
1586 | spin_unlock(®_requests_lock); | 1584 | spin_unlock(®_requests_lock); |
1587 | goto out; | 1585 | return; |
1588 | } | 1586 | } |
1589 | 1587 | ||
1590 | reg_request = list_first_entry(®_requests_list, | 1588 | reg_request = list_first_entry(®_requests_list, |
@@ -1595,10 +1593,6 @@ static void reg_process_pending_hints(void) | |||
1595 | spin_unlock(®_requests_lock); | 1593 | spin_unlock(®_requests_lock); |
1596 | 1594 | ||
1597 | reg_process_hint(reg_request, reg_request->initiator); | 1595 | reg_process_hint(reg_request, reg_request->initiator); |
1598 | |||
1599 | out: | ||
1600 | mutex_unlock(®_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(®_mutex); | ||
1612 | |||
1613 | /* This goes through the _pending_ beacon list */ | 1604 | /* This goes through the _pending_ beacon list */ |
1614 | spin_lock_bh(®_pending_beacons_lock); | 1605 | spin_lock_bh(®_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(®_pending_beacons_lock); | 1619 | spin_unlock_bh(®_pending_beacons_lock); |
1629 | mutex_unlock(®_mutex); | ||
1630 | mutex_unlock(&cfg80211_mutex); | ||
1631 | } | 1620 | } |
1632 | 1621 | ||
1633 | static void reg_todo(struct work_struct *work) | 1622 | static void reg_todo(struct work_struct *work) |
1634 | { | 1623 | { |
1624 | rtnl_lock(); | ||
1625 | mutex_lock(®_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(®_mutex); | ||
1629 | rtnl_unlock(); | ||
1637 | } | 1630 | } |
1638 | 1631 | ||
1639 | static void queue_regulatory_request(struct regulatory_request *request) | 1632 | static void queue_regulatory_request(struct regulatory_request *request) |
@@ -1717,10 +1710,6 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2) | |||
1717 | } | 1710 | } |
1718 | EXPORT_SYMBOL(regulatory_hint); | 1711 | EXPORT_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 | */ | ||
1724 | void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band, | 1713 | void 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(®_mutex); | 1852 | mutex_lock(®_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(®_requests_lock); | 1905 | spin_unlock(®_requests_lock); |
1916 | 1906 | ||
1917 | mutex_unlock(®_mutex); | 1907 | mutex_unlock(®_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(®_mutex); | 2286 | mutex_unlock(®_mutex); |
2298 | } | 2287 | } |
2299 | 2288 | ||
2300 | /* Caller must hold cfg80211_mutex */ | ||
2301 | void wiphy_regulatory_deregister(struct wiphy *wiphy) | 2289 | void 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 | ||
238 | void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) | 238 | void 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 | } |
246 | EXPORT_SYMBOL(cfg80211_scan_done); | 247 | EXPORT_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 | ||
276 | void cfg80211_sched_scan_results(struct wiphy *wiphy) | 277 | void 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 | } |
296 | EXPORT_SYMBOL(cfg80211_sched_scan_stopped); | 297 | EXPORT_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); | |||
1043 | static struct cfg80211_registered_device * | 1044 | static struct cfg80211_registered_device * |
1044 | cfg80211_get_dev_from_ifindex(struct net *net, int ifindex) | 1045 | cfg80211_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 | } |
1198 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan); | 1194 | EXPORT_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 | } |
1510 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwscan); | 1502 | EXPORT_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 | ||
69 | static void disconnect_work(struct work_struct *work) | 63 | static 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 | ||
77 | static DECLARE_WORK(cfg80211_disconnect_work, disconnect_work); | 71 | static 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 | ||
819 | int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | 815 | int 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 | } |
107 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwmode); | 102 | EXPORT_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 | ||