Commit 92b0f7b2 authored by Emmanuel Grumbach's avatar Emmanuel Grumbach Committed by Luca Coelho

iwlwifi: split the regulatory rules when the bandwidth flags require it

When we create a regulatory domain out of an MCC
notification, we need to make sure that all the channels
in the rule have the exact same properties.
The current code mixes channel 36 and 40 although 36 can be
a control channel with HT40+ (36, 40) whereas 40 can't be
a control channel with HT40+ since  (40, 44) is invalid.

Because of that, cfg80211 would allow to connect in 40MHz
to APs that are configured to channel 40 HT40+ and that made
our firmware assert.

Fix this by checking the bandwidth flags before taking the
decision if the rule should be split.

This fixes https://bugzilla.kernel.org/show_bug.cgi?id=195299 partly.

Fixes: af45a900 ("iwlwifi: create regdomain from mcc_update_cmd response")
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent 58877d74
...@@ -785,7 +785,8 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, ...@@ -785,7 +785,8 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
int num_of_ch, __le32 *channels, u16 fw_mcc) int num_of_ch, __le32 *channels, u16 fw_mcc)
{ {
int ch_idx; int ch_idx;
u16 ch_flags, prev_ch_flags = 0; u16 ch_flags;
u32 reg_rule_flags, prev_reg_rule_flags = 0;
const u8 *nvm_chan = cfg->ext_nvm ? const u8 *nvm_chan = cfg->ext_nvm ?
iwl_ext_nvm_channels : iwl_nvm_channels; iwl_ext_nvm_channels : iwl_nvm_channels;
struct ieee80211_regdomain *regd; struct ieee80211_regdomain *regd;
...@@ -834,8 +835,11 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, ...@@ -834,8 +835,11 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
continue; continue;
} }
reg_rule_flags = iwl_nvm_get_regdom_bw_flags(nvm_chan, ch_idx,
ch_flags, cfg);
/* we can't continue the same rule */ /* we can't continue the same rule */
if (ch_idx == 0 || prev_ch_flags != ch_flags || if (ch_idx == 0 || prev_reg_rule_flags != reg_rule_flags ||
center_freq - prev_center_freq > 20) { center_freq - prev_center_freq > 20) {
valid_rules++; valid_rules++;
new_rule = true; new_rule = true;
...@@ -854,18 +858,17 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, ...@@ -854,18 +858,17 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
rule->power_rule.max_eirp = rule->power_rule.max_eirp =
DBM_TO_MBM(IWL_DEFAULT_MAX_TX_POWER); DBM_TO_MBM(IWL_DEFAULT_MAX_TX_POWER);
rule->flags = iwl_nvm_get_regdom_bw_flags(nvm_chan, ch_idx, rule->flags = reg_rule_flags;
ch_flags, cfg);
/* rely on auto-calculation to merge BW of contiguous chans */ /* rely on auto-calculation to merge BW of contiguous chans */
rule->flags |= NL80211_RRF_AUTO_BW; rule->flags |= NL80211_RRF_AUTO_BW;
rule->freq_range.max_bandwidth_khz = 0; rule->freq_range.max_bandwidth_khz = 0;
prev_ch_flags = ch_flags;
prev_center_freq = center_freq; prev_center_freq = center_freq;
prev_reg_rule_flags = reg_rule_flags;
IWL_DEBUG_DEV(dev, IWL_DL_LAR, IWL_DEBUG_DEV(dev, IWL_DL_LAR,
"Ch. %d [%sGHz] %s%s%s%s%s%s%s%s%s(0x%02x): Ad-Hoc %ssupported\n", "Ch. %d [%sGHz] %s%s%s%s%s%s%s%s%s(0x%02x) reg_flags 0x%x: %s\n",
center_freq, center_freq,
band == NL80211_BAND_5GHZ ? "5.2" : "2.4", band == NL80211_BAND_5GHZ ? "5.2" : "2.4",
CHECK_AND_PRINT_I(VALID), CHECK_AND_PRINT_I(VALID),
...@@ -877,10 +880,10 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, ...@@ -877,10 +880,10 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
CHECK_AND_PRINT_I(160MHZ), CHECK_AND_PRINT_I(160MHZ),
CHECK_AND_PRINT_I(INDOOR_ONLY), CHECK_AND_PRINT_I(INDOOR_ONLY),
CHECK_AND_PRINT_I(GO_CONCURRENT), CHECK_AND_PRINT_I(GO_CONCURRENT),
ch_flags, ch_flags, reg_rule_flags,
((ch_flags & NVM_CHANNEL_ACTIVE) && ((ch_flags & NVM_CHANNEL_ACTIVE) &&
!(ch_flags & NVM_CHANNEL_RADAR)) !(ch_flags & NVM_CHANNEL_RADAR))
? "" : "not "); ? "Ad-Hoc" : "");
} }
regd->n_reg_rules = valid_rules; regd->n_reg_rules = valid_rules;
......
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