iwlwifi: fix sar geo table initialization
When adding support for version 3 of the GEO_TX_POWER_LIMIT command, the table argument of iwl_sar_geo_init was changed from a pointer a 1d array of now-removed iwl_per_chain_offset_group_v1 to a pointer to a 2d array of iwl_per_chain_offset (iwl_per_chain_offset_group_v1 was a struct containing 2 copies of iwl_per_chain_offset). So even for version 2 where the second dimension is of length 2, which means that the underlying memory layout of the array didn't change, this requires a small change in the way we loop over it, and this was missed. Additionally, for the case of version 3 where the second dimension is now 3, in order to fill the first two elements of each row correctly (lb and hb), iwl_sar_geo_init must get the true number of bands supported. But because we don't yet store any values for the 3rd (uhb) band, skip that band. Signed-off-by: Naftali Goldstein <naftali.goldstein@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org> Link: https://lore.kernel.org/r/iwlwifi.20201008181047.73605b6e0548.Id0ec98333277ff9e017e3938ae413b34acc68947@changeid
This commit is contained in:

committed by
Kalle Valo

parent
853f4954ba
commit
45acebf8d6
@@ -923,14 +923,39 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
|
||||
{
|
||||
union iwl_geo_tx_power_profiles_cmd cmd;
|
||||
u16 len;
|
||||
u32 n_bands;
|
||||
int ret;
|
||||
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, PHY_OPS_GROUP,
|
||||
GEO_TX_POWER_LIMIT,
|
||||
IWL_FW_CMD_VER_UNKNOWN);
|
||||
|
||||
/* the table is also at the same position both in v1 and v2 */
|
||||
ret = iwl_sar_geo_init(&mvm->fwrt, &cmd.v1.table[0][0],
|
||||
ACPI_WGDS_NUM_BANDS);
|
||||
BUILD_BUG_ON(offsetof(struct iwl_geo_tx_power_profiles_cmd_v1, ops) !=
|
||||
offsetof(struct iwl_geo_tx_power_profiles_cmd_v2, ops) ||
|
||||
offsetof(struct iwl_geo_tx_power_profiles_cmd_v2, ops) !=
|
||||
offsetof(struct iwl_geo_tx_power_profiles_cmd_v3, ops));
|
||||
/* the ops field is at the same spot for all versions, so set in v1 */
|
||||
cmd.v1.ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_SET_TABLES);
|
||||
|
||||
if (cmd_ver == 3) {
|
||||
len = sizeof(cmd.v3);
|
||||
n_bands = ARRAY_SIZE(cmd.v3.table[0]);
|
||||
cmd.v3.table_revision = cpu_to_le32(mvm->fwrt.geo_rev);
|
||||
} else if (fw_has_api(&mvm->fwrt.fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_SAR_TABLE_VER)) {
|
||||
len = sizeof(cmd.v2);
|
||||
n_bands = ARRAY_SIZE(cmd.v2.table[0]);
|
||||
cmd.v2.table_revision = cpu_to_le32(mvm->fwrt.geo_rev);
|
||||
} else {
|
||||
len = sizeof(cmd.v1);
|
||||
n_bands = ARRAY_SIZE(cmd.v1.table[0]);
|
||||
}
|
||||
|
||||
BUILD_BUG_ON(offsetof(struct iwl_geo_tx_power_profiles_cmd_v1, table) !=
|
||||
offsetof(struct iwl_geo_tx_power_profiles_cmd_v2, table) ||
|
||||
offsetof(struct iwl_geo_tx_power_profiles_cmd_v2, table) !=
|
||||
offsetof(struct iwl_geo_tx_power_profiles_cmd_v3, table));
|
||||
/* the table is at the same position for all versions, so set use v1 */
|
||||
ret = iwl_sar_geo_init(&mvm->fwrt, &cmd.v1.table[0][0], n_bands);
|
||||
|
||||
/*
|
||||
* It is a valid scenario to not support SAR, or miss wgds table,
|
||||
@@ -939,20 +964,6 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
|
||||
if (ret)
|
||||
return 0;
|
||||
|
||||
/* the ops field is at the same spot for all versions, so set in v1 */
|
||||
cmd.v1.ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_SET_TABLES);
|
||||
|
||||
if (cmd_ver == 3) {
|
||||
len = sizeof(cmd.v3);
|
||||
cmd.v3.table_revision = cpu_to_le32(mvm->fwrt.geo_rev);
|
||||
} else if (fw_has_api(&mvm->fwrt.fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_SAR_TABLE_VER)) {
|
||||
len = sizeof(cmd.v2);
|
||||
cmd.v2.table_revision = cpu_to_le32(mvm->fwrt.geo_rev);
|
||||
} else {
|
||||
len = sizeof(cmd.v1);
|
||||
}
|
||||
|
||||
return iwl_mvm_send_cmd_pdu(mvm,
|
||||
WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT),
|
||||
0, len, &cmd);
|
||||
|
Reference in New Issue
Block a user