diff options
author | Janusz Dziedzic <janusz.dziedzic@tieto.com> | 2013-11-06 07:55:53 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-11-25 14:50:49 -0500 |
commit | 6bc54fbcee6836f08355fcca76549c22ad2c2940 (patch) | |
tree | 0f5e275aacd29ee197061a11df171393aef727f6 /net/wireless/chan.c | |
parent | d2859df5e7f00469011482d850fba652517a2eab (diff) |
cfg80211: allow beaconing after DFS CAC
Allow beconing after we pass Channel Availability Check (CAC).
Allow non-DFS and DFS channels mix. All DFS channels have to
be in NL80211_DFS_AVAILABLE state (pass CAC).
Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless/chan.c')
-rw-r--r-- | net/wireless/chan.c | 85 |
1 files changed, 74 insertions, 11 deletions
diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 3b6daf8b47d9..78559b5bbd1f 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c | |||
@@ -425,9 +425,9 @@ bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy, | |||
425 | } | 425 | } |
426 | 426 | ||
427 | 427 | ||
428 | static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, | 428 | static bool cfg80211_get_chans_dfs_available(struct wiphy *wiphy, |
429 | u32 center_freq, u32 bandwidth, | 429 | u32 center_freq, |
430 | u32 prohibited_flags) | 430 | u32 bandwidth) |
431 | { | 431 | { |
432 | struct ieee80211_channel *c; | 432 | struct ieee80211_channel *c; |
433 | u32 freq, start_freq, end_freq; | 433 | u32 freq, start_freq, end_freq; |
@@ -435,18 +435,75 @@ static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, | |||
435 | start_freq = cfg80211_get_start_freq(center_freq, bandwidth); | 435 | start_freq = cfg80211_get_start_freq(center_freq, bandwidth); |
436 | end_freq = cfg80211_get_end_freq(center_freq, bandwidth); | 436 | end_freq = cfg80211_get_end_freq(center_freq, bandwidth); |
437 | 437 | ||
438 | /* | ||
439 | * Check entire range of channels for the bandwidth. | ||
440 | * If any channel in between is disabled or has not | ||
441 | * had gone through CAC return false | ||
442 | */ | ||
438 | for (freq = start_freq; freq <= end_freq; freq += 20) { | 443 | for (freq = start_freq; freq <= end_freq; freq += 20) { |
439 | c = ieee80211_get_channel(wiphy, freq); | 444 | c = ieee80211_get_channel(wiphy, freq); |
440 | if (!c) | 445 | if (!c) |
441 | return false; | 446 | return false; |
442 | 447 | ||
443 | /* check for radar flags */ | 448 | if (c->flags & IEEE80211_CHAN_DISABLED) |
444 | if ((prohibited_flags & c->flags & IEEE80211_CHAN_RADAR) && | 449 | return false; |
450 | |||
451 | if ((c->flags & IEEE80211_CHAN_RADAR) && | ||
445 | (c->dfs_state != NL80211_DFS_AVAILABLE)) | 452 | (c->dfs_state != NL80211_DFS_AVAILABLE)) |
446 | return false; | 453 | return false; |
454 | } | ||
455 | |||
456 | return true; | ||
457 | } | ||
458 | |||
459 | static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy, | ||
460 | const struct cfg80211_chan_def *chandef) | ||
461 | { | ||
462 | int width; | ||
463 | int r; | ||
464 | |||
465 | if (WARN_ON(!cfg80211_chandef_valid(chandef))) | ||
466 | return false; | ||
467 | |||
468 | width = cfg80211_chandef_get_width(chandef); | ||
469 | if (width < 0) | ||
470 | return false; | ||
471 | |||
472 | r = cfg80211_get_chans_dfs_available(wiphy, chandef->center_freq1, | ||
473 | width); | ||
474 | |||
475 | /* If any of channels unavailable for cf1 just return */ | ||
476 | if (!r) | ||
477 | return r; | ||
478 | |||
479 | switch (chandef->width) { | ||
480 | case NL80211_CHAN_WIDTH_80P80: | ||
481 | WARN_ON(!chandef->center_freq2); | ||
482 | r = cfg80211_get_chans_dfs_available(wiphy, | ||
483 | chandef->center_freq2, | ||
484 | width); | ||
485 | default: | ||
486 | WARN_ON(chandef->center_freq2); | ||
487 | break; | ||
488 | } | ||
489 | |||
490 | return r; | ||
491 | } | ||
492 | |||
493 | |||
494 | static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, | ||
495 | u32 center_freq, u32 bandwidth, | ||
496 | u32 prohibited_flags) | ||
497 | { | ||
498 | struct ieee80211_channel *c; | ||
499 | u32 freq, start_freq, end_freq; | ||
447 | 500 | ||
448 | /* check for the other flags */ | 501 | start_freq = cfg80211_get_start_freq(center_freq, bandwidth); |
449 | if (c->flags & prohibited_flags & ~IEEE80211_CHAN_RADAR) | 502 | end_freq = cfg80211_get_end_freq(center_freq, bandwidth); |
503 | |||
504 | for (freq = start_freq; freq <= end_freq; freq += 20) { | ||
505 | c = ieee80211_get_channel(wiphy, freq); | ||
506 | if (!c || c->flags & prohibited_flags) | ||
450 | return false; | 507 | return false; |
451 | } | 508 | } |
452 | 509 | ||
@@ -552,13 +609,19 @@ bool cfg80211_reg_can_beacon(struct wiphy *wiphy, | |||
552 | struct cfg80211_chan_def *chandef) | 609 | struct cfg80211_chan_def *chandef) |
553 | { | 610 | { |
554 | bool res; | 611 | bool res; |
612 | u32 prohibited_flags = IEEE80211_CHAN_DISABLED | | ||
613 | IEEE80211_CHAN_NO_IR | | ||
614 | IEEE80211_CHAN_RADAR; | ||
555 | 615 | ||
556 | trace_cfg80211_reg_can_beacon(wiphy, chandef); | 616 | trace_cfg80211_reg_can_beacon(wiphy, chandef); |
557 | 617 | ||
558 | res = cfg80211_chandef_usable(wiphy, chandef, | 618 | if (cfg80211_chandef_dfs_required(wiphy, chandef) > 0 && |
559 | IEEE80211_CHAN_DISABLED | | 619 | cfg80211_chandef_dfs_available(wiphy, chandef)) { |
560 | IEEE80211_CHAN_NO_IR | | 620 | /* We can skip IEEE80211_CHAN_NO_IR if chandef dfs available */ |
561 | IEEE80211_CHAN_RADAR); | 621 | prohibited_flags = IEEE80211_CHAN_DISABLED; |
622 | } | ||
623 | |||
624 | res = cfg80211_chandef_usable(wiphy, chandef, prohibited_flags); | ||
562 | 625 | ||
563 | trace_cfg80211_return_bool(res); | 626 | trace_cfg80211_return_bool(res); |
564 | return res; | 627 | return res; |