aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/chan.c
diff options
context:
space:
mode:
authorJanusz Dziedzic <janusz.dziedzic@tieto.com>2013-11-06 07:55:53 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-11-25 14:50:49 -0500
commit6bc54fbcee6836f08355fcca76549c22ad2c2940 (patch)
tree0f5e275aacd29ee197061a11df171393aef727f6 /net/wireless/chan.c
parentd2859df5e7f00469011482d850fba652517a2eab (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.c85
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
428static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, 428static 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
459static 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
494static 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;