diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 0edb2566c14c..fb877b5621b7 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -1307,7 +1307,11 @@ enum nl80211_bitrate_attr { * wireless core it thinks its knows the regulatory domain we should be in. * @NL80211_REGDOM_SET_BY_COUNTRY_IE: the wireless core has received an * 802.11 country information element with regulatory information it - * thinks we should consider. + * thinks we should consider. cfg80211 only processes the country + * code from the IE, and relies on the regulatory domain information + * structure pased by userspace (CRDA) from our wireless-regdb. + * If a channel is enabled but the country code indicates it should + * be disabled we disable the channel and re-enable it upon disassociation. */ enum nl80211_reg_initiator { NL80211_REGDOM_SET_BY_CORE, diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 1bc8131a5185..8ab65f2afe70 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -750,8 +750,26 @@ static void handle_channel(struct wiphy *wiphy, desired_bw_khz, ®_rule); - if (r) + if (r) { + /* + * We will disable all channels that do not match our + * recieved regulatory rule unless the hint is coming + * from a Country IE and the Country IE had no information + * about a band. The IEEE 802.11 spec allows for an AP + * to send only a subset of the regulatory rules allowed, + * so an AP in the US that only supports 2.4 GHz may only send + * a country IE with information for the 2.4 GHz band + * while 5 GHz is still supported. + */ + if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE && + r == -ERANGE) + return; + + REG_DBG_PRINT("cfg80211: Disabling freq %d MHz\n", + chan->center_freq); + chan->flags = IEEE80211_CHAN_DISABLED; return; + } power_rule = ®_rule->power_rule; freq_range = ®_rule->freq_range;