From: "Luis R. Rodriguez" <mcgrof@xxxxxxxxxxxxxxxx> It turns out that what is known as UNII 1 (5180 MHz - 5240 MHz) and UNII 3 (5745 MHz - 5825 MHz) share the same regulatory permissions globally. This fact can be used to enable enhancing world roaming quite a bit by taking advantage of beacon hints [0]. If we receive a beacon hint on UNII 1 it means we can not only take advantage of that beacon hint to lift passive scan flags on that channel but all other UNII 1 channels. The same applies to UNII 3. This implements UNII 1 and UNII 3 beacon hints. [0] http://wireless.kernel.org/en/developers/Regulatory/processing_rules#Beacon_hints Signed-off-by: Luis R. Rodriguez <mcgrof@xxxxxxxxxxxxxxxx> --- net/wireless/reg.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 123 insertions(+), 1 deletion(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 8525ece..2366ea2 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1061,6 +1061,128 @@ static bool reg_chan_process_beacon_hint(struct wiphy *wiphy, return channel_changed; } +enum reg_5ghz_unii_band { + REG_5GHZ_UNKNOWN, /* all others */ + REG_5GHZ_UNII_1, /* 5180 MHz - 5240 MHz */ + REG_5GHZ_UNII_2, /* 5260 MHz - 5320 MHz */ + REG_5GHZ_MID_BAND, /* 5500 MHz - 5700 MHz */ + REG_5GHZ_UNII_3, /* 5745 MHz - 5825 MHz */ +}; + +static bool reg_is_5ghz_unii_1(struct ieee80211_channel *chan) +{ + if (chan->center_freq >= 5180 && + chan->center_freq <= 5240) + return true; + return false; +} + +static bool reg_is_5ghz_unii_2(struct ieee80211_channel *chan) +{ + if (chan->center_freq >= 5260 && + chan->center_freq <= 5320 ) + return true; + return false; +} + +static bool reg_is_5ghz_mid_band(struct ieee80211_channel *chan) +{ + if (chan->center_freq >= 5500 && + chan->center_freq <= 5700) + return true; + return false; +} + +static bool reg_is_5ghz_unii_3(struct ieee80211_channel *chan) +{ + if (chan->center_freq >= 5745 && + chan->center_freq <= 5825) + return true; + return false; +} + +static enum reg_5ghz_unii_band +reg_get_5ghz_unii_band(struct ieee80211_channel *chan) +{ + if (reg_is_5ghz_unii_1(chan)) + return REG_5GHZ_UNII_1; + if (reg_is_5ghz_unii_2(chan)) + return REG_5GHZ_UNII_2; + if (reg_is_5ghz_mid_band(chan)) + return REG_5GHZ_MID_BAND; + if (reg_is_5ghz_mid_band(chan)) + return REG_5GHZ_UNII_3; + + return REG_5GHZ_UNKNOWN; +} + +static void reg_unii_5ghz_beacon_hint_unii(struct wiphy *wiphy, + struct ieee80211_channel *chan, + enum reg_5ghz_unii_band unii_band) +{ + struct ieee80211_supported_band *sband; + unsigned int i; + + assert_cfg80211_lock(); + + sband = wiphy->bands[chan->band]; + + /* + * Only process UNII 1 hints for UNII 1 channels + * Only process UNII 3 hints for UNII 3 channels + */ + for (i = 0; i < sband->n_channels; i++) { + struct ieee80211_channel *c = &sband->channels[i]; + + switch (unii_band) { + case REG_5GHZ_UNII_1: + if (!reg_is_5ghz_unii_1(c)) + continue; + break; + case REG_5GHZ_UNII_3: + if (!reg_is_5ghz_unii_3(c)) + continue; + break; + default: + WARN_ONCE(1, "unexpected regulatory unii hint\n"); + continue; + } + + reg_chan_process_beacon_hint(wiphy, chan); + } + + REG_DBG_PRINT("Processed 5 GHz UNII %d beacon hint\n", + (unii_band == REG_5GHZ_UNII_1) ? 1 : 3); +} + +static void reg_unii_5ghz_beacon_hint(struct wiphy *wiphy, + struct ieee80211_channel *chan) +{ + enum reg_5ghz_unii_band unii_band = reg_get_5ghz_unii_band(chan); + + switch (unii_band) { + case REG_5GHZ_UNKNOWN: + return; + /* + * These should not happen given that typically DFS + * is always enabled on the rest of the 5 GHz frequencies. + * We'll just bail out. + */ + case REG_5GHZ_UNII_2: + case REG_5GHZ_MID_BAND: + return; + /* + * 5 GHz UNII hints are only enabled for UNII1 and UNII3 + */ + case REG_5GHZ_UNII_1: + case REG_5GHZ_UNII_3: + reg_unii_5ghz_beacon_hint_unii(wiphy, chan, unii_band); + break; + default: + break; + } +} + static void handle_reg_beacon(struct wiphy *wiphy, unsigned int chan_idx, struct reg_beacon *reg_beacon) @@ -1080,7 +1202,7 @@ static void handle_reg_beacon(struct wiphy *wiphy, channel_changed = reg_chan_process_beacon_hint(wiphy, chan); if (channel_changed) - return; /* some band hint could potenially go here */ + reg_unii_5ghz_beacon_hint(wiphy, chan); } /* -- 1.7.10.4 -- 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