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>
This commit is contained in:
parent
d2859df5e7
commit
6bc54fbcee
1 changed files with 77 additions and 14 deletions
|
@ -425,6 +425,72 @@ bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool cfg80211_get_chans_dfs_available(struct wiphy *wiphy,
|
||||||
|
u32 center_freq,
|
||||||
|
u32 bandwidth)
|
||||||
|
{
|
||||||
|
struct ieee80211_channel *c;
|
||||||
|
u32 freq, start_freq, end_freq;
|
||||||
|
|
||||||
|
start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
|
||||||
|
end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check entire range of channels for the bandwidth.
|
||||||
|
* If any channel in between is disabled or has not
|
||||||
|
* had gone through CAC return false
|
||||||
|
*/
|
||||||
|
for (freq = start_freq; freq <= end_freq; freq += 20) {
|
||||||
|
c = ieee80211_get_channel(wiphy, freq);
|
||||||
|
if (!c)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (c->flags & IEEE80211_CHAN_DISABLED)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ((c->flags & IEEE80211_CHAN_RADAR) &&
|
||||||
|
(c->dfs_state != NL80211_DFS_AVAILABLE))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy,
|
||||||
|
const struct cfg80211_chan_def *chandef)
|
||||||
|
{
|
||||||
|
int width;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (WARN_ON(!cfg80211_chandef_valid(chandef)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
width = cfg80211_chandef_get_width(chandef);
|
||||||
|
if (width < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
r = cfg80211_get_chans_dfs_available(wiphy, chandef->center_freq1,
|
||||||
|
width);
|
||||||
|
|
||||||
|
/* If any of channels unavailable for cf1 just return */
|
||||||
|
if (!r)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
switch (chandef->width) {
|
||||||
|
case NL80211_CHAN_WIDTH_80P80:
|
||||||
|
WARN_ON(!chandef->center_freq2);
|
||||||
|
r = cfg80211_get_chans_dfs_available(wiphy,
|
||||||
|
chandef->center_freq2,
|
||||||
|
width);
|
||||||
|
default:
|
||||||
|
WARN_ON(chandef->center_freq2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
|
static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
|
||||||
u32 center_freq, u32 bandwidth,
|
u32 center_freq, u32 bandwidth,
|
||||||
u32 prohibited_flags)
|
u32 prohibited_flags)
|
||||||
|
@ -437,16 +503,7 @@ static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
|
||||||
|
|
||||||
for (freq = start_freq; freq <= end_freq; freq += 20) {
|
for (freq = start_freq; freq <= end_freq; freq += 20) {
|
||||||
c = ieee80211_get_channel(wiphy, freq);
|
c = ieee80211_get_channel(wiphy, freq);
|
||||||
if (!c)
|
if (!c || c->flags & prohibited_flags)
|
||||||
return false;
|
|
||||||
|
|
||||||
/* check for radar flags */
|
|
||||||
if ((prohibited_flags & c->flags & IEEE80211_CHAN_RADAR) &&
|
|
||||||
(c->dfs_state != NL80211_DFS_AVAILABLE))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/* check for the other flags */
|
|
||||||
if (c->flags & prohibited_flags & ~IEEE80211_CHAN_RADAR)
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -552,13 +609,19 @@ bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
|
||||||
struct cfg80211_chan_def *chandef)
|
struct cfg80211_chan_def *chandef)
|
||||||
{
|
{
|
||||||
bool res;
|
bool res;
|
||||||
|
u32 prohibited_flags = IEEE80211_CHAN_DISABLED |
|
||||||
|
IEEE80211_CHAN_NO_IR |
|
||||||
|
IEEE80211_CHAN_RADAR;
|
||||||
|
|
||||||
trace_cfg80211_reg_can_beacon(wiphy, chandef);
|
trace_cfg80211_reg_can_beacon(wiphy, chandef);
|
||||||
|
|
||||||
res = cfg80211_chandef_usable(wiphy, chandef,
|
if (cfg80211_chandef_dfs_required(wiphy, chandef) > 0 &&
|
||||||
IEEE80211_CHAN_DISABLED |
|
cfg80211_chandef_dfs_available(wiphy, chandef)) {
|
||||||
IEEE80211_CHAN_NO_IR |
|
/* We can skip IEEE80211_CHAN_NO_IR if chandef dfs available */
|
||||||
IEEE80211_CHAN_RADAR);
|
prohibited_flags = IEEE80211_CHAN_DISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = cfg80211_chandef_usable(wiphy, chandef, prohibited_flags);
|
||||||
|
|
||||||
trace_cfg80211_return_bool(res);
|
trace_cfg80211_return_bool(res);
|
||||||
return res;
|
return res;
|
||||||
|
|
Loading…
Add table
Reference in a new issue