diff options
Diffstat (limited to 'net/wireless/chan.c')
-rw-r--r-- | net/wireless/chan.c | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 1d25a462b145..96c97800e247 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c | |||
@@ -351,6 +351,80 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy, | |||
351 | } | 351 | } |
352 | EXPORT_SYMBOL(cfg80211_chandef_dfs_required); | 352 | EXPORT_SYMBOL(cfg80211_chandef_dfs_required); |
353 | 353 | ||
354 | static int cfg80211_get_chans_dfs_usable(struct wiphy *wiphy, | ||
355 | u32 center_freq, | ||
356 | u32 bandwidth) | ||
357 | { | ||
358 | struct ieee80211_channel *c; | ||
359 | u32 freq, start_freq, end_freq; | ||
360 | int count = 0; | ||
361 | |||
362 | start_freq = cfg80211_get_start_freq(center_freq, bandwidth); | ||
363 | end_freq = cfg80211_get_end_freq(center_freq, bandwidth); | ||
364 | |||
365 | /* | ||
366 | * Check entire range of channels for the bandwidth. | ||
367 | * Check all channels are DFS channels (DFS_USABLE or | ||
368 | * DFS_AVAILABLE). Return number of usable channels | ||
369 | * (require CAC). Allow DFS and non-DFS channel mix. | ||
370 | */ | ||
371 | for (freq = start_freq; freq <= end_freq; freq += 20) { | ||
372 | c = ieee80211_get_channel(wiphy, freq); | ||
373 | if (!c) | ||
374 | return -EINVAL; | ||
375 | |||
376 | if (c->flags & IEEE80211_CHAN_DISABLED) | ||
377 | return -EINVAL; | ||
378 | |||
379 | if (c->flags & IEEE80211_CHAN_RADAR) { | ||
380 | if (c->dfs_state == NL80211_DFS_UNAVAILABLE) | ||
381 | return -EINVAL; | ||
382 | |||
383 | if (c->dfs_state == NL80211_DFS_USABLE) | ||
384 | count++; | ||
385 | } | ||
386 | } | ||
387 | |||
388 | return count; | ||
389 | } | ||
390 | |||
391 | bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy, | ||
392 | const struct cfg80211_chan_def *chandef) | ||
393 | { | ||
394 | int width; | ||
395 | int r1, r2 = 0; | ||
396 | |||
397 | if (WARN_ON(!cfg80211_chandef_valid(chandef))) | ||
398 | return false; | ||
399 | |||
400 | width = cfg80211_chandef_get_width(chandef); | ||
401 | if (width < 0) | ||
402 | return false; | ||
403 | |||
404 | r1 = cfg80211_get_chans_dfs_usable(wiphy, chandef->center_freq1, | ||
405 | width); | ||
406 | |||
407 | if (r1 < 0) | ||
408 | return false; | ||
409 | |||
410 | switch (chandef->width) { | ||
411 | case NL80211_CHAN_WIDTH_80P80: | ||
412 | WARN_ON(!chandef->center_freq2); | ||
413 | r2 = cfg80211_get_chans_dfs_usable(wiphy, | ||
414 | chandef->center_freq2, | ||
415 | width); | ||
416 | if (r2 < 0) | ||
417 | return false; | ||
418 | break; | ||
419 | default: | ||
420 | WARN_ON(chandef->center_freq2); | ||
421 | break; | ||
422 | } | ||
423 | |||
424 | return (r1 + r2 > 0); | ||
425 | } | ||
426 | |||
427 | |||
354 | static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, | 428 | static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, |
355 | u32 center_freq, u32 bandwidth, | 429 | u32 center_freq, u32 bandwidth, |
356 | u32 prohibited_flags) | 430 | u32 prohibited_flags) |