diff options
-rw-r--r-- | net/wireless/core.c | 64 | ||||
-rw-r--r-- | net/wireless/core.h | 3 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 52 | ||||
-rw-r--r-- | net/wireless/scan.c | 8 | ||||
-rw-r--r-- | net/wireless/sme.c | 6 | ||||
-rw-r--r-- | net/wireless/wext-sme.c | 6 |
6 files changed, 92 insertions, 47 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c index 922002105062..11743d48cbc2 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -212,6 +212,39 @@ static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data) | |||
212 | rdev_rfkill_poll(rdev); | 212 | rdev_rfkill_poll(rdev); |
213 | } | 213 | } |
214 | 214 | ||
215 | void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, | ||
216 | struct wireless_dev *wdev) | ||
217 | { | ||
218 | lockdep_assert_held(&rdev->devlist_mtx); | ||
219 | lockdep_assert_held(&rdev->sched_scan_mtx); | ||
220 | |||
221 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)) | ||
222 | return; | ||
223 | |||
224 | if (!wdev->p2p_started) | ||
225 | return; | ||
226 | |||
227 | rdev_stop_p2p_device(rdev, wdev); | ||
228 | wdev->p2p_started = false; | ||
229 | |||
230 | rdev->opencount--; | ||
231 | |||
232 | if (rdev->scan_req && rdev->scan_req->wdev == wdev) { | ||
233 | bool busy = work_busy(&rdev->scan_done_wk); | ||
234 | |||
235 | /* | ||
236 | * If the work isn't pending or running (in which case it would | ||
237 | * be waiting for the lock we hold) the driver didn't properly | ||
238 | * cancel the scan when the interface was removed. In this case | ||
239 | * warn and leak the scan request object to not crash later. | ||
240 | */ | ||
241 | WARN_ON(!busy); | ||
242 | |||
243 | rdev->scan_req->aborted = true; | ||
244 | ___cfg80211_scan_done(rdev, !busy); | ||
245 | } | ||
246 | } | ||
247 | |||
215 | static int cfg80211_rfkill_set_block(void *data, bool blocked) | 248 | static int cfg80211_rfkill_set_block(void *data, bool blocked) |
216 | { | 249 | { |
217 | struct cfg80211_registered_device *rdev = data; | 250 | struct cfg80211_registered_device *rdev = data; |
@@ -221,7 +254,8 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked) | |||
221 | return 0; | 254 | return 0; |
222 | 255 | ||
223 | rtnl_lock(); | 256 | rtnl_lock(); |
224 | mutex_lock(&rdev->devlist_mtx); | 257 | |
258 | /* read-only iteration need not hold the devlist_mtx */ | ||
225 | 259 | ||
226 | list_for_each_entry(wdev, &rdev->wdev_list, list) { | 260 | list_for_each_entry(wdev, &rdev->wdev_list, list) { |
227 | if (wdev->netdev) { | 261 | if (wdev->netdev) { |
@@ -231,18 +265,18 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked) | |||
231 | /* otherwise, check iftype */ | 265 | /* otherwise, check iftype */ |
232 | switch (wdev->iftype) { | 266 | switch (wdev->iftype) { |
233 | case NL80211_IFTYPE_P2P_DEVICE: | 267 | case NL80211_IFTYPE_P2P_DEVICE: |
234 | if (!wdev->p2p_started) | 268 | /* but this requires it */ |
235 | break; | 269 | mutex_lock(&rdev->devlist_mtx); |
236 | rdev_stop_p2p_device(rdev, wdev); | 270 | mutex_lock(&rdev->sched_scan_mtx); |
237 | wdev->p2p_started = false; | 271 | cfg80211_stop_p2p_device(rdev, wdev); |
238 | rdev->opencount--; | 272 | mutex_unlock(&rdev->sched_scan_mtx); |
273 | mutex_unlock(&rdev->devlist_mtx); | ||
239 | break; | 274 | break; |
240 | default: | 275 | default: |
241 | break; | 276 | break; |
242 | } | 277 | } |
243 | } | 278 | } |
244 | 279 | ||
245 | mutex_unlock(&rdev->devlist_mtx); | ||
246 | rtnl_unlock(); | 280 | rtnl_unlock(); |
247 | 281 | ||
248 | return 0; | 282 | return 0; |
@@ -745,17 +779,13 @@ static void wdev_cleanup_work(struct work_struct *work) | |||
745 | wdev = container_of(work, struct wireless_dev, cleanup_work); | 779 | wdev = container_of(work, struct wireless_dev, cleanup_work); |
746 | rdev = wiphy_to_dev(wdev->wiphy); | 780 | rdev = wiphy_to_dev(wdev->wiphy); |
747 | 781 | ||
748 | cfg80211_lock_rdev(rdev); | 782 | mutex_lock(&rdev->sched_scan_mtx); |
749 | 783 | ||
750 | if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) { | 784 | if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) { |
751 | rdev->scan_req->aborted = true; | 785 | rdev->scan_req->aborted = true; |
752 | ___cfg80211_scan_done(rdev, true); | 786 | ___cfg80211_scan_done(rdev, true); |
753 | } | 787 | } |
754 | 788 | ||
755 | cfg80211_unlock_rdev(rdev); | ||
756 | |||
757 | mutex_lock(&rdev->sched_scan_mtx); | ||
758 | |||
759 | if (WARN_ON(rdev->sched_scan_req && | 789 | if (WARN_ON(rdev->sched_scan_req && |
760 | rdev->sched_scan_req->dev == wdev->netdev)) { | 790 | rdev->sched_scan_req->dev == wdev->netdev)) { |
761 | __cfg80211_stop_sched_scan(rdev, false); | 791 | __cfg80211_stop_sched_scan(rdev, false); |
@@ -781,21 +811,19 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev) | |||
781 | return; | 811 | return; |
782 | 812 | ||
783 | mutex_lock(&rdev->devlist_mtx); | 813 | mutex_lock(&rdev->devlist_mtx); |
814 | mutex_lock(&rdev->sched_scan_mtx); | ||
784 | list_del_rcu(&wdev->list); | 815 | list_del_rcu(&wdev->list); |
785 | rdev->devlist_generation++; | 816 | rdev->devlist_generation++; |
786 | 817 | ||
787 | switch (wdev->iftype) { | 818 | switch (wdev->iftype) { |
788 | case NL80211_IFTYPE_P2P_DEVICE: | 819 | case NL80211_IFTYPE_P2P_DEVICE: |
789 | if (!wdev->p2p_started) | 820 | cfg80211_stop_p2p_device(rdev, wdev); |
790 | break; | ||
791 | rdev_stop_p2p_device(rdev, wdev); | ||
792 | wdev->p2p_started = false; | ||
793 | rdev->opencount--; | ||
794 | break; | 821 | break; |
795 | default: | 822 | default: |
796 | WARN_ON_ONCE(1); | 823 | WARN_ON_ONCE(1); |
797 | break; | 824 | break; |
798 | } | 825 | } |
826 | mutex_unlock(&rdev->sched_scan_mtx); | ||
799 | mutex_unlock(&rdev->devlist_mtx); | 827 | mutex_unlock(&rdev->devlist_mtx); |
800 | } | 828 | } |
801 | EXPORT_SYMBOL(cfg80211_unregister_wdev); | 829 | EXPORT_SYMBOL(cfg80211_unregister_wdev); |
@@ -937,6 +965,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | |||
937 | cfg80211_update_iface_num(rdev, wdev->iftype, 1); | 965 | cfg80211_update_iface_num(rdev, wdev->iftype, 1); |
938 | cfg80211_lock_rdev(rdev); | 966 | cfg80211_lock_rdev(rdev); |
939 | mutex_lock(&rdev->devlist_mtx); | 967 | mutex_lock(&rdev->devlist_mtx); |
968 | mutex_lock(&rdev->sched_scan_mtx); | ||
940 | wdev_lock(wdev); | 969 | wdev_lock(wdev); |
941 | switch (wdev->iftype) { | 970 | switch (wdev->iftype) { |
942 | #ifdef CONFIG_CFG80211_WEXT | 971 | #ifdef CONFIG_CFG80211_WEXT |
@@ -968,6 +997,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | |||
968 | break; | 997 | break; |
969 | } | 998 | } |
970 | wdev_unlock(wdev); | 999 | wdev_unlock(wdev); |
1000 | mutex_unlock(&rdev->sched_scan_mtx); | ||
971 | rdev->opencount++; | 1001 | rdev->opencount++; |
972 | mutex_unlock(&rdev->devlist_mtx); | 1002 | mutex_unlock(&rdev->devlist_mtx); |
973 | cfg80211_unlock_rdev(rdev); | 1003 | cfg80211_unlock_rdev(rdev); |
diff --git a/net/wireless/core.h b/net/wireless/core.h index 3aec0e429d8a..5845c2b37aa8 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -503,6 +503,9 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, | |||
503 | void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, | 503 | void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, |
504 | enum nl80211_iftype iftype, int num); | 504 | enum nl80211_iftype iftype, int num); |
505 | 505 | ||
506 | void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, | ||
507 | struct wireless_dev *wdev); | ||
508 | |||
506 | #define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10 | 509 | #define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10 |
507 | 510 | ||
508 | #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS | 511 | #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index d44ab216c0ec..58e13a8c95f9 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -4702,14 +4702,19 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
4702 | if (!rdev->ops->scan) | 4702 | if (!rdev->ops->scan) |
4703 | return -EOPNOTSUPP; | 4703 | return -EOPNOTSUPP; |
4704 | 4704 | ||
4705 | if (rdev->scan_req) | 4705 | mutex_lock(&rdev->sched_scan_mtx); |
4706 | return -EBUSY; | 4706 | if (rdev->scan_req) { |
4707 | err = -EBUSY; | ||
4708 | goto unlock; | ||
4709 | } | ||
4707 | 4710 | ||
4708 | if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { | 4711 | if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { |
4709 | n_channels = validate_scan_freqs( | 4712 | n_channels = validate_scan_freqs( |
4710 | info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]); | 4713 | info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]); |
4711 | if (!n_channels) | 4714 | if (!n_channels) { |
4712 | return -EINVAL; | 4715 | err = -EINVAL; |
4716 | goto unlock; | ||
4717 | } | ||
4713 | } else { | 4718 | } else { |
4714 | enum ieee80211_band band; | 4719 | enum ieee80211_band band; |
4715 | n_channels = 0; | 4720 | n_channels = 0; |
@@ -4723,23 +4728,29 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
4723 | nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) | 4728 | nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) |
4724 | n_ssids++; | 4729 | n_ssids++; |
4725 | 4730 | ||
4726 | if (n_ssids > wiphy->max_scan_ssids) | 4731 | if (n_ssids > wiphy->max_scan_ssids) { |
4727 | return -EINVAL; | 4732 | err = -EINVAL; |
4733 | goto unlock; | ||
4734 | } | ||
4728 | 4735 | ||
4729 | if (info->attrs[NL80211_ATTR_IE]) | 4736 | if (info->attrs[NL80211_ATTR_IE]) |
4730 | ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); | 4737 | ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); |
4731 | else | 4738 | else |
4732 | ie_len = 0; | 4739 | ie_len = 0; |
4733 | 4740 | ||
4734 | if (ie_len > wiphy->max_scan_ie_len) | 4741 | if (ie_len > wiphy->max_scan_ie_len) { |
4735 | return -EINVAL; | 4742 | err = -EINVAL; |
4743 | goto unlock; | ||
4744 | } | ||
4736 | 4745 | ||
4737 | request = kzalloc(sizeof(*request) | 4746 | request = kzalloc(sizeof(*request) |
4738 | + sizeof(*request->ssids) * n_ssids | 4747 | + sizeof(*request->ssids) * n_ssids |
4739 | + sizeof(*request->channels) * n_channels | 4748 | + sizeof(*request->channels) * n_channels |
4740 | + ie_len, GFP_KERNEL); | 4749 | + ie_len, GFP_KERNEL); |
4741 | if (!request) | 4750 | if (!request) { |
4742 | return -ENOMEM; | 4751 | err = -ENOMEM; |
4752 | goto unlock; | ||
4753 | } | ||
4743 | 4754 | ||
4744 | if (n_ssids) | 4755 | if (n_ssids) |
4745 | request->ssids = (void *)&request->channels[n_channels]; | 4756 | request->ssids = (void *)&request->channels[n_channels]; |
@@ -4876,6 +4887,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
4876 | kfree(request); | 4887 | kfree(request); |
4877 | } | 4888 | } |
4878 | 4889 | ||
4890 | unlock: | ||
4891 | mutex_unlock(&rdev->sched_scan_mtx); | ||
4879 | return err; | 4892 | return err; |
4880 | } | 4893 | } |
4881 | 4894 | ||
@@ -7749,20 +7762,9 @@ static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info) | |||
7749 | if (!rdev->ops->stop_p2p_device) | 7762 | if (!rdev->ops->stop_p2p_device) |
7750 | return -EOPNOTSUPP; | 7763 | return -EOPNOTSUPP; |
7751 | 7764 | ||
7752 | if (!wdev->p2p_started) | 7765 | mutex_lock(&rdev->sched_scan_mtx); |
7753 | return 0; | 7766 | cfg80211_stop_p2p_device(rdev, wdev); |
7754 | 7767 | mutex_unlock(&rdev->sched_scan_mtx); | |
7755 | rdev_stop_p2p_device(rdev, wdev); | ||
7756 | wdev->p2p_started = false; | ||
7757 | |||
7758 | mutex_lock(&rdev->devlist_mtx); | ||
7759 | rdev->opencount--; | ||
7760 | mutex_unlock(&rdev->devlist_mtx); | ||
7761 | |||
7762 | if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) { | ||
7763 | rdev->scan_req->aborted = true; | ||
7764 | ___cfg80211_scan_done(rdev, true); | ||
7765 | } | ||
7766 | 7768 | ||
7767 | return 0; | 7769 | return 0; |
7768 | } | 7770 | } |
@@ -8486,7 +8488,7 @@ static int nl80211_add_scan_req(struct sk_buff *msg, | |||
8486 | struct nlattr *nest; | 8488 | struct nlattr *nest; |
8487 | int i; | 8489 | int i; |
8488 | 8490 | ||
8489 | ASSERT_RDEV_LOCK(rdev); | 8491 | lockdep_assert_held(&rdev->sched_scan_mtx); |
8490 | 8492 | ||
8491 | if (WARN_ON(!req)) | 8493 | if (WARN_ON(!req)) |
8492 | return 0; | 8494 | return 0; |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index e93bd31d23bb..fd99ea495b7e 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 | ASSERT_RDEV_LOCK(rdev); | 172 | lockdep_assert_held(&rdev->sched_scan_mtx); |
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 | cfg80211_lock_rdev(rdev); | 233 | mutex_lock(&rdev->sched_scan_mtx); |
234 | ___cfg80211_scan_done(rdev, false); | 234 | ___cfg80211_scan_done(rdev, false); |
235 | cfg80211_unlock_rdev(rdev); | 235 | mutex_unlock(&rdev->sched_scan_mtx); |
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) |
@@ -1062,6 +1062,7 @@ int cfg80211_wext_siwscan(struct net_device *dev, | |||
1062 | if (IS_ERR(rdev)) | 1062 | if (IS_ERR(rdev)) |
1063 | return PTR_ERR(rdev); | 1063 | return PTR_ERR(rdev); |
1064 | 1064 | ||
1065 | mutex_lock(&rdev->sched_scan_mtx); | ||
1065 | if (rdev->scan_req) { | 1066 | if (rdev->scan_req) { |
1066 | err = -EBUSY; | 1067 | err = -EBUSY; |
1067 | goto out; | 1068 | goto out; |
@@ -1168,6 +1169,7 @@ int cfg80211_wext_siwscan(struct net_device *dev, | |||
1168 | dev_hold(dev); | 1169 | dev_hold(dev); |
1169 | } | 1170 | } |
1170 | out: | 1171 | out: |
1172 | mutex_unlock(&rdev->sched_scan_mtx); | ||
1171 | kfree(creq); | 1173 | kfree(creq); |
1172 | cfg80211_unlock_rdev(rdev); | 1174 | cfg80211_unlock_rdev(rdev); |
1173 | return err; | 1175 | return err; |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index f432bd3755b1..09d994d192ff 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -85,6 +85,7 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev) | |||
85 | ASSERT_RTNL(); | 85 | ASSERT_RTNL(); |
86 | ASSERT_RDEV_LOCK(rdev); | 86 | ASSERT_RDEV_LOCK(rdev); |
87 | ASSERT_WDEV_LOCK(wdev); | 87 | ASSERT_WDEV_LOCK(wdev); |
88 | lockdep_assert_held(&rdev->sched_scan_mtx); | ||
88 | 89 | ||
89 | if (rdev->scan_req) | 90 | if (rdev->scan_req) |
90 | return -EBUSY; | 91 | return -EBUSY; |
@@ -320,11 +321,9 @@ void cfg80211_sme_scan_done(struct net_device *dev) | |||
320 | { | 321 | { |
321 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 322 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
322 | 323 | ||
323 | mutex_lock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx); | ||
324 | wdev_lock(wdev); | 324 | wdev_lock(wdev); |
325 | __cfg80211_sme_scan_done(dev); | 325 | __cfg80211_sme_scan_done(dev); |
326 | wdev_unlock(wdev); | 326 | wdev_unlock(wdev); |
327 | mutex_unlock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx); | ||
328 | } | 327 | } |
329 | 328 | ||
330 | void cfg80211_sme_rx_auth(struct net_device *dev, | 329 | void cfg80211_sme_rx_auth(struct net_device *dev, |
@@ -924,9 +923,12 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev, | |||
924 | int err; | 923 | int err; |
925 | 924 | ||
926 | mutex_lock(&rdev->devlist_mtx); | 925 | mutex_lock(&rdev->devlist_mtx); |
926 | /* might request scan - scan_mtx -> wdev_mtx dependency */ | ||
927 | mutex_lock(&rdev->sched_scan_mtx); | ||
927 | wdev_lock(dev->ieee80211_ptr); | 928 | wdev_lock(dev->ieee80211_ptr); |
928 | err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL); | 929 | err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL); |
929 | wdev_unlock(dev->ieee80211_ptr); | 930 | wdev_unlock(dev->ieee80211_ptr); |
931 | mutex_unlock(&rdev->sched_scan_mtx); | ||
930 | mutex_unlock(&rdev->devlist_mtx); | 932 | mutex_unlock(&rdev->devlist_mtx); |
931 | 933 | ||
932 | return err; | 934 | return err; |
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c index fb9622f6d99c..e79cb5c0655a 100644 --- a/net/wireless/wext-sme.c +++ b/net/wireless/wext-sme.c | |||
@@ -89,6 +89,7 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev, | |||
89 | 89 | ||
90 | cfg80211_lock_rdev(rdev); | 90 | cfg80211_lock_rdev(rdev); |
91 | mutex_lock(&rdev->devlist_mtx); | 91 | mutex_lock(&rdev->devlist_mtx); |
92 | mutex_lock(&rdev->sched_scan_mtx); | ||
92 | wdev_lock(wdev); | 93 | wdev_lock(wdev); |
93 | 94 | ||
94 | if (wdev->sme_state != CFG80211_SME_IDLE) { | 95 | if (wdev->sme_state != CFG80211_SME_IDLE) { |
@@ -135,6 +136,7 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev, | |||
135 | err = cfg80211_mgd_wext_connect(rdev, wdev); | 136 | err = cfg80211_mgd_wext_connect(rdev, wdev); |
136 | out: | 137 | out: |
137 | wdev_unlock(wdev); | 138 | wdev_unlock(wdev); |
139 | mutex_unlock(&rdev->sched_scan_mtx); | ||
138 | mutex_unlock(&rdev->devlist_mtx); | 140 | mutex_unlock(&rdev->devlist_mtx); |
139 | cfg80211_unlock_rdev(rdev); | 141 | cfg80211_unlock_rdev(rdev); |
140 | return err; | 142 | return err; |
@@ -190,6 +192,7 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev, | |||
190 | 192 | ||
191 | cfg80211_lock_rdev(rdev); | 193 | cfg80211_lock_rdev(rdev); |
192 | mutex_lock(&rdev->devlist_mtx); | 194 | mutex_lock(&rdev->devlist_mtx); |
195 | mutex_lock(&rdev->sched_scan_mtx); | ||
193 | wdev_lock(wdev); | 196 | wdev_lock(wdev); |
194 | 197 | ||
195 | err = 0; | 198 | err = 0; |
@@ -223,6 +226,7 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev, | |||
223 | err = cfg80211_mgd_wext_connect(rdev, wdev); | 226 | err = cfg80211_mgd_wext_connect(rdev, wdev); |
224 | out: | 227 | out: |
225 | wdev_unlock(wdev); | 228 | wdev_unlock(wdev); |
229 | mutex_unlock(&rdev->sched_scan_mtx); | ||
226 | mutex_unlock(&rdev->devlist_mtx); | 230 | mutex_unlock(&rdev->devlist_mtx); |
227 | cfg80211_unlock_rdev(rdev); | 231 | cfg80211_unlock_rdev(rdev); |
228 | return err; | 232 | return err; |
@@ -285,6 +289,7 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev, | |||
285 | 289 | ||
286 | cfg80211_lock_rdev(rdev); | 290 | cfg80211_lock_rdev(rdev); |
287 | mutex_lock(&rdev->devlist_mtx); | 291 | mutex_lock(&rdev->devlist_mtx); |
292 | mutex_lock(&rdev->sched_scan_mtx); | ||
288 | wdev_lock(wdev); | 293 | wdev_lock(wdev); |
289 | 294 | ||
290 | if (wdev->sme_state != CFG80211_SME_IDLE) { | 295 | if (wdev->sme_state != CFG80211_SME_IDLE) { |
@@ -313,6 +318,7 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev, | |||
313 | err = cfg80211_mgd_wext_connect(rdev, wdev); | 318 | err = cfg80211_mgd_wext_connect(rdev, wdev); |
314 | out: | 319 | out: |
315 | wdev_unlock(wdev); | 320 | wdev_unlock(wdev); |
321 | mutex_unlock(&rdev->sched_scan_mtx); | ||
316 | mutex_unlock(&rdev->devlist_mtx); | 322 | mutex_unlock(&rdev->devlist_mtx); |
317 | cfg80211_unlock_rdev(rdev); | 323 | cfg80211_unlock_rdev(rdev); |
318 | return err; | 324 | return err; |