diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c index 838b2844e3d67..e93656e461eae 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c @@ -645,7 +645,7 @@ bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt) IWL_EXPORT_SYMBOL(iwl_sar_geo_support); int iwl_sar_geo_init(struct iwl_fw_runtime *fwrt, - struct iwl_per_chain_offset_group_v1 *table) + struct iwl_per_chain_offset *table, u32 n_bands) { int ret, i, j; @@ -661,16 +661,11 @@ int iwl_sar_geo_init(struct iwl_fw_runtime *fwrt, return -ENOENT; } - BUILD_BUG_ON(ACPI_NUM_GEO_PROFILES * ACPI_WGDS_NUM_BANDS * - ACPI_WGDS_TABLE_SIZE + 1 != ACPI_WGDS_WIFI_DATA_SIZE); - - BUILD_BUG_ON(ACPI_NUM_GEO_PROFILES > IWL_NUM_GEO_PROFILES); - for (i = 0; i < ACPI_NUM_GEO_PROFILES; i++) { struct iwl_per_chain_offset *chain = (struct iwl_per_chain_offset *)&table[i]; - for (j = 0; j < ACPI_WGDS_NUM_BANDS; j++) { + for (j = 0; j < n_bands; j++) { u8 *value; value = &fwrt->geo_profiles[i].values[j * diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h index 94fabe6cd3686..9d08d74e69394 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h @@ -196,7 +196,7 @@ int iwl_sar_get_wgds_table(struct iwl_fw_runtime *fwrt); bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt); int iwl_sar_geo_init(struct iwl_fw_runtime *fwrt, - struct iwl_per_chain_offset_group_v1 *table); + struct iwl_per_chain_offset *table, u32 n_bands); int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt, __le32 *black_list_array, int *black_list_size); @@ -269,8 +269,8 @@ static inline bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt) return false; } -static inline int iwl_sar_geo_init(struct iwl_fw_runtime *fwrt, - struct iwl_per_chain_offset_group *table) +static int iwl_sar_geo_init(struct iwl_fw_runtime *fwrt, + struct iwl_per_chain_offset *table, u32 n_bands) { return -ENOENT; } diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h index c3111a1e9f573..4e6ad1793d0a1 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h @@ -437,6 +437,8 @@ struct iwl_dev_tx_power_cmd { }; #define IWL_NUM_GEO_PROFILES 3 +#define IWL_NUM_BANDS_PER_CHAIN_V1 2 +#define IWL_NUM_BANDS_PER_CHAIN_V2 3 /** * enum iwl_geo_per_chain_offset_operation - type of operation @@ -460,11 +462,6 @@ struct iwl_per_chain_offset { u8 chain_b; } __packed; /* PER_CHAIN_LIMIT_OFFSET_PER_CHAIN_S_VER_1 */ -struct iwl_per_chain_offset_group_v1 { - struct iwl_per_chain_offset lb; - struct iwl_per_chain_offset hb; -} __packed; /* PER_CHAIN_LIMIT_OFFSET_GROUP_S_VER_1 */ - /** * struct iwl_geo_tx_power_profile_cmd_v1 - struct for GEO_TX_POWER_LIMIT cmd. * @ops: operations, value from &enum iwl_geo_per_chain_offset_operation @@ -472,24 +469,37 @@ struct iwl_per_chain_offset_group_v1 { */ struct iwl_geo_tx_power_profiles_cmd_v1 { __le32 ops; - struct iwl_per_chain_offset_group_v1 table[IWL_NUM_GEO_PROFILES]; + struct iwl_per_chain_offset table[IWL_NUM_GEO_PROFILES][IWL_NUM_BANDS_PER_CHAIN_V1]; } __packed; /* GEO_TX_POWER_LIMIT_VER_1 */ /** - * struct iwl_geo_tx_power_profile_cmd - struct for GEO_TX_POWER_LIMIT cmd. + * struct iwl_geo_tx_power_profile_cmd_v2 - struct for GEO_TX_POWER_LIMIT cmd. * @ops: operations, value from &enum iwl_geo_per_chain_offset_operation * @table: offset profile per band. * @table_revision: BIOS table revision. */ struct iwl_geo_tx_power_profiles_cmd_v2 { __le32 ops; - struct iwl_per_chain_offset_group_v1 table[IWL_NUM_GEO_PROFILES]; + struct iwl_per_chain_offset table[IWL_NUM_GEO_PROFILES][IWL_NUM_BANDS_PER_CHAIN_V1]; __le32 table_revision; } __packed; /* GEO_TX_POWER_LIMIT_VER_2 */ +/** + * struct iwl_geo_tx_power_profile_cmd_v3 - struct for GEO_TX_POWER_LIMIT cmd. + * @ops: operations, value from &enum iwl_geo_per_chain_offset_operation + * @table: offset profile per band. + * @table_revision: BIOS table revision. + */ +struct iwl_geo_tx_power_profiles_cmd_v3 { + __le32 ops; + struct iwl_per_chain_offset table[IWL_NUM_GEO_PROFILES][IWL_NUM_BANDS_PER_CHAIN_V2]; + __le32 table_revision; +} __packed; /* GEO_TX_POWER_LIMIT_VER_3 */ + union iwl_geo_tx_power_profiles_cmd { struct iwl_geo_tx_power_profiles_cmd_v1 v1; struct iwl_geo_tx_power_profiles_cmd_v2 v2; + struct iwl_geo_tx_power_profiles_cmd_v3 v3; }; /** diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 644bd59cb0f07..06bb8ad84efb0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -787,13 +787,17 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm) u16 len; int ret; struct iwl_host_cmd cmd; + u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, + PHY_OPS_GROUP, GEO_TX_POWER_LIMIT); /* the ops field is at the same spot for all versions, so set in v1 */ geo_tx_cmd.v1.ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_GET_CURRENT_TABLE); - if (fw_has_api(&mvm->fwrt.fw->ucode_capa, - IWL_UCODE_TLV_API_SAR_TABLE_VER)) + if (cmd_ver == 3) + len = sizeof(geo_tx_cmd.v3); + else if (fw_has_api(&mvm->fwrt.fw->ucode_capa, + IWL_UCODE_TLV_API_SAR_TABLE_VER)) len = sizeof(geo_tx_cmd.v2); else len = sizeof(geo_tx_cmd.v1); @@ -829,9 +833,12 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm) union iwl_geo_tx_power_profiles_cmd cmd; u16 len; int ret; + u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, + PHY_OPS_GROUP, GEO_TX_POWER_LIMIT); /* the table is also at the same position both in v1 and v2 */ - ret = iwl_sar_geo_init(&mvm->fwrt, cmd.v1.table); + ret = iwl_sar_geo_init(&mvm->fwrt, &cmd.v1.table[0][0], + ACPI_WGDS_NUM_BANDS); /* * It is a valid scenario to not support SAR, or miss wgds table, @@ -843,8 +850,11 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm) /* 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 (fw_has_api(&mvm->fwrt.fw->ucode_capa, - IWL_UCODE_TLV_API_SAR_TABLE_VER)) { + 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 {