diff options
author | Johannes Berg <johannes.berg@intel.com> | 2013-04-22 09:31:43 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-04-22 09:31:43 -0400 |
commit | a42c74ee608a424342ef7069ccddf196d873040c (patch) | |
tree | 75adfb9f5e06ebb7c7d5d5e5a5408fa0d6d504b9 /net/wireless | |
parent | 97990a060e6757f48b931a3946b17c1c4362c3fb (diff) | |
parent | 9b383672452bb1097124c76fcb4903e0021f6baf (diff) |
Merge remote-tracking branch 'wireless-next/master' into mac80211-next
Diffstat (limited to 'net/wireless')
-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 | 24 | ||||
-rw-r--r-- | net/wireless/sme.c | 8 | ||||
-rw-r--r-- | net/wireless/trace.h | 5 | ||||
-rw-r--r-- | net/wireless/wext-sme.c | 6 |
7 files changed, 108 insertions, 54 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c index 92e3fd44e3b0..84c9ad7e1dca 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); |
@@ -945,6 +973,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | |||
945 | cfg80211_update_iface_num(rdev, wdev->iftype, 1); | 973 | cfg80211_update_iface_num(rdev, wdev->iftype, 1); |
946 | cfg80211_lock_rdev(rdev); | 974 | cfg80211_lock_rdev(rdev); |
947 | mutex_lock(&rdev->devlist_mtx); | 975 | mutex_lock(&rdev->devlist_mtx); |
976 | mutex_lock(&rdev->sched_scan_mtx); | ||
948 | wdev_lock(wdev); | 977 | wdev_lock(wdev); |
949 | switch (wdev->iftype) { | 978 | switch (wdev->iftype) { |
950 | #ifdef CONFIG_CFG80211_WEXT | 979 | #ifdef CONFIG_CFG80211_WEXT |
@@ -976,6 +1005,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | |||
976 | break; | 1005 | break; |
977 | } | 1006 | } |
978 | wdev_unlock(wdev); | 1007 | wdev_unlock(wdev); |
1008 | mutex_unlock(&rdev->sched_scan_mtx); | ||
979 | rdev->opencount++; | 1009 | rdev->opencount++; |
980 | mutex_unlock(&rdev->devlist_mtx); | 1010 | mutex_unlock(&rdev->devlist_mtx); |
981 | cfg80211_unlock_rdev(rdev); | 1011 | cfg80211_unlock_rdev(rdev); |
diff --git a/net/wireless/core.h b/net/wireless/core.h index d5d06fdea961..124e5e773fbc 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -503,6 +503,9 @@ void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, | |||
503 | void cfg80211_leave(struct cfg80211_registered_device *rdev, | 503 | void cfg80211_leave(struct cfg80211_registered_device *rdev, |
504 | struct wireless_dev *wdev); | 504 | struct wireless_dev *wdev); |
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 8c8a57937b22..212d2aa7a1c5 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -5060,14 +5060,19 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
5060 | if (!rdev->ops->scan) | 5060 | if (!rdev->ops->scan) |
5061 | return -EOPNOTSUPP; | 5061 | return -EOPNOTSUPP; |
5062 | 5062 | ||
5063 | if (rdev->scan_req) | 5063 | mutex_lock(&rdev->sched_scan_mtx); |
5064 | return -EBUSY; | 5064 | if (rdev->scan_req) { |
5065 | err = -EBUSY; | ||
5066 | goto unlock; | ||
5067 | } | ||
5065 | 5068 | ||
5066 | if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { | 5069 | if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { |
5067 | n_channels = validate_scan_freqs( | 5070 | n_channels = validate_scan_freqs( |
5068 | info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]); | 5071 | info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]); |
5069 | if (!n_channels) | 5072 | if (!n_channels) { |
5070 | return -EINVAL; | 5073 | err = -EINVAL; |
5074 | goto unlock; | ||
5075 | } | ||
5071 | } else { | 5076 | } else { |
5072 | enum ieee80211_band band; | 5077 | enum ieee80211_band band; |
5073 | n_channels = 0; | 5078 | n_channels = 0; |
@@ -5081,23 +5086,29 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
5081 | nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) | 5086 | nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) |
5082 | n_ssids++; | 5087 | n_ssids++; |
5083 | 5088 | ||
5084 | if (n_ssids > wiphy->max_scan_ssids) | 5089 | if (n_ssids > wiphy->max_scan_ssids) { |
5085 | return -EINVAL; | 5090 | err = -EINVAL; |
5091 | goto unlock; | ||
5092 | } | ||
5086 | 5093 | ||
5087 | if (info->attrs[NL80211_ATTR_IE]) | 5094 | if (info->attrs[NL80211_ATTR_IE]) |
5088 | ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); | 5095 | ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); |
5089 | else | 5096 | else |
5090 | ie_len = 0; | 5097 | ie_len = 0; |
5091 | 5098 | ||
5092 | if (ie_len > wiphy->max_scan_ie_len) | 5099 | if (ie_len > wiphy->max_scan_ie_len) { |
5093 | return -EINVAL; | 5100 | err = -EINVAL; |
5101 | goto unlock; | ||
5102 | } | ||
5094 | 5103 | ||
5095 | request = kzalloc(sizeof(*request) | 5104 | request = kzalloc(sizeof(*request) |
5096 | + sizeof(*request->ssids) * n_ssids | 5105 | + sizeof(*request->ssids) * n_ssids |
5097 | + sizeof(*request->channels) * n_channels | 5106 | + sizeof(*request->channels) * n_channels |
5098 | + ie_len, GFP_KERNEL); | 5107 | + ie_len, GFP_KERNEL); |
5099 | if (!request) | 5108 | if (!request) { |
5100 | return -ENOMEM; | 5109 | err = -ENOMEM; |
5110 | goto unlock; | ||
5111 | } | ||
5101 | 5112 | ||
5102 | if (n_ssids) | 5113 | if (n_ssids) |
5103 | request->ssids = (void *)&request->channels[n_channels]; | 5114 | request->ssids = (void *)&request->channels[n_channels]; |
@@ -5234,6 +5245,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
5234 | kfree(request); | 5245 | kfree(request); |
5235 | } | 5246 | } |
5236 | 5247 | ||
5248 | unlock: | ||
5249 | mutex_unlock(&rdev->sched_scan_mtx); | ||
5237 | return err; | 5250 | return err; |
5238 | } | 5251 | } |
5239 | 5252 | ||
@@ -8146,20 +8159,9 @@ static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info) | |||
8146 | if (!rdev->ops->stop_p2p_device) | 8159 | if (!rdev->ops->stop_p2p_device) |
8147 | return -EOPNOTSUPP; | 8160 | return -EOPNOTSUPP; |
8148 | 8161 | ||
8149 | if (!wdev->p2p_started) | 8162 | mutex_lock(&rdev->sched_scan_mtx); |
8150 | return 0; | 8163 | cfg80211_stop_p2p_device(rdev, wdev); |
8151 | 8164 | mutex_unlock(&rdev->sched_scan_mtx); | |
8152 | rdev_stop_p2p_device(rdev, wdev); | ||
8153 | wdev->p2p_started = false; | ||
8154 | |||
8155 | mutex_lock(&rdev->devlist_mtx); | ||
8156 | rdev->opencount--; | ||
8157 | mutex_unlock(&rdev->devlist_mtx); | ||
8158 | |||
8159 | if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) { | ||
8160 | rdev->scan_req->aborted = true; | ||
8161 | ___cfg80211_scan_done(rdev, true); | ||
8162 | } | ||
8163 | 8165 | ||
8164 | return 0; | 8166 | return 0; |
8165 | } | 8167 | } |
@@ -8945,7 +8947,7 @@ static int nl80211_add_scan_req(struct sk_buff *msg, | |||
8945 | struct nlattr *nest; | 8947 | struct nlattr *nest; |
8946 | int i; | 8948 | int i; |
8947 | 8949 | ||
8948 | ASSERT_RDEV_LOCK(rdev); | 8950 | lockdep_assert_held(&rdev->sched_scan_mtx); |
8949 | 8951 | ||
8950 | if (WARN_ON(!req)) | 8952 | if (WARN_ON(!req)) |
8951 | return 0; | 8953 | return 0; |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 674aadca0079..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) |
@@ -698,11 +698,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
698 | found = rb_find_bss(dev, tmp, BSS_CMP_REGULAR); | 698 | found = rb_find_bss(dev, tmp, BSS_CMP_REGULAR); |
699 | 699 | ||
700 | if (found) { | 700 | if (found) { |
701 | found->pub.beacon_interval = tmp->pub.beacon_interval; | ||
702 | found->pub.signal = tmp->pub.signal; | ||
703 | found->pub.capability = tmp->pub.capability; | ||
704 | found->ts = tmp->ts; | ||
705 | |||
706 | /* Update IEs */ | 701 | /* Update IEs */ |
707 | if (rcu_access_pointer(tmp->pub.proberesp_ies)) { | 702 | if (rcu_access_pointer(tmp->pub.proberesp_ies)) { |
708 | const struct cfg80211_bss_ies *old; | 703 | const struct cfg80211_bss_ies *old; |
@@ -723,6 +718,8 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
723 | 718 | ||
724 | if (found->pub.hidden_beacon_bss && | 719 | if (found->pub.hidden_beacon_bss && |
725 | !list_empty(&found->hidden_list)) { | 720 | !list_empty(&found->hidden_list)) { |
721 | const struct cfg80211_bss_ies *f; | ||
722 | |||
726 | /* | 723 | /* |
727 | * The found BSS struct is one of the probe | 724 | * The found BSS struct is one of the probe |
728 | * response members of a group, but we're | 725 | * response members of a group, but we're |
@@ -732,6 +729,10 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
732 | * SSID to showing it, which is confusing so | 729 | * SSID to showing it, which is confusing so |
733 | * drop this information. | 730 | * drop this information. |
734 | */ | 731 | */ |
732 | |||
733 | f = rcu_access_pointer(tmp->pub.beacon_ies); | ||
734 | kfree_rcu((struct cfg80211_bss_ies *)f, | ||
735 | rcu_head); | ||
735 | goto drop; | 736 | goto drop; |
736 | } | 737 | } |
737 | 738 | ||
@@ -761,6 +762,11 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
761 | kfree_rcu((struct cfg80211_bss_ies *)old, | 762 | kfree_rcu((struct cfg80211_bss_ies *)old, |
762 | rcu_head); | 763 | rcu_head); |
763 | } | 764 | } |
765 | |||
766 | found->pub.beacon_interval = tmp->pub.beacon_interval; | ||
767 | found->pub.signal = tmp->pub.signal; | ||
768 | found->pub.capability = tmp->pub.capability; | ||
769 | found->ts = tmp->ts; | ||
764 | } else { | 770 | } else { |
765 | struct cfg80211_internal_bss *new; | 771 | struct cfg80211_internal_bss *new; |
766 | struct cfg80211_internal_bss *hidden; | 772 | struct cfg80211_internal_bss *hidden; |
@@ -1056,6 +1062,7 @@ int cfg80211_wext_siwscan(struct net_device *dev, | |||
1056 | if (IS_ERR(rdev)) | 1062 | if (IS_ERR(rdev)) |
1057 | return PTR_ERR(rdev); | 1063 | return PTR_ERR(rdev); |
1058 | 1064 | ||
1065 | mutex_lock(&rdev->sched_scan_mtx); | ||
1059 | if (rdev->scan_req) { | 1066 | if (rdev->scan_req) { |
1060 | err = -EBUSY; | 1067 | err = -EBUSY; |
1061 | goto out; | 1068 | goto out; |
@@ -1162,6 +1169,7 @@ int cfg80211_wext_siwscan(struct net_device *dev, | |||
1162 | dev_hold(dev); | 1169 | dev_hold(dev); |
1163 | } | 1170 | } |
1164 | out: | 1171 | out: |
1172 | mutex_unlock(&rdev->sched_scan_mtx); | ||
1165 | kfree(creq); | 1173 | kfree(creq); |
1166 | cfg80211_unlock_rdev(rdev); | 1174 | cfg80211_unlock_rdev(rdev); |
1167 | return err; | 1175 | return err; |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 88fc9aa54fe0..a9dc5c736df0 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; |
@@ -227,6 +228,7 @@ void cfg80211_conn_work(struct work_struct *work) | |||
227 | rtnl_lock(); | 228 | rtnl_lock(); |
228 | cfg80211_lock_rdev(rdev); | 229 | cfg80211_lock_rdev(rdev); |
229 | mutex_lock(&rdev->devlist_mtx); | 230 | mutex_lock(&rdev->devlist_mtx); |
231 | mutex_lock(&rdev->sched_scan_mtx); | ||
230 | 232 | ||
231 | list_for_each_entry(wdev, &rdev->wdev_list, list) { | 233 | list_for_each_entry(wdev, &rdev->wdev_list, list) { |
232 | wdev_lock(wdev); | 234 | wdev_lock(wdev); |
@@ -251,6 +253,7 @@ void cfg80211_conn_work(struct work_struct *work) | |||
251 | wdev_unlock(wdev); | 253 | wdev_unlock(wdev); |
252 | } | 254 | } |
253 | 255 | ||
256 | mutex_unlock(&rdev->sched_scan_mtx); | ||
254 | mutex_unlock(&rdev->devlist_mtx); | 257 | mutex_unlock(&rdev->devlist_mtx); |
255 | cfg80211_unlock_rdev(rdev); | 258 | cfg80211_unlock_rdev(rdev); |
256 | rtnl_unlock(); | 259 | rtnl_unlock(); |
@@ -324,11 +327,9 @@ void cfg80211_sme_scan_done(struct net_device *dev) | |||
324 | { | 327 | { |
325 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 328 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
326 | 329 | ||
327 | mutex_lock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx); | ||
328 | wdev_lock(wdev); | 330 | wdev_lock(wdev); |
329 | __cfg80211_sme_scan_done(dev); | 331 | __cfg80211_sme_scan_done(dev); |
330 | wdev_unlock(wdev); | 332 | wdev_unlock(wdev); |
331 | mutex_unlock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx); | ||
332 | } | 333 | } |
333 | 334 | ||
334 | void cfg80211_sme_rx_auth(struct net_device *dev, | 335 | void cfg80211_sme_rx_auth(struct net_device *dev, |
@@ -928,9 +929,12 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev, | |||
928 | int err; | 929 | int err; |
929 | 930 | ||
930 | mutex_lock(&rdev->devlist_mtx); | 931 | mutex_lock(&rdev->devlist_mtx); |
932 | /* might request scan - scan_mtx -> wdev_mtx dependency */ | ||
933 | mutex_lock(&rdev->sched_scan_mtx); | ||
931 | wdev_lock(dev->ieee80211_ptr); | 934 | wdev_lock(dev->ieee80211_ptr); |
932 | err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL); | 935 | err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL); |
933 | wdev_unlock(dev->ieee80211_ptr); | 936 | wdev_unlock(dev->ieee80211_ptr); |
937 | mutex_unlock(&rdev->sched_scan_mtx); | ||
934 | mutex_unlock(&rdev->devlist_mtx); | 938 | mutex_unlock(&rdev->devlist_mtx); |
935 | 939 | ||
936 | return err; | 940 | return err; |
diff --git a/net/wireless/trace.h b/net/wireless/trace.h index ccadef2106ac..3c2033b8f596 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h | |||
@@ -27,7 +27,8 @@ | |||
27 | #define WIPHY_PR_ARG __entry->wiphy_name | 27 | #define WIPHY_PR_ARG __entry->wiphy_name |
28 | 28 | ||
29 | #define WDEV_ENTRY __field(u32, id) | 29 | #define WDEV_ENTRY __field(u32, id) |
30 | #define WDEV_ASSIGN (__entry->id) = (wdev ? wdev->identifier : 0) | 30 | #define WDEV_ASSIGN (__entry->id) = (!IS_ERR_OR_NULL(wdev) \ |
31 | ? wdev->identifier : 0) | ||
31 | #define WDEV_PR_FMT "wdev(%u)" | 32 | #define WDEV_PR_FMT "wdev(%u)" |
32 | #define WDEV_PR_ARG (__entry->id) | 33 | #define WDEV_PR_ARG (__entry->id) |
33 | 34 | ||
@@ -1778,7 +1779,7 @@ TRACE_EVENT(rdev_set_mac_acl, | |||
1778 | ), | 1779 | ), |
1779 | TP_fast_assign( | 1780 | TP_fast_assign( |
1780 | WIPHY_ASSIGN; | 1781 | WIPHY_ASSIGN; |
1781 | WIPHY_ASSIGN; | 1782 | NETDEV_ASSIGN; |
1782 | __entry->acl_policy = params->acl_policy; | 1783 | __entry->acl_policy = params->acl_policy; |
1783 | ), | 1784 | ), |
1784 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", acl policy: %d", | 1785 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", acl policy: %d", |
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; |