On 20 November 2013 10:41, Janusz Dziedzic <janusz.dziedzic@xxxxxxxxx> wrote: > When nominal bandwidth falls completely or partly > within the band 5600MHz to 5650MHz the CAC time shall > be 10 minutes. > This is ETSI requirement. FCC forbids weather channels usage. > > Signed-off-by: Janusz Dziedzic <janusz.dziedzic@xxxxxxxxx> > --- > include/net/cfg80211.h | 7 ++++- > net/wireless/chan.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++ > net/wireless/core.h | 4 +++ > net/wireless/mlme.c | 2 +- > net/wireless/nl80211.c | 7 ++++- > 5 files changed, 96 insertions(+), 3 deletions(-) > > diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h > index ba640e9..6045ddc 100644 > --- a/include/net/cfg80211.h > +++ b/include/net/cfg80211.h > @@ -125,9 +125,12 @@ enum ieee80211_channel_flags { > #define IEEE80211_CHAN_NO_HT40 \ > (IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS) > > -#define IEEE80211_DFS_MIN_CAC_TIME_MS 60000 > +#define IEEE80211_DFS_MIN_CAC_TIME_MS (60 * 1000) > #define IEEE80211_DFS_MIN_NOP_TIME_MS (30 * 60 * 1000) > > +/* ETSI EN 301 893 V1.7.0 - Table D.1 */ > +#define IEEE80211_DFS_WEATHER_MIN_CAC_TIME_MS (10 * 60 * 1000) > + > /** > * struct ieee80211_channel - channel definition > * > @@ -3039,6 +3042,7 @@ struct cfg80211_cached_keys; > * @p2p_started: true if this is a P2P Device that has been started > * @cac_started: true if DFS channel availability check has been started > * @cac_start_time: timestamp (jiffies) when the dfs state was entered. > + * @cac_time_ms: CAC time in ms > * @ps: powersave mode is enabled > * @ps_timeout: dynamic powersave timeout > * @ap_unexpected_nlportid: (private) netlink port ID of application > @@ -3096,6 +3100,7 @@ struct wireless_dev { > > bool cac_started; > unsigned long cac_start_time; > + unsigned int cac_time_ms; > > #ifdef CONFIG_CFG80211_WEXT > /* wext data */ > diff --git a/net/wireless/chan.c b/net/wireless/chan.c > index 78559b5..057edde 100644 > --- a/net/wireless/chan.c > +++ b/net/wireless/chan.c > @@ -490,6 +490,85 @@ static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy, > return r; > } > > +static int cfg80211_get_chans_dfs_is_weather(struct wiphy *wiphy, > + u32 center_freq, > + u32 bandwidth) > +{ > + u32 start_freq, end_freq; > + > + start_freq = cfg80211_get_start_freq(center_freq, bandwidth) - 10; > + end_freq = cfg80211_get_end_freq(center_freq, bandwidth) + 10; > + > + /* > + * ETSI EN 301 893 V1.7.0 Table D.1 > + * TODO In the future we can get this from regdb eg. channel flag > + * IEEE80211_CHAN_TDWR. > + */ > + if ((start_freq >= 5600 && start_freq < 5650) || > + (end_freq > 5600 && end_freq <= 5650)) > + return 1; > + > + return 0; > +} > + > +static int > +cfg80211_chandef_dfs_is_weather(struct wiphy *wiphy, > + const struct cfg80211_chan_def *chandef) > +{ > + int width; > + int r; > + > + if (WARN_ON(!cfg80211_chandef_valid(chandef))) > + return -EINVAL; > + > + width = cfg80211_chandef_get_width(chandef); > + if (width < 0) > + return -EINVAL; > + > + r = cfg80211_get_chans_dfs_is_weather(wiphy, > + chandef->center_freq1, > + width); > + > + if (r) > + return r; > + > + switch (chandef->width) { > + case NL80211_CHAN_WIDTH_80P80: > + WARN_ON(!chandef->center_freq2); > + r = cfg80211_get_chans_dfs_is_weather(wiphy, > + chandef->center_freq2, > + width); Seems break is missing here. Will update after review. > + default: > + WARN_ON(chandef->center_freq2); > + break; > + } > + > + return r; > +} > + > +unsigned int > +cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy, > + const struct cfg80211_chan_def *chandef, > + enum nl80211_dfs_regions dfs_region) > +{ > + unsigned int timeout_ms = IEEE80211_DFS_MIN_CAC_TIME_MS; > + > + switch (dfs_region) { > + case NL80211_DFS_ETSI: > + if (cfg80211_chandef_dfs_is_weather(wiphy, chandef)) > + timeout_ms = IEEE80211_DFS_WEATHER_MIN_CAC_TIME_MS; > + break; > + /* TODO check JP CAC time */ > + case NL80211_DFS_JP: > + break; > + /* FCC don't allow weather channels */ > + case NL80211_DFS_FCC: > + default: > + break; > + } > + > + return timeout_ms; > +} > > static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, > u32 center_freq, u32 bandwidth, > diff --git a/net/wireless/core.h b/net/wireless/core.h > index 5390aeb..f497ea1 100644 > --- a/net/wireless/core.h > +++ b/net/wireless/core.h > @@ -401,6 +401,10 @@ void cfg80211_set_dfs_state(struct wiphy *wiphy, > > void cfg80211_dfs_channels_update_work(struct work_struct *work); > > +unsigned int > +cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy, > + const struct cfg80211_chan_def *chandef, > + enum nl80211_dfs_regions dfs_region); > > static inline int > cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, > diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c > index 733265f..30e2b50 100644 > --- a/net/wireless/mlme.c > +++ b/net/wireless/mlme.c > @@ -780,7 +780,7 @@ void cfg80211_cac_event(struct net_device *netdev, > switch (event) { > case NL80211_RADAR_CAC_FINISHED: > timeout = wdev->cac_start_time + > - msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS); > + msecs_to_jiffies(wdev->cac_time_ms); > WARN_ON(!time_after_eq(jiffies, timeout)); > cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE); > break; > diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c > index ea9ee18..c3b6694 100644 > --- a/net/wireless/nl80211.c > +++ b/net/wireless/nl80211.c > @@ -5632,6 +5632,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, > struct wireless_dev *wdev = dev->ieee80211_ptr; > struct cfg80211_chan_def chandef; > enum nl80211_dfs_regions dfs_region; > + unsigned int cac_time_ms; > int err; > > dfs_region = reg_get_dfs_region(wdev->wiphy); > @@ -5667,12 +5668,16 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, > if (err) > return err; > > + cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, &chandef, > + dfs_region); > + > err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef, > - IEEE80211_DFS_MIN_CAC_TIME_MS); > + cac_time_ms); > if (!err) { > wdev->channel = chandef.chan; > wdev->cac_started = true; > wdev->cac_start_time = jiffies; > + wdev->cac_time_ms = cac_time_ms; > } > return err; > } > -- > 1.7.9.5 > -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html