diff options
author | John W. Linville <linville@tuxdriver.com> | 2013-06-11 14:48:32 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-06-11 14:48:32 -0400 |
commit | 3899ba90a4ab2f3cab8e0f91a76c14ff131c8293 (patch) | |
tree | ae82b469f8a7ceb42547d11dd1fe5c73abc8635b /net/wireless | |
parent | 45203a3b380cee28f570475c0d28c169f908c209 (diff) | |
parent | 8b3e7be437a6b62118d0485ad971e724afe23fdf (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Conflicts:
drivers/net/wireless/ath/ath9k/debug.c
net/mac80211/iface.c
Diffstat (limited to 'net/wireless')
-rw-r--r-- | net/wireless/core.c | 224 | ||||
-rw-r--r-- | net/wireless/core.h | 93 | ||||
-rw-r--r-- | net/wireless/debugfs.c | 4 | ||||
-rw-r--r-- | net/wireless/ibss.c | 10 | ||||
-rw-r--r-- | net/wireless/mesh.c | 3 | ||||
-rw-r--r-- | net/wireless/mlme.c | 216 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 350 | ||||
-rw-r--r-- | net/wireless/reg.c | 136 | ||||
-rw-r--r-- | net/wireless/scan.c | 47 | ||||
-rw-r--r-- | net/wireless/sme.c | 107 | ||||
-rw-r--r-- | net/wireless/sysfs.c | 8 | ||||
-rw-r--r-- | net/wireless/trace.h | 4 | ||||
-rw-r--r-- | net/wireless/util.c | 39 | ||||
-rw-r--r-- | net/wireless/wext-compat.c | 22 | ||||
-rw-r--r-- | net/wireless/wext-sme.c | 41 |
15 files changed, 443 insertions, 861 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c index 01e41191f1bf..e4df77490229 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -34,13 +34,12 @@ | |||
34 | MODULE_AUTHOR("Johannes Berg"); | 34 | MODULE_AUTHOR("Johannes Berg"); |
35 | MODULE_LICENSE("GPL"); | 35 | MODULE_LICENSE("GPL"); |
36 | MODULE_DESCRIPTION("wireless configuration support"); | 36 | MODULE_DESCRIPTION("wireless configuration support"); |
37 | MODULE_ALIAS_GENL_FAMILY(NL80211_GENL_NAME); | ||
37 | 38 | ||
38 | /* RCU-protected (and cfg80211_mutex for writers) */ | 39 | /* RCU-protected (and RTNL for writers) */ |
39 | LIST_HEAD(cfg80211_rdev_list); | 40 | LIST_HEAD(cfg80211_rdev_list); |
40 | int cfg80211_rdev_list_generation; | 41 | int cfg80211_rdev_list_generation; |
41 | 42 | ||
42 | DEFINE_MUTEX(cfg80211_mutex); | ||
43 | |||
44 | /* for debugfs */ | 43 | /* for debugfs */ |
45 | static struct dentry *ieee80211_debugfs_dir; | 44 | static struct dentry *ieee80211_debugfs_dir; |
46 | 45 | ||
@@ -52,12 +51,11 @@ module_param(cfg80211_disable_40mhz_24ghz, bool, 0644); | |||
52 | MODULE_PARM_DESC(cfg80211_disable_40mhz_24ghz, | 51 | MODULE_PARM_DESC(cfg80211_disable_40mhz_24ghz, |
53 | "Disable 40MHz support in the 2.4GHz band"); | 52 | "Disable 40MHz support in the 2.4GHz band"); |
54 | 53 | ||
55 | /* requires cfg80211_mutex to be held! */ | ||
56 | 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) |
57 | { | 55 | { |
58 | struct cfg80211_registered_device *result = NULL, *rdev; | 56 | struct cfg80211_registered_device *result = NULL, *rdev; |
59 | 57 | ||
60 | assert_cfg80211_lock(); | 58 | ASSERT_RTNL(); |
61 | 59 | ||
62 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) { | 60 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) { |
63 | if (rdev->wiphy_idx == wiphy_idx) { | 61 | if (rdev->wiphy_idx == wiphy_idx) { |
@@ -76,12 +74,11 @@ int get_wiphy_idx(struct wiphy *wiphy) | |||
76 | return rdev->wiphy_idx; | 74 | return rdev->wiphy_idx; |
77 | } | 75 | } |
78 | 76 | ||
79 | /* requires cfg80211_rdev_mutex to be held! */ | ||
80 | struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx) | 77 | struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx) |
81 | { | 78 | { |
82 | struct cfg80211_registered_device *rdev; | 79 | struct cfg80211_registered_device *rdev; |
83 | 80 | ||
84 | assert_cfg80211_lock(); | 81 | ASSERT_RTNL(); |
85 | 82 | ||
86 | rdev = cfg80211_rdev_by_wiphy_idx(wiphy_idx); | 83 | rdev = cfg80211_rdev_by_wiphy_idx(wiphy_idx); |
87 | if (!rdev) | 84 | if (!rdev) |
@@ -89,35 +86,13 @@ struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx) | |||
89 | return &rdev->wiphy; | 86 | return &rdev->wiphy; |
90 | } | 87 | } |
91 | 88 | ||
92 | struct cfg80211_registered_device * | ||
93 | cfg80211_get_dev_from_ifindex(struct net *net, int ifindex) | ||
94 | { | ||
95 | struct cfg80211_registered_device *rdev = ERR_PTR(-ENODEV); | ||
96 | struct net_device *dev; | ||
97 | |||
98 | mutex_lock(&cfg80211_mutex); | ||
99 | dev = dev_get_by_index(net, ifindex); | ||
100 | if (!dev) | ||
101 | goto out; | ||
102 | if (dev->ieee80211_ptr) { | ||
103 | rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy); | ||
104 | mutex_lock(&rdev->mtx); | ||
105 | } else | ||
106 | rdev = ERR_PTR(-ENODEV); | ||
107 | dev_put(dev); | ||
108 | out: | ||
109 | mutex_unlock(&cfg80211_mutex); | ||
110 | return rdev; | ||
111 | } | ||
112 | |||
113 | /* requires cfg80211_mutex to be held */ | ||
114 | int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, | 89 | int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, |
115 | char *newname) | 90 | char *newname) |
116 | { | 91 | { |
117 | struct cfg80211_registered_device *rdev2; | 92 | struct cfg80211_registered_device *rdev2; |
118 | int wiphy_idx, taken = -1, result, digits; | 93 | int wiphy_idx, taken = -1, result, digits; |
119 | 94 | ||
120 | assert_cfg80211_lock(); | 95 | ASSERT_RTNL(); |
121 | 96 | ||
122 | /* 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 */ |
123 | sscanf(newname, PHY_NAME "%d%n", &wiphy_idx, &taken); | 98 | sscanf(newname, PHY_NAME "%d%n", &wiphy_idx, &taken); |
@@ -215,8 +190,7 @@ static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data) | |||
215 | void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, | 190 | void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, |
216 | struct wireless_dev *wdev) | 191 | struct wireless_dev *wdev) |
217 | { | 192 | { |
218 | lockdep_assert_held(&rdev->devlist_mtx); | 193 | ASSERT_RTNL(); |
219 | lockdep_assert_held(&rdev->sched_scan_mtx); | ||
220 | 194 | ||
221 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)) | 195 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)) |
222 | return; | 196 | return; |
@@ -230,18 +204,15 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, | |||
230 | rdev->opencount--; | 204 | rdev->opencount--; |
231 | 205 | ||
232 | if (rdev->scan_req && rdev->scan_req->wdev == wdev) { | 206 | if (rdev->scan_req && rdev->scan_req->wdev == wdev) { |
233 | bool busy = work_busy(&rdev->scan_done_wk); | ||
234 | |||
235 | /* | 207 | /* |
236 | * If the work isn't pending or running (in which case it would | 208 | * If the scan request wasn't notified as done, set it |
237 | * be waiting for the lock we hold) the driver didn't properly | 209 | * to aborted and leak it after a warning. The driver |
238 | * cancel the scan when the interface was removed. In this case | 210 | * should have notified us that it ended at the latest |
239 | * warn and leak the scan request object to not crash later. | 211 | * during rdev_stop_p2p_device(). |
240 | */ | 212 | */ |
241 | WARN_ON(!busy); | 213 | if (WARN_ON(!rdev->scan_req->notified)) |
242 | 214 | rdev->scan_req->aborted = true; | |
243 | rdev->scan_req->aborted = true; | 215 | ___cfg80211_scan_done(rdev, !rdev->scan_req->notified); |
244 | ___cfg80211_scan_done(rdev, !busy); | ||
245 | } | 216 | } |
246 | } | 217 | } |
247 | 218 | ||
@@ -255,8 +226,6 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked) | |||
255 | 226 | ||
256 | rtnl_lock(); | 227 | rtnl_lock(); |
257 | 228 | ||
258 | /* read-only iteration need not hold the devlist_mtx */ | ||
259 | |||
260 | list_for_each_entry(wdev, &rdev->wdev_list, list) { | 229 | list_for_each_entry(wdev, &rdev->wdev_list, list) { |
261 | if (wdev->netdev) { | 230 | if (wdev->netdev) { |
262 | dev_close(wdev->netdev); | 231 | dev_close(wdev->netdev); |
@@ -265,12 +234,7 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked) | |||
265 | /* otherwise, check iftype */ | 234 | /* otherwise, check iftype */ |
266 | switch (wdev->iftype) { | 235 | switch (wdev->iftype) { |
267 | case NL80211_IFTYPE_P2P_DEVICE: | 236 | case NL80211_IFTYPE_P2P_DEVICE: |
268 | /* but this requires it */ | ||
269 | mutex_lock(&rdev->devlist_mtx); | ||
270 | mutex_lock(&rdev->sched_scan_mtx); | ||
271 | cfg80211_stop_p2p_device(rdev, wdev); | 237 | cfg80211_stop_p2p_device(rdev, wdev); |
272 | mutex_unlock(&rdev->sched_scan_mtx); | ||
273 | mutex_unlock(&rdev->devlist_mtx); | ||
274 | break; | 238 | break; |
275 | default: | 239 | default: |
276 | break; | 240 | break; |
@@ -298,10 +262,7 @@ static void cfg80211_event_work(struct work_struct *work) | |||
298 | event_work); | 262 | event_work); |
299 | 263 | ||
300 | rtnl_lock(); | 264 | rtnl_lock(); |
301 | cfg80211_lock_rdev(rdev); | ||
302 | |||
303 | cfg80211_process_rdev_events(rdev); | 265 | cfg80211_process_rdev_events(rdev); |
304 | cfg80211_unlock_rdev(rdev); | ||
305 | rtnl_unlock(); | 266 | rtnl_unlock(); |
306 | } | 267 | } |
307 | 268 | ||
@@ -309,7 +270,7 @@ static void cfg80211_event_work(struct work_struct *work) | |||
309 | 270 | ||
310 | struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) | 271 | struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) |
311 | { | 272 | { |
312 | static int wiphy_counter; | 273 | static atomic_t wiphy_counter = ATOMIC_INIT(0); |
313 | 274 | ||
314 | struct cfg80211_registered_device *rdev; | 275 | struct cfg80211_registered_device *rdev; |
315 | int alloc_size; | 276 | int alloc_size; |
@@ -331,26 +292,18 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) | |||
331 | 292 | ||
332 | rdev->ops = ops; | 293 | rdev->ops = ops; |
333 | 294 | ||
334 | mutex_lock(&cfg80211_mutex); | 295 | rdev->wiphy_idx = atomic_inc_return(&wiphy_counter); |
335 | |||
336 | rdev->wiphy_idx = wiphy_counter++; | ||
337 | 296 | ||
338 | if (unlikely(rdev->wiphy_idx < 0)) { | 297 | if (unlikely(rdev->wiphy_idx < 0)) { |
339 | wiphy_counter--; | ||
340 | mutex_unlock(&cfg80211_mutex); | ||
341 | /* ugh, wrapped! */ | 298 | /* ugh, wrapped! */ |
299 | atomic_dec(&wiphy_counter); | ||
342 | kfree(rdev); | 300 | kfree(rdev); |
343 | return NULL; | 301 | return NULL; |
344 | } | 302 | } |
345 | 303 | ||
346 | mutex_unlock(&cfg80211_mutex); | ||
347 | |||
348 | /* give it a proper name */ | 304 | /* give it a proper name */ |
349 | dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx); | 305 | dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx); |
350 | 306 | ||
351 | mutex_init(&rdev->mtx); | ||
352 | mutex_init(&rdev->devlist_mtx); | ||
353 | mutex_init(&rdev->sched_scan_mtx); | ||
354 | INIT_LIST_HEAD(&rdev->wdev_list); | 307 | INIT_LIST_HEAD(&rdev->wdev_list); |
355 | INIT_LIST_HEAD(&rdev->beacon_registrations); | 308 | INIT_LIST_HEAD(&rdev->beacon_registrations); |
356 | spin_lock_init(&rdev->beacon_registrations_lock); | 309 | spin_lock_init(&rdev->beacon_registrations_lock); |
@@ -598,11 +551,11 @@ int wiphy_register(struct wiphy *wiphy) | |||
598 | /* check and set up bitrates */ | 551 | /* check and set up bitrates */ |
599 | ieee80211_set_bitrate_flags(wiphy); | 552 | ieee80211_set_bitrate_flags(wiphy); |
600 | 553 | ||
601 | mutex_lock(&cfg80211_mutex); | 554 | rtnl_lock(); |
602 | 555 | ||
603 | res = device_add(&rdev->wiphy.dev); | 556 | res = device_add(&rdev->wiphy.dev); |
604 | if (res) { | 557 | if (res) { |
605 | mutex_unlock(&cfg80211_mutex); | 558 | rtnl_unlock(); |
606 | return res; | 559 | return res; |
607 | } | 560 | } |
608 | 561 | ||
@@ -631,25 +584,18 @@ int wiphy_register(struct wiphy *wiphy) | |||
631 | } | 584 | } |
632 | 585 | ||
633 | cfg80211_debugfs_rdev_add(rdev); | 586 | cfg80211_debugfs_rdev_add(rdev); |
634 | mutex_unlock(&cfg80211_mutex); | ||
635 | 587 | ||
636 | /* | ||
637 | * due to a locking dependency this has to be outside of the | ||
638 | * cfg80211_mutex lock | ||
639 | */ | ||
640 | res = rfkill_register(rdev->rfkill); | 588 | res = rfkill_register(rdev->rfkill); |
641 | if (res) { | 589 | if (res) { |
642 | device_del(&rdev->wiphy.dev); | 590 | device_del(&rdev->wiphy.dev); |
643 | 591 | ||
644 | mutex_lock(&cfg80211_mutex); | ||
645 | debugfs_remove_recursive(rdev->wiphy.debugfsdir); | 592 | debugfs_remove_recursive(rdev->wiphy.debugfsdir); |
646 | list_del_rcu(&rdev->list); | 593 | list_del_rcu(&rdev->list); |
647 | wiphy_regulatory_deregister(wiphy); | 594 | wiphy_regulatory_deregister(wiphy); |
648 | mutex_unlock(&cfg80211_mutex); | 595 | rtnl_unlock(); |
649 | return res; | 596 | return res; |
650 | } | 597 | } |
651 | 598 | ||
652 | rtnl_lock(); | ||
653 | rdev->wiphy.registered = true; | 599 | rdev->wiphy.registered = true; |
654 | rtnl_unlock(); | 600 | rtnl_unlock(); |
655 | return 0; | 601 | return 0; |
@@ -679,25 +625,19 @@ void wiphy_unregister(struct wiphy *wiphy) | |||
679 | { | 625 | { |
680 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 626 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
681 | 627 | ||
682 | rtnl_lock(); | ||
683 | rdev->wiphy.registered = false; | ||
684 | rtnl_unlock(); | ||
685 | |||
686 | rfkill_unregister(rdev->rfkill); | ||
687 | |||
688 | /* protect the device list */ | ||
689 | mutex_lock(&cfg80211_mutex); | ||
690 | |||
691 | wait_event(rdev->dev_wait, ({ | 628 | wait_event(rdev->dev_wait, ({ |
692 | int __count; | 629 | int __count; |
693 | mutex_lock(&rdev->devlist_mtx); | 630 | rtnl_lock(); |
694 | __count = rdev->opencount; | 631 | __count = rdev->opencount; |
695 | mutex_unlock(&rdev->devlist_mtx); | 632 | rtnl_unlock(); |
696 | __count == 0; })); | 633 | __count == 0; })); |
697 | 634 | ||
698 | mutex_lock(&rdev->devlist_mtx); | 635 | rtnl_lock(); |
636 | rdev->wiphy.registered = false; | ||
637 | |||
638 | rfkill_unregister(rdev->rfkill); | ||
639 | |||
699 | BUG_ON(!list_empty(&rdev->wdev_list)); | 640 | BUG_ON(!list_empty(&rdev->wdev_list)); |
700 | mutex_unlock(&rdev->devlist_mtx); | ||
701 | 641 | ||
702 | /* | 642 | /* |
703 | * First remove the hardware from everywhere, this makes | 643 | * First remove the hardware from everywhere, this makes |
@@ -708,20 +648,6 @@ void wiphy_unregister(struct wiphy *wiphy) | |||
708 | synchronize_rcu(); | 648 | synchronize_rcu(); |
709 | 649 | ||
710 | /* | 650 | /* |
711 | * Try to grab rdev->mtx. If a command is still in progress, | ||
712 | * hopefully the driver will refuse it since it's tearing | ||
713 | * down the device already. We wait for this command to complete | ||
714 | * before unlinking the item from the list. | ||
715 | * Note: as codified by the BUG_ON above we cannot get here if | ||
716 | * a virtual interface is still present. Hence, we can only get | ||
717 | * to lock contention here if userspace issues a command that | ||
718 | * identified the hardware by wiphy index. | ||
719 | */ | ||
720 | cfg80211_lock_rdev(rdev); | ||
721 | /* nothing */ | ||
722 | cfg80211_unlock_rdev(rdev); | ||
723 | |||
724 | /* | ||
725 | * If this device got a regulatory hint tell core its | 651 | * If this device got a regulatory hint tell core its |
726 | * free to listen now to a new shiny device regulatory hint | 652 | * free to listen now to a new shiny device regulatory hint |
727 | */ | 653 | */ |
@@ -730,15 +656,17 @@ void wiphy_unregister(struct wiphy *wiphy) | |||
730 | cfg80211_rdev_list_generation++; | 656 | cfg80211_rdev_list_generation++; |
731 | device_del(&rdev->wiphy.dev); | 657 | device_del(&rdev->wiphy.dev); |
732 | 658 | ||
733 | mutex_unlock(&cfg80211_mutex); | 659 | rtnl_unlock(); |
734 | 660 | ||
735 | flush_work(&rdev->scan_done_wk); | 661 | flush_work(&rdev->scan_done_wk); |
736 | cancel_work_sync(&rdev->conn_work); | 662 | cancel_work_sync(&rdev->conn_work); |
737 | flush_work(&rdev->event_work); | 663 | flush_work(&rdev->event_work); |
738 | cancel_delayed_work_sync(&rdev->dfs_update_channels_wk); | 664 | cancel_delayed_work_sync(&rdev->dfs_update_channels_wk); |
739 | 665 | ||
740 | if (rdev->wowlan && rdev->ops->set_wakeup) | 666 | #ifdef CONFIG_PM |
667 | if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup) | ||
741 | rdev_set_wakeup(rdev, false); | 668 | rdev_set_wakeup(rdev, false); |
669 | #endif | ||
742 | cfg80211_rdev_free_wowlan(rdev); | 670 | cfg80211_rdev_free_wowlan(rdev); |
743 | } | 671 | } |
744 | EXPORT_SYMBOL(wiphy_unregister); | 672 | EXPORT_SYMBOL(wiphy_unregister); |
@@ -748,9 +676,6 @@ void cfg80211_dev_free(struct cfg80211_registered_device *rdev) | |||
748 | struct cfg80211_internal_bss *scan, *tmp; | 676 | struct cfg80211_internal_bss *scan, *tmp; |
749 | struct cfg80211_beacon_registration *reg, *treg; | 677 | struct cfg80211_beacon_registration *reg, *treg; |
750 | rfkill_destroy(rdev->rfkill); | 678 | rfkill_destroy(rdev->rfkill); |
751 | mutex_destroy(&rdev->mtx); | ||
752 | mutex_destroy(&rdev->devlist_mtx); | ||
753 | mutex_destroy(&rdev->sched_scan_mtx); | ||
754 | list_for_each_entry_safe(reg, treg, &rdev->beacon_registrations, list) { | 679 | list_for_each_entry_safe(reg, treg, &rdev->beacon_registrations, list) { |
755 | list_del(®->list); | 680 | list_del(®->list); |
756 | kfree(reg); | 681 | kfree(reg); |
@@ -775,36 +700,6 @@ void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked) | |||
775 | } | 700 | } |
776 | EXPORT_SYMBOL(wiphy_rfkill_set_hw_state); | 701 | EXPORT_SYMBOL(wiphy_rfkill_set_hw_state); |
777 | 702 | ||
778 | static void wdev_cleanup_work(struct work_struct *work) | ||
779 | { | ||
780 | struct wireless_dev *wdev; | ||
781 | struct cfg80211_registered_device *rdev; | ||
782 | |||
783 | wdev = container_of(work, struct wireless_dev, cleanup_work); | ||
784 | rdev = wiphy_to_dev(wdev->wiphy); | ||
785 | |||
786 | mutex_lock(&rdev->sched_scan_mtx); | ||
787 | |||
788 | if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) { | ||
789 | rdev->scan_req->aborted = true; | ||
790 | ___cfg80211_scan_done(rdev, true); | ||
791 | } | ||
792 | |||
793 | if (WARN_ON(rdev->sched_scan_req && | ||
794 | rdev->sched_scan_req->dev == wdev->netdev)) { | ||
795 | __cfg80211_stop_sched_scan(rdev, false); | ||
796 | } | ||
797 | |||
798 | mutex_unlock(&rdev->sched_scan_mtx); | ||
799 | |||
800 | mutex_lock(&rdev->devlist_mtx); | ||
801 | rdev->opencount--; | ||
802 | mutex_unlock(&rdev->devlist_mtx); | ||
803 | wake_up(&rdev->dev_wait); | ||
804 | |||
805 | dev_put(wdev->netdev); | ||
806 | } | ||
807 | |||
808 | void cfg80211_unregister_wdev(struct wireless_dev *wdev) | 703 | void cfg80211_unregister_wdev(struct wireless_dev *wdev) |
809 | { | 704 | { |
810 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | 705 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); |
@@ -814,8 +709,6 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev) | |||
814 | if (WARN_ON(wdev->netdev)) | 709 | if (WARN_ON(wdev->netdev)) |
815 | return; | 710 | return; |
816 | 711 | ||
817 | mutex_lock(&rdev->devlist_mtx); | ||
818 | mutex_lock(&rdev->sched_scan_mtx); | ||
819 | list_del_rcu(&wdev->list); | 712 | list_del_rcu(&wdev->list); |
820 | rdev->devlist_generation++; | 713 | rdev->devlist_generation++; |
821 | 714 | ||
@@ -827,8 +720,6 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev) | |||
827 | WARN_ON_ONCE(1); | 720 | WARN_ON_ONCE(1); |
828 | break; | 721 | break; |
829 | } | 722 | } |
830 | mutex_unlock(&rdev->sched_scan_mtx); | ||
831 | mutex_unlock(&rdev->devlist_mtx); | ||
832 | } | 723 | } |
833 | EXPORT_SYMBOL(cfg80211_unregister_wdev); | 724 | EXPORT_SYMBOL(cfg80211_unregister_wdev); |
834 | 725 | ||
@@ -847,7 +738,7 @@ void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, | |||
847 | } | 738 | } |
848 | 739 | ||
849 | void cfg80211_leave(struct cfg80211_registered_device *rdev, | 740 | void cfg80211_leave(struct cfg80211_registered_device *rdev, |
850 | struct wireless_dev *wdev) | 741 | struct wireless_dev *wdev) |
851 | { | 742 | { |
852 | struct net_device *dev = wdev->netdev; | 743 | struct net_device *dev = wdev->netdev; |
853 | 744 | ||
@@ -857,9 +748,7 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev, | |||
857 | break; | 748 | break; |
858 | case NL80211_IFTYPE_P2P_CLIENT: | 749 | case NL80211_IFTYPE_P2P_CLIENT: |
859 | case NL80211_IFTYPE_STATION: | 750 | case NL80211_IFTYPE_STATION: |
860 | mutex_lock(&rdev->sched_scan_mtx); | ||
861 | __cfg80211_stop_sched_scan(rdev, false); | 751 | __cfg80211_stop_sched_scan(rdev, false); |
862 | mutex_unlock(&rdev->sched_scan_mtx); | ||
863 | 752 | ||
864 | wdev_lock(wdev); | 753 | wdev_lock(wdev); |
865 | #ifdef CONFIG_CFG80211_WEXT | 754 | #ifdef CONFIG_CFG80211_WEXT |
@@ -868,8 +757,8 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev, | |||
868 | wdev->wext.ie_len = 0; | 757 | wdev->wext.ie_len = 0; |
869 | wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; | 758 | wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; |
870 | #endif | 759 | #endif |
871 | __cfg80211_disconnect(rdev, dev, | 760 | cfg80211_disconnect(rdev, dev, |
872 | WLAN_REASON_DEAUTH_LEAVING, true); | 761 | WLAN_REASON_DEAUTH_LEAVING, true); |
873 | wdev_unlock(wdev); | 762 | wdev_unlock(wdev); |
874 | break; | 763 | break; |
875 | case NL80211_IFTYPE_MESH_POINT: | 764 | case NL80211_IFTYPE_MESH_POINT: |
@@ -911,13 +800,11 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | |||
911 | * are added with nl80211. | 800 | * are added with nl80211. |
912 | */ | 801 | */ |
913 | mutex_init(&wdev->mtx); | 802 | mutex_init(&wdev->mtx); |
914 | INIT_WORK(&wdev->cleanup_work, wdev_cleanup_work); | ||
915 | INIT_LIST_HEAD(&wdev->event_list); | 803 | INIT_LIST_HEAD(&wdev->event_list); |
916 | spin_lock_init(&wdev->event_lock); | 804 | spin_lock_init(&wdev->event_lock); |
917 | INIT_LIST_HEAD(&wdev->mgmt_registrations); | 805 | INIT_LIST_HEAD(&wdev->mgmt_registrations); |
918 | spin_lock_init(&wdev->mgmt_registrations_lock); | 806 | spin_lock_init(&wdev->mgmt_registrations_lock); |
919 | 807 | ||
920 | mutex_lock(&rdev->devlist_mtx); | ||
921 | wdev->identifier = ++rdev->wdev_id; | 808 | wdev->identifier = ++rdev->wdev_id; |
922 | list_add_rcu(&wdev->list, &rdev->wdev_list); | 809 | list_add_rcu(&wdev->list, &rdev->wdev_list); |
923 | rdev->devlist_generation++; | 810 | rdev->devlist_generation++; |
@@ -930,7 +817,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | |||
930 | } | 817 | } |
931 | wdev->netdev = dev; | 818 | wdev->netdev = dev; |
932 | wdev->sme_state = CFG80211_SME_IDLE; | 819 | wdev->sme_state = CFG80211_SME_IDLE; |
933 | mutex_unlock(&rdev->devlist_mtx); | ||
934 | #ifdef CONFIG_CFG80211_WEXT | 820 | #ifdef CONFIG_CFG80211_WEXT |
935 | wdev->wext.default_key = -1; | 821 | wdev->wext.default_key = -1; |
936 | wdev->wext.default_mgmt_key = -1; | 822 | wdev->wext.default_mgmt_key = -1; |
@@ -956,26 +842,22 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | |||
956 | break; | 842 | break; |
957 | case NETDEV_DOWN: | 843 | case NETDEV_DOWN: |
958 | cfg80211_update_iface_num(rdev, wdev->iftype, -1); | 844 | cfg80211_update_iface_num(rdev, wdev->iftype, -1); |
959 | dev_hold(dev); | 845 | if (rdev->scan_req && rdev->scan_req->wdev == wdev) { |
960 | queue_work(cfg80211_wq, &wdev->cleanup_work); | 846 | if (WARN_ON(!rdev->scan_req->notified)) |
847 | rdev->scan_req->aborted = true; | ||
848 | ___cfg80211_scan_done(rdev, true); | ||
849 | } | ||
850 | |||
851 | if (WARN_ON(rdev->sched_scan_req && | ||
852 | rdev->sched_scan_req->dev == wdev->netdev)) { | ||
853 | __cfg80211_stop_sched_scan(rdev, false); | ||
854 | } | ||
855 | |||
856 | rdev->opencount--; | ||
857 | wake_up(&rdev->dev_wait); | ||
961 | break; | 858 | break; |
962 | case NETDEV_UP: | 859 | case NETDEV_UP: |
963 | /* | ||
964 | * If we have a really quick DOWN/UP succession we may | ||
965 | * have this work still pending ... cancel it and see | ||
966 | * if it was pending, in which case we need to account | ||
967 | * for some of the work it would have done. | ||
968 | */ | ||
969 | if (cancel_work_sync(&wdev->cleanup_work)) { | ||
970 | mutex_lock(&rdev->devlist_mtx); | ||
971 | rdev->opencount--; | ||
972 | mutex_unlock(&rdev->devlist_mtx); | ||
973 | dev_put(dev); | ||
974 | } | ||
975 | cfg80211_update_iface_num(rdev, wdev->iftype, 1); | 860 | cfg80211_update_iface_num(rdev, wdev->iftype, 1); |
976 | cfg80211_lock_rdev(rdev); | ||
977 | mutex_lock(&rdev->devlist_mtx); | ||
978 | mutex_lock(&rdev->sched_scan_mtx); | ||
979 | wdev_lock(wdev); | 861 | wdev_lock(wdev); |
980 | switch (wdev->iftype) { | 862 | switch (wdev->iftype) { |
981 | #ifdef CONFIG_CFG80211_WEXT | 863 | #ifdef CONFIG_CFG80211_WEXT |
@@ -1007,10 +889,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | |||
1007 | break; | 889 | break; |
1008 | } | 890 | } |
1009 | wdev_unlock(wdev); | 891 | wdev_unlock(wdev); |
1010 | mutex_unlock(&rdev->sched_scan_mtx); | ||
1011 | rdev->opencount++; | 892 | rdev->opencount++; |
1012 | mutex_unlock(&rdev->devlist_mtx); | ||
1013 | cfg80211_unlock_rdev(rdev); | ||
1014 | 893 | ||
1015 | /* | 894 | /* |
1016 | * Configure power management to the driver here so that its | 895 | * Configure power management to the driver here so that its |
@@ -1027,12 +906,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | |||
1027 | break; | 906 | break; |
1028 | case NETDEV_UNREGISTER: | 907 | case NETDEV_UNREGISTER: |
1029 | /* | 908 | /* |
1030 | * NB: cannot take rdev->mtx here because this may be | ||
1031 | * called within code protected by it when interfaces | ||
1032 | * are removed with nl80211. | ||
1033 | */ | ||
1034 | mutex_lock(&rdev->devlist_mtx); | ||
1035 | /* | ||
1036 | * It is possible to get NETDEV_UNREGISTER | 909 | * It is possible to get NETDEV_UNREGISTER |
1037 | * multiple times. To detect that, check | 910 | * multiple times. To detect that, check |
1038 | * that the interface is still on the list | 911 | * that the interface is still on the list |
@@ -1048,7 +921,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | |||
1048 | kfree(wdev->wext.keys); | 921 | kfree(wdev->wext.keys); |
1049 | #endif | 922 | #endif |
1050 | } | 923 | } |
1051 | mutex_unlock(&rdev->devlist_mtx); | ||
1052 | /* | 924 | /* |
1053 | * synchronise (so that we won't find this netdev | 925 | * synchronise (so that we won't find this netdev |
1054 | * from other code any more) and then clear the list | 926 | * from other code any more) and then clear the list |
@@ -1068,9 +940,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | |||
1068 | return notifier_from_errno(-EOPNOTSUPP); | 940 | return notifier_from_errno(-EOPNOTSUPP); |
1069 | if (rfkill_blocked(rdev->rfkill)) | 941 | if (rfkill_blocked(rdev->rfkill)) |
1070 | return notifier_from_errno(-ERFKILL); | 942 | return notifier_from_errno(-ERFKILL); |
1071 | mutex_lock(&rdev->devlist_mtx); | ||
1072 | ret = cfg80211_can_add_interface(rdev, wdev->iftype); | 943 | ret = cfg80211_can_add_interface(rdev, wdev->iftype); |
1073 | mutex_unlock(&rdev->devlist_mtx); | ||
1074 | if (ret) | 944 | if (ret) |
1075 | return notifier_from_errno(ret); | 945 | return notifier_from_errno(ret); |
1076 | break; | 946 | break; |
@@ -1088,12 +958,10 @@ static void __net_exit cfg80211_pernet_exit(struct net *net) | |||
1088 | struct cfg80211_registered_device *rdev; | 958 | struct cfg80211_registered_device *rdev; |
1089 | 959 | ||
1090 | rtnl_lock(); | 960 | rtnl_lock(); |
1091 | mutex_lock(&cfg80211_mutex); | ||
1092 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) { | 961 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) { |
1093 | if (net_eq(wiphy_net(&rdev->wiphy), net)) | 962 | if (net_eq(wiphy_net(&rdev->wiphy), net)) |
1094 | WARN_ON(cfg80211_switch_netns(rdev, &init_net)); | 963 | WARN_ON(cfg80211_switch_netns(rdev, &init_net)); |
1095 | } | 964 | } |
1096 | mutex_unlock(&cfg80211_mutex); | ||
1097 | rtnl_unlock(); | 965 | rtnl_unlock(); |
1098 | } | 966 | } |
1099 | 967 | ||
diff --git a/net/wireless/core.h b/net/wireless/core.h index fd35dae547c4..a65eaf8a84c1 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 |
@@ -84,8 +74,6 @@ struct cfg80211_registered_device { | |||
84 | struct work_struct conn_work; | 74 | struct work_struct conn_work; |
85 | struct work_struct event_work; | 75 | struct work_struct event_work; |
86 | 76 | ||
87 | struct cfg80211_wowlan *wowlan; | ||
88 | |||
89 | struct delayed_work dfs_update_channels_wk; | 77 | struct delayed_work dfs_update_channels_wk; |
90 | 78 | ||
91 | /* netlink port which started critical protocol (0 means not started) */ | 79 | /* netlink port which started critical protocol (0 means not started) */ |
@@ -106,29 +94,26 @@ struct cfg80211_registered_device *wiphy_to_dev(struct wiphy *wiphy) | |||
106 | static inline void | 94 | static inline void |
107 | cfg80211_rdev_free_wowlan(struct cfg80211_registered_device *rdev) | 95 | cfg80211_rdev_free_wowlan(struct cfg80211_registered_device *rdev) |
108 | { | 96 | { |
97 | #ifdef CONFIG_PM | ||
109 | int i; | 98 | int i; |
110 | 99 | ||
111 | if (!rdev->wowlan) | 100 | if (!rdev->wiphy.wowlan_config) |
112 | return; | 101 | return; |
113 | for (i = 0; i < rdev->wowlan->n_patterns; i++) | 102 | for (i = 0; i < rdev->wiphy.wowlan_config->n_patterns; i++) |
114 | kfree(rdev->wowlan->patterns[i].mask); | 103 | kfree(rdev->wiphy.wowlan_config->patterns[i].mask); |
115 | kfree(rdev->wowlan->patterns); | 104 | kfree(rdev->wiphy.wowlan_config->patterns); |
116 | if (rdev->wowlan->tcp && rdev->wowlan->tcp->sock) | 105 | if (rdev->wiphy.wowlan_config->tcp && |
117 | sock_release(rdev->wowlan->tcp->sock); | 106 | rdev->wiphy.wowlan_config->tcp->sock) |
118 | kfree(rdev->wowlan->tcp); | 107 | sock_release(rdev->wiphy.wowlan_config->tcp->sock); |
119 | kfree(rdev->wowlan); | 108 | kfree(rdev->wiphy.wowlan_config->tcp); |
109 | kfree(rdev->wiphy.wowlan_config); | ||
110 | #endif | ||
120 | } | 111 | } |
121 | 112 | ||
122 | extern struct workqueue_struct *cfg80211_wq; | 113 | extern struct workqueue_struct *cfg80211_wq; |
123 | extern struct mutex cfg80211_mutex; | ||
124 | extern struct list_head cfg80211_rdev_list; | 114 | extern struct list_head cfg80211_rdev_list; |
125 | extern int cfg80211_rdev_list_generation; | 115 | extern int cfg80211_rdev_list_generation; |
126 | 116 | ||
127 | static inline void assert_cfg80211_lock(void) | ||
128 | { | ||
129 | lockdep_assert_held(&cfg80211_mutex); | ||
130 | } | ||
131 | |||
132 | struct cfg80211_internal_bss { | 117 | struct cfg80211_internal_bss { |
133 | struct list_head list; | 118 | struct list_head list; |
134 | struct list_head hidden_list; | 119 | struct list_head hidden_list; |
@@ -161,27 +146,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); | 146 | struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx); |
162 | int get_wiphy_idx(struct wiphy *wiphy); | 147 | int get_wiphy_idx(struct wiphy *wiphy); |
163 | 148 | ||
164 | /* requires cfg80211_rdev_mutex to be held! */ | ||
165 | struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx); | 149 | struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx); |
166 | 150 | ||
167 | /* identical to cfg80211_get_dev_from_info but only operate on ifindex */ | ||
168 | extern struct cfg80211_registered_device * | ||
169 | cfg80211_get_dev_from_ifindex(struct net *net, int ifindex); | ||
170 | |||
171 | int cfg80211_switch_netns(struct cfg80211_registered_device *rdev, | 151 | int cfg80211_switch_netns(struct cfg80211_registered_device *rdev, |
172 | struct net *net); | 152 | struct net *net); |
173 | 153 | ||
174 | static inline void cfg80211_lock_rdev(struct cfg80211_registered_device *rdev) | ||
175 | { | ||
176 | mutex_lock(&rdev->mtx); | ||
177 | } | ||
178 | |||
179 | static inline void cfg80211_unlock_rdev(struct cfg80211_registered_device *rdev) | ||
180 | { | ||
181 | BUG_ON(IS_ERR(rdev) || !rdev); | ||
182 | mutex_unlock(&rdev->mtx); | ||
183 | } | ||
184 | |||
185 | static inline void wdev_lock(struct wireless_dev *wdev) | 154 | static inline void wdev_lock(struct wireless_dev *wdev) |
186 | __acquires(wdev) | 155 | __acquires(wdev) |
187 | { | 156 | { |
@@ -196,7 +165,7 @@ static inline void wdev_unlock(struct wireless_dev *wdev) | |||
196 | mutex_unlock(&wdev->mtx); | 165 | mutex_unlock(&wdev->mtx); |
197 | } | 166 | } |
198 | 167 | ||
199 | #define ASSERT_RDEV_LOCK(rdev) lockdep_assert_held(&(rdev)->mtx) | 168 | #define ASSERT_RDEV_LOCK(rdev) ASSERT_RTNL() |
200 | #define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx) | 169 | #define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx) |
201 | 170 | ||
202 | static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev) | 171 | static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev) |
@@ -314,38 +283,21 @@ int cfg80211_stop_ap(struct cfg80211_registered_device *rdev, | |||
314 | struct net_device *dev); | 283 | struct net_device *dev); |
315 | 284 | ||
316 | /* MLME */ | 285 | /* MLME */ |
317 | int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | ||
318 | struct net_device *dev, | ||
319 | struct ieee80211_channel *chan, | ||
320 | enum nl80211_auth_type auth_type, | ||
321 | const u8 *bssid, | ||
322 | const u8 *ssid, int ssid_len, | ||
323 | const u8 *ie, int ie_len, | ||
324 | const u8 *key, int key_len, int key_idx, | ||
325 | const u8 *sae_data, int sae_data_len); | ||
326 | int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | 286 | int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, |
327 | struct net_device *dev, struct ieee80211_channel *chan, | 287 | struct net_device *dev, |
328 | enum nl80211_auth_type auth_type, const u8 *bssid, | 288 | struct ieee80211_channel *chan, |
289 | enum nl80211_auth_type auth_type, | ||
290 | const u8 *bssid, | ||
329 | const u8 *ssid, int ssid_len, | 291 | const u8 *ssid, int ssid_len, |
330 | const u8 *ie, int ie_len, | 292 | const u8 *ie, int ie_len, |
331 | const u8 *key, int key_len, int key_idx, | 293 | const u8 *key, int key_len, int key_idx, |
332 | const u8 *sae_data, int sae_data_len); | 294 | const u8 *sae_data, int sae_data_len); |
333 | int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | ||
334 | struct net_device *dev, | ||
335 | struct ieee80211_channel *chan, | ||
336 | const u8 *bssid, | ||
337 | const u8 *ssid, int ssid_len, | ||
338 | struct cfg80211_assoc_request *req); | ||
339 | int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | 295 | int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, |
340 | struct net_device *dev, | 296 | struct net_device *dev, |
341 | struct ieee80211_channel *chan, | 297 | struct ieee80211_channel *chan, |
342 | const u8 *bssid, | 298 | const u8 *bssid, |
343 | const u8 *ssid, int ssid_len, | 299 | const u8 *ssid, int ssid_len, |
344 | struct cfg80211_assoc_request *req); | 300 | struct cfg80211_assoc_request *req); |
345 | int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | ||
346 | struct net_device *dev, const u8 *bssid, | ||
347 | const u8 *ie, int ie_len, u16 reason, | ||
348 | bool local_state_change); | ||
349 | int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | 301 | int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, |
350 | struct net_device *dev, const u8 *bssid, | 302 | struct net_device *dev, const u8 *bssid, |
351 | const u8 *ie, int ie_len, u16 reason, | 303 | const u8 *ie, int ie_len, u16 reason, |
@@ -377,18 +329,11 @@ void cfg80211_oper_and_vht_capa(struct ieee80211_vht_cap *vht_capa, | |||
377 | const struct ieee80211_vht_cap *vht_capa_mask); | 329 | const struct ieee80211_vht_cap *vht_capa_mask); |
378 | 330 | ||
379 | /* SME */ | 331 | /* SME */ |
380 | int __cfg80211_connect(struct cfg80211_registered_device *rdev, | ||
381 | struct net_device *dev, | ||
382 | struct cfg80211_connect_params *connect, | ||
383 | struct cfg80211_cached_keys *connkeys, | ||
384 | const u8 *prev_bssid); | ||
385 | int cfg80211_connect(struct cfg80211_registered_device *rdev, | 332 | int cfg80211_connect(struct cfg80211_registered_device *rdev, |
386 | struct net_device *dev, | 333 | struct net_device *dev, |
387 | struct cfg80211_connect_params *connect, | 334 | struct cfg80211_connect_params *connect, |
388 | struct cfg80211_cached_keys *connkeys); | 335 | struct cfg80211_cached_keys *connkeys, |
389 | int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, | 336 | const u8 *prev_bssid); |
390 | struct net_device *dev, u16 reason, | ||
391 | bool wextev); | ||
392 | int cfg80211_disconnect(struct cfg80211_registered_device *rdev, | 337 | int cfg80211_disconnect(struct cfg80211_registered_device *rdev, |
393 | struct net_device *dev, u16 reason, | 338 | struct net_device *dev, u16 reason, |
394 | bool wextev); | 339 | bool wextev); |
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 0bb93f3061a4..5dfb289ab761 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c | |||
@@ -82,6 +82,7 @@ const struct mesh_setup default_mesh_setup = { | |||
82 | .sync_method = IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET, | 82 | .sync_method = IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET, |
83 | .path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP, | 83 | .path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP, |
84 | .path_metric = IEEE80211_PATH_METRIC_AIRTIME, | 84 | .path_metric = IEEE80211_PATH_METRIC_AIRTIME, |
85 | .auth_id = 0, /* open */ | ||
85 | .ie = NULL, | 86 | .ie = NULL, |
86 | .ie_len = 0, | 87 | .ie_len = 0, |
87 | .is_secure = false, | 88 | .is_secure = false, |
@@ -185,11 +186,9 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | |||
185 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 186 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
186 | int err; | 187 | int err; |
187 | 188 | ||
188 | mutex_lock(&rdev->devlist_mtx); | ||
189 | wdev_lock(wdev); | 189 | wdev_lock(wdev); |
190 | err = __cfg80211_join_mesh(rdev, dev, setup, conf); | 190 | err = __cfg80211_join_mesh(rdev, dev, setup, conf); |
191 | wdev_unlock(wdev); | 191 | wdev_unlock(wdev); |
192 | mutex_unlock(&rdev->devlist_mtx); | ||
193 | 192 | ||
194 | return err; | 193 | return err; |
195 | } | 194 | } |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 0c7b7dd855f6..7bde5d9c0003 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -25,12 +25,9 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len) | |||
25 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 25 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
26 | 26 | ||
27 | trace_cfg80211_send_rx_auth(dev); | 27 | trace_cfg80211_send_rx_auth(dev); |
28 | wdev_lock(wdev); | ||
29 | 28 | ||
30 | nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL); | 29 | nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL); |
31 | cfg80211_sme_rx_auth(dev, buf, len); | 30 | cfg80211_sme_rx_auth(dev, buf, len); |
32 | |||
33 | wdev_unlock(wdev); | ||
34 | } | 31 | } |
35 | EXPORT_SYMBOL(cfg80211_send_rx_auth); | 32 | EXPORT_SYMBOL(cfg80211_send_rx_auth); |
36 | 33 | ||
@@ -46,7 +43,6 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss, | |||
46 | int ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); | 43 | int ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); |
47 | 44 | ||
48 | trace_cfg80211_send_rx_assoc(dev, bss); | 45 | trace_cfg80211_send_rx_assoc(dev, bss); |
49 | wdev_lock(wdev); | ||
50 | 46 | ||
51 | status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); | 47 | status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); |
52 | 48 | ||
@@ -59,7 +55,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss, | |||
59 | if (status_code != WLAN_STATUS_SUCCESS && wdev->conn && | 55 | if (status_code != WLAN_STATUS_SUCCESS && wdev->conn && |
60 | cfg80211_sme_failed_reassoc(wdev)) { | 56 | cfg80211_sme_failed_reassoc(wdev)) { |
61 | cfg80211_put_bss(wiphy, bss); | 57 | cfg80211_put_bss(wiphy, bss); |
62 | goto out; | 58 | return; |
63 | } | 59 | } |
64 | 60 | ||
65 | nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL); | 61 | nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL); |
@@ -71,7 +67,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss, | |||
71 | * sme will schedule work that does it later. | 67 | * sme will schedule work that does it later. |
72 | */ | 68 | */ |
73 | cfg80211_put_bss(wiphy, bss); | 69 | cfg80211_put_bss(wiphy, bss); |
74 | goto out; | 70 | return; |
75 | } | 71 | } |
76 | 72 | ||
77 | if (!wdev->conn && wdev->sme_state == CFG80211_SME_IDLE) { | 73 | if (!wdev->conn && wdev->sme_state == CFG80211_SME_IDLE) { |
@@ -87,13 +83,11 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss, | |||
87 | __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs, | 83 | __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs, |
88 | status_code, | 84 | status_code, |
89 | status_code == WLAN_STATUS_SUCCESS, bss); | 85 | status_code == WLAN_STATUS_SUCCESS, bss); |
90 | out: | ||
91 | wdev_unlock(wdev); | ||
92 | } | 86 | } |
93 | EXPORT_SYMBOL(cfg80211_send_rx_assoc); | 87 | EXPORT_SYMBOL(cfg80211_send_rx_assoc); |
94 | 88 | ||
95 | void __cfg80211_send_deauth(struct net_device *dev, | 89 | void cfg80211_send_deauth(struct net_device *dev, |
96 | const u8 *buf, size_t len) | 90 | const u8 *buf, size_t len) |
97 | { | 91 | { |
98 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 92 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
99 | struct wiphy *wiphy = wdev->wiphy; | 93 | struct wiphy *wiphy = wdev->wiphy; |
@@ -102,7 +96,7 @@ void __cfg80211_send_deauth(struct net_device *dev, | |||
102 | const u8 *bssid = mgmt->bssid; | 96 | const u8 *bssid = mgmt->bssid; |
103 | bool was_current = false; | 97 | bool was_current = false; |
104 | 98 | ||
105 | trace___cfg80211_send_deauth(dev); | 99 | trace_cfg80211_send_deauth(dev); |
106 | ASSERT_WDEV_LOCK(wdev); | 100 | ASSERT_WDEV_LOCK(wdev); |
107 | 101 | ||
108 | if (wdev->current_bss && | 102 | if (wdev->current_bss && |
@@ -129,20 +123,10 @@ void __cfg80211_send_deauth(struct net_device *dev, | |||
129 | false, NULL); | 123 | false, NULL); |
130 | } | 124 | } |
131 | } | 125 | } |
132 | EXPORT_SYMBOL(__cfg80211_send_deauth); | ||
133 | |||
134 | void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len) | ||
135 | { | ||
136 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
137 | |||
138 | wdev_lock(wdev); | ||
139 | __cfg80211_send_deauth(dev, buf, len); | ||
140 | wdev_unlock(wdev); | ||
141 | } | ||
142 | EXPORT_SYMBOL(cfg80211_send_deauth); | 126 | EXPORT_SYMBOL(cfg80211_send_deauth); |
143 | 127 | ||
144 | void __cfg80211_send_disassoc(struct net_device *dev, | 128 | void cfg80211_send_disassoc(struct net_device *dev, |
145 | const u8 *buf, size_t len) | 129 | const u8 *buf, size_t len) |
146 | { | 130 | { |
147 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 131 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
148 | struct wiphy *wiphy = wdev->wiphy; | 132 | struct wiphy *wiphy = wdev->wiphy; |
@@ -152,7 +136,7 @@ void __cfg80211_send_disassoc(struct net_device *dev, | |||
152 | u16 reason_code; | 136 | u16 reason_code; |
153 | bool from_ap; | 137 | bool from_ap; |
154 | 138 | ||
155 | trace___cfg80211_send_disassoc(dev); | 139 | trace_cfg80211_send_disassoc(dev); |
156 | ASSERT_WDEV_LOCK(wdev); | 140 | ASSERT_WDEV_LOCK(wdev); |
157 | 141 | ||
158 | nl80211_send_disassoc(rdev, dev, buf, len, GFP_KERNEL); | 142 | nl80211_send_disassoc(rdev, dev, buf, len, GFP_KERNEL); |
@@ -175,16 +159,6 @@ void __cfg80211_send_disassoc(struct net_device *dev, | |||
175 | from_ap = !ether_addr_equal(mgmt->sa, dev->dev_addr); | 159 | from_ap = !ether_addr_equal(mgmt->sa, dev->dev_addr); |
176 | __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap); | 160 | __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap); |
177 | } | 161 | } |
178 | EXPORT_SYMBOL(__cfg80211_send_disassoc); | ||
179 | |||
180 | void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len) | ||
181 | { | ||
182 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
183 | |||
184 | wdev_lock(wdev); | ||
185 | __cfg80211_send_disassoc(dev, buf, len); | ||
186 | wdev_unlock(wdev); | ||
187 | } | ||
188 | EXPORT_SYMBOL(cfg80211_send_disassoc); | 162 | EXPORT_SYMBOL(cfg80211_send_disassoc); |
189 | 163 | ||
190 | void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) | 164 | void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) |
@@ -194,15 +168,12 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) | |||
194 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 168 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
195 | 169 | ||
196 | trace_cfg80211_send_auth_timeout(dev, addr); | 170 | trace_cfg80211_send_auth_timeout(dev, addr); |
197 | wdev_lock(wdev); | ||
198 | 171 | ||
199 | nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL); | 172 | nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL); |
200 | if (wdev->sme_state == CFG80211_SME_CONNECTING) | 173 | if (wdev->sme_state == CFG80211_SME_CONNECTING) |
201 | __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0, | 174 | __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0, |
202 | WLAN_STATUS_UNSPECIFIED_FAILURE, | 175 | WLAN_STATUS_UNSPECIFIED_FAILURE, |
203 | false, NULL); | 176 | false, NULL); |
204 | |||
205 | wdev_unlock(wdev); | ||
206 | } | 177 | } |
207 | EXPORT_SYMBOL(cfg80211_send_auth_timeout); | 178 | EXPORT_SYMBOL(cfg80211_send_auth_timeout); |
208 | 179 | ||
@@ -213,15 +184,12 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr) | |||
213 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 184 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
214 | 185 | ||
215 | trace_cfg80211_send_assoc_timeout(dev, addr); | 186 | trace_cfg80211_send_assoc_timeout(dev, addr); |
216 | wdev_lock(wdev); | ||
217 | 187 | ||
218 | nl80211_send_assoc_timeout(rdev, dev, addr, GFP_KERNEL); | 188 | nl80211_send_assoc_timeout(rdev, dev, addr, GFP_KERNEL); |
219 | if (wdev->sme_state == CFG80211_SME_CONNECTING) | 189 | if (wdev->sme_state == CFG80211_SME_CONNECTING) |
220 | __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0, | 190 | __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0, |
221 | WLAN_STATUS_UNSPECIFIED_FAILURE, | 191 | WLAN_STATUS_UNSPECIFIED_FAILURE, |
222 | false, NULL); | 192 | false, NULL); |
223 | |||
224 | wdev_unlock(wdev); | ||
225 | } | 193 | } |
226 | EXPORT_SYMBOL(cfg80211_send_assoc_timeout); | 194 | EXPORT_SYMBOL(cfg80211_send_assoc_timeout); |
227 | 195 | ||
@@ -253,18 +221,27 @@ void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr, | |||
253 | EXPORT_SYMBOL(cfg80211_michael_mic_failure); | 221 | EXPORT_SYMBOL(cfg80211_michael_mic_failure); |
254 | 222 | ||
255 | /* some MLME handling for userspace SME */ | 223 | /* some MLME handling for userspace SME */ |
256 | int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | 224 | int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, |
257 | struct net_device *dev, | 225 | struct net_device *dev, |
258 | struct ieee80211_channel *chan, | 226 | struct ieee80211_channel *chan, |
259 | enum nl80211_auth_type auth_type, | 227 | enum nl80211_auth_type auth_type, |
260 | const u8 *bssid, | 228 | const u8 *bssid, |
261 | const u8 *ssid, int ssid_len, | 229 | const u8 *ssid, int ssid_len, |
262 | const u8 *ie, int ie_len, | 230 | const u8 *ie, int ie_len, |
263 | const u8 *key, int key_len, int key_idx, | 231 | const u8 *key, int key_len, int key_idx, |
264 | const u8 *sae_data, int sae_data_len) | 232 | const u8 *sae_data, int sae_data_len) |
265 | { | 233 | { |
266 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 234 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
267 | struct cfg80211_auth_request req; | 235 | struct cfg80211_auth_request req = { |
236 | .ie = ie, | ||
237 | .ie_len = ie_len, | ||
238 | .sae_data = sae_data, | ||
239 | .sae_data_len = sae_data_len, | ||
240 | .auth_type = auth_type, | ||
241 | .key = key, | ||
242 | .key_len = key_len, | ||
243 | .key_idx = key_idx, | ||
244 | }; | ||
268 | int err; | 245 | int err; |
269 | 246 | ||
270 | ASSERT_WDEV_LOCK(wdev); | 247 | ASSERT_WDEV_LOCK(wdev); |
@@ -277,18 +254,8 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
277 | ether_addr_equal(bssid, wdev->current_bss->pub.bssid)) | 254 | ether_addr_equal(bssid, wdev->current_bss->pub.bssid)) |
278 | return -EALREADY; | 255 | return -EALREADY; |
279 | 256 | ||
280 | memset(&req, 0, sizeof(req)); | ||
281 | |||
282 | req.ie = ie; | ||
283 | req.ie_len = ie_len; | ||
284 | req.sae_data = sae_data; | ||
285 | req.sae_data_len = sae_data_len; | ||
286 | req.auth_type = auth_type; | ||
287 | req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, | 257 | req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, |
288 | WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); | 258 | WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); |
289 | req.key = key; | ||
290 | req.key_len = key_len; | ||
291 | req.key_idx = key_idx; | ||
292 | if (!req.bss) | 259 | if (!req.bss) |
293 | return -ENOENT; | 260 | return -ENOENT; |
294 | 261 | ||
@@ -304,28 +271,6 @@ out: | |||
304 | return err; | 271 | return err; |
305 | } | 272 | } |
306 | 273 | ||
307 | int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | ||
308 | struct net_device *dev, struct ieee80211_channel *chan, | ||
309 | enum nl80211_auth_type auth_type, const u8 *bssid, | ||
310 | const u8 *ssid, int ssid_len, | ||
311 | const u8 *ie, int ie_len, | ||
312 | const u8 *key, int key_len, int key_idx, | ||
313 | const u8 *sae_data, int sae_data_len) | ||
314 | { | ||
315 | int err; | ||
316 | |||
317 | mutex_lock(&rdev->devlist_mtx); | ||
318 | wdev_lock(dev->ieee80211_ptr); | ||
319 | err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, | ||
320 | ssid, ssid_len, ie, ie_len, | ||
321 | key, key_len, key_idx, | ||
322 | sae_data, sae_data_len); | ||
323 | wdev_unlock(dev->ieee80211_ptr); | ||
324 | mutex_unlock(&rdev->devlist_mtx); | ||
325 | |||
326 | return err; | ||
327 | } | ||
328 | |||
329 | /* Do a logical ht_capa &= ht_capa_mask. */ | 274 | /* Do a logical ht_capa &= ht_capa_mask. */ |
330 | void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa, | 275 | void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa, |
331 | const struct ieee80211_ht_cap *ht_capa_mask) | 276 | const struct ieee80211_ht_cap *ht_capa_mask) |
@@ -360,12 +305,12 @@ void cfg80211_oper_and_vht_capa(struct ieee80211_vht_cap *vht_capa, | |||
360 | p1[i] &= p2[i]; | 305 | p1[i] &= p2[i]; |
361 | } | 306 | } |
362 | 307 | ||
363 | int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | 308 | int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, |
364 | struct net_device *dev, | 309 | struct net_device *dev, |
365 | struct ieee80211_channel *chan, | 310 | struct ieee80211_channel *chan, |
366 | const u8 *bssid, | 311 | const u8 *bssid, |
367 | const u8 *ssid, int ssid_len, | 312 | const u8 *ssid, int ssid_len, |
368 | struct cfg80211_assoc_request *req) | 313 | struct cfg80211_assoc_request *req) |
369 | { | 314 | { |
370 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 315 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
371 | int err; | 316 | int err; |
@@ -415,30 +360,10 @@ out: | |||
415 | return err; | 360 | return err; |
416 | } | 361 | } |
417 | 362 | ||
418 | int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | 363 | int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, |
419 | struct net_device *dev, | 364 | struct net_device *dev, const u8 *bssid, |
420 | struct ieee80211_channel *chan, | 365 | const u8 *ie, int ie_len, u16 reason, |
421 | const u8 *bssid, | 366 | bool local_state_change) |
422 | const u8 *ssid, int ssid_len, | ||
423 | struct cfg80211_assoc_request *req) | ||
424 | { | ||
425 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
426 | int err; | ||
427 | |||
428 | mutex_lock(&rdev->devlist_mtx); | ||
429 | wdev_lock(wdev); | ||
430 | err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, | ||
431 | ssid, ssid_len, req); | ||
432 | wdev_unlock(wdev); | ||
433 | mutex_unlock(&rdev->devlist_mtx); | ||
434 | |||
435 | return err; | ||
436 | } | ||
437 | |||
438 | int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | ||
439 | struct net_device *dev, const u8 *bssid, | ||
440 | const u8 *ie, int ie_len, u16 reason, | ||
441 | bool local_state_change) | ||
442 | { | 367 | { |
443 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 368 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
444 | struct cfg80211_deauth_request req = { | 369 | struct cfg80211_deauth_request req = { |
@@ -458,29 +383,18 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | |||
458 | return rdev_deauth(rdev, dev, &req); | 383 | return rdev_deauth(rdev, dev, &req); |
459 | } | 384 | } |
460 | 385 | ||
461 | int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | 386 | int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, |
462 | struct net_device *dev, const u8 *bssid, | 387 | struct net_device *dev, const u8 *bssid, |
463 | const u8 *ie, int ie_len, u16 reason, | 388 | const u8 *ie, int ie_len, u16 reason, |
464 | bool local_state_change) | 389 | bool local_state_change) |
465 | { | ||
466 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
467 | int err; | ||
468 | |||
469 | wdev_lock(wdev); | ||
470 | err = __cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason, | ||
471 | local_state_change); | ||
472 | wdev_unlock(wdev); | ||
473 | |||
474 | return err; | ||
475 | } | ||
476 | |||
477 | static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, | ||
478 | struct net_device *dev, const u8 *bssid, | ||
479 | const u8 *ie, int ie_len, u16 reason, | ||
480 | bool local_state_change) | ||
481 | { | 390 | { |
482 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 391 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
483 | struct cfg80211_disassoc_request req; | 392 | struct cfg80211_disassoc_request req = { |
393 | .reason_code = reason, | ||
394 | .local_state_change = local_state_change, | ||
395 | .ie = ie, | ||
396 | .ie_len = ie_len, | ||
397 | }; | ||
484 | 398 | ||
485 | ASSERT_WDEV_LOCK(wdev); | 399 | ASSERT_WDEV_LOCK(wdev); |
486 | 400 | ||
@@ -490,11 +404,6 @@ static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, | |||
490 | if (WARN(!wdev->current_bss, "sme_state=%d\n", wdev->sme_state)) | 404 | if (WARN(!wdev->current_bss, "sme_state=%d\n", wdev->sme_state)) |
491 | return -ENOTCONN; | 405 | return -ENOTCONN; |
492 | 406 | ||
493 | memset(&req, 0, sizeof(req)); | ||
494 | req.reason_code = reason; | ||
495 | req.local_state_change = local_state_change; | ||
496 | req.ie = ie; | ||
497 | req.ie_len = ie_len; | ||
498 | if (ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) | 407 | if (ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) |
499 | req.bss = &wdev->current_bss->pub; | 408 | req.bss = &wdev->current_bss->pub; |
500 | else | 409 | else |
@@ -503,44 +412,25 @@ static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, | |||
503 | return rdev_disassoc(rdev, dev, &req); | 412 | return rdev_disassoc(rdev, dev, &req); |
504 | } | 413 | } |
505 | 414 | ||
506 | int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, | ||
507 | struct net_device *dev, const u8 *bssid, | ||
508 | const u8 *ie, int ie_len, u16 reason, | ||
509 | bool local_state_change) | ||
510 | { | ||
511 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
512 | int err; | ||
513 | |||
514 | wdev_lock(wdev); | ||
515 | err = __cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason, | ||
516 | local_state_change); | ||
517 | wdev_unlock(wdev); | ||
518 | |||
519 | return err; | ||
520 | } | ||
521 | |||
522 | void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, | 415 | void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, |
523 | struct net_device *dev) | 416 | struct net_device *dev) |
524 | { | 417 | { |
525 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 418 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
526 | struct cfg80211_deauth_request req; | ||
527 | u8 bssid[ETH_ALEN]; | 419 | u8 bssid[ETH_ALEN]; |
420 | struct cfg80211_deauth_request req = { | ||
421 | .reason_code = WLAN_REASON_DEAUTH_LEAVING, | ||
422 | .bssid = bssid, | ||
423 | }; | ||
528 | 424 | ||
529 | ASSERT_WDEV_LOCK(wdev); | 425 | ASSERT_WDEV_LOCK(wdev); |
530 | 426 | ||
531 | if (!rdev->ops->deauth) | 427 | if (!rdev->ops->deauth) |
532 | return; | 428 | return; |
533 | 429 | ||
534 | memset(&req, 0, sizeof(req)); | ||
535 | req.reason_code = WLAN_REASON_DEAUTH_LEAVING; | ||
536 | req.ie = NULL; | ||
537 | req.ie_len = 0; | ||
538 | |||
539 | if (!wdev->current_bss) | 430 | if (!wdev->current_bss) |
540 | return; | 431 | return; |
541 | 432 | ||
542 | memcpy(bssid, wdev->current_bss->pub.bssid, ETH_ALEN); | 433 | memcpy(bssid, wdev->current_bss->pub.bssid, ETH_ALEN); |
543 | req.bssid = bssid; | ||
544 | rdev_deauth(rdev, dev, &req); | 434 | rdev_deauth(rdev, dev, &req); |
545 | 435 | ||
546 | if (wdev->current_bss) { | 436 | if (wdev->current_bss) { |
@@ -848,7 +738,7 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work) | |||
848 | dfs_update_channels_wk); | 738 | dfs_update_channels_wk); |
849 | wiphy = &rdev->wiphy; | 739 | wiphy = &rdev->wiphy; |
850 | 740 | ||
851 | mutex_lock(&cfg80211_mutex); | 741 | rtnl_lock(); |
852 | for (bandid = 0; bandid < IEEE80211_NUM_BANDS; bandid++) { | 742 | for (bandid = 0; bandid < IEEE80211_NUM_BANDS; bandid++) { |
853 | sband = wiphy->bands[bandid]; | 743 | sband = wiphy->bands[bandid]; |
854 | if (!sband) | 744 | if (!sband) |
@@ -881,7 +771,7 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work) | |||
881 | check_again = true; | 771 | check_again = true; |
882 | } | 772 | } |
883 | } | 773 | } |
884 | mutex_unlock(&cfg80211_mutex); | 774 | rtnl_unlock(); |
885 | 775 | ||
886 | /* reschedule if there are other channels waiting to be cleared again */ | 776 | /* reschedule if there are other channels waiting to be cleared again */ |
887 | if (check_again) | 777 | if (check_again) |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index d5aed3bb3945..31d265f36d2c 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -37,10 +37,10 @@ static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb, | |||
37 | 37 | ||
38 | /* the netlink family */ | 38 | /* the netlink family */ |
39 | static struct genl_family nl80211_fam = { | 39 | static struct genl_family nl80211_fam = { |
40 | .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */ | 40 | .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */ |
41 | .name = "nl80211", /* have users key off the name instead */ | 41 | .name = NL80211_GENL_NAME, /* have users key off the name instead */ |
42 | .hdrsize = 0, /* no private header */ | 42 | .hdrsize = 0, /* no private header */ |
43 | .version = 1, /* no particular meaning now */ | 43 | .version = 1, /* no particular meaning now */ |
44 | .maxattr = NL80211_ATTR_MAX, | 44 | .maxattr = NL80211_ATTR_MAX, |
45 | .netnsok = true, | 45 | .netnsok = true, |
46 | .pre_doit = nl80211_pre_doit, | 46 | .pre_doit = nl80211_pre_doit, |
@@ -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 */ |
@@ -378,6 +348,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
378 | [NL80211_ATTR_MDID] = { .type = NLA_U16 }, | 348 | [NL80211_ATTR_MDID] = { .type = NLA_U16 }, |
379 | [NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY, | 349 | [NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY, |
380 | .len = IEEE80211_MAX_DATA_LEN }, | 350 | .len = IEEE80211_MAX_DATA_LEN }, |
351 | [NL80211_ATTR_PEER_AID] = { .type = NLA_U16 }, | ||
381 | }; | 352 | }; |
382 | 353 | ||
383 | /* policy for the key attributes */ | 354 | /* policy for the key attributes */ |
@@ -455,7 +426,6 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb, | |||
455 | int err; | 426 | int err; |
456 | 427 | ||
457 | rtnl_lock(); | 428 | rtnl_lock(); |
458 | mutex_lock(&cfg80211_mutex); | ||
459 | 429 | ||
460 | if (!cb->args[0]) { | 430 | if (!cb->args[0]) { |
461 | err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, | 431 | err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, |
@@ -484,14 +454,12 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb, | |||
484 | *rdev = wiphy_to_dev(wiphy); | 454 | *rdev = wiphy_to_dev(wiphy); |
485 | *wdev = NULL; | 455 | *wdev = NULL; |
486 | 456 | ||
487 | mutex_lock(&(*rdev)->devlist_mtx); | ||
488 | list_for_each_entry(tmp, &(*rdev)->wdev_list, list) { | 457 | list_for_each_entry(tmp, &(*rdev)->wdev_list, list) { |
489 | if (tmp->identifier == cb->args[1]) { | 458 | if (tmp->identifier == cb->args[1]) { |
490 | *wdev = tmp; | 459 | *wdev = tmp; |
491 | break; | 460 | break; |
492 | } | 461 | } |
493 | } | 462 | } |
494 | mutex_unlock(&(*rdev)->devlist_mtx); | ||
495 | 463 | ||
496 | if (!*wdev) { | 464 | if (!*wdev) { |
497 | err = -ENODEV; | 465 | err = -ENODEV; |
@@ -499,19 +467,14 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb, | |||
499 | } | 467 | } |
500 | } | 468 | } |
501 | 469 | ||
502 | cfg80211_lock_rdev(*rdev); | ||
503 | |||
504 | mutex_unlock(&cfg80211_mutex); | ||
505 | return 0; | 470 | return 0; |
506 | out_unlock: | 471 | out_unlock: |
507 | mutex_unlock(&cfg80211_mutex); | ||
508 | rtnl_unlock(); | 472 | rtnl_unlock(); |
509 | return err; | 473 | return err; |
510 | } | 474 | } |
511 | 475 | ||
512 | static void nl80211_finish_wdev_dump(struct cfg80211_registered_device *rdev) | 476 | static void nl80211_finish_wdev_dump(struct cfg80211_registered_device *rdev) |
513 | { | 477 | { |
514 | cfg80211_unlock_rdev(rdev); | ||
515 | rtnl_unlock(); | 478 | rtnl_unlock(); |
516 | } | 479 | } |
517 | 480 | ||
@@ -1567,7 +1530,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) | |||
1567 | struct nlattr **tb = nl80211_fam.attrbuf; | 1530 | struct nlattr **tb = nl80211_fam.attrbuf; |
1568 | int res; | 1531 | int res; |
1569 | 1532 | ||
1570 | mutex_lock(&cfg80211_mutex); | 1533 | rtnl_lock(); |
1571 | res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, | 1534 | res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, |
1572 | tb, nl80211_fam.maxattr, nl80211_policy); | 1535 | tb, nl80211_fam.maxattr, nl80211_policy); |
1573 | if (res == 0) { | 1536 | if (res == 0) { |
@@ -1581,10 +1544,8 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) | |||
1581 | int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]); | 1544 | int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]); |
1582 | 1545 | ||
1583 | netdev = dev_get_by_index(sock_net(skb->sk), ifidx); | 1546 | netdev = dev_get_by_index(sock_net(skb->sk), ifidx); |
1584 | if (!netdev) { | 1547 | if (!netdev) |
1585 | mutex_unlock(&cfg80211_mutex); | ||
1586 | return -ENODEV; | 1548 | return -ENODEV; |
1587 | } | ||
1588 | if (netdev->ieee80211_ptr) { | 1549 | if (netdev->ieee80211_ptr) { |
1589 | dev = wiphy_to_dev( | 1550 | dev = wiphy_to_dev( |
1590 | netdev->ieee80211_ptr->wiphy); | 1551 | netdev->ieee80211_ptr->wiphy); |
@@ -1628,7 +1589,6 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) | |||
1628 | !skb->len && | 1589 | !skb->len && |
1629 | cb->min_dump_alloc < 4096) { | 1590 | cb->min_dump_alloc < 4096) { |
1630 | cb->min_dump_alloc = 4096; | 1591 | cb->min_dump_alloc = 4096; |
1631 | mutex_unlock(&cfg80211_mutex); | ||
1632 | return 1; | 1592 | return 1; |
1633 | } | 1593 | } |
1634 | idx--; | 1594 | idx--; |
@@ -1637,7 +1597,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) | |||
1637 | } while (cb->args[1] > 0); | 1597 | } while (cb->args[1] > 0); |
1638 | break; | 1598 | break; |
1639 | } | 1599 | } |
1640 | mutex_unlock(&cfg80211_mutex); | 1600 | rtnl_unlock(); |
1641 | 1601 | ||
1642 | cb->args[0] = idx; | 1602 | cb->args[0] = idx; |
1643 | 1603 | ||
@@ -1792,7 +1752,6 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, | |||
1792 | if (result) | 1752 | if (result) |
1793 | return result; | 1753 | return result; |
1794 | 1754 | ||
1795 | mutex_lock(&rdev->devlist_mtx); | ||
1796 | switch (iftype) { | 1755 | switch (iftype) { |
1797 | case NL80211_IFTYPE_AP: | 1756 | case NL80211_IFTYPE_AP: |
1798 | case NL80211_IFTYPE_P2P_GO: | 1757 | case NL80211_IFTYPE_P2P_GO: |
@@ -1816,7 +1775,6 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, | |||
1816 | default: | 1775 | default: |
1817 | result = -EINVAL; | 1776 | result = -EINVAL; |
1818 | } | 1777 | } |
1819 | mutex_unlock(&rdev->devlist_mtx); | ||
1820 | 1778 | ||
1821 | return result; | 1779 | return result; |
1822 | } | 1780 | } |
@@ -1865,6 +1823,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
1865 | u32 frag_threshold = 0, rts_threshold = 0; | 1823 | u32 frag_threshold = 0, rts_threshold = 0; |
1866 | u8 coverage_class = 0; | 1824 | u8 coverage_class = 0; |
1867 | 1825 | ||
1826 | ASSERT_RTNL(); | ||
1827 | |||
1868 | /* | 1828 | /* |
1869 | * Try to find the wiphy and netdev. Normally this | 1829 | * Try to find the wiphy and netdev. Normally this |
1870 | * function shouldn't need the netdev, but this is | 1830 | * function shouldn't need the netdev, but this is |
@@ -1874,31 +1834,25 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
1874 | * also passed a netdev to set_wiphy, so that it is | 1834 | * also passed a netdev to set_wiphy, so that it is |
1875 | * possible to let that go to the right netdev! | 1835 | * possible to let that go to the right netdev! |
1876 | */ | 1836 | */ |
1877 | mutex_lock(&cfg80211_mutex); | ||
1878 | 1837 | ||
1879 | if (info->attrs[NL80211_ATTR_IFINDEX]) { | 1838 | if (info->attrs[NL80211_ATTR_IFINDEX]) { |
1880 | int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]); | 1839 | int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]); |
1881 | 1840 | ||
1882 | netdev = dev_get_by_index(genl_info_net(info), ifindex); | 1841 | netdev = dev_get_by_index(genl_info_net(info), ifindex); |
1883 | if (netdev && netdev->ieee80211_ptr) { | 1842 | if (netdev && netdev->ieee80211_ptr) |
1884 | rdev = wiphy_to_dev(netdev->ieee80211_ptr->wiphy); | 1843 | rdev = wiphy_to_dev(netdev->ieee80211_ptr->wiphy); |
1885 | mutex_lock(&rdev->mtx); | 1844 | else |
1886 | } else | ||
1887 | netdev = NULL; | 1845 | netdev = NULL; |
1888 | } | 1846 | } |
1889 | 1847 | ||
1890 | if (!netdev) { | 1848 | if (!netdev) { |
1891 | rdev = __cfg80211_rdev_from_attrs(genl_info_net(info), | 1849 | rdev = __cfg80211_rdev_from_attrs(genl_info_net(info), |
1892 | info->attrs); | 1850 | info->attrs); |
1893 | if (IS_ERR(rdev)) { | 1851 | if (IS_ERR(rdev)) |
1894 | mutex_unlock(&cfg80211_mutex); | ||
1895 | return PTR_ERR(rdev); | 1852 | return PTR_ERR(rdev); |
1896 | } | ||
1897 | wdev = NULL; | 1853 | wdev = NULL; |
1898 | netdev = NULL; | 1854 | netdev = NULL; |
1899 | result = 0; | 1855 | result = 0; |
1900 | |||
1901 | mutex_lock(&rdev->mtx); | ||
1902 | } else | 1856 | } else |
1903 | wdev = netdev->ieee80211_ptr; | 1857 | wdev = netdev->ieee80211_ptr; |
1904 | 1858 | ||
@@ -1911,8 +1865,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
1911 | result = cfg80211_dev_rename( | 1865 | result = cfg80211_dev_rename( |
1912 | rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME])); | 1866 | rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME])); |
1913 | 1867 | ||
1914 | mutex_unlock(&cfg80211_mutex); | ||
1915 | |||
1916 | if (result) | 1868 | if (result) |
1917 | goto bad_res; | 1869 | goto bad_res; |
1918 | 1870 | ||
@@ -2119,7 +2071,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
2119 | } | 2071 | } |
2120 | 2072 | ||
2121 | bad_res: | 2073 | bad_res: |
2122 | mutex_unlock(&rdev->mtx); | ||
2123 | if (netdev) | 2074 | if (netdev) |
2124 | dev_put(netdev); | 2075 | dev_put(netdev); |
2125 | return result; | 2076 | return result; |
@@ -2217,7 +2168,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback * | |||
2217 | struct cfg80211_registered_device *rdev; | 2168 | struct cfg80211_registered_device *rdev; |
2218 | struct wireless_dev *wdev; | 2169 | struct wireless_dev *wdev; |
2219 | 2170 | ||
2220 | mutex_lock(&cfg80211_mutex); | 2171 | rtnl_lock(); |
2221 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) { | 2172 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) { |
2222 | if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk))) | 2173 | if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk))) |
2223 | continue; | 2174 | continue; |
@@ -2227,7 +2178,6 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback * | |||
2227 | } | 2178 | } |
2228 | if_idx = 0; | 2179 | if_idx = 0; |
2229 | 2180 | ||
2230 | mutex_lock(&rdev->devlist_mtx); | ||
2231 | list_for_each_entry(wdev, &rdev->wdev_list, list) { | 2181 | list_for_each_entry(wdev, &rdev->wdev_list, list) { |
2232 | if (if_idx < if_start) { | 2182 | if (if_idx < if_start) { |
2233 | if_idx++; | 2183 | if_idx++; |
@@ -2236,17 +2186,15 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback * | |||
2236 | if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).portid, | 2186 | if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).portid, |
2237 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | 2187 | cb->nlh->nlmsg_seq, NLM_F_MULTI, |
2238 | rdev, wdev) < 0) { | 2188 | rdev, wdev) < 0) { |
2239 | mutex_unlock(&rdev->devlist_mtx); | ||
2240 | goto out; | 2189 | goto out; |
2241 | } | 2190 | } |
2242 | if_idx++; | 2191 | if_idx++; |
2243 | } | 2192 | } |
2244 | mutex_unlock(&rdev->devlist_mtx); | ||
2245 | 2193 | ||
2246 | wp_idx++; | 2194 | wp_idx++; |
2247 | } | 2195 | } |
2248 | out: | 2196 | out: |
2249 | mutex_unlock(&cfg80211_mutex); | 2197 | rtnl_unlock(); |
2250 | 2198 | ||
2251 | cb->args[0] = wp_idx; | 2199 | cb->args[0] = wp_idx; |
2252 | cb->args[1] = if_idx; | 2200 | cb->args[1] = if_idx; |
@@ -2279,6 +2227,7 @@ static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = { | |||
2279 | [NL80211_MNTR_FLAG_CONTROL] = { .type = NLA_FLAG }, | 2227 | [NL80211_MNTR_FLAG_CONTROL] = { .type = NLA_FLAG }, |
2280 | [NL80211_MNTR_FLAG_OTHER_BSS] = { .type = NLA_FLAG }, | 2228 | [NL80211_MNTR_FLAG_OTHER_BSS] = { .type = NLA_FLAG }, |
2281 | [NL80211_MNTR_FLAG_COOK_FRAMES] = { .type = NLA_FLAG }, | 2229 | [NL80211_MNTR_FLAG_COOK_FRAMES] = { .type = NLA_FLAG }, |
2230 | [NL80211_MNTR_FLAG_ACTIVE] = { .type = NLA_FLAG }, | ||
2282 | }; | 2231 | }; |
2283 | 2232 | ||
2284 | static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags) | 2233 | static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags) |
@@ -2390,6 +2339,10 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) | |||
2390 | change = true; | 2339 | change = true; |
2391 | } | 2340 | } |
2392 | 2341 | ||
2342 | if (flags && (*flags & NL80211_MNTR_FLAG_ACTIVE) && | ||
2343 | !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR)) | ||
2344 | return -EOPNOTSUPP; | ||
2345 | |||
2393 | if (change) | 2346 | if (change) |
2394 | err = cfg80211_change_iface(rdev, dev, ntype, flags, ¶ms); | 2347 | err = cfg80211_change_iface(rdev, dev, ntype, flags, ¶ms); |
2395 | else | 2348 | else |
@@ -2447,6 +2400,11 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) | |||
2447 | err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? | 2400 | err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? |
2448 | info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL, | 2401 | info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL, |
2449 | &flags); | 2402 | &flags); |
2403 | |||
2404 | if (!err && (flags & NL80211_MNTR_FLAG_ACTIVE) && | ||
2405 | !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR)) | ||
2406 | return -EOPNOTSUPP; | ||
2407 | |||
2450 | wdev = rdev_add_virtual_intf(rdev, | 2408 | wdev = rdev_add_virtual_intf(rdev, |
2451 | nla_data(info->attrs[NL80211_ATTR_IFNAME]), | 2409 | nla_data(info->attrs[NL80211_ATTR_IFNAME]), |
2452 | type, err ? NULL : &flags, ¶ms); | 2410 | type, err ? NULL : &flags, ¶ms); |
@@ -2479,11 +2437,9 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) | |||
2479 | INIT_LIST_HEAD(&wdev->mgmt_registrations); | 2437 | INIT_LIST_HEAD(&wdev->mgmt_registrations); |
2480 | spin_lock_init(&wdev->mgmt_registrations_lock); | 2438 | spin_lock_init(&wdev->mgmt_registrations_lock); |
2481 | 2439 | ||
2482 | mutex_lock(&rdev->devlist_mtx); | ||
2483 | wdev->identifier = ++rdev->wdev_id; | 2440 | wdev->identifier = ++rdev->wdev_id; |
2484 | list_add_rcu(&wdev->list, &rdev->wdev_list); | 2441 | list_add_rcu(&wdev->list, &rdev->wdev_list); |
2485 | rdev->devlist_generation++; | 2442 | rdev->devlist_generation++; |
2486 | mutex_unlock(&rdev->devlist_mtx); | ||
2487 | break; | 2443 | break; |
2488 | default: | 2444 | default: |
2489 | break; | 2445 | break; |
@@ -2992,8 +2948,6 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev, | |||
2992 | struct wireless_dev *wdev; | 2948 | struct wireless_dev *wdev; |
2993 | bool ret = false; | 2949 | bool ret = false; |
2994 | 2950 | ||
2995 | mutex_lock(&rdev->devlist_mtx); | ||
2996 | |||
2997 | list_for_each_entry(wdev, &rdev->wdev_list, list) { | 2951 | list_for_each_entry(wdev, &rdev->wdev_list, list) { |
2998 | if (wdev->iftype != NL80211_IFTYPE_AP && | 2952 | if (wdev->iftype != NL80211_IFTYPE_AP && |
2999 | wdev->iftype != NL80211_IFTYPE_P2P_GO) | 2953 | wdev->iftype != NL80211_IFTYPE_P2P_GO) |
@@ -3007,8 +2961,6 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev, | |||
3007 | break; | 2961 | break; |
3008 | } | 2962 | } |
3009 | 2963 | ||
3010 | mutex_unlock(&rdev->devlist_mtx); | ||
3011 | |||
3012 | return ret; | 2964 | return ret; |
3013 | } | 2965 | } |
3014 | 2966 | ||
@@ -3170,13 +3122,10 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) | |||
3170 | params.radar_required = true; | 3122 | params.radar_required = true; |
3171 | } | 3123 | } |
3172 | 3124 | ||
3173 | mutex_lock(&rdev->devlist_mtx); | ||
3174 | err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, | 3125 | err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, |
3175 | params.chandef.chan, | 3126 | params.chandef.chan, |
3176 | CHAN_MODE_SHARED, | 3127 | CHAN_MODE_SHARED, |
3177 | radar_detect_width); | 3128 | radar_detect_width); |
3178 | mutex_unlock(&rdev->devlist_mtx); | ||
3179 | |||
3180 | if (err) | 3129 | if (err) |
3181 | return err; | 3130 | return err; |
3182 | 3131 | ||
@@ -3376,6 +3325,32 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, | |||
3376 | return true; | 3325 | return true; |
3377 | } | 3326 | } |
3378 | 3327 | ||
3328 | static bool nl80211_put_signal(struct sk_buff *msg, u8 mask, s8 *signal, | ||
3329 | int id) | ||
3330 | { | ||
3331 | void *attr; | ||
3332 | int i = 0; | ||
3333 | |||
3334 | if (!mask) | ||
3335 | return true; | ||
3336 | |||
3337 | attr = nla_nest_start(msg, id); | ||
3338 | if (!attr) | ||
3339 | return false; | ||
3340 | |||
3341 | for (i = 0; i < IEEE80211_MAX_CHAINS; i++) { | ||
3342 | if (!(mask & BIT(i))) | ||
3343 | continue; | ||
3344 | |||
3345 | if (nla_put_u8(msg, i, signal[i])) | ||
3346 | return false; | ||
3347 | } | ||
3348 | |||
3349 | nla_nest_end(msg, attr); | ||
3350 | |||
3351 | return true; | ||
3352 | } | ||
3353 | |||
3379 | static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq, | 3354 | static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq, |
3380 | int flags, | 3355 | int flags, |
3381 | struct cfg80211_registered_device *rdev, | 3356 | struct cfg80211_registered_device *rdev, |
@@ -3447,6 +3422,18 @@ static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq, | |||
3447 | default: | 3422 | default: |
3448 | break; | 3423 | break; |
3449 | } | 3424 | } |
3425 | if (sinfo->filled & STATION_INFO_CHAIN_SIGNAL) { | ||
3426 | if (!nl80211_put_signal(msg, sinfo->chains, | ||
3427 | sinfo->chain_signal, | ||
3428 | NL80211_STA_INFO_CHAIN_SIGNAL)) | ||
3429 | goto nla_put_failure; | ||
3430 | } | ||
3431 | if (sinfo->filled & STATION_INFO_CHAIN_SIGNAL_AVG) { | ||
3432 | if (!nl80211_put_signal(msg, sinfo->chains, | ||
3433 | sinfo->chain_signal_avg, | ||
3434 | NL80211_STA_INFO_CHAIN_SIGNAL_AVG)) | ||
3435 | goto nla_put_failure; | ||
3436 | } | ||
3450 | if (sinfo->filled & STATION_INFO_TX_BITRATE) { | 3437 | if (sinfo->filled & STATION_INFO_TX_BITRATE) { |
3451 | if (!nl80211_put_sta_rate(msg, &sinfo->txrate, | 3438 | if (!nl80211_put_sta_rate(msg, &sinfo->txrate, |
3452 | NL80211_STA_INFO_TX_BITRATE)) | 3439 | NL80211_STA_INFO_TX_BITRATE)) |
@@ -3834,6 +3821,8 @@ static int nl80211_set_station_tdls(struct genl_info *info, | |||
3834 | struct station_parameters *params) | 3821 | struct station_parameters *params) |
3835 | { | 3822 | { |
3836 | /* Dummy STA entry gets updated once the peer capabilities are known */ | 3823 | /* Dummy STA entry gets updated once the peer capabilities are known */ |
3824 | if (info->attrs[NL80211_ATTR_PEER_AID]) | ||
3825 | params->aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]); | ||
3837 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) | 3826 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) |
3838 | params->ht_capa = | 3827 | params->ht_capa = |
3839 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); | 3828 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); |
@@ -3974,7 +3963,8 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
3974 | if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) | 3963 | if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) |
3975 | return -EINVAL; | 3964 | return -EINVAL; |
3976 | 3965 | ||
3977 | if (!info->attrs[NL80211_ATTR_STA_AID]) | 3966 | if (!info->attrs[NL80211_ATTR_STA_AID] && |
3967 | !info->attrs[NL80211_ATTR_PEER_AID]) | ||
3978 | return -EINVAL; | 3968 | return -EINVAL; |
3979 | 3969 | ||
3980 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | 3970 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); |
@@ -3985,7 +3975,10 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
3985 | params.listen_interval = | 3975 | params.listen_interval = |
3986 | nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); | 3976 | nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); |
3987 | 3977 | ||
3988 | params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); | 3978 | if (info->attrs[NL80211_ATTR_STA_AID]) |
3979 | params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); | ||
3980 | else | ||
3981 | params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]); | ||
3989 | if (!params.aid || params.aid > IEEE80211_MAX_AID) | 3982 | if (!params.aid || params.aid > IEEE80211_MAX_AID) |
3990 | return -EINVAL; | 3983 | return -EINVAL; |
3991 | 3984 | ||
@@ -4634,6 +4627,7 @@ static const struct nla_policy | |||
4634 | [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 }, | 4627 | [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 }, |
4635 | [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 }, | 4628 | [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 }, |
4636 | [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG }, | 4629 | [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG }, |
4630 | [NL80211_MESH_SETUP_AUTH_PROTOCOL] = { .type = NLA_U8 }, | ||
4637 | [NL80211_MESH_SETUP_USERSPACE_MPM] = { .type = NLA_FLAG }, | 4631 | [NL80211_MESH_SETUP_USERSPACE_MPM] = { .type = NLA_FLAG }, |
4638 | [NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY, | 4632 | [NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY, |
4639 | .len = IEEE80211_MAX_DATA_LEN }, | 4633 | .len = IEEE80211_MAX_DATA_LEN }, |
@@ -4819,6 +4813,13 @@ static int nl80211_parse_mesh_setup(struct genl_info *info, | |||
4819 | if (setup->is_secure) | 4813 | if (setup->is_secure) |
4820 | setup->user_mpm = true; | 4814 | setup->user_mpm = true; |
4821 | 4815 | ||
4816 | if (tb[NL80211_MESH_SETUP_AUTH_PROTOCOL]) { | ||
4817 | if (!setup->user_mpm) | ||
4818 | return -EINVAL; | ||
4819 | setup->auth_id = | ||
4820 | nla_get_u8(tb[NL80211_MESH_SETUP_AUTH_PROTOCOL]); | ||
4821 | } | ||
4822 | |||
4822 | return 0; | 4823 | return 0; |
4823 | } | 4824 | } |
4824 | 4825 | ||
@@ -4861,18 +4862,13 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) | |||
4861 | void *hdr = NULL; | 4862 | void *hdr = NULL; |
4862 | struct nlattr *nl_reg_rules; | 4863 | struct nlattr *nl_reg_rules; |
4863 | unsigned int i; | 4864 | unsigned int i; |
4864 | int err = -EINVAL; | ||
4865 | |||
4866 | mutex_lock(&cfg80211_mutex); | ||
4867 | 4865 | ||
4868 | if (!cfg80211_regdomain) | 4866 | if (!cfg80211_regdomain) |
4869 | goto out; | 4867 | return -EINVAL; |
4870 | 4868 | ||
4871 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 4869 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
4872 | if (!msg) { | 4870 | if (!msg) |
4873 | err = -ENOBUFS; | 4871 | return -ENOBUFS; |
4874 | goto out; | ||
4875 | } | ||
4876 | 4872 | ||
4877 | hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0, | 4873 | hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0, |
4878 | NL80211_CMD_GET_REG); | 4874 | NL80211_CMD_GET_REG); |
@@ -4931,8 +4927,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) | |||
4931 | nla_nest_end(msg, nl_reg_rules); | 4927 | nla_nest_end(msg, nl_reg_rules); |
4932 | 4928 | ||
4933 | genlmsg_end(msg, hdr); | 4929 | genlmsg_end(msg, hdr); |
4934 | err = genlmsg_reply(msg, info); | 4930 | return genlmsg_reply(msg, info); |
4935 | goto out; | ||
4936 | 4931 | ||
4937 | nla_put_failure_rcu: | 4932 | nla_put_failure_rcu: |
4938 | rcu_read_unlock(); | 4933 | rcu_read_unlock(); |
@@ -4940,10 +4935,7 @@ nla_put_failure: | |||
4940 | genlmsg_cancel(msg, hdr); | 4935 | genlmsg_cancel(msg, hdr); |
4941 | put_failure: | 4936 | put_failure: |
4942 | nlmsg_free(msg); | 4937 | nlmsg_free(msg); |
4943 | err = -EMSGSIZE; | 4938 | return -EMSGSIZE; |
4944 | out: | ||
4945 | mutex_unlock(&cfg80211_mutex); | ||
4946 | return err; | ||
4947 | } | 4939 | } |
4948 | 4940 | ||
4949 | static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) | 4941 | static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) |
@@ -5009,12 +5001,9 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) | |||
5009 | } | 5001 | } |
5010 | } | 5002 | } |
5011 | 5003 | ||
5012 | mutex_lock(&cfg80211_mutex); | ||
5013 | |||
5014 | r = set_regdom(rd); | 5004 | r = set_regdom(rd); |
5015 | /* set_regdom took ownership */ | 5005 | /* set_regdom took ownership */ |
5016 | rd = NULL; | 5006 | rd = NULL; |
5017 | mutex_unlock(&cfg80211_mutex); | ||
5018 | 5007 | ||
5019 | bad_reg: | 5008 | bad_reg: |
5020 | kfree(rd); | 5009 | kfree(rd); |
@@ -5064,7 +5053,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
5064 | if (!rdev->ops->scan) | 5053 | if (!rdev->ops->scan) |
5065 | return -EOPNOTSUPP; | 5054 | return -EOPNOTSUPP; |
5066 | 5055 | ||
5067 | mutex_lock(&rdev->sched_scan_mtx); | ||
5068 | if (rdev->scan_req) { | 5056 | if (rdev->scan_req) { |
5069 | err = -EBUSY; | 5057 | err = -EBUSY; |
5070 | goto unlock; | 5058 | goto unlock; |
@@ -5250,7 +5238,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
5250 | } | 5238 | } |
5251 | 5239 | ||
5252 | unlock: | 5240 | unlock: |
5253 | mutex_unlock(&rdev->sched_scan_mtx); | ||
5254 | return err; | 5241 | return err; |
5255 | } | 5242 | } |
5256 | 5243 | ||
@@ -5322,8 +5309,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, | |||
5322 | if (ie_len > wiphy->max_sched_scan_ie_len) | 5309 | if (ie_len > wiphy->max_sched_scan_ie_len) |
5323 | return -EINVAL; | 5310 | return -EINVAL; |
5324 | 5311 | ||
5325 | mutex_lock(&rdev->sched_scan_mtx); | ||
5326 | |||
5327 | if (rdev->sched_scan_req) { | 5312 | if (rdev->sched_scan_req) { |
5328 | err = -EINPROGRESS; | 5313 | err = -EINPROGRESS; |
5329 | goto out; | 5314 | goto out; |
@@ -5491,7 +5476,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, | |||
5491 | out_free: | 5476 | out_free: |
5492 | kfree(request); | 5477 | kfree(request); |
5493 | out: | 5478 | out: |
5494 | mutex_unlock(&rdev->sched_scan_mtx); | ||
5495 | return err; | 5479 | return err; |
5496 | } | 5480 | } |
5497 | 5481 | ||
@@ -5499,17 +5483,12 @@ static int nl80211_stop_sched_scan(struct sk_buff *skb, | |||
5499 | struct genl_info *info) | 5483 | struct genl_info *info) |
5500 | { | 5484 | { |
5501 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 5485 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
5502 | int err; | ||
5503 | 5486 | ||
5504 | if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) || | 5487 | if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) || |
5505 | !rdev->ops->sched_scan_stop) | 5488 | !rdev->ops->sched_scan_stop) |
5506 | return -EOPNOTSUPP; | 5489 | return -EOPNOTSUPP; |
5507 | 5490 | ||
5508 | mutex_lock(&rdev->sched_scan_mtx); | 5491 | return __cfg80211_stop_sched_scan(rdev, false); |
5509 | err = __cfg80211_stop_sched_scan(rdev, false); | ||
5510 | mutex_unlock(&rdev->sched_scan_mtx); | ||
5511 | |||
5512 | return err; | ||
5513 | } | 5492 | } |
5514 | 5493 | ||
5515 | static int nl80211_start_radar_detection(struct sk_buff *skb, | 5494 | static int nl80211_start_radar_detection(struct sk_buff *skb, |
@@ -5541,12 +5520,11 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, | |||
5541 | if (!rdev->ops->start_radar_detection) | 5520 | if (!rdev->ops->start_radar_detection) |
5542 | return -EOPNOTSUPP; | 5521 | return -EOPNOTSUPP; |
5543 | 5522 | ||
5544 | mutex_lock(&rdev->devlist_mtx); | ||
5545 | err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, | 5523 | err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, |
5546 | chandef.chan, CHAN_MODE_SHARED, | 5524 | chandef.chan, CHAN_MODE_SHARED, |
5547 | BIT(chandef.width)); | 5525 | BIT(chandef.width)); |
5548 | if (err) | 5526 | if (err) |
5549 | goto err_locked; | 5527 | return err; |
5550 | 5528 | ||
5551 | err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef); | 5529 | err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef); |
5552 | if (!err) { | 5530 | if (!err) { |
@@ -5554,9 +5532,6 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, | |||
5554 | wdev->cac_started = true; | 5532 | wdev->cac_started = true; |
5555 | wdev->cac_start_time = jiffies; | 5533 | wdev->cac_start_time = jiffies; |
5556 | } | 5534 | } |
5557 | err_locked: | ||
5558 | mutex_unlock(&rdev->devlist_mtx); | ||
5559 | |||
5560 | return err; | 5535 | return err; |
5561 | } | 5536 | } |
5562 | 5537 | ||
@@ -5939,10 +5914,13 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | |||
5939 | if (local_state_change) | 5914 | if (local_state_change) |
5940 | return 0; | 5915 | return 0; |
5941 | 5916 | ||
5942 | return cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, | 5917 | wdev_lock(dev->ieee80211_ptr); |
5943 | ssid, ssid_len, ie, ie_len, | 5918 | err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, |
5944 | key.p.key, key.p.key_len, key.idx, | 5919 | ssid, ssid_len, ie, ie_len, |
5945 | sae_data, sae_data_len); | 5920 | key.p.key, key.p.key_len, key.idx, |
5921 | sae_data, sae_data_len); | ||
5922 | wdev_unlock(dev->ieee80211_ptr); | ||
5923 | return err; | ||
5946 | } | 5924 | } |
5947 | 5925 | ||
5948 | static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, | 5926 | static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, |
@@ -6109,9 +6087,12 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) | |||
6109 | } | 6087 | } |
6110 | 6088 | ||
6111 | err = nl80211_crypto_settings(rdev, info, &req.crypto, 1); | 6089 | err = nl80211_crypto_settings(rdev, info, &req.crypto, 1); |
6112 | if (!err) | 6090 | if (!err) { |
6091 | wdev_lock(dev->ieee80211_ptr); | ||
6113 | err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, | 6092 | err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, |
6114 | ssid, ssid_len, &req); | 6093 | ssid, ssid_len, &req); |
6094 | wdev_unlock(dev->ieee80211_ptr); | ||
6095 | } | ||
6115 | 6096 | ||
6116 | return err; | 6097 | return err; |
6117 | } | 6098 | } |
@@ -6121,7 +6102,7 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) | |||
6121 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 6102 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
6122 | struct net_device *dev = info->user_ptr[1]; | 6103 | struct net_device *dev = info->user_ptr[1]; |
6123 | const u8 *ie = NULL, *bssid; | 6104 | const u8 *ie = NULL, *bssid; |
6124 | int ie_len = 0; | 6105 | int ie_len = 0, err; |
6125 | u16 reason_code; | 6106 | u16 reason_code; |
6126 | bool local_state_change; | 6107 | bool local_state_change; |
6127 | 6108 | ||
@@ -6156,8 +6137,11 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) | |||
6156 | 6137 | ||
6157 | local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; | 6138 | local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; |
6158 | 6139 | ||
6159 | return cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code, | 6140 | wdev_lock(dev->ieee80211_ptr); |
6160 | local_state_change); | 6141 | err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code, |
6142 | local_state_change); | ||
6143 | wdev_unlock(dev->ieee80211_ptr); | ||
6144 | return err; | ||
6161 | } | 6145 | } |
6162 | 6146 | ||
6163 | static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) | 6147 | static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) |
@@ -6165,7 +6149,7 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) | |||
6165 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 6149 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
6166 | struct net_device *dev = info->user_ptr[1]; | 6150 | struct net_device *dev = info->user_ptr[1]; |
6167 | const u8 *ie = NULL, *bssid; | 6151 | const u8 *ie = NULL, *bssid; |
6168 | int ie_len = 0; | 6152 | int ie_len = 0, err; |
6169 | u16 reason_code; | 6153 | u16 reason_code; |
6170 | bool local_state_change; | 6154 | bool local_state_change; |
6171 | 6155 | ||
@@ -6200,8 +6184,11 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) | |||
6200 | 6184 | ||
6201 | local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; | 6185 | local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; |
6202 | 6186 | ||
6203 | return cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code, | 6187 | wdev_lock(dev->ieee80211_ptr); |
6204 | local_state_change); | 6188 | err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code, |
6189 | local_state_change); | ||
6190 | wdev_unlock(dev->ieee80211_ptr); | ||
6191 | return err; | ||
6205 | } | 6192 | } |
6206 | 6193 | ||
6207 | static bool | 6194 | static bool |
@@ -6419,6 +6406,8 @@ static int nl80211_testmode_dump(struct sk_buff *skb, | |||
6419 | void *data = NULL; | 6406 | void *data = NULL; |
6420 | int data_len = 0; | 6407 | int data_len = 0; |
6421 | 6408 | ||
6409 | rtnl_lock(); | ||
6410 | |||
6422 | if (cb->args[0]) { | 6411 | if (cb->args[0]) { |
6423 | /* | 6412 | /* |
6424 | * 0 is a valid index, but not valid for args[0], | 6413 | * 0 is a valid index, but not valid for args[0], |
@@ -6430,18 +6419,16 @@ static int nl80211_testmode_dump(struct sk_buff *skb, | |||
6430 | nl80211_fam.attrbuf, nl80211_fam.maxattr, | 6419 | nl80211_fam.attrbuf, nl80211_fam.maxattr, |
6431 | nl80211_policy); | 6420 | nl80211_policy); |
6432 | if (err) | 6421 | if (err) |
6433 | return err; | 6422 | goto out_err; |
6434 | 6423 | ||
6435 | mutex_lock(&cfg80211_mutex); | ||
6436 | rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), | 6424 | rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), |
6437 | nl80211_fam.attrbuf); | 6425 | nl80211_fam.attrbuf); |
6438 | if (IS_ERR(rdev)) { | 6426 | if (IS_ERR(rdev)) { |
6439 | mutex_unlock(&cfg80211_mutex); | 6427 | err = PTR_ERR(rdev); |
6440 | return PTR_ERR(rdev); | 6428 | goto out_err; |
6441 | } | 6429 | } |
6442 | phy_idx = rdev->wiphy_idx; | 6430 | phy_idx = rdev->wiphy_idx; |
6443 | rdev = NULL; | 6431 | rdev = NULL; |
6444 | mutex_unlock(&cfg80211_mutex); | ||
6445 | 6432 | ||
6446 | if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA]) | 6433 | if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA]) |
6447 | cb->args[1] = | 6434 | cb->args[1] = |
@@ -6453,14 +6440,11 @@ static int nl80211_testmode_dump(struct sk_buff *skb, | |||
6453 | data_len = nla_len((void *)cb->args[1]); | 6440 | data_len = nla_len((void *)cb->args[1]); |
6454 | } | 6441 | } |
6455 | 6442 | ||
6456 | mutex_lock(&cfg80211_mutex); | ||
6457 | rdev = cfg80211_rdev_by_wiphy_idx(phy_idx); | 6443 | rdev = cfg80211_rdev_by_wiphy_idx(phy_idx); |
6458 | if (!rdev) { | 6444 | if (!rdev) { |
6459 | mutex_unlock(&cfg80211_mutex); | 6445 | err = -ENOENT; |
6460 | return -ENOENT; | 6446 | goto out_err; |
6461 | } | 6447 | } |
6462 | cfg80211_lock_rdev(rdev); | ||
6463 | mutex_unlock(&cfg80211_mutex); | ||
6464 | 6448 | ||
6465 | if (!rdev->ops->testmode_dump) { | 6449 | if (!rdev->ops->testmode_dump) { |
6466 | err = -EOPNOTSUPP; | 6450 | err = -EOPNOTSUPP; |
@@ -6501,7 +6485,7 @@ static int nl80211_testmode_dump(struct sk_buff *skb, | |||
6501 | /* see above */ | 6485 | /* see above */ |
6502 | cb->args[0] = phy_idx + 1; | 6486 | cb->args[0] = phy_idx + 1; |
6503 | out_err: | 6487 | out_err: |
6504 | cfg80211_unlock_rdev(rdev); | 6488 | rtnl_unlock(); |
6505 | return err; | 6489 | return err; |
6506 | } | 6490 | } |
6507 | 6491 | ||
@@ -6709,7 +6693,9 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) | |||
6709 | sizeof(connect.vht_capa)); | 6693 | sizeof(connect.vht_capa)); |
6710 | } | 6694 | } |
6711 | 6695 | ||
6712 | err = cfg80211_connect(rdev, dev, &connect, connkeys); | 6696 | wdev_lock(dev->ieee80211_ptr); |
6697 | err = cfg80211_connect(rdev, dev, &connect, connkeys, NULL); | ||
6698 | wdev_unlock(dev->ieee80211_ptr); | ||
6713 | if (err) | 6699 | if (err) |
6714 | kfree(connkeys); | 6700 | kfree(connkeys); |
6715 | return err; | 6701 | return err; |
@@ -6720,6 +6706,7 @@ static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info) | |||
6720 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 6706 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
6721 | struct net_device *dev = info->user_ptr[1]; | 6707 | struct net_device *dev = info->user_ptr[1]; |
6722 | u16 reason; | 6708 | u16 reason; |
6709 | int ret; | ||
6723 | 6710 | ||
6724 | if (!info->attrs[NL80211_ATTR_REASON_CODE]) | 6711 | if (!info->attrs[NL80211_ATTR_REASON_CODE]) |
6725 | reason = WLAN_REASON_DEAUTH_LEAVING; | 6712 | reason = WLAN_REASON_DEAUTH_LEAVING; |
@@ -6733,7 +6720,10 @@ static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info) | |||
6733 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) | 6720 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) |
6734 | return -EOPNOTSUPP; | 6721 | return -EOPNOTSUPP; |
6735 | 6722 | ||
6736 | return cfg80211_disconnect(rdev, dev, reason, true); | 6723 | wdev_lock(dev->ieee80211_ptr); |
6724 | ret = cfg80211_disconnect(rdev, dev, reason, true); | ||
6725 | wdev_unlock(dev->ieee80211_ptr); | ||
6726 | return ret; | ||
6737 | } | 6727 | } |
6738 | 6728 | ||
6739 | static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info) | 6729 | static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info) |
@@ -7509,28 +7499,29 @@ static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info) | |||
7509 | static int nl80211_send_wowlan_patterns(struct sk_buff *msg, | 7499 | static int nl80211_send_wowlan_patterns(struct sk_buff *msg, |
7510 | struct cfg80211_registered_device *rdev) | 7500 | struct cfg80211_registered_device *rdev) |
7511 | { | 7501 | { |
7502 | struct cfg80211_wowlan *wowlan = rdev->wiphy.wowlan_config; | ||
7512 | struct nlattr *nl_pats, *nl_pat; | 7503 | struct nlattr *nl_pats, *nl_pat; |
7513 | int i, pat_len; | 7504 | int i, pat_len; |
7514 | 7505 | ||
7515 | if (!rdev->wowlan->n_patterns) | 7506 | if (!wowlan->n_patterns) |
7516 | return 0; | 7507 | return 0; |
7517 | 7508 | ||
7518 | nl_pats = nla_nest_start(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN); | 7509 | nl_pats = nla_nest_start(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN); |
7519 | if (!nl_pats) | 7510 | if (!nl_pats) |
7520 | return -ENOBUFS; | 7511 | return -ENOBUFS; |
7521 | 7512 | ||
7522 | for (i = 0; i < rdev->wowlan->n_patterns; i++) { | 7513 | for (i = 0; i < wowlan->n_patterns; i++) { |
7523 | nl_pat = nla_nest_start(msg, i + 1); | 7514 | nl_pat = nla_nest_start(msg, i + 1); |
7524 | if (!nl_pat) | 7515 | if (!nl_pat) |
7525 | return -ENOBUFS; | 7516 | return -ENOBUFS; |
7526 | pat_len = rdev->wowlan->patterns[i].pattern_len; | 7517 | pat_len = wowlan->patterns[i].pattern_len; |
7527 | if (nla_put(msg, NL80211_WOWLAN_PKTPAT_MASK, | 7518 | if (nla_put(msg, NL80211_WOWLAN_PKTPAT_MASK, |
7528 | DIV_ROUND_UP(pat_len, 8), | 7519 | DIV_ROUND_UP(pat_len, 8), |
7529 | rdev->wowlan->patterns[i].mask) || | 7520 | wowlan->patterns[i].mask) || |
7530 | nla_put(msg, NL80211_WOWLAN_PKTPAT_PATTERN, | 7521 | nla_put(msg, NL80211_WOWLAN_PKTPAT_PATTERN, |
7531 | pat_len, rdev->wowlan->patterns[i].pattern) || | 7522 | pat_len, wowlan->patterns[i].pattern) || |
7532 | nla_put_u32(msg, NL80211_WOWLAN_PKTPAT_OFFSET, | 7523 | nla_put_u32(msg, NL80211_WOWLAN_PKTPAT_OFFSET, |
7533 | rdev->wowlan->patterns[i].pkt_offset)) | 7524 | wowlan->patterns[i].pkt_offset)) |
7534 | return -ENOBUFS; | 7525 | return -ENOBUFS; |
7535 | nla_nest_end(msg, nl_pat); | 7526 | nla_nest_end(msg, nl_pat); |
7536 | } | 7527 | } |
@@ -7593,12 +7584,12 @@ static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
7593 | !rdev->wiphy.wowlan.tcp) | 7584 | !rdev->wiphy.wowlan.tcp) |
7594 | return -EOPNOTSUPP; | 7585 | return -EOPNOTSUPP; |
7595 | 7586 | ||
7596 | if (rdev->wowlan && rdev->wowlan->tcp) { | 7587 | if (rdev->wiphy.wowlan_config && rdev->wiphy.wowlan_config->tcp) { |
7597 | /* adjust size to have room for all the data */ | 7588 | /* adjust size to have room for all the data */ |
7598 | size += rdev->wowlan->tcp->tokens_size + | 7589 | size += rdev->wiphy.wowlan_config->tcp->tokens_size + |
7599 | rdev->wowlan->tcp->payload_len + | 7590 | rdev->wiphy.wowlan_config->tcp->payload_len + |
7600 | rdev->wowlan->tcp->wake_len + | 7591 | rdev->wiphy.wowlan_config->tcp->wake_len + |
7601 | rdev->wowlan->tcp->wake_len / 8; | 7592 | rdev->wiphy.wowlan_config->tcp->wake_len / 8; |
7602 | } | 7593 | } |
7603 | 7594 | ||
7604 | msg = nlmsg_new(size, GFP_KERNEL); | 7595 | msg = nlmsg_new(size, GFP_KERNEL); |
@@ -7610,33 +7601,34 @@ static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
7610 | if (!hdr) | 7601 | if (!hdr) |
7611 | goto nla_put_failure; | 7602 | goto nla_put_failure; |
7612 | 7603 | ||
7613 | if (rdev->wowlan) { | 7604 | if (rdev->wiphy.wowlan_config) { |
7614 | struct nlattr *nl_wowlan; | 7605 | struct nlattr *nl_wowlan; |
7615 | 7606 | ||
7616 | nl_wowlan = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS); | 7607 | nl_wowlan = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS); |
7617 | if (!nl_wowlan) | 7608 | if (!nl_wowlan) |
7618 | goto nla_put_failure; | 7609 | goto nla_put_failure; |
7619 | 7610 | ||
7620 | if ((rdev->wowlan->any && | 7611 | if ((rdev->wiphy.wowlan_config->any && |
7621 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) || | 7612 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) || |
7622 | (rdev->wowlan->disconnect && | 7613 | (rdev->wiphy.wowlan_config->disconnect && |
7623 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) || | 7614 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) || |
7624 | (rdev->wowlan->magic_pkt && | 7615 | (rdev->wiphy.wowlan_config->magic_pkt && |
7625 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) || | 7616 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) || |
7626 | (rdev->wowlan->gtk_rekey_failure && | 7617 | (rdev->wiphy.wowlan_config->gtk_rekey_failure && |
7627 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) || | 7618 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) || |
7628 | (rdev->wowlan->eap_identity_req && | 7619 | (rdev->wiphy.wowlan_config->eap_identity_req && |
7629 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) || | 7620 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) || |
7630 | (rdev->wowlan->four_way_handshake && | 7621 | (rdev->wiphy.wowlan_config->four_way_handshake && |
7631 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) || | 7622 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) || |
7632 | (rdev->wowlan->rfkill_release && | 7623 | (rdev->wiphy.wowlan_config->rfkill_release && |
7633 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))) | 7624 | nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))) |
7634 | goto nla_put_failure; | 7625 | goto nla_put_failure; |
7635 | 7626 | ||
7636 | if (nl80211_send_wowlan_patterns(msg, rdev)) | 7627 | if (nl80211_send_wowlan_patterns(msg, rdev)) |
7637 | goto nla_put_failure; | 7628 | goto nla_put_failure; |
7638 | 7629 | ||
7639 | if (nl80211_send_wowlan_tcp(msg, rdev->wowlan->tcp)) | 7630 | if (nl80211_send_wowlan_tcp(msg, |
7631 | rdev->wiphy.wowlan_config->tcp)) | ||
7640 | goto nla_put_failure; | 7632 | goto nla_put_failure; |
7641 | 7633 | ||
7642 | nla_nest_end(msg, nl_wowlan); | 7634 | nla_nest_end(msg, nl_wowlan); |
@@ -7803,7 +7795,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
7803 | struct cfg80211_wowlan *ntrig; | 7795 | struct cfg80211_wowlan *ntrig; |
7804 | struct wiphy_wowlan_support *wowlan = &rdev->wiphy.wowlan; | 7796 | struct wiphy_wowlan_support *wowlan = &rdev->wiphy.wowlan; |
7805 | int err, i; | 7797 | int err, i; |
7806 | bool prev_enabled = rdev->wowlan; | 7798 | bool prev_enabled = rdev->wiphy.wowlan_config; |
7807 | 7799 | ||
7808 | if (!rdev->wiphy.wowlan.flags && !rdev->wiphy.wowlan.n_patterns && | 7800 | if (!rdev->wiphy.wowlan.flags && !rdev->wiphy.wowlan.n_patterns && |
7809 | !rdev->wiphy.wowlan.tcp) | 7801 | !rdev->wiphy.wowlan.tcp) |
@@ -7811,7 +7803,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
7811 | 7803 | ||
7812 | if (!info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]) { | 7804 | if (!info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]) { |
7813 | cfg80211_rdev_free_wowlan(rdev); | 7805 | cfg80211_rdev_free_wowlan(rdev); |
7814 | rdev->wowlan = NULL; | 7806 | rdev->wiphy.wowlan_config = NULL; |
7815 | goto set_wakeup; | 7807 | goto set_wakeup; |
7816 | } | 7808 | } |
7817 | 7809 | ||
@@ -7947,11 +7939,12 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
7947 | goto error; | 7939 | goto error; |
7948 | } | 7940 | } |
7949 | cfg80211_rdev_free_wowlan(rdev); | 7941 | cfg80211_rdev_free_wowlan(rdev); |
7950 | rdev->wowlan = ntrig; | 7942 | rdev->wiphy.wowlan_config = ntrig; |
7951 | 7943 | ||
7952 | set_wakeup: | 7944 | set_wakeup: |
7953 | if (rdev->ops->set_wakeup && prev_enabled != !!rdev->wowlan) | 7945 | if (rdev->ops->set_wakeup && |
7954 | rdev_set_wakeup(rdev, rdev->wowlan); | 7946 | prev_enabled != !!rdev->wiphy.wowlan_config) |
7947 | rdev_set_wakeup(rdev, rdev->wiphy.wowlan_config); | ||
7955 | 7948 | ||
7956 | return 0; | 7949 | return 0; |
7957 | error: | 7950 | error: |
@@ -8136,9 +8129,7 @@ static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info) | |||
8136 | if (wdev->p2p_started) | 8129 | if (wdev->p2p_started) |
8137 | return 0; | 8130 | return 0; |
8138 | 8131 | ||
8139 | mutex_lock(&rdev->devlist_mtx); | ||
8140 | err = cfg80211_can_add_interface(rdev, wdev->iftype); | 8132 | err = cfg80211_can_add_interface(rdev, wdev->iftype); |
8141 | mutex_unlock(&rdev->devlist_mtx); | ||
8142 | if (err) | 8133 | if (err) |
8143 | return err; | 8134 | return err; |
8144 | 8135 | ||
@@ -8147,9 +8138,7 @@ static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info) | |||
8147 | return err; | 8138 | return err; |
8148 | 8139 | ||
8149 | wdev->p2p_started = true; | 8140 | wdev->p2p_started = true; |
8150 | mutex_lock(&rdev->devlist_mtx); | ||
8151 | rdev->opencount++; | 8141 | rdev->opencount++; |
8152 | mutex_unlock(&rdev->devlist_mtx); | ||
8153 | 8142 | ||
8154 | return 0; | 8143 | return 0; |
8155 | } | 8144 | } |
@@ -8165,11 +8154,7 @@ static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info) | |||
8165 | if (!rdev->ops->stop_p2p_device) | 8154 | if (!rdev->ops->stop_p2p_device) |
8166 | return -EOPNOTSUPP; | 8155 | return -EOPNOTSUPP; |
8167 | 8156 | ||
8168 | mutex_lock(&rdev->devlist_mtx); | ||
8169 | mutex_lock(&rdev->sched_scan_mtx); | ||
8170 | cfg80211_stop_p2p_device(rdev, wdev); | 8157 | cfg80211_stop_p2p_device(rdev, wdev); |
8171 | mutex_unlock(&rdev->sched_scan_mtx); | ||
8172 | mutex_unlock(&rdev->devlist_mtx); | ||
8173 | 8158 | ||
8174 | return 0; | 8159 | return 0; |
8175 | } | 8160 | } |
@@ -8312,11 +8297,11 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, | |||
8312 | info->user_ptr[0] = rdev; | 8297 | info->user_ptr[0] = rdev; |
8313 | } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV || | 8298 | } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV || |
8314 | ops->internal_flags & NL80211_FLAG_NEED_WDEV) { | 8299 | ops->internal_flags & NL80211_FLAG_NEED_WDEV) { |
8315 | mutex_lock(&cfg80211_mutex); | 8300 | ASSERT_RTNL(); |
8301 | |||
8316 | wdev = __cfg80211_wdev_from_attrs(genl_info_net(info), | 8302 | wdev = __cfg80211_wdev_from_attrs(genl_info_net(info), |
8317 | info->attrs); | 8303 | info->attrs); |
8318 | if (IS_ERR(wdev)) { | 8304 | if (IS_ERR(wdev)) { |
8319 | mutex_unlock(&cfg80211_mutex); | ||
8320 | if (rtnl) | 8305 | if (rtnl) |
8321 | rtnl_unlock(); | 8306 | rtnl_unlock(); |
8322 | return PTR_ERR(wdev); | 8307 | return PTR_ERR(wdev); |
@@ -8327,7 +8312,6 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, | |||
8327 | 8312 | ||
8328 | if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) { | 8313 | if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) { |
8329 | if (!dev) { | 8314 | if (!dev) { |
8330 | mutex_unlock(&cfg80211_mutex); | ||
8331 | if (rtnl) | 8315 | if (rtnl) |
8332 | rtnl_unlock(); | 8316 | rtnl_unlock(); |
8333 | return -EINVAL; | 8317 | return -EINVAL; |
@@ -8341,7 +8325,6 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, | |||
8341 | if (dev) { | 8325 | if (dev) { |
8342 | if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP && | 8326 | if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP && |
8343 | !netif_running(dev)) { | 8327 | !netif_running(dev)) { |
8344 | mutex_unlock(&cfg80211_mutex); | ||
8345 | if (rtnl) | 8328 | if (rtnl) |
8346 | rtnl_unlock(); | 8329 | rtnl_unlock(); |
8347 | return -ENETDOWN; | 8330 | return -ENETDOWN; |
@@ -8350,17 +8333,12 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, | |||
8350 | dev_hold(dev); | 8333 | dev_hold(dev); |
8351 | } else if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP) { | 8334 | } else if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP) { |
8352 | if (!wdev->p2p_started) { | 8335 | if (!wdev->p2p_started) { |
8353 | mutex_unlock(&cfg80211_mutex); | ||
8354 | if (rtnl) | 8336 | if (rtnl) |
8355 | rtnl_unlock(); | 8337 | rtnl_unlock(); |
8356 | return -ENETDOWN; | 8338 | return -ENETDOWN; |
8357 | } | 8339 | } |
8358 | } | 8340 | } |
8359 | 8341 | ||
8360 | cfg80211_lock_rdev(rdev); | ||
8361 | |||
8362 | mutex_unlock(&cfg80211_mutex); | ||
8363 | |||
8364 | info->user_ptr[0] = rdev; | 8342 | info->user_ptr[0] = rdev; |
8365 | } | 8343 | } |
8366 | 8344 | ||
@@ -8370,8 +8348,6 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, | |||
8370 | static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb, | 8348 | static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb, |
8371 | struct genl_info *info) | 8349 | struct genl_info *info) |
8372 | { | 8350 | { |
8373 | if (info->user_ptr[0]) | ||
8374 | cfg80211_unlock_rdev(info->user_ptr[0]); | ||
8375 | if (info->user_ptr[1]) { | 8351 | if (info->user_ptr[1]) { |
8376 | if (ops->internal_flags & NL80211_FLAG_NEED_WDEV) { | 8352 | if (ops->internal_flags & NL80211_FLAG_NEED_WDEV) { |
8377 | struct wireless_dev *wdev = info->user_ptr[1]; | 8353 | struct wireless_dev *wdev = info->user_ptr[1]; |
@@ -8393,7 +8369,8 @@ static struct genl_ops nl80211_ops[] = { | |||
8393 | .dumpit = nl80211_dump_wiphy, | 8369 | .dumpit = nl80211_dump_wiphy, |
8394 | .policy = nl80211_policy, | 8370 | .policy = nl80211_policy, |
8395 | /* can be retrieved by unprivileged users */ | 8371 | /* can be retrieved by unprivileged users */ |
8396 | .internal_flags = NL80211_FLAG_NEED_WIPHY, | 8372 | .internal_flags = NL80211_FLAG_NEED_WIPHY | |
8373 | NL80211_FLAG_NEED_RTNL, | ||
8397 | }, | 8374 | }, |
8398 | { | 8375 | { |
8399 | .cmd = NL80211_CMD_SET_WIPHY, | 8376 | .cmd = NL80211_CMD_SET_WIPHY, |
@@ -8408,7 +8385,8 @@ static struct genl_ops nl80211_ops[] = { | |||
8408 | .dumpit = nl80211_dump_interface, | 8385 | .dumpit = nl80211_dump_interface, |
8409 | .policy = nl80211_policy, | 8386 | .policy = nl80211_policy, |
8410 | /* can be retrieved by unprivileged users */ | 8387 | /* can be retrieved by unprivileged users */ |
8411 | .internal_flags = NL80211_FLAG_NEED_WDEV, | 8388 | .internal_flags = NL80211_FLAG_NEED_WDEV | |
8389 | NL80211_FLAG_NEED_RTNL, | ||
8412 | }, | 8390 | }, |
8413 | { | 8391 | { |
8414 | .cmd = NL80211_CMD_SET_INTERFACE, | 8392 | .cmd = NL80211_CMD_SET_INTERFACE, |
@@ -8567,6 +8545,7 @@ static struct genl_ops nl80211_ops[] = { | |||
8567 | .cmd = NL80211_CMD_GET_REG, | 8545 | .cmd = NL80211_CMD_GET_REG, |
8568 | .doit = nl80211_get_reg, | 8546 | .doit = nl80211_get_reg, |
8569 | .policy = nl80211_policy, | 8547 | .policy = nl80211_policy, |
8548 | .internal_flags = NL80211_FLAG_NEED_RTNL, | ||
8570 | /* can be retrieved by unprivileged users */ | 8549 | /* can be retrieved by unprivileged users */ |
8571 | }, | 8550 | }, |
8572 | { | 8551 | { |
@@ -8574,6 +8553,7 @@ static struct genl_ops nl80211_ops[] = { | |||
8574 | .doit = nl80211_set_reg, | 8553 | .doit = nl80211_set_reg, |
8575 | .policy = nl80211_policy, | 8554 | .policy = nl80211_policy, |
8576 | .flags = GENL_ADMIN_PERM, | 8555 | .flags = GENL_ADMIN_PERM, |
8556 | .internal_flags = NL80211_FLAG_NEED_RTNL, | ||
8577 | }, | 8557 | }, |
8578 | { | 8558 | { |
8579 | .cmd = NL80211_CMD_REQ_SET_REG, | 8559 | .cmd = NL80211_CMD_REQ_SET_REG, |
@@ -9029,8 +9009,6 @@ static int nl80211_add_scan_req(struct sk_buff *msg, | |||
9029 | struct nlattr *nest; | 9009 | struct nlattr *nest; |
9030 | int i; | 9010 | int i; |
9031 | 9011 | ||
9032 | lockdep_assert_held(&rdev->sched_scan_mtx); | ||
9033 | |||
9034 | if (WARN_ON(!req)) | 9012 | if (WARN_ON(!req)) |
9035 | return 0; | 9013 | return 0; |
9036 | 9014 | ||
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index cc35fbaa4578..e1d6749234c6 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -81,7 +81,10 @@ static struct regulatory_request core_request_world = { | |||
81 | .country_ie_env = ENVIRON_ANY, | 81 | .country_ie_env = ENVIRON_ANY, |
82 | }; | 82 | }; |
83 | 83 | ||
84 | /* Receipt of information from last regulatory request */ | 84 | /* |
85 | * Receipt of information from last regulatory request, | ||
86 | * protected by RTNL (and can be accessed with RCU protection) | ||
87 | */ | ||
85 | static struct regulatory_request __rcu *last_request = | 88 | static struct regulatory_request __rcu *last_request = |
86 | (void __rcu *)&core_request_world; | 89 | (void __rcu *)&core_request_world; |
87 | 90 | ||
@@ -96,39 +99,25 @@ static struct device_type reg_device_type = { | |||
96 | * Central wireless core regulatory domains, we only need two, | 99 | * Central wireless core regulatory domains, we only need two, |
97 | * the current one and a world regulatory domain in case we have no | 100 | * the current one and a world regulatory domain in case we have no |
98 | * information to give us an alpha2. | 101 | * information to give us an alpha2. |
102 | * (protected by RTNL, can be read under RCU) | ||
99 | */ | 103 | */ |
100 | const struct ieee80211_regdomain __rcu *cfg80211_regdomain; | 104 | const struct ieee80211_regdomain __rcu *cfg80211_regdomain; |
101 | 105 | ||
102 | /* | 106 | /* |
103 | * Protects static reg.c components: | ||
104 | * - cfg80211_regdomain (if not used with RCU) | ||
105 | * - cfg80211_world_regdom | ||
106 | * - last_request (if not used with RCU) | ||
107 | * - reg_num_devs_support_basehint | ||
108 | */ | ||
109 | static DEFINE_MUTEX(reg_mutex); | ||
110 | |||
111 | /* | ||
112 | * Number of devices that registered to the core | 107 | * Number of devices that registered to the core |
113 | * that support cellular base station regulatory hints | 108 | * that support cellular base station regulatory hints |
109 | * (protected by RTNL) | ||
114 | */ | 110 | */ |
115 | static int reg_num_devs_support_basehint; | 111 | static int reg_num_devs_support_basehint; |
116 | 112 | ||
117 | static inline void assert_reg_lock(void) | ||
118 | { | ||
119 | lockdep_assert_held(®_mutex); | ||
120 | } | ||
121 | |||
122 | static const struct ieee80211_regdomain *get_cfg80211_regdom(void) | 113 | static const struct ieee80211_regdomain *get_cfg80211_regdom(void) |
123 | { | 114 | { |
124 | return rcu_dereference_protected(cfg80211_regdomain, | 115 | return rtnl_dereference(cfg80211_regdomain); |
125 | lockdep_is_held(®_mutex)); | ||
126 | } | 116 | } |
127 | 117 | ||
128 | static const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy) | 118 | static const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy) |
129 | { | 119 | { |
130 | return rcu_dereference_protected(wiphy->regd, | 120 | return rtnl_dereference(wiphy->regd); |
131 | lockdep_is_held(®_mutex)); | ||
132 | } | 121 | } |
133 | 122 | ||
134 | static void rcu_free_regdom(const struct ieee80211_regdomain *r) | 123 | static void rcu_free_regdom(const struct ieee80211_regdomain *r) |
@@ -140,8 +129,7 @@ static void rcu_free_regdom(const struct ieee80211_regdomain *r) | |||
140 | 129 | ||
141 | static struct regulatory_request *get_last_request(void) | 130 | static struct regulatory_request *get_last_request(void) |
142 | { | 131 | { |
143 | return rcu_dereference_check(last_request, | 132 | return rcu_dereference_rtnl(last_request); |
144 | lockdep_is_held(®_mutex)); | ||
145 | } | 133 | } |
146 | 134 | ||
147 | /* Used to queue up regulatory hints */ | 135 | /* Used to queue up regulatory hints */ |
@@ -200,6 +188,7 @@ static const struct ieee80211_regdomain world_regdom = { | |||
200 | } | 188 | } |
201 | }; | 189 | }; |
202 | 190 | ||
191 | /* protected by RTNL */ | ||
203 | static const struct ieee80211_regdomain *cfg80211_world_regdom = | 192 | static const struct ieee80211_regdomain *cfg80211_world_regdom = |
204 | &world_regdom; | 193 | &world_regdom; |
205 | 194 | ||
@@ -215,7 +204,7 @@ static void reset_regdomains(bool full_reset, | |||
215 | const struct ieee80211_regdomain *r; | 204 | const struct ieee80211_regdomain *r; |
216 | struct regulatory_request *lr; | 205 | struct regulatory_request *lr; |
217 | 206 | ||
218 | assert_reg_lock(); | 207 | ASSERT_RTNL(); |
219 | 208 | ||
220 | r = get_cfg80211_regdom(); | 209 | r = get_cfg80211_regdom(); |
221 | 210 | ||
@@ -377,7 +366,7 @@ static void reg_regdb_search(struct work_struct *work) | |||
377 | const struct ieee80211_regdomain *curdom, *regdom = NULL; | 366 | const struct ieee80211_regdomain *curdom, *regdom = NULL; |
378 | int i; | 367 | int i; |
379 | 368 | ||
380 | mutex_lock(&cfg80211_mutex); | 369 | rtnl_lock(); |
381 | 370 | ||
382 | mutex_lock(®_regdb_search_mutex); | 371 | mutex_lock(®_regdb_search_mutex); |
383 | while (!list_empty(®_regdb_search_list)) { | 372 | while (!list_empty(®_regdb_search_list)) { |
@@ -402,7 +391,7 @@ static void reg_regdb_search(struct work_struct *work) | |||
402 | if (!IS_ERR_OR_NULL(regdom)) | 391 | if (!IS_ERR_OR_NULL(regdom)) |
403 | set_regdom(regdom); | 392 | set_regdom(regdom); |
404 | 393 | ||
405 | mutex_unlock(&cfg80211_mutex); | 394 | rtnl_unlock(); |
406 | } | 395 | } |
407 | 396 | ||
408 | static DECLARE_WORK(reg_regdb_work, reg_regdb_search); | 397 | static DECLARE_WORK(reg_regdb_work, reg_regdb_search); |
@@ -936,13 +925,7 @@ static bool reg_request_cell_base(struct regulatory_request *request) | |||
936 | 925 | ||
937 | bool reg_last_request_cell_base(void) | 926 | bool reg_last_request_cell_base(void) |
938 | { | 927 | { |
939 | bool val; | 928 | return reg_request_cell_base(get_last_request()); |
940 | |||
941 | mutex_lock(®_mutex); | ||
942 | val = reg_request_cell_base(get_last_request()); | ||
943 | mutex_unlock(®_mutex); | ||
944 | |||
945 | return val; | ||
946 | } | 929 | } |
947 | 930 | ||
948 | #ifdef CONFIG_CFG80211_CERTIFICATION_ONUS | 931 | #ifdef CONFIG_CFG80211_CERTIFICATION_ONUS |
@@ -1225,7 +1208,7 @@ static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator) | |||
1225 | struct cfg80211_registered_device *rdev; | 1208 | struct cfg80211_registered_device *rdev; |
1226 | struct wiphy *wiphy; | 1209 | struct wiphy *wiphy; |
1227 | 1210 | ||
1228 | assert_cfg80211_lock(); | 1211 | ASSERT_RTNL(); |
1229 | 1212 | ||
1230 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) { | 1213 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) { |
1231 | wiphy = &rdev->wiphy; | 1214 | wiphy = &rdev->wiphy; |
@@ -1444,8 +1427,6 @@ static void reg_set_request_processed(void) | |||
1444 | * what it believes should be the current regulatory domain. | 1427 | * what it believes should be the current regulatory domain. |
1445 | * | 1428 | * |
1446 | * Returns one of the different reg request treatment values. | 1429 | * Returns one of the different reg request treatment values. |
1447 | * | ||
1448 | * Caller must hold ®_mutex | ||
1449 | */ | 1430 | */ |
1450 | static enum reg_request_treatment | 1431 | static enum reg_request_treatment |
1451 | __regulatory_hint(struct wiphy *wiphy, | 1432 | __regulatory_hint(struct wiphy *wiphy, |
@@ -1570,21 +1551,19 @@ static void reg_process_pending_hints(void) | |||
1570 | { | 1551 | { |
1571 | struct regulatory_request *reg_request, *lr; | 1552 | struct regulatory_request *reg_request, *lr; |
1572 | 1553 | ||
1573 | mutex_lock(&cfg80211_mutex); | ||
1574 | mutex_lock(®_mutex); | ||
1575 | lr = get_last_request(); | 1554 | lr = get_last_request(); |
1576 | 1555 | ||
1577 | /* When last_request->processed becomes true this will be rescheduled */ | 1556 | /* When last_request->processed becomes true this will be rescheduled */ |
1578 | if (lr && !lr->processed) { | 1557 | if (lr && !lr->processed) { |
1579 | REG_DBG_PRINT("Pending regulatory request, waiting for it to be processed...\n"); | 1558 | REG_DBG_PRINT("Pending regulatory request, waiting for it to be processed...\n"); |
1580 | goto out; | 1559 | return; |
1581 | } | 1560 | } |
1582 | 1561 | ||
1583 | spin_lock(®_requests_lock); | 1562 | spin_lock(®_requests_lock); |
1584 | 1563 | ||
1585 | if (list_empty(®_requests_list)) { | 1564 | if (list_empty(®_requests_list)) { |
1586 | spin_unlock(®_requests_lock); | 1565 | spin_unlock(®_requests_lock); |
1587 | goto out; | 1566 | return; |
1588 | } | 1567 | } |
1589 | 1568 | ||
1590 | reg_request = list_first_entry(®_requests_list, | 1569 | reg_request = list_first_entry(®_requests_list, |
@@ -1595,10 +1574,6 @@ static void reg_process_pending_hints(void) | |||
1595 | spin_unlock(®_requests_lock); | 1574 | spin_unlock(®_requests_lock); |
1596 | 1575 | ||
1597 | reg_process_hint(reg_request, reg_request->initiator); | 1576 | reg_process_hint(reg_request, reg_request->initiator); |
1598 | |||
1599 | out: | ||
1600 | mutex_unlock(®_mutex); | ||
1601 | mutex_unlock(&cfg80211_mutex); | ||
1602 | } | 1577 | } |
1603 | 1578 | ||
1604 | /* Processes beacon hints -- this has nothing to do with country IEs */ | 1579 | /* Processes beacon hints -- this has nothing to do with country IEs */ |
@@ -1607,9 +1582,6 @@ static void reg_process_pending_beacon_hints(void) | |||
1607 | struct cfg80211_registered_device *rdev; | 1582 | struct cfg80211_registered_device *rdev; |
1608 | struct reg_beacon *pending_beacon, *tmp; | 1583 | struct reg_beacon *pending_beacon, *tmp; |
1609 | 1584 | ||
1610 | mutex_lock(&cfg80211_mutex); | ||
1611 | mutex_lock(®_mutex); | ||
1612 | |||
1613 | /* This goes through the _pending_ beacon list */ | 1585 | /* This goes through the _pending_ beacon list */ |
1614 | spin_lock_bh(®_pending_beacons_lock); | 1586 | spin_lock_bh(®_pending_beacons_lock); |
1615 | 1587 | ||
@@ -1626,14 +1598,14 @@ static void reg_process_pending_beacon_hints(void) | |||
1626 | } | 1598 | } |
1627 | 1599 | ||
1628 | spin_unlock_bh(®_pending_beacons_lock); | 1600 | spin_unlock_bh(®_pending_beacons_lock); |
1629 | mutex_unlock(®_mutex); | ||
1630 | mutex_unlock(&cfg80211_mutex); | ||
1631 | } | 1601 | } |
1632 | 1602 | ||
1633 | static void reg_todo(struct work_struct *work) | 1603 | static void reg_todo(struct work_struct *work) |
1634 | { | 1604 | { |
1605 | rtnl_lock(); | ||
1635 | reg_process_pending_hints(); | 1606 | reg_process_pending_hints(); |
1636 | reg_process_pending_beacon_hints(); | 1607 | reg_process_pending_beacon_hints(); |
1608 | rtnl_unlock(); | ||
1637 | } | 1609 | } |
1638 | 1610 | ||
1639 | static void queue_regulatory_request(struct regulatory_request *request) | 1611 | static void queue_regulatory_request(struct regulatory_request *request) |
@@ -1717,29 +1689,23 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2) | |||
1717 | } | 1689 | } |
1718 | EXPORT_SYMBOL(regulatory_hint); | 1690 | EXPORT_SYMBOL(regulatory_hint); |
1719 | 1691 | ||
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, | 1692 | void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band, |
1725 | const u8 *country_ie, u8 country_ie_len) | 1693 | const u8 *country_ie, u8 country_ie_len) |
1726 | { | 1694 | { |
1727 | char alpha2[2]; | 1695 | char alpha2[2]; |
1728 | enum environment_cap env = ENVIRON_ANY; | 1696 | enum environment_cap env = ENVIRON_ANY; |
1729 | struct regulatory_request *request, *lr; | 1697 | struct regulatory_request *request = NULL, *lr; |
1730 | |||
1731 | mutex_lock(®_mutex); | ||
1732 | lr = get_last_request(); | ||
1733 | |||
1734 | if (unlikely(!lr)) | ||
1735 | goto out; | ||
1736 | 1698 | ||
1737 | /* IE len must be evenly divisible by 2 */ | 1699 | /* IE len must be evenly divisible by 2 */ |
1738 | if (country_ie_len & 0x01) | 1700 | if (country_ie_len & 0x01) |
1739 | goto out; | 1701 | return; |
1740 | 1702 | ||
1741 | if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) | 1703 | if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) |
1742 | goto out; | 1704 | return; |
1705 | |||
1706 | request = kzalloc(sizeof(*request), GFP_KERNEL); | ||
1707 | if (!request) | ||
1708 | return; | ||
1743 | 1709 | ||
1744 | alpha2[0] = country_ie[0]; | 1710 | alpha2[0] = country_ie[0]; |
1745 | alpha2[1] = country_ie[1]; | 1711 | alpha2[1] = country_ie[1]; |
@@ -1749,19 +1715,21 @@ void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band, | |||
1749 | else if (country_ie[2] == 'O') | 1715 | else if (country_ie[2] == 'O') |
1750 | env = ENVIRON_OUTDOOR; | 1716 | env = ENVIRON_OUTDOOR; |
1751 | 1717 | ||
1718 | rcu_read_lock(); | ||
1719 | lr = get_last_request(); | ||
1720 | |||
1721 | if (unlikely(!lr)) | ||
1722 | goto out; | ||
1723 | |||
1752 | /* | 1724 | /* |
1753 | * We will run this only upon a successful connection on cfg80211. | 1725 | * We will run this only upon a successful connection on cfg80211. |
1754 | * We leave conflict resolution to the workqueue, where can hold | 1726 | * We leave conflict resolution to the workqueue, where can hold |
1755 | * cfg80211_mutex. | 1727 | * the RTNL. |
1756 | */ | 1728 | */ |
1757 | if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE && | 1729 | if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE && |
1758 | lr->wiphy_idx != WIPHY_IDX_INVALID) | 1730 | lr->wiphy_idx != WIPHY_IDX_INVALID) |
1759 | goto out; | 1731 | goto out; |
1760 | 1732 | ||
1761 | request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL); | ||
1762 | if (!request) | ||
1763 | goto out; | ||
1764 | |||
1765 | request->wiphy_idx = get_wiphy_idx(wiphy); | 1733 | request->wiphy_idx = get_wiphy_idx(wiphy); |
1766 | request->alpha2[0] = alpha2[0]; | 1734 | request->alpha2[0] = alpha2[0]; |
1767 | request->alpha2[1] = alpha2[1]; | 1735 | request->alpha2[1] = alpha2[1]; |
@@ -1769,8 +1737,10 @@ void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band, | |||
1769 | request->country_ie_env = env; | 1737 | request->country_ie_env = env; |
1770 | 1738 | ||
1771 | queue_regulatory_request(request); | 1739 | queue_regulatory_request(request); |
1740 | request = NULL; | ||
1772 | out: | 1741 | out: |
1773 | mutex_unlock(®_mutex); | 1742 | kfree(request); |
1743 | rcu_read_unlock(); | ||
1774 | } | 1744 | } |
1775 | 1745 | ||
1776 | static void restore_alpha2(char *alpha2, bool reset_user) | 1746 | static void restore_alpha2(char *alpha2, bool reset_user) |
@@ -1858,8 +1828,7 @@ static void restore_regulatory_settings(bool reset_user) | |||
1858 | LIST_HEAD(tmp_reg_req_list); | 1828 | LIST_HEAD(tmp_reg_req_list); |
1859 | struct cfg80211_registered_device *rdev; | 1829 | struct cfg80211_registered_device *rdev; |
1860 | 1830 | ||
1861 | mutex_lock(&cfg80211_mutex); | 1831 | ASSERT_RTNL(); |
1862 | mutex_lock(®_mutex); | ||
1863 | 1832 | ||
1864 | reset_regdomains(true, &world_regdom); | 1833 | reset_regdomains(true, &world_regdom); |
1865 | restore_alpha2(alpha2, reset_user); | 1834 | restore_alpha2(alpha2, reset_user); |
@@ -1914,9 +1883,6 @@ static void restore_regulatory_settings(bool reset_user) | |||
1914 | list_splice_tail_init(&tmp_reg_req_list, ®_requests_list); | 1883 | list_splice_tail_init(&tmp_reg_req_list, ®_requests_list); |
1915 | spin_unlock(®_requests_lock); | 1884 | spin_unlock(®_requests_lock); |
1916 | 1885 | ||
1917 | mutex_unlock(®_mutex); | ||
1918 | mutex_unlock(&cfg80211_mutex); | ||
1919 | |||
1920 | REG_DBG_PRINT("Kicking the queue\n"); | 1886 | REG_DBG_PRINT("Kicking the queue\n"); |
1921 | 1887 | ||
1922 | schedule_work(®_work); | 1888 | schedule_work(®_work); |
@@ -2231,7 +2197,6 @@ int set_regdom(const struct ieee80211_regdomain *rd) | |||
2231 | struct regulatory_request *lr; | 2197 | struct regulatory_request *lr; |
2232 | int r; | 2198 | int r; |
2233 | 2199 | ||
2234 | mutex_lock(®_mutex); | ||
2235 | lr = get_last_request(); | 2200 | lr = get_last_request(); |
2236 | 2201 | ||
2237 | /* Note that this doesn't update the wiphys, this is done below */ | 2202 | /* Note that this doesn't update the wiphys, this is done below */ |
@@ -2241,14 +2206,12 @@ int set_regdom(const struct ieee80211_regdomain *rd) | |||
2241 | reg_set_request_processed(); | 2206 | reg_set_request_processed(); |
2242 | 2207 | ||
2243 | kfree(rd); | 2208 | kfree(rd); |
2244 | goto out; | 2209 | return r; |
2245 | } | 2210 | } |
2246 | 2211 | ||
2247 | /* This would make this whole thing pointless */ | 2212 | /* This would make this whole thing pointless */ |
2248 | if (WARN_ON(!lr->intersect && rd != get_cfg80211_regdom())) { | 2213 | if (WARN_ON(!lr->intersect && rd != get_cfg80211_regdom())) |
2249 | r = -EINVAL; | 2214 | return -EINVAL; |
2250 | goto out; | ||
2251 | } | ||
2252 | 2215 | ||
2253 | /* update all wiphys now with the new established regulatory domain */ | 2216 | /* update all wiphys now with the new established regulatory domain */ |
2254 | update_all_wiphy_regulatory(lr->initiator); | 2217 | update_all_wiphy_regulatory(lr->initiator); |
@@ -2259,10 +2222,7 @@ int set_regdom(const struct ieee80211_regdomain *rd) | |||
2259 | 2222 | ||
2260 | reg_set_request_processed(); | 2223 | reg_set_request_processed(); |
2261 | 2224 | ||
2262 | out: | 2225 | return 0; |
2263 | mutex_unlock(®_mutex); | ||
2264 | |||
2265 | return r; | ||
2266 | } | 2226 | } |
2267 | 2227 | ||
2268 | int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env) | 2228 | int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env) |
@@ -2287,23 +2247,17 @@ int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
2287 | 2247 | ||
2288 | void wiphy_regulatory_register(struct wiphy *wiphy) | 2248 | void wiphy_regulatory_register(struct wiphy *wiphy) |
2289 | { | 2249 | { |
2290 | mutex_lock(®_mutex); | ||
2291 | |||
2292 | if (!reg_dev_ignore_cell_hint(wiphy)) | 2250 | if (!reg_dev_ignore_cell_hint(wiphy)) |
2293 | reg_num_devs_support_basehint++; | 2251 | reg_num_devs_support_basehint++; |
2294 | 2252 | ||
2295 | wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE); | 2253 | wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE); |
2296 | |||
2297 | mutex_unlock(®_mutex); | ||
2298 | } | 2254 | } |
2299 | 2255 | ||
2300 | /* Caller must hold cfg80211_mutex */ | ||
2301 | void wiphy_regulatory_deregister(struct wiphy *wiphy) | 2256 | void wiphy_regulatory_deregister(struct wiphy *wiphy) |
2302 | { | 2257 | { |
2303 | struct wiphy *request_wiphy = NULL; | 2258 | struct wiphy *request_wiphy = NULL; |
2304 | struct regulatory_request *lr; | 2259 | struct regulatory_request *lr; |
2305 | 2260 | ||
2306 | mutex_lock(®_mutex); | ||
2307 | lr = get_last_request(); | 2261 | lr = get_last_request(); |
2308 | 2262 | ||
2309 | if (!reg_dev_ignore_cell_hint(wiphy)) | 2263 | if (!reg_dev_ignore_cell_hint(wiphy)) |
@@ -2316,12 +2270,10 @@ void wiphy_regulatory_deregister(struct wiphy *wiphy) | |||
2316 | request_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx); | 2270 | request_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx); |
2317 | 2271 | ||
2318 | if (!request_wiphy || request_wiphy != wiphy) | 2272 | if (!request_wiphy || request_wiphy != wiphy) |
2319 | goto out; | 2273 | return; |
2320 | 2274 | ||
2321 | lr->wiphy_idx = WIPHY_IDX_INVALID; | 2275 | lr->wiphy_idx = WIPHY_IDX_INVALID; |
2322 | lr->country_ie_env = ENVIRON_ANY; | 2276 | lr->country_ie_env = ENVIRON_ANY; |
2323 | out: | ||
2324 | mutex_unlock(®_mutex); | ||
2325 | } | 2277 | } |
2326 | 2278 | ||
2327 | static void reg_timeout_work(struct work_struct *work) | 2279 | static void reg_timeout_work(struct work_struct *work) |
@@ -2385,9 +2337,9 @@ void regulatory_exit(void) | |||
2385 | cancel_delayed_work_sync(®_timeout); | 2337 | cancel_delayed_work_sync(®_timeout); |
2386 | 2338 | ||
2387 | /* Lock to suppress warnings */ | 2339 | /* Lock to suppress warnings */ |
2388 | mutex_lock(®_mutex); | 2340 | rtnl_lock(); |
2389 | reset_regdomains(true, NULL); | 2341 | reset_regdomains(true, NULL); |
2390 | mutex_unlock(®_mutex); | 2342 | rtnl_unlock(); |
2391 | 2343 | ||
2392 | dev_set_uevent_suppress(®_pdev->dev, true); | 2344 | dev_set_uevent_suppress(®_pdev->dev, true); |
2393 | 2345 | ||
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index fd99ea495b7e..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; |
@@ -1040,6 +1041,25 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub) | |||
1040 | EXPORT_SYMBOL(cfg80211_unlink_bss); | 1041 | EXPORT_SYMBOL(cfg80211_unlink_bss); |
1041 | 1042 | ||
1042 | #ifdef CONFIG_CFG80211_WEXT | 1043 | #ifdef CONFIG_CFG80211_WEXT |
1044 | static struct cfg80211_registered_device * | ||
1045 | cfg80211_get_dev_from_ifindex(struct net *net, int ifindex) | ||
1046 | { | ||
1047 | struct cfg80211_registered_device *rdev; | ||
1048 | struct net_device *dev; | ||
1049 | |||
1050 | ASSERT_RTNL(); | ||
1051 | |||
1052 | dev = dev_get_by_index(net, ifindex); | ||
1053 | if (!dev) | ||
1054 | return ERR_PTR(-ENODEV); | ||
1055 | if (dev->ieee80211_ptr) | ||
1056 | rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy); | ||
1057 | else | ||
1058 | rdev = ERR_PTR(-ENODEV); | ||
1059 | dev_put(dev); | ||
1060 | return rdev; | ||
1061 | } | ||
1062 | |||
1043 | int cfg80211_wext_siwscan(struct net_device *dev, | 1063 | int cfg80211_wext_siwscan(struct net_device *dev, |
1044 | struct iw_request_info *info, | 1064 | struct iw_request_info *info, |
1045 | union iwreq_data *wrqu, char *extra) | 1065 | union iwreq_data *wrqu, char *extra) |
@@ -1062,7 +1082,6 @@ int cfg80211_wext_siwscan(struct net_device *dev, | |||
1062 | if (IS_ERR(rdev)) | 1082 | if (IS_ERR(rdev)) |
1063 | return PTR_ERR(rdev); | 1083 | return PTR_ERR(rdev); |
1064 | 1084 | ||
1065 | mutex_lock(&rdev->sched_scan_mtx); | ||
1066 | if (rdev->scan_req) { | 1085 | if (rdev->scan_req) { |
1067 | err = -EBUSY; | 1086 | err = -EBUSY; |
1068 | goto out; | 1087 | goto out; |
@@ -1169,9 +1188,7 @@ int cfg80211_wext_siwscan(struct net_device *dev, | |||
1169 | dev_hold(dev); | 1188 | dev_hold(dev); |
1170 | } | 1189 | } |
1171 | out: | 1190 | out: |
1172 | mutex_unlock(&rdev->sched_scan_mtx); | ||
1173 | kfree(creq); | 1191 | kfree(creq); |
1174 | cfg80211_unlock_rdev(rdev); | ||
1175 | return err; | 1192 | return err; |
1176 | } | 1193 | } |
1177 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan); | 1194 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan); |
@@ -1470,10 +1487,8 @@ int cfg80211_wext_giwscan(struct net_device *dev, | |||
1470 | if (IS_ERR(rdev)) | 1487 | if (IS_ERR(rdev)) |
1471 | return PTR_ERR(rdev); | 1488 | return PTR_ERR(rdev); |
1472 | 1489 | ||
1473 | if (rdev->scan_req) { | 1490 | if (rdev->scan_req) |
1474 | res = -EAGAIN; | 1491 | return -EAGAIN; |
1475 | goto out; | ||
1476 | } | ||
1477 | 1492 | ||
1478 | res = ieee80211_scan_results(rdev, info, extra, data->length); | 1493 | res = ieee80211_scan_results(rdev, info, extra, data->length); |
1479 | data->length = 0; | 1494 | data->length = 0; |
@@ -1482,8 +1497,6 @@ int cfg80211_wext_giwscan(struct net_device *dev, | |||
1482 | res = 0; | 1497 | res = 0; |
1483 | } | 1498 | } |
1484 | 1499 | ||
1485 | out: | ||
1486 | cfg80211_unlock_rdev(rdev); | ||
1487 | return res; | 1500 | return res; |
1488 | } | 1501 | } |
1489 | 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..81be95f3be74 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; |
@@ -176,13 +169,13 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) | |||
176 | case CFG80211_CONN_AUTHENTICATE_NEXT: | 169 | case CFG80211_CONN_AUTHENTICATE_NEXT: |
177 | BUG_ON(!rdev->ops->auth); | 170 | BUG_ON(!rdev->ops->auth); |
178 | wdev->conn->state = CFG80211_CONN_AUTHENTICATING; | 171 | wdev->conn->state = CFG80211_CONN_AUTHENTICATING; |
179 | return __cfg80211_mlme_auth(rdev, wdev->netdev, | 172 | return cfg80211_mlme_auth(rdev, wdev->netdev, |
180 | params->channel, params->auth_type, | 173 | params->channel, params->auth_type, |
181 | params->bssid, | 174 | params->bssid, |
182 | params->ssid, params->ssid_len, | 175 | params->ssid, params->ssid_len, |
183 | NULL, 0, | 176 | NULL, 0, |
184 | params->key, params->key_len, | 177 | params->key, params->key_len, |
185 | params->key_idx, NULL, 0); | 178 | params->key_idx, NULL, 0); |
186 | case CFG80211_CONN_ASSOCIATE_NEXT: | 179 | case CFG80211_CONN_ASSOCIATE_NEXT: |
187 | BUG_ON(!rdev->ops->assoc); | 180 | BUG_ON(!rdev->ops->assoc); |
188 | wdev->conn->state = CFG80211_CONN_ASSOCIATING; | 181 | wdev->conn->state = CFG80211_CONN_ASSOCIATING; |
@@ -198,19 +191,19 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) | |||
198 | req.vht_capa = params->vht_capa; | 191 | req.vht_capa = params->vht_capa; |
199 | req.vht_capa_mask = params->vht_capa_mask; | 192 | req.vht_capa_mask = params->vht_capa_mask; |
200 | 193 | ||
201 | err = __cfg80211_mlme_assoc(rdev, wdev->netdev, params->channel, | 194 | err = cfg80211_mlme_assoc(rdev, wdev->netdev, params->channel, |
202 | params->bssid, params->ssid, | 195 | params->bssid, params->ssid, |
203 | params->ssid_len, &req); | 196 | params->ssid_len, &req); |
204 | if (err) | 197 | if (err) |
205 | __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, | 198 | cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, |
206 | NULL, 0, | 199 | NULL, 0, |
207 | WLAN_REASON_DEAUTH_LEAVING, | 200 | WLAN_REASON_DEAUTH_LEAVING, |
208 | false); | 201 | false); |
209 | return err; | 202 | return err; |
210 | case CFG80211_CONN_DEAUTH_ASSOC_FAIL: | 203 | case CFG80211_CONN_DEAUTH_ASSOC_FAIL: |
211 | __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, | 204 | cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, |
212 | NULL, 0, | 205 | NULL, 0, |
213 | WLAN_REASON_DEAUTH_LEAVING, false); | 206 | WLAN_REASON_DEAUTH_LEAVING, false); |
214 | /* return an error so that we call __cfg80211_connect_result() */ | 207 | /* return an error so that we call __cfg80211_connect_result() */ |
215 | return -EINVAL; | 208 | return -EINVAL; |
216 | default: | 209 | default: |
@@ -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 | ||
@@ -773,11 +760,11 @@ void cfg80211_disconnected(struct net_device *dev, u16 reason, | |||
773 | } | 760 | } |
774 | EXPORT_SYMBOL(cfg80211_disconnected); | 761 | EXPORT_SYMBOL(cfg80211_disconnected); |
775 | 762 | ||
776 | int __cfg80211_connect(struct cfg80211_registered_device *rdev, | 763 | int cfg80211_connect(struct cfg80211_registered_device *rdev, |
777 | struct net_device *dev, | 764 | struct net_device *dev, |
778 | struct cfg80211_connect_params *connect, | 765 | struct cfg80211_connect_params *connect, |
779 | struct cfg80211_cached_keys *connkeys, | 766 | struct cfg80211_cached_keys *connkeys, |
780 | const u8 *prev_bssid) | 767 | const u8 *prev_bssid) |
781 | { | 768 | { |
782 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 769 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
783 | struct cfg80211_bss *bss = NULL; | 770 | struct cfg80211_bss *bss = NULL; |
@@ -924,27 +911,8 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev, | |||
924 | } | 911 | } |
925 | } | 912 | } |
926 | 913 | ||
927 | int cfg80211_connect(struct cfg80211_registered_device *rdev, | 914 | int cfg80211_disconnect(struct cfg80211_registered_device *rdev, |
928 | struct net_device *dev, | 915 | struct net_device *dev, u16 reason, bool wextev) |
929 | struct cfg80211_connect_params *connect, | ||
930 | struct cfg80211_cached_keys *connkeys) | ||
931 | { | ||
932 | int err; | ||
933 | |||
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); | ||
938 | err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL); | ||
939 | wdev_unlock(dev->ieee80211_ptr); | ||
940 | mutex_unlock(&rdev->sched_scan_mtx); | ||
941 | mutex_unlock(&rdev->devlist_mtx); | ||
942 | |||
943 | return err; | ||
944 | } | ||
945 | |||
946 | int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, | ||
947 | struct net_device *dev, u16 reason, bool wextev) | ||
948 | { | 916 | { |
949 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 917 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
950 | int err; | 918 | int err; |
@@ -979,7 +947,7 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, | |||
979 | } | 947 | } |
980 | 948 | ||
981 | /* wdev->conn->params.bssid must be set if > SCANNING */ | 949 | /* wdev->conn->params.bssid must be set if > SCANNING */ |
982 | err = __cfg80211_mlme_deauth(rdev, dev, | 950 | err = cfg80211_mlme_deauth(rdev, dev, |
983 | wdev->conn->params.bssid, | 951 | wdev->conn->params.bssid, |
984 | NULL, 0, reason, false); | 952 | NULL, 0, reason, false); |
985 | if (err) | 953 | if (err) |
@@ -1001,19 +969,6 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, | |||
1001 | return 0; | 969 | return 0; |
1002 | } | 970 | } |
1003 | 971 | ||
1004 | int cfg80211_disconnect(struct cfg80211_registered_device *rdev, | ||
1005 | struct net_device *dev, | ||
1006 | u16 reason, bool wextev) | ||
1007 | { | ||
1008 | int err; | ||
1009 | |||
1010 | wdev_lock(dev->ieee80211_ptr); | ||
1011 | err = __cfg80211_disconnect(rdev, dev, reason, wextev); | ||
1012 | wdev_unlock(dev->ieee80211_ptr); | ||
1013 | |||
1014 | return err; | ||
1015 | } | ||
1016 | |||
1017 | void cfg80211_sme_disassoc(struct net_device *dev, | 972 | void cfg80211_sme_disassoc(struct net_device *dev, |
1018 | struct cfg80211_internal_bss *bss) | 973 | struct cfg80211_internal_bss *bss) |
1019 | { | 974 | { |
@@ -1036,6 +991,6 @@ void cfg80211_sme_disassoc(struct net_device *dev, | |||
1036 | 991 | ||
1037 | memcpy(bssid, bss->pub.bssid, ETH_ALEN); | 992 | memcpy(bssid, bss->pub.bssid, ETH_ALEN); |
1038 | 993 | ||
1039 | __cfg80211_mlme_deauth(rdev, dev, bssid, NULL, 0, | 994 | cfg80211_mlme_deauth(rdev, dev, bssid, NULL, 0, |
1040 | WLAN_REASON_DEAUTH_LEAVING, false); | 995 | WLAN_REASON_DEAUTH_LEAVING, false); |
1041 | } | 996 | } |
diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c index 8f28b9f798d8..360a42c6f694 100644 --- a/net/wireless/sysfs.c +++ b/net/wireless/sysfs.c | |||
@@ -91,6 +91,7 @@ static void cfg80211_leave_all(struct cfg80211_registered_device *rdev) | |||
91 | cfg80211_leave(rdev, wdev); | 91 | cfg80211_leave(rdev, wdev); |
92 | } | 92 | } |
93 | 93 | ||
94 | #ifdef CONFIG_PM | ||
94 | static int wiphy_suspend(struct device *dev, pm_message_t state) | 95 | static int wiphy_suspend(struct device *dev, pm_message_t state) |
95 | { | 96 | { |
96 | struct cfg80211_registered_device *rdev = dev_to_rdev(dev); | 97 | struct cfg80211_registered_device *rdev = dev_to_rdev(dev); |
@@ -100,10 +101,10 @@ static int wiphy_suspend(struct device *dev, pm_message_t state) | |||
100 | 101 | ||
101 | rtnl_lock(); | 102 | rtnl_lock(); |
102 | if (rdev->wiphy.registered) { | 103 | if (rdev->wiphy.registered) { |
103 | if (!rdev->wowlan) | 104 | if (!rdev->wiphy.wowlan_config) |
104 | cfg80211_leave_all(rdev); | 105 | cfg80211_leave_all(rdev); |
105 | if (rdev->ops->suspend) | 106 | if (rdev->ops->suspend) |
106 | ret = rdev_suspend(rdev, rdev->wowlan); | 107 | ret = rdev_suspend(rdev, rdev->wiphy.wowlan_config); |
107 | if (ret == 1) { | 108 | if (ret == 1) { |
108 | /* Driver refuse to configure wowlan */ | 109 | /* Driver refuse to configure wowlan */ |
109 | cfg80211_leave_all(rdev); | 110 | cfg80211_leave_all(rdev); |
@@ -132,6 +133,7 @@ static int wiphy_resume(struct device *dev) | |||
132 | 133 | ||
133 | return ret; | 134 | return ret; |
134 | } | 135 | } |
136 | #endif | ||
135 | 137 | ||
136 | static const void *wiphy_namespace(struct device *d) | 138 | static const void *wiphy_namespace(struct device *d) |
137 | { | 139 | { |
@@ -146,8 +148,10 @@ struct class ieee80211_class = { | |||
146 | .dev_release = wiphy_dev_release, | 148 | .dev_release = wiphy_dev_release, |
147 | .dev_attrs = ieee80211_dev_attrs, | 149 | .dev_attrs = ieee80211_dev_attrs, |
148 | .dev_uevent = wiphy_uevent, | 150 | .dev_uevent = wiphy_uevent, |
151 | #ifdef CONFIG_PM | ||
149 | .suspend = wiphy_suspend, | 152 | .suspend = wiphy_suspend, |
150 | .resume = wiphy_resume, | 153 | .resume = wiphy_resume, |
154 | #endif | ||
151 | .ns_type = &net_ns_type_operations, | 155 | .ns_type = &net_ns_type_operations, |
152 | .namespace = wiphy_namespace, | 156 | .namespace = wiphy_namespace, |
153 | }; | 157 | }; |
diff --git a/net/wireless/trace.h b/net/wireless/trace.h index 5755bc14abbd..23fafeae8a10 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h | |||
@@ -1911,12 +1911,12 @@ TRACE_EVENT(cfg80211_send_rx_assoc, | |||
1911 | NETDEV_PR_ARG, MAC_PR_ARG(bssid), CHAN_PR_ARG) | 1911 | NETDEV_PR_ARG, MAC_PR_ARG(bssid), CHAN_PR_ARG) |
1912 | ); | 1912 | ); |
1913 | 1913 | ||
1914 | DEFINE_EVENT(netdev_evt_only, __cfg80211_send_deauth, | 1914 | DEFINE_EVENT(netdev_evt_only, cfg80211_send_deauth, |
1915 | TP_PROTO(struct net_device *netdev), | 1915 | TP_PROTO(struct net_device *netdev), |
1916 | TP_ARGS(netdev) | 1916 | TP_ARGS(netdev) |
1917 | ); | 1917 | ); |
1918 | 1918 | ||
1919 | DEFINE_EVENT(netdev_evt_only, __cfg80211_send_disassoc, | 1919 | DEFINE_EVENT(netdev_evt_only, cfg80211_send_disassoc, |
1920 | TP_PROTO(struct net_device *netdev), | 1920 | TP_PROTO(struct net_device *netdev), |
1921 | TP_ARGS(netdev) | 1921 | TP_ARGS(netdev) |
1922 | ); | 1922 | ); |
diff --git a/net/wireless/util.c b/net/wireless/util.c index f5ad4d94ba88..74458b7f61eb 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -33,6 +33,29 @@ ieee80211_get_response_rate(struct ieee80211_supported_band *sband, | |||
33 | } | 33 | } |
34 | EXPORT_SYMBOL(ieee80211_get_response_rate); | 34 | EXPORT_SYMBOL(ieee80211_get_response_rate); |
35 | 35 | ||
36 | u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband) | ||
37 | { | ||
38 | struct ieee80211_rate *bitrates; | ||
39 | u32 mandatory_rates = 0; | ||
40 | enum ieee80211_rate_flags mandatory_flag; | ||
41 | int i; | ||
42 | |||
43 | if (WARN_ON(!sband)) | ||
44 | return 1; | ||
45 | |||
46 | if (sband->band == IEEE80211_BAND_2GHZ) | ||
47 | mandatory_flag = IEEE80211_RATE_MANDATORY_B; | ||
48 | else | ||
49 | mandatory_flag = IEEE80211_RATE_MANDATORY_A; | ||
50 | |||
51 | bitrates = sband->bitrates; | ||
52 | for (i = 0; i < sband->n_bitrates; i++) | ||
53 | if (bitrates[i].flags & mandatory_flag) | ||
54 | mandatory_rates |= BIT(i); | ||
55 | return mandatory_rates; | ||
56 | } | ||
57 | EXPORT_SYMBOL(ieee80211_mandatory_rates); | ||
58 | |||
36 | int ieee80211_channel_to_frequency(int chan, enum ieee80211_band band) | 59 | int ieee80211_channel_to_frequency(int chan, enum ieee80211_band band) |
37 | { | 60 | { |
38 | /* see 802.11 17.3.8.3.2 and Annex J | 61 | /* see 802.11 17.3.8.3.2 and Annex J |
@@ -785,12 +808,8 @@ void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev) | |||
785 | ASSERT_RTNL(); | 808 | ASSERT_RTNL(); |
786 | ASSERT_RDEV_LOCK(rdev); | 809 | ASSERT_RDEV_LOCK(rdev); |
787 | 810 | ||
788 | mutex_lock(&rdev->devlist_mtx); | ||
789 | |||
790 | list_for_each_entry(wdev, &rdev->wdev_list, list) | 811 | list_for_each_entry(wdev, &rdev->wdev_list, list) |
791 | cfg80211_process_wdev_events(wdev); | 812 | cfg80211_process_wdev_events(wdev); |
792 | |||
793 | mutex_unlock(&rdev->devlist_mtx); | ||
794 | } | 813 | } |
795 | 814 | ||
796 | int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | 815 | int cfg80211_change_iface(struct cfg80211_registered_device *rdev, |
@@ -822,10 +841,8 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | |||
822 | return -EBUSY; | 841 | return -EBUSY; |
823 | 842 | ||
824 | if (ntype != otype && netif_running(dev)) { | 843 | if (ntype != otype && netif_running(dev)) { |
825 | mutex_lock(&rdev->devlist_mtx); | ||
826 | err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr, | 844 | err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr, |
827 | ntype); | 845 | ntype); |
828 | mutex_unlock(&rdev->devlist_mtx); | ||
829 | if (err) | 846 | if (err) |
830 | return err; | 847 | return err; |
831 | 848 | ||
@@ -841,8 +858,10 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | |||
841 | break; | 858 | break; |
842 | case NL80211_IFTYPE_STATION: | 859 | case NL80211_IFTYPE_STATION: |
843 | case NL80211_IFTYPE_P2P_CLIENT: | 860 | case NL80211_IFTYPE_P2P_CLIENT: |
861 | wdev_lock(dev->ieee80211_ptr); | ||
844 | cfg80211_disconnect(rdev, dev, | 862 | cfg80211_disconnect(rdev, dev, |
845 | WLAN_REASON_DEAUTH_LEAVING, true); | 863 | WLAN_REASON_DEAUTH_LEAVING, true); |
864 | wdev_unlock(dev->ieee80211_ptr); | ||
846 | break; | 865 | break; |
847 | case NL80211_IFTYPE_MESH_POINT: | 866 | case NL80211_IFTYPE_MESH_POINT: |
848 | /* mesh should be handled? */ | 867 | /* mesh should be handled? */ |
@@ -1169,6 +1188,9 @@ bool ieee80211_operating_class_to_band(u8 operating_class, | |||
1169 | case 84: | 1188 | case 84: |
1170 | *band = IEEE80211_BAND_2GHZ; | 1189 | *band = IEEE80211_BAND_2GHZ; |
1171 | return true; | 1190 | return true; |
1191 | case 180: | ||
1192 | *band = IEEE80211_BAND_60GHZ; | ||
1193 | return true; | ||
1172 | } | 1194 | } |
1173 | 1195 | ||
1174 | return false; | 1196 | return false; |
@@ -1184,8 +1206,6 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, | |||
1184 | if (!beacon_int) | 1206 | if (!beacon_int) |
1185 | return -EINVAL; | 1207 | return -EINVAL; |
1186 | 1208 | ||
1187 | mutex_lock(&rdev->devlist_mtx); | ||
1188 | |||
1189 | list_for_each_entry(wdev, &rdev->wdev_list, list) { | 1209 | list_for_each_entry(wdev, &rdev->wdev_list, list) { |
1190 | if (!wdev->beacon_interval) | 1210 | if (!wdev->beacon_interval) |
1191 | continue; | 1211 | continue; |
@@ -1195,8 +1215,6 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, | |||
1195 | } | 1215 | } |
1196 | } | 1216 | } |
1197 | 1217 | ||
1198 | mutex_unlock(&rdev->devlist_mtx); | ||
1199 | |||
1200 | return res; | 1218 | return res; |
1201 | } | 1219 | } |
1202 | 1220 | ||
@@ -1220,7 +1238,6 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | |||
1220 | int i, j; | 1238 | int i, j; |
1221 | 1239 | ||
1222 | ASSERT_RTNL(); | 1240 | ASSERT_RTNL(); |
1223 | lockdep_assert_held(&rdev->devlist_mtx); | ||
1224 | 1241 | ||
1225 | if (WARN_ON(hweight32(radar_detect) > 1)) | 1242 | if (WARN_ON(hweight32(radar_detect) > 1)) |
1226 | return -EINVAL; | 1243 | 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..a53f8404f451 100644 --- a/net/wireless/wext-sme.c +++ b/net/wireless/wext-sme.c | |||
@@ -54,8 +54,8 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev, | |||
54 | if (wdev->wext.prev_bssid_valid) | 54 | if (wdev->wext.prev_bssid_valid) |
55 | prev_bssid = wdev->wext.prev_bssid; | 55 | prev_bssid = wdev->wext.prev_bssid; |
56 | 56 | ||
57 | err = __cfg80211_connect(rdev, wdev->netdev, | 57 | err = cfg80211_connect(rdev, wdev->netdev, |
58 | &wdev->wext.connect, ck, prev_bssid); | 58 | &wdev->wext.connect, ck, prev_bssid); |
59 | if (err) | 59 | if (err) |
60 | kfree(ck); | 60 | kfree(ck); |
61 | 61 | ||
@@ -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) { |
@@ -103,8 +100,8 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev, | |||
103 | /* if SSID set, we'll try right again, avoid event */ | 100 | /* if SSID set, we'll try right again, avoid event */ |
104 | if (wdev->wext.connect.ssid_len) | 101 | if (wdev->wext.connect.ssid_len) |
105 | event = false; | 102 | event = false; |
106 | err = __cfg80211_disconnect(rdev, dev, | 103 | err = cfg80211_disconnect(rdev, dev, |
107 | WLAN_REASON_DEAUTH_LEAVING, event); | 104 | WLAN_REASON_DEAUTH_LEAVING, event); |
108 | if (err) | 105 | if (err) |
109 | goto out; | 106 | goto out; |
110 | } | 107 | } |
@@ -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; |
@@ -208,8 +199,8 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev, | |||
208 | /* if SSID set now, we'll try to connect, avoid event */ | 199 | /* if SSID set now, we'll try to connect, avoid event */ |
209 | if (len) | 200 | if (len) |
210 | event = false; | 201 | event = false; |
211 | err = __cfg80211_disconnect(rdev, dev, | 202 | err = cfg80211_disconnect(rdev, dev, |
212 | WLAN_REASON_DEAUTH_LEAVING, event); | 203 | WLAN_REASON_DEAUTH_LEAVING, event); |
213 | if (err) | 204 | if (err) |
214 | goto out; | 205 | goto out; |
215 | } | 206 | } |
@@ -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) { |
@@ -303,8 +288,8 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev, | |||
303 | ether_addr_equal(bssid, wdev->wext.connect.bssid)) | 288 | ether_addr_equal(bssid, wdev->wext.connect.bssid)) |
304 | goto out; | 289 | goto out; |
305 | 290 | ||
306 | err = __cfg80211_disconnect(rdev, dev, | 291 | err = cfg80211_disconnect(rdev, dev, |
307 | WLAN_REASON_DEAUTH_LEAVING, false); | 292 | WLAN_REASON_DEAUTH_LEAVING, false); |
308 | if (err) | 293 | if (err) |
309 | goto out; | 294 | goto out; |
310 | } | 295 | } |
@@ -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 | ||
@@ -383,8 +365,8 @@ int cfg80211_wext_siwgenie(struct net_device *dev, | |||
383 | wdev->wext.ie_len = ie_len; | 365 | wdev->wext.ie_len = ie_len; |
384 | 366 | ||
385 | if (wdev->sme_state != CFG80211_SME_IDLE) { | 367 | if (wdev->sme_state != CFG80211_SME_IDLE) { |
386 | err = __cfg80211_disconnect(rdev, dev, | 368 | err = cfg80211_disconnect(rdev, dev, |
387 | WLAN_REASON_DEAUTH_LEAVING, false); | 369 | WLAN_REASON_DEAUTH_LEAVING, false); |
388 | if (err) | 370 | if (err) |
389 | goto out; | 371 | goto out; |
390 | } | 372 | } |
@@ -420,8 +402,7 @@ int cfg80211_wext_siwmlme(struct net_device *dev, | |||
420 | switch (mlme->cmd) { | 402 | switch (mlme->cmd) { |
421 | case IW_MLME_DEAUTH: | 403 | case IW_MLME_DEAUTH: |
422 | case IW_MLME_DISASSOC: | 404 | case IW_MLME_DISASSOC: |
423 | err = __cfg80211_disconnect(rdev, dev, mlme->reason_code, | 405 | err = cfg80211_disconnect(rdev, dev, mlme->reason_code, true); |
424 | true); | ||
425 | break; | 406 | break; |
426 | default: | 407 | default: |
427 | err = -EOPNOTSUPP; | 408 | err = -EOPNOTSUPP; |