aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorLuciano Coelho <luciano.coelho@intel.com>2014-02-13 04:31:59 -0500
committerJohannes Berg <johannes.berg@intel.com>2014-04-09 04:55:43 -0400
commit73de86a38962b18edad3205c2358599dd9c83e9f (patch)
treecaf27b6e5000427c940a07d325d1210417ba87ad /net
parent2beb6dab2d799ee8934cb0801845e551ad8c70f2 (diff)
cfg80211/mac80211: move interface counting for combination check to mac80211
Move the counting part of the interface combination check from cfg80211 to mac80211. This is needed to simplify locking when the driver has to perform a combination check by itself (eg. with channel-switch). Signed-off-by: Luciano Coelho <luciano.coelho@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/cfg.c2
-rw-r--r--net/mac80211/chan.c17
-rw-r--r--net/mac80211/ieee80211_i.h4
-rw-r--r--net/mac80211/util.c72
-rw-r--r--net/wireless/core.h13
-rw-r--r--net/wireless/ibss.c4
-rw-r--r--net/wireless/mesh.c28
-rw-r--r--net/wireless/mlme.c14
-rw-r--r--net/wireless/nl80211.c29
-rw-r--r--net/wireless/util.c5
10 files changed, 110 insertions, 78 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 906bc3b05aae..8bf94eaa0456 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -972,7 +972,6 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
972 sdata->needed_rx_chains = sdata->local->rx_chains; 972 sdata->needed_rx_chains = sdata->local->rx_chains;
973 973
974 mutex_lock(&local->mtx); 974 mutex_lock(&local->mtx);
975 sdata->radar_required = params->radar_required;
976 err = ieee80211_vif_use_channel(sdata, &params->chandef, 975 err = ieee80211_vif_use_channel(sdata, &params->chandef,
977 IEEE80211_CHANCTX_SHARED); 976 IEEE80211_CHANCTX_SHARED);
978 mutex_unlock(&local->mtx); 977 mutex_unlock(&local->mtx);
@@ -2930,7 +2929,6 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy,
2930 /* whatever, but channel contexts should not complain about that one */ 2929 /* whatever, but channel contexts should not complain about that one */
2931 sdata->smps_mode = IEEE80211_SMPS_OFF; 2930 sdata->smps_mode = IEEE80211_SMPS_OFF;
2932 sdata->needed_rx_chains = local->rx_chains; 2931 sdata->needed_rx_chains = local->rx_chains;
2933 sdata->radar_required = true;
2934 2932
2935 err = ieee80211_vif_use_channel(sdata, chandef, 2933 err = ieee80211_vif_use_channel(sdata, chandef,
2936 IEEE80211_CHANCTX_SHARED); 2934 IEEE80211_CHANCTX_SHARED);
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index b297bd3043a8..623b336f3efd 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -519,6 +519,7 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
519{ 519{
520 struct ieee80211_local *local = sdata->local; 520 struct ieee80211_local *local = sdata->local;
521 struct ieee80211_chanctx *ctx; 521 struct ieee80211_chanctx *ctx;
522 u8 radar_detect_width = 0;
522 int ret; 523 int ret;
523 524
524 lockdep_assert_held(&local->mtx); 525 lockdep_assert_held(&local->mtx);
@@ -526,6 +527,22 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
526 WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev)); 527 WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
527 528
528 mutex_lock(&local->chanctx_mtx); 529 mutex_lock(&local->chanctx_mtx);
530
531 ret = cfg80211_chandef_dfs_required(local->hw.wiphy,
532 chandef,
533 sdata->wdev.iftype);
534 if (ret < 0)
535 goto out;
536 if (ret > 0)
537 radar_detect_width = BIT(chandef->width);
538
539 sdata->radar_required = ret;
540
541 ret = ieee80211_check_combinations(sdata, chandef, mode,
542 radar_detect_width);
543 if (ret < 0)
544 goto out;
545
529 __ieee80211_vif_release_channel(sdata); 546 __ieee80211_vif_release_channel(sdata);
530 547
531 ctx = ieee80211_find_chanctx(local, chandef, mode); 548 ctx = ieee80211_find_chanctx(local, chandef, mode);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 222c28b75315..09213fd87f8d 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1805,6 +1805,10 @@ int ieee80211_cs_headroom(struct ieee80211_local *local,
1805 enum nl80211_iftype iftype); 1805 enum nl80211_iftype iftype);
1806void ieee80211_recalc_dtim(struct ieee80211_local *local, 1806void ieee80211_recalc_dtim(struct ieee80211_local *local,
1807 struct ieee80211_sub_if_data *sdata); 1807 struct ieee80211_sub_if_data *sdata);
1808int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
1809 const struct cfg80211_chan_def *chandef,
1810 enum ieee80211_chanctx_mode chanmode,
1811 u8 radar_detect);
1808 1812
1809#ifdef CONFIG_MAC80211_NOINLINE 1813#ifdef CONFIG_MAC80211_NOINLINE
1810#define debug_noinline noinline 1814#define debug_noinline noinline
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 73af7398850b..436f98870066 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2797,3 +2797,75 @@ void ieee80211_recalc_dtim(struct ieee80211_local *local,
2797 2797
2798 ps->dtim_count = dtim_count; 2798 ps->dtim_count = dtim_count;
2799} 2799}
2800
2801int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
2802 const struct cfg80211_chan_def *chandef,
2803 enum ieee80211_chanctx_mode chanmode,
2804 u8 radar_detect)
2805{
2806 struct ieee80211_local *local = sdata->local;
2807 struct ieee80211_sub_if_data *sdata_iter;
2808 enum nl80211_iftype iftype = sdata->wdev.iftype;
2809 int num[NUM_NL80211_IFTYPES];
2810 struct ieee80211_chanctx *ctx;
2811 int num_different_channels = 1;
2812 int total = 1;
2813
2814 lockdep_assert_held(&local->chanctx_mtx);
2815
2816 if (WARN_ON(hweight32(radar_detect) > 1))
2817 return -EINVAL;
2818
2819 if (WARN_ON(chanmode == IEEE80211_CHANCTX_SHARED && !chandef->chan))
2820 return -EINVAL;
2821
2822 if (WARN_ON(iftype >= NUM_NL80211_IFTYPES))
2823 return -EINVAL;
2824
2825 /* Always allow software iftypes */
2826 if (local->hw.wiphy->software_iftypes & BIT(iftype)) {
2827 if (radar_detect)
2828 return -EINVAL;
2829 return 0;
2830 }
2831
2832 memset(num, 0, sizeof(num));
2833
2834 if (iftype != NL80211_IFTYPE_UNSPECIFIED)
2835 num[iftype] = 1;
2836
2837 list_for_each_entry(ctx, &local->chanctx_list, list) {
2838 if (ctx->conf.radar_enabled)
2839 radar_detect |= BIT(ctx->conf.def.width);
2840 if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) {
2841 num_different_channels++;
2842 continue;
2843 }
2844 if ((chanmode == IEEE80211_CHANCTX_SHARED) &&
2845 cfg80211_chandef_compatible(chandef,
2846 &ctx->conf.def))
2847 continue;
2848 num_different_channels++;
2849 }
2850
2851 list_for_each_entry_rcu(sdata_iter, &local->interfaces, list) {
2852 struct wireless_dev *wdev_iter;
2853
2854 wdev_iter = &sdata_iter->wdev;
2855
2856 if (sdata_iter == sdata ||
2857 rcu_access_pointer(sdata_iter->vif.chanctx_conf) == NULL ||
2858 local->hw.wiphy->software_iftypes & BIT(wdev_iter->iftype))
2859 continue;
2860
2861 num[wdev_iter->iftype]++;
2862 total++;
2863 }
2864
2865 if (total == 1 && !radar_detect)
2866 return 0;
2867
2868 return cfg80211_check_combinations(local->hw.wiphy,
2869 num_different_channels,
2870 radar_detect, num);
2871}
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 6f6f75609852..6684c5d965d8 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -417,6 +417,9 @@ cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
417 struct wireless_dev *wdev, 417 struct wireless_dev *wdev,
418 enum nl80211_iftype iftype) 418 enum nl80211_iftype iftype)
419{ 419{
420 /* TODO: For this function, we'll probably need to keep some
421 * kind of interface combination check in cfg80211...
422 */
420 return cfg80211_can_use_iftype_chan(rdev, wdev, iftype, NULL, 423 return cfg80211_can_use_iftype_chan(rdev, wdev, iftype, NULL,
421 CHAN_MODE_UNDEFINED, 0); 424 CHAN_MODE_UNDEFINED, 0);
422} 425}
@@ -431,16 +434,6 @@ cfg80211_can_add_interface(struct cfg80211_registered_device *rdev,
431 return cfg80211_can_change_interface(rdev, NULL, iftype); 434 return cfg80211_can_change_interface(rdev, NULL, iftype);
432} 435}
433 436
434static inline int
435cfg80211_can_use_chan(struct cfg80211_registered_device *rdev,
436 struct wireless_dev *wdev,
437 struct ieee80211_channel *chan,
438 enum cfg80211_chan_mode chanmode)
439{
440 return cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
441 chan, chanmode, 0);
442}
443
444static inline unsigned int elapsed_jiffies_msecs(unsigned long start) 437static inline unsigned int elapsed_jiffies_msecs(unsigned long start)
445{ 438{
446 unsigned long end = jiffies; 439 unsigned long end = jiffies;
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index a6b5bdad039c..faf4961d47d8 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -135,6 +135,10 @@ static int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
135 radar_detect_width = BIT(params->chandef.width); 135 radar_detect_width = BIT(params->chandef.width);
136 } 136 }
137 137
138 /* TODO: We need to check the combinations at this point, we
139 * probably must move this call down to join_ibss() in
140 * mac80211.
141 */
138 err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, 142 err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
139 check_chan, 143 check_chan,
140 (params->channel_fixed && 144 (params->channel_fixed &&
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
index 6ebe883653a4..3ddfb7cd335e 100644
--- a/net/wireless/mesh.c
+++ b/net/wireless/mesh.c
@@ -99,7 +99,6 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
99 const struct mesh_config *conf) 99 const struct mesh_config *conf)
100{ 100{
101 struct wireless_dev *wdev = dev->ieee80211_ptr; 101 struct wireless_dev *wdev = dev->ieee80211_ptr;
102 u8 radar_detect_width = 0;
103 int err; 102 int err;
104 103
105 BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN != IEEE80211_MAX_MESH_ID_LEN); 104 BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN != IEEE80211_MAX_MESH_ID_LEN);
@@ -179,22 +178,6 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
179 NL80211_IFTYPE_MESH_POINT)) 178 NL80211_IFTYPE_MESH_POINT))
180 return -EINVAL; 179 return -EINVAL;
181 180
182 err = cfg80211_chandef_dfs_required(wdev->wiphy,
183 &setup->chandef,
184 NL80211_IFTYPE_MESH_POINT);
185 if (err < 0)
186 return err;
187
188 if (err > 0)
189 radar_detect_width = BIT(setup->chandef.width);
190
191 err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
192 setup->chandef.chan,
193 CHAN_MODE_SHARED,
194 radar_detect_width);
195 if (err)
196 return err;
197
198 err = rdev_join_mesh(rdev, dev, conf, setup); 181 err = rdev_join_mesh(rdev, dev, conf, setup);
199 if (!err) { 182 if (!err) {
200 memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len); 183 memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len);
@@ -240,17 +223,6 @@ int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev,
240 if (!netif_running(wdev->netdev)) 223 if (!netif_running(wdev->netdev))
241 return -ENETDOWN; 224 return -ENETDOWN;
242 225
243 /* cfg80211_can_use_chan() calls
244 * cfg80211_can_use_iftype_chan() with no radar
245 * detection, so if we're trying to use a radar
246 * channel here, something is wrong.
247 */
248 WARN_ON_ONCE(chandef->chan->flags & IEEE80211_CHAN_RADAR);
249 err = cfg80211_can_use_chan(rdev, wdev, chandef->chan,
250 CHAN_MODE_SHARED);
251 if (err)
252 return err;
253
254 err = rdev_libertas_set_mesh_channel(rdev, wdev->netdev, 226 err = rdev_libertas_set_mesh_channel(rdev, wdev->netdev,
255 chandef->chan); 227 chandef->chan);
256 if (!err) 228 if (!err)
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index c52ff59a3e96..4b4ba707fab9 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -233,14 +233,8 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
233 if (!req.bss) 233 if (!req.bss)
234 return -ENOENT; 234 return -ENOENT;
235 235
236 err = cfg80211_can_use_chan(rdev, wdev, req.bss->channel,
237 CHAN_MODE_SHARED);
238 if (err)
239 goto out;
240
241 err = rdev_auth(rdev, dev, &req); 236 err = rdev_auth(rdev, dev, &req);
242 237
243out:
244 cfg80211_put_bss(&rdev->wiphy, req.bss); 238 cfg80211_put_bss(&rdev->wiphy, req.bss);
245 return err; 239 return err;
246} 240}
@@ -306,16 +300,10 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
306 if (!req->bss) 300 if (!req->bss)
307 return -ENOENT; 301 return -ENOENT;
308 302
309 err = cfg80211_can_use_chan(rdev, wdev, chan, CHAN_MODE_SHARED);
310 if (err)
311 goto out;
312
313 err = rdev_assoc(rdev, dev, req); 303 err = rdev_assoc(rdev, dev, req);
314 if (!err) 304 if (!err)
315 cfg80211_hold_bss(bss_from_pub(req->bss)); 305 cfg80211_hold_bss(bss_from_pub(req->bss));
316 306 else
317out:
318 if (err)
319 cfg80211_put_bss(&rdev->wiphy, req->bss); 307 cfg80211_put_bss(&rdev->wiphy, req->bss);
320 308
321 return err; 309 return err;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 4f82b9b71db1..2b99aad33ae0 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3155,7 +3155,6 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
3155 struct wireless_dev *wdev = dev->ieee80211_ptr; 3155 struct wireless_dev *wdev = dev->ieee80211_ptr;
3156 struct cfg80211_ap_settings params; 3156 struct cfg80211_ap_settings params;
3157 int err; 3157 int err;
3158 u8 radar_detect_width = 0;
3159 3158
3160 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && 3159 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
3161 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) 3160 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
@@ -3275,24 +3274,6 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
3275 wdev->iftype)) 3274 wdev->iftype))
3276 return -EINVAL; 3275 return -EINVAL;
3277 3276
3278 err = cfg80211_chandef_dfs_required(wdev->wiphy,
3279 &params.chandef,
3280 NL80211_IFTYPE_AP);
3281 if (err < 0)
3282 return err;
3283
3284 if (err > 0) {
3285 params.radar_required = true;
3286 radar_detect_width = BIT(params.chandef.width);
3287 }
3288
3289 err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
3290 params.chandef.chan,
3291 CHAN_MODE_SHARED,
3292 radar_detect_width);
3293 if (err)
3294 return err;
3295
3296 if (info->attrs[NL80211_ATTR_ACL_POLICY]) { 3277 if (info->attrs[NL80211_ATTR_ACL_POLICY]) {
3297 params.acl = parse_acl_data(&rdev->wiphy, info); 3278 params.acl = parse_acl_data(&rdev->wiphy, info);
3298 if (IS_ERR(params.acl)) 3279 if (IS_ERR(params.acl))
@@ -5823,12 +5804,6 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
5823 if (!rdev->ops->start_radar_detection) 5804 if (!rdev->ops->start_radar_detection)
5824 return -EOPNOTSUPP; 5805 return -EOPNOTSUPP;
5825 5806
5826 err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
5827 chandef.chan, CHAN_MODE_SHARED,
5828 BIT(chandef.width));
5829 if (err)
5830 return err;
5831
5832 cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, &chandef); 5807 cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, &chandef);
5833 if (WARN_ON(!cac_time_ms)) 5808 if (WARN_ON(!cac_time_ms))
5834 cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS; 5809 cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
@@ -5957,6 +5932,10 @@ skip_beacons:
5957 params.radar_required = true; 5932 params.radar_required = true;
5958 } 5933 }
5959 5934
5935 /* TODO: I left this here for now. With channel switch, the
5936 * verification is a bit more complicated, because we only do
5937 * it later when the channel switch really happens.
5938 */
5960 err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, 5939 err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
5961 params.chandef.chan, 5940 params.chandef.chan,
5962 CHAN_MODE_SHARED, 5941 CHAN_MODE_SHARED,
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 46f404df35e3..9bfc4c621509 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1375,6 +1375,11 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
1375 1375
1376 num[iftype] = 1; 1376 num[iftype] = 1;
1377 1377
1378 /* TODO: We'll probably not need this anymore, since this
1379 * should only be called with CHAN_MODE_UNDEFINED. There are
1380 * still a couple of pending calls where other chanmodes are
1381 * used, but we should get rid of them.
1382 */
1378 switch (chanmode) { 1383 switch (chanmode) {
1379 case CHAN_MODE_UNDEFINED: 1384 case CHAN_MODE_UNDEFINED:
1380 break; 1385 break;