aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/cfg80211.h2
-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
11 files changed, 110 insertions, 80 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 92a65c331cf4..fb8afcee62b4 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -662,7 +662,6 @@ struct cfg80211_acl_data {
662 * @p2p_opp_ps: P2P opportunistic PS 662 * @p2p_opp_ps: P2P opportunistic PS
663 * @acl: ACL configuration used by the drivers which has support for 663 * @acl: ACL configuration used by the drivers which has support for
664 * MAC address based access control 664 * MAC address based access control
665 * @radar_required: set if radar detection is required
666 */ 665 */
667struct cfg80211_ap_settings { 666struct cfg80211_ap_settings {
668 struct cfg80211_chan_def chandef; 667 struct cfg80211_chan_def chandef;
@@ -680,7 +679,6 @@ struct cfg80211_ap_settings {
680 u8 p2p_ctwindow; 679 u8 p2p_ctwindow;
681 bool p2p_opp_ps; 680 bool p2p_opp_ps;
682 const struct cfg80211_acl_data *acl; 681 const struct cfg80211_acl_data *acl;
683 bool radar_required;
684}; 682};
685 683
686/** 684/**
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;