diff options
author | Michal Kazior <michal.kazior@tieto.com> | 2012-06-29 06:47:08 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2012-06-29 07:39:19 -0400 |
commit | e4e32459c2daea59516da59999706b357e6eb480 (patch) | |
tree | 110014ac72ebcf7aed16caa0fa83da75e319fa86 /net | |
parent | d4e50c5917e110451ced8f8de594cea858791f37 (diff) |
cfg80211: respect iface combinations when starting operation
devlist_mtx locking is changed to accomodate changes.
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/wireless/core.c | 2 | ||||
-rw-r--r-- | net/wireless/ibss.c | 10 | ||||
-rw-r--r-- | net/wireless/mesh.c | 12 | ||||
-rw-r--r-- | net/wireless/mlme.c | 16 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 8 | ||||
-rw-r--r-- | net/wireless/util.c | 9 |
6 files changed, 52 insertions, 5 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c index b26695ad3e97..ca2b95f24846 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -990,7 +990,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | |||
990 | return notifier_from_errno(-EOPNOTSUPP); | 990 | return notifier_from_errno(-EOPNOTSUPP); |
991 | if (rfkill_blocked(rdev->rfkill)) | 991 | if (rfkill_blocked(rdev->rfkill)) |
992 | return notifier_from_errno(-ERFKILL); | 992 | return notifier_from_errno(-ERFKILL); |
993 | mutex_lock(&rdev->devlist_mtx); | ||
993 | ret = cfg80211_can_add_interface(rdev, wdev->iftype); | 994 | ret = cfg80211_can_add_interface(rdev, wdev->iftype); |
995 | mutex_unlock(&rdev->devlist_mtx); | ||
994 | if (ret) | 996 | if (ret) |
995 | return notifier_from_errno(ret); | 997 | return notifier_from_errno(ret); |
996 | cfg80211_lock_rdev(rdev); | 998 | cfg80211_lock_rdev(rdev); |
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index b90fd86b2d18..ca5672f6ee2f 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c | |||
@@ -118,6 +118,16 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | |||
118 | wdev->wext.ibss.channel = params->channel; | 118 | wdev->wext.ibss.channel = params->channel; |
119 | #endif | 119 | #endif |
120 | wdev->sme_state = CFG80211_SME_CONNECTING; | 120 | wdev->sme_state = CFG80211_SME_CONNECTING; |
121 | |||
122 | err = cfg80211_can_use_chan(rdev, wdev, params->channel, | ||
123 | params->channel_fixed | ||
124 | ? CHAN_MODE_SHARED | ||
125 | : CHAN_MODE_EXCLUSIVE); | ||
126 | if (err) { | ||
127 | wdev->connect_keys = NULL; | ||
128 | return err; | ||
129 | } | ||
130 | |||
121 | err = rdev->ops->join_ibss(&rdev->wiphy, dev, params); | 131 | err = rdev->ops->join_ibss(&rdev->wiphy, dev, params); |
122 | if (err) { | 132 | if (err) { |
123 | wdev->connect_keys = NULL; | 133 | wdev->connect_keys = NULL; |
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index bab381344723..c384e77ff77a 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c | |||
@@ -155,6 +155,11 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | |||
155 | setup->channel_type)) | 155 | setup->channel_type)) |
156 | return -EINVAL; | 156 | return -EINVAL; |
157 | 157 | ||
158 | err = cfg80211_can_use_chan(rdev, wdev, setup->channel, | ||
159 | CHAN_MODE_SHARED); | ||
160 | if (err) | ||
161 | return err; | ||
162 | |||
158 | err = rdev->ops->join_mesh(&rdev->wiphy, dev, conf, setup); | 163 | err = rdev->ops->join_mesh(&rdev->wiphy, dev, conf, setup); |
159 | if (!err) { | 164 | if (!err) { |
160 | memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len); | 165 | memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len); |
@@ -173,9 +178,11 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | |||
173 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 178 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
174 | int err; | 179 | int err; |
175 | 180 | ||
181 | mutex_lock(&rdev->devlist_mtx); | ||
176 | wdev_lock(wdev); | 182 | wdev_lock(wdev); |
177 | err = __cfg80211_join_mesh(rdev, dev, setup, conf); | 183 | err = __cfg80211_join_mesh(rdev, dev, setup, conf); |
178 | wdev_unlock(wdev); | 184 | wdev_unlock(wdev); |
185 | mutex_unlock(&rdev->devlist_mtx); | ||
179 | 186 | ||
180 | return err; | 187 | return err; |
181 | } | 188 | } |
@@ -208,6 +215,11 @@ int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev, | |||
208 | if (!netif_running(wdev->netdev)) | 215 | if (!netif_running(wdev->netdev)) |
209 | return -ENETDOWN; | 216 | return -ENETDOWN; |
210 | 217 | ||
218 | err = cfg80211_can_use_chan(rdev, wdev, channel, | ||
219 | CHAN_MODE_SHARED); | ||
220 | if (err) | ||
221 | return err; | ||
222 | |||
211 | err = rdev->ops->libertas_set_mesh_channel(&rdev->wiphy, | 223 | err = rdev->ops->libertas_set_mesh_channel(&rdev->wiphy, |
212 | wdev->netdev, | 224 | wdev->netdev, |
213 | channel); | 225 | channel); |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index a7882eb8c46e..d4fece3bb18a 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -302,8 +302,14 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
302 | if (!req.bss) | 302 | if (!req.bss) |
303 | return -ENOENT; | 303 | return -ENOENT; |
304 | 304 | ||
305 | err = cfg80211_can_use_chan(rdev, wdev, req.bss->channel, | ||
306 | CHAN_MODE_SHARED); | ||
307 | if (err) | ||
308 | goto out; | ||
309 | |||
305 | err = rdev->ops->auth(&rdev->wiphy, dev, &req); | 310 | err = rdev->ops->auth(&rdev->wiphy, dev, &req); |
306 | 311 | ||
312 | out: | ||
307 | cfg80211_put_bss(req.bss); | 313 | cfg80211_put_bss(req.bss); |
308 | return err; | 314 | return err; |
309 | } | 315 | } |
@@ -317,11 +323,13 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
317 | { | 323 | { |
318 | int err; | 324 | int err; |
319 | 325 | ||
326 | mutex_lock(&rdev->devlist_mtx); | ||
320 | wdev_lock(dev->ieee80211_ptr); | 327 | wdev_lock(dev->ieee80211_ptr); |
321 | err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, | 328 | err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, |
322 | ssid, ssid_len, ie, ie_len, | 329 | ssid, ssid_len, ie, ie_len, |
323 | key, key_len, key_idx); | 330 | key, key_len, key_idx); |
324 | wdev_unlock(dev->ieee80211_ptr); | 331 | wdev_unlock(dev->ieee80211_ptr); |
332 | mutex_unlock(&rdev->devlist_mtx); | ||
325 | 333 | ||
326 | return err; | 334 | return err; |
327 | } | 335 | } |
@@ -397,8 +405,14 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | |||
397 | return -ENOENT; | 405 | return -ENOENT; |
398 | } | 406 | } |
399 | 407 | ||
408 | err = cfg80211_can_use_chan(rdev, wdev, req.bss->channel, | ||
409 | CHAN_MODE_SHARED); | ||
410 | if (err) | ||
411 | goto out; | ||
412 | |||
400 | err = rdev->ops->assoc(&rdev->wiphy, dev, &req); | 413 | err = rdev->ops->assoc(&rdev->wiphy, dev, &req); |
401 | 414 | ||
415 | out: | ||
402 | if (err) { | 416 | if (err) { |
403 | if (was_connected) | 417 | if (was_connected) |
404 | wdev->sme_state = CFG80211_SME_CONNECTED; | 418 | wdev->sme_state = CFG80211_SME_CONNECTED; |
@@ -421,11 +435,13 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | |||
421 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 435 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
422 | int err; | 436 | int err; |
423 | 437 | ||
438 | mutex_lock(&rdev->devlist_mtx); | ||
424 | wdev_lock(wdev); | 439 | wdev_lock(wdev); |
425 | err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid, | 440 | err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid, |
426 | ssid, ssid_len, ie, ie_len, use_mfp, crypt, | 441 | ssid, ssid_len, ie, ie_len, use_mfp, crypt, |
427 | assoc_flags, ht_capa, ht_capa_mask); | 442 | assoc_flags, ht_capa, ht_capa_mask); |
428 | wdev_unlock(wdev); | 443 | wdev_unlock(wdev); |
444 | mutex_unlock(&rdev->devlist_mtx); | ||
429 | 445 | ||
430 | return err; | 446 | return err; |
431 | } | 447 | } |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 5d29ed1f7c62..77102e66f1ea 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -2478,6 +2478,14 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) | |||
2478 | params.channel_type)) | 2478 | params.channel_type)) |
2479 | return -EINVAL; | 2479 | return -EINVAL; |
2480 | 2480 | ||
2481 | mutex_lock(&rdev->devlist_mtx); | ||
2482 | err = cfg80211_can_use_chan(rdev, wdev, params.channel, | ||
2483 | CHAN_MODE_SHARED); | ||
2484 | mutex_unlock(&rdev->devlist_mtx); | ||
2485 | |||
2486 | if (err) | ||
2487 | return err; | ||
2488 | |||
2481 | err = rdev->ops->start_ap(&rdev->wiphy, dev, ¶ms); | 2489 | err = rdev->ops->start_ap(&rdev->wiphy, dev, ¶ms); |
2482 | if (!err) { | 2490 | if (!err) { |
2483 | wdev->preset_chan = params.channel; | 2491 | wdev->preset_chan = params.channel; |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 4713cea9a2fa..a9260ac85cf1 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -805,8 +805,10 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | |||
805 | return -EBUSY; | 805 | return -EBUSY; |
806 | 806 | ||
807 | if (ntype != otype && netif_running(dev)) { | 807 | if (ntype != otype && netif_running(dev)) { |
808 | mutex_lock(&rdev->devlist_mtx); | ||
808 | err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr, | 809 | err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr, |
809 | ntype); | 810 | ntype); |
811 | mutex_unlock(&rdev->devlist_mtx); | ||
810 | if (err) | 812 | if (err) |
811 | return err; | 813 | return err; |
812 | 814 | ||
@@ -956,6 +958,7 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | |||
956 | int i, j; | 958 | int i, j; |
957 | 959 | ||
958 | ASSERT_RTNL(); | 960 | ASSERT_RTNL(); |
961 | lockdep_assert_held(&rdev->devlist_mtx); | ||
959 | 962 | ||
960 | /* Always allow software iftypes */ | 963 | /* Always allow software iftypes */ |
961 | if (rdev->wiphy.software_iftypes & BIT(iftype)) | 964 | if (rdev->wiphy.software_iftypes & BIT(iftype)) |
@@ -979,7 +982,6 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | |||
979 | break; | 982 | break; |
980 | } | 983 | } |
981 | 984 | ||
982 | mutex_lock(&rdev->devlist_mtx); | ||
983 | list_for_each_entry(wdev_iter, &rdev->netdev_list, list) { | 985 | list_for_each_entry(wdev_iter, &rdev->netdev_list, list) { |
984 | if (wdev_iter == wdev) | 986 | if (wdev_iter == wdev) |
985 | continue; | 987 | continue; |
@@ -999,10 +1001,8 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | |||
999 | if (!used_channels[i] || used_channels[i] == ch) | 1001 | if (!used_channels[i] || used_channels[i] == ch) |
1000 | break; | 1002 | break; |
1001 | 1003 | ||
1002 | if (i == CFG80211_MAX_NUM_DIFFERENT_CHANNELS) { | 1004 | if (i == CFG80211_MAX_NUM_DIFFERENT_CHANNELS) |
1003 | mutex_unlock(&rdev->devlist_mtx); | ||
1004 | return -EBUSY; | 1005 | return -EBUSY; |
1005 | } | ||
1006 | 1006 | ||
1007 | if (used_channels[i] == NULL) { | 1007 | if (used_channels[i] == NULL) { |
1008 | used_channels[i] = ch; | 1008 | used_channels[i] = ch; |
@@ -1018,7 +1018,6 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | |||
1018 | total++; | 1018 | total++; |
1019 | used_iftypes |= BIT(wdev_iter->iftype); | 1019 | used_iftypes |= BIT(wdev_iter->iftype); |
1020 | } | 1020 | } |
1021 | mutex_unlock(&rdev->devlist_mtx); | ||
1022 | 1021 | ||
1023 | if (total == 1) | 1022 | if (total == 1) |
1024 | return 0; | 1023 | return 0; |