Commit 6bc54fbc authored by Janusz Dziedzic's avatar Janusz Dziedzic Committed by Johannes Berg

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: default avatarJanusz Dziedzic <janusz.dziedzic@tieto.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent d2859df5
...@@ -425,9 +425,9 @@ bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy, ...@@ -425,9 +425,9 @@ bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy,
} }
static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, static bool cfg80211_get_chans_dfs_available(struct wiphy *wiphy,
u32 center_freq, u32 bandwidth, u32 center_freq,
u32 prohibited_flags) u32 bandwidth)
{ {
struct ieee80211_channel *c; struct ieee80211_channel *c;
u32 freq, start_freq, end_freq; u32 freq, start_freq, end_freq;
...@@ -435,18 +435,75 @@ static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, ...@@ -435,18 +435,75 @@ static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
start_freq = cfg80211_get_start_freq(center_freq, bandwidth); start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
end_freq = cfg80211_get_end_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) { 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)
return false; return false;
/* check for radar flags */ if (c->flags & IEEE80211_CHAN_DISABLED)
if ((prohibited_flags & c->flags & IEEE80211_CHAN_RADAR) && return false;
if ((c->flags & IEEE80211_CHAN_RADAR) &&
(c->dfs_state != NL80211_DFS_AVAILABLE)) (c->dfs_state != NL80211_DFS_AVAILABLE))
return false; 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,
u32 center_freq, u32 bandwidth,
u32 prohibited_flags)
{
struct ieee80211_channel *c;
u32 freq, start_freq, end_freq;
/* check for the other flags */ start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
if (c->flags & prohibited_flags & ~IEEE80211_CHAN_RADAR) end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
for (freq = start_freq; freq <= end_freq; freq += 20) {
c = ieee80211_get_channel(wiphy, freq);
if (!c || c->flags & prohibited_flags)
return false; return false;
} }
...@@ -552,13 +609,19 @@ bool cfg80211_reg_can_beacon(struct wiphy *wiphy, ...@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment