diff options
author | Kalle Valo <kvalo@codeaurora.org> | 2018-04-26 13:26:37 +0300 |
---|---|---|
committer | Kalle Valo <kvalo@codeaurora.org> | 2018-04-26 13:26:37 +0300 |
commit | 0ddcf3e76ae4d02918e609342a1020b50258fadd (patch) | |
tree | 940b90c384895782eeb769e93a65ecf14ff474ae /drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c | |
parent | 51c12756de427ee0ff90e2f00e121d2f5311c140 (diff) | |
parent | af8a41cccf8f469165c6debc8fe07c5fd2ca501a (diff) | |
download | linux-0ddcf3e76ae4d02918e609342a1020b50258fadd.tar.xz |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers.git
To fix a conflict reported by Stephen Rothwell <sfr@canb.auug.org.au>:
Today's linux-next merge of the wireless-drivers-next tree got a
conflict in:
drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
between commit:
77e30e10ee28 ("iwlwifi: mvm: query regdb for wmm rule if needed")
from the wireless-drivers tree and commits:
9c4f7d512740 ("iwlwifi: move all NVM parsing code to the common files")
4c625c564ba2 ("iwlwifi: get rid of fw/nvm.c")
from the wireless-drivers-next tree.
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c')
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c | 96 |
1 files changed, 87 insertions, 9 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index 6d33c14579d9..1f31d7bfdffc 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -855,21 +855,31 @@ static u32 iwl_nvm_get_regdom_bw_flags(const u8 *nvm_chan, return flags; } +struct regdb_ptrs { + struct ieee80211_wmm_rule *rule; + u32 token; +}; + struct ieee80211_regdomain * 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, + u16 geo_info) { int ch_idx; u16 ch_flags; u32 reg_rule_flags, prev_reg_rule_flags = 0; const u8 *nvm_chan = cfg->nvm_type == IWL_NVM_EXT ? iwl_ext_nvm_channels : iwl_nvm_channels; - struct ieee80211_regdomain *regd; - int size_of_regd; + struct ieee80211_regdomain *regd, *copy_rd; + int size_of_regd, regd_to_copy, wmms_to_copy; + int size_of_wmms = 0; struct ieee80211_reg_rule *rule; + struct ieee80211_wmm_rule *wmm_rule, *d_wmm, *s_wmm; + struct regdb_ptrs *regdb_ptrs; enum nl80211_band band; int center_freq, prev_center_freq = 0; - int valid_rules = 0; + int valid_rules = 0, n_wmms = 0; + int i; bool new_rule; int max_num_ch = cfg->nvm_type == IWL_NVM_EXT ? IWL_NVM_NUM_CHANNELS_EXT : IWL_NVM_NUM_CHANNELS; @@ -888,10 +898,26 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, sizeof(struct ieee80211_regdomain) + num_of_ch * sizeof(struct ieee80211_reg_rule); - regd = kzalloc(size_of_regd, GFP_KERNEL); + if (geo_info & GEO_WMM_ETSI_5GHZ_INFO) + size_of_wmms = + num_of_ch * sizeof(struct ieee80211_wmm_rule); + + regd = kzalloc(size_of_regd + size_of_wmms, GFP_KERNEL); if (!regd) return ERR_PTR(-ENOMEM); + regdb_ptrs = kcalloc(num_of_ch, sizeof(*regdb_ptrs), GFP_KERNEL); + if (!regdb_ptrs) { + copy_rd = ERR_PTR(-ENOMEM); + goto out; + } + + /* set alpha2 from FW. */ + regd->alpha2[0] = fw_mcc >> 8; + regd->alpha2[1] = fw_mcc & 0xff; + + wmm_rule = (struct ieee80211_wmm_rule *)((u8 *)regd + size_of_regd); + for (ch_idx = 0; ch_idx < num_of_ch; ch_idx++) { ch_flags = (u16)__le32_to_cpup(channels + ch_idx); band = (ch_idx < NUM_2GHZ_CHANNELS) ? @@ -940,15 +966,67 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, iwl_nvm_print_channel_flags(dev, IWL_DL_LAR, nvm_chan[ch_idx], ch_flags); + + if (!(geo_info & GEO_WMM_ETSI_5GHZ_INFO) || + band == NL80211_BAND_2GHZ) + continue; + + if (!reg_query_regdb_wmm(regd->alpha2, center_freq, + ®db_ptrs[n_wmms].token, wmm_rule)) { + /* Add only new rules */ + for (i = 0; i < n_wmms; i++) { + if (regdb_ptrs[i].token == + regdb_ptrs[n_wmms].token) { + rule->wmm_rule = regdb_ptrs[i].rule; + break; + } + } + if (i == n_wmms) { + rule->wmm_rule = wmm_rule; + regdb_ptrs[n_wmms++].rule = wmm_rule; + wmm_rule++; + } + } } regd->n_reg_rules = valid_rules; + regd->n_wmm_rules = n_wmms; - /* set alpha2 from FW. */ - regd->alpha2[0] = fw_mcc >> 8; - regd->alpha2[1] = fw_mcc & 0xff; + /* + * Narrow down regdom for unused regulatory rules to prevent hole + * between reg rules to wmm rules. + */ + regd_to_copy = sizeof(struct ieee80211_regdomain) + + valid_rules * sizeof(struct ieee80211_reg_rule); + + wmms_to_copy = sizeof(struct ieee80211_wmm_rule) * n_wmms; + + copy_rd = kzalloc(regd_to_copy + wmms_to_copy, GFP_KERNEL); + if (!copy_rd) { + copy_rd = ERR_PTR(-ENOMEM); + goto out; + } - return regd; + memcpy(copy_rd, regd, regd_to_copy); + memcpy((u8 *)copy_rd + regd_to_copy, (u8 *)regd + size_of_regd, + wmms_to_copy); + + d_wmm = (struct ieee80211_wmm_rule *)((u8 *)copy_rd + regd_to_copy); + s_wmm = (struct ieee80211_wmm_rule *)((u8 *)regd + size_of_regd); + + for (i = 0; i < regd->n_reg_rules; i++) { + if (!regd->reg_rules[i].wmm_rule) + continue; + + copy_rd->reg_rules[i].wmm_rule = d_wmm + + (regd->reg_rules[i].wmm_rule - s_wmm) / + sizeof(struct ieee80211_wmm_rule); + } + +out: + kfree(regdb_ptrs); + kfree(regd); + return copy_rd; } IWL_EXPORT_SYMBOL(iwl_parse_nvm_mcc_info); |