Commit e27c506a authored by Gil Adam's avatar Gil Adam Committed by Luca Coelho

iwlwifi: regulatory: regulatory capabilities api change

Support v2 of regulatory capability flags parsed from the device
NVM. New API support is determined by FW lookup of the MCC update
command resposnse version, where version 6 supports the new API.
Signed-off-by: default avatarGil Adam <gil.adam@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/iwlwifi.20200926002540.3d47f4e8ab98.I0fdd2ce23166c18284d2a7a624c40f35ea81cbc2@changeidSigned-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent ba8f6f4a
......@@ -254,6 +254,65 @@ enum iwl_reg_capa_flags {
REG_CAPA_11AX_DISABLED = BIT(10),
};
/**
* enum iwl_reg_capa_flags_v2 - global flags applied for the whole regulatory
* domain (version 2).
* @REG_CAPA_V2_STRADDLE_DISABLED: Straddle channels (144, 142, 138) are
* disabled.
* @REG_CAPA_V2_BF_CCD_LOW_BAND: Beam-forming or Cyclic Delay Diversity in the
* 2.4Ghz band is allowed.
* @REG_CAPA_V2_BF_CCD_HIGH_BAND: Beam-forming or Cyclic Delay Diversity in the
* 5Ghz band is allowed.
* @REG_CAPA_V2_160MHZ_ALLOWED: 11ac channel with a width of 160Mhz is allowed
* for this regulatory domain (valid only in 5Ghz).
* @REG_CAPA_V2_80MHZ_ALLOWED: 11ac channel with a width of 80Mhz is allowed
* for this regulatory domain (valid only in 5Ghz).
* @REG_CAPA_V2_MCS_8_ALLOWED: 11ac with MCS 8 is allowed.
* @REG_CAPA_V2_MCS_9_ALLOWED: 11ac with MCS 9 is allowed.
* @REG_CAPA_V2_WEATHER_DISABLED: Weather radar channels (120, 124, 128, 118,
* 126, 122) are disabled.
* @REG_CAPA_V2_40MHZ_ALLOWED: 11n channel with a width of 40Mhz is allowed
* for this regulatory domain (uvalid only in 5Ghz).
* @REG_CAPA_V2_11AX_DISABLED: 11ax is forbidden for this regulatory domain.
*/
enum iwl_reg_capa_flags_v2 {
REG_CAPA_V2_STRADDLE_DISABLED = BIT(0),
REG_CAPA_V2_BF_CCD_LOW_BAND = BIT(1),
REG_CAPA_V2_BF_CCD_HIGH_BAND = BIT(2),
REG_CAPA_V2_160MHZ_ALLOWED = BIT(3),
REG_CAPA_V2_80MHZ_ALLOWED = BIT(4),
REG_CAPA_V2_MCS_8_ALLOWED = BIT(5),
REG_CAPA_V2_MCS_9_ALLOWED = BIT(6),
REG_CAPA_V2_WEATHER_DISABLED = BIT(7),
REG_CAPA_V2_40MHZ_ALLOWED = BIT(8),
REG_CAPA_V2_11AX_DISABLED = BIT(13),
};
/*
* API v2 for reg_capa_flags is relevant from version 6 and onwards of the
* MCC update command response.
*/
#define REG_CAPA_V2_RESP_VER 6
/**
* struct iwl_reg_capa - struct for global regulatory capabilities, Used for
* handling the different APIs of reg_capa_flags.
*
* @allow_40mhz: 11n channel with a width of 40Mhz is allowed
* for this regulatory domain (valid only in 5Ghz).
* @allow_80mhz: 11ac channel with a width of 80Mhz is allowed
* for this regulatory domain (valid only in 5Ghz).
* @allow_160mhz: 11ac channel with a width of 160Mhz is allowed
* for this regulatory domain (valid only in 5Ghz).
* @disable_11ax: 11ax is forbidden for this regulatory domain.
*/
struct iwl_reg_capa {
u16 allow_40mhz;
u16 allow_80mhz;
u16 allow_160mhz;
u16 disable_11ax;
};
static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level,
int chan, u32 flags)
{
......@@ -1064,7 +1123,7 @@ IWL_EXPORT_SYMBOL(iwl_parse_nvm_data);
static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan,
int ch_idx, u16 nvm_flags,
u16 cap_flags,
struct iwl_reg_capa reg_capa,
const struct iwl_cfg *cfg)
{
u32 flags = NL80211_RRF_NO_HT40;
......@@ -1104,29 +1163,46 @@ static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan,
flags |= NL80211_RRF_GO_CONCURRENT;
/*
* cap_flags is per regulatory domain so apply it for every channel
* reg_capa is per regulatory domain so apply it for every channel
*/
if (ch_idx >= NUM_2GHZ_CHANNELS) {
if (cap_flags & REG_CAPA_40MHZ_FORBIDDEN)
if (!reg_capa.allow_40mhz)
flags |= NL80211_RRF_NO_HT40;
if (!(cap_flags & REG_CAPA_80MHZ_ALLOWED))
if (!reg_capa.allow_80mhz)
flags |= NL80211_RRF_NO_80MHZ;
if (!(cap_flags & REG_CAPA_160MHZ_ALLOWED))
if (!reg_capa.allow_160mhz)
flags |= NL80211_RRF_NO_160MHZ;
}
if (cap_flags & REG_CAPA_11AX_DISABLED)
if (reg_capa.disable_11ax)
flags |= NL80211_RRF_NO_HE;
return flags;
}
static struct iwl_reg_capa iwl_get_reg_capa(u16 flags, u8 resp_ver)
{
struct iwl_reg_capa reg_capa;
if (resp_ver >= REG_CAPA_V2_RESP_VER) {
reg_capa.allow_40mhz = flags & REG_CAPA_V2_40MHZ_ALLOWED;
reg_capa.allow_80mhz = flags & REG_CAPA_V2_80MHZ_ALLOWED;
reg_capa.allow_160mhz = flags & REG_CAPA_V2_160MHZ_ALLOWED;
reg_capa.disable_11ax = flags & REG_CAPA_V2_11AX_DISABLED;
} else {
reg_capa.allow_40mhz = !(flags & REG_CAPA_40MHZ_FORBIDDEN);
reg_capa.allow_80mhz = flags & REG_CAPA_80MHZ_ALLOWED;
reg_capa.allow_160mhz = flags & REG_CAPA_160MHZ_ALLOWED;
reg_capa.disable_11ax = flags & REG_CAPA_11AX_DISABLED;
}
return reg_capa;
}
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,
u16 geo_info, u16 cap)
u16 geo_info, u16 cap, u8 resp_ver)
{
int ch_idx;
u16 ch_flags;
......@@ -1139,6 +1215,7 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
int valid_rules = 0;
bool new_rule;
int max_num_ch;
struct iwl_reg_capa reg_capa;
if (cfg->uhb_supported) {
max_num_ch = IWL_NVM_NUM_CHANNELS_UHB;
......@@ -1169,6 +1246,9 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
regd->alpha2[0] = fw_mcc >> 8;
regd->alpha2[1] = fw_mcc & 0xff;
/* parse regulatory capability flags */
reg_capa = iwl_get_reg_capa(cap, resp_ver);
for (ch_idx = 0; ch_idx < num_of_ch; ch_idx++) {
ch_flags = (u16)__le32_to_cpup(channels + ch_idx);
band = iwl_nl80211_band_from_channel_idx(ch_idx);
......@@ -1183,7 +1263,7 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
}
reg_rule_flags = iwl_nvm_get_regdom_bw_flags(nvm_chan, ch_idx,
ch_flags, cap,
ch_flags, reg_capa,
cfg);
/* we can't continue the same rule */
......
......@@ -104,7 +104,7 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
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,
u16 geo_info, u16 cap);
u16 geo_info, u16 cap, u8 resp_ver);
/**
* struct iwl_nvm_section - describes an NVM section in memory.
......
......@@ -234,6 +234,7 @@ struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy,
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mcc_update_resp *resp;
u8 resp_ver;
IWL_DEBUG_LAR(mvm, "Getting regdomain data for %s from FW\n", alpha2);
......@@ -252,13 +253,16 @@ struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy,
*changed = (status == MCC_RESP_NEW_CHAN_PROFILE ||
status == MCC_RESP_ILLEGAL);
}
resp_ver = iwl_fw_lookup_notif_ver(mvm->fw, IWL_ALWAYS_LONG_GROUP,
MCC_UPDATE_CMD, 0);
IWL_DEBUG_LAR(mvm, "MCC update response version: %d\n", resp_ver);
regd = iwl_parse_nvm_mcc_info(mvm->trans->dev, mvm->cfg,
__le32_to_cpu(resp->n_channels),
resp->channels,
__le16_to_cpu(resp->mcc),
__le16_to_cpu(resp->geo_info),
__le16_to_cpu(resp->cap));
__le16_to_cpu(resp->cap), resp_ver);
/* Store the return source id */
src_id = resp->source_id;
kfree(resp);
......
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