diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c index b64abb8439b7..d00191e84f20 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c @@ -981,6 +981,7 @@ int iwl_acpi_get_ppag_table(struct iwl_fw_runtime *fwrt) } } + iwl_bios_print_ppag(fwrt, num_sub_bands); fwrt->ppag_bios_source = BIOS_SOURCE_ACPI; ret = 0; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h index 0cd8a12e0f7c..118c08f95649 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h @@ -269,6 +269,7 @@ enum iwl_dev_tx_power_cmd_mode { #define IWL_NUM_CHAIN_LIMITS 2 #define IWL_NUM_SUB_BANDS_V1 5 #define IWL_NUM_SUB_BANDS_V2 11 +#define IWL_NUM_SUB_BANDS_V3 12 /** * struct iwl_dev_tx_power_common - Common part of the TX power reduction cmd @@ -573,6 +574,7 @@ enum iwl_ppag_flags { * @v1: command version 1 structure. * @v5: command version 5 structure. * @v7: command version 7 structure. + * @v8: command version 8 structure. * @v1.flags: values from &enum iwl_ppag_flags * @v1.gain: table of antenna gain values per chain and sub-band * @v1.reserved: reserved @@ -581,6 +583,8 @@ enum iwl_ppag_flags { * @v7.ppag_config_info: see @struct bios_value_u32 * @v7.gain: table of antenna gain values per chain and sub-band * @v7.reserved: reserved + * @v8.ppag_config_info: see @struct bios_value_u32 + * @v8.gain: table of antenna gain values per chain and sub-band */ union iwl_ppag_table_cmd { struct { @@ -598,6 +602,10 @@ union iwl_ppag_table_cmd { s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2]; s8 reserved[2]; } __packed v7; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_7 */ + struct { + struct bios_value_u32 ppag_config_info; + s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V3]; + } __packed v8; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_8 */ } __packed; #define IWL_PPAG_CMD_V1_MASK (IWL_PPAG_ETSI_MASK | IWL_PPAG_CHINA_MASK) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c index 9e834cc1b054..55128caac7ed 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c @@ -318,6 +318,27 @@ bool iwl_is_ppag_approved(struct iwl_fw_runtime *fwrt) } IWL_EXPORT_SYMBOL(iwl_is_ppag_approved); +/* Print the PPAG table as read from BIOS */ +void iwl_bios_print_ppag(struct iwl_fw_runtime *fwrt, int n_subbands) +{ + int i, j; + + IWL_DEBUG_RADIO(fwrt, "PPAG table as read from BIOS:\n"); + IWL_DEBUG_RADIO(fwrt, "PPAG revision = %d\n", fwrt->ppag_bios_rev); + IWL_DEBUG_RADIO(fwrt, "PPAG flags = 0x%x\n", fwrt->ppag_flags); + + if (WARN_ON_ONCE(n_subbands > + ARRAY_SIZE(fwrt->ppag_chains[0].subbands))) + return; + + for (i = 0; i < ARRAY_SIZE(fwrt->ppag_chains); i++) + for (j = 0; j < n_subbands; j++) + IWL_DEBUG_RADIO(fwrt, + "ppag_chains[%d].subbands[%d] = %d\n", + i, j, + fwrt->ppag_chains[i].subbands[j]); +} + bool iwl_is_tas_approved(void) { return dmi_check_system(dmi_tas_approved_list); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h index 8e04b0e2d507..446c8a2c4f9d 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h @@ -22,6 +22,7 @@ #define BIOS_SAR_MAX_CHAINS_PER_PROFILE 4 #define BIOS_SAR_NUM_CHAINS 2 #define BIOS_SAR_MAX_SUB_BANDS_NUM 11 +#define BIOS_PPAG_MAX_SUB_BANDS_NUM 12 #define BIOS_GEO_NUM_CHAINS 2 #define BIOS_GEO_MAX_NUM_BANDS 3 @@ -100,7 +101,7 @@ struct iwl_geo_profile { /* Same thing as with SAR, all revisions fit in revision 2 */ struct iwl_ppag_chain { - s8 subbands[BIOS_SAR_MAX_SUB_BANDS_NUM]; + s8 subbands[BIOS_PPAG_MAX_SUB_BANDS_NUM]; }; struct iwl_tas_data { @@ -180,6 +181,9 @@ enum iwl_dsm_masks_reg { struct iwl_fw_runtime; +/* Print the PPAG table as read from BIOS */ +void iwl_bios_print_ppag(struct iwl_fw_runtime *fwrt, int n_subbands); + bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt); int iwl_sar_geo_fill_table(struct iwl_fw_runtime *fwrt, diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c index 38f9d9adf90e..fba41976be6b 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c @@ -607,6 +607,7 @@ int iwl_uefi_get_ppag_table(struct iwl_fw_runtime *fwrt) data->vals[chain * UEFI_PPAG_SUB_BANDS_NUM + subband]; } + iwl_bios_print_ppag(fwrt, UEFI_PPAG_SUB_BANDS_NUM); fwrt->ppag_bios_source = BIOS_SOURCE_UEFI; out: kfree(data); diff --git a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c index d1a55b565898..27059ec93847 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c @@ -166,30 +166,74 @@ static int iwl_mld_ppag_send_cmd(struct iwl_mld *mld) { struct iwl_fw_runtime *fwrt = &mld->fwrt; union iwl_ppag_table_cmd cmd = { - .v7.ppag_config_info.hdr.table_source = fwrt->ppag_bios_source, - .v7.ppag_config_info.hdr.table_revision = fwrt->ppag_bios_rev, - .v7.ppag_config_info.value = cpu_to_le32(fwrt->ppag_flags), + /* v7 and v8 have the same layout for the ppag_config_info */ + .v8.ppag_config_info.hdr.table_source = fwrt->ppag_bios_source, + .v8.ppag_config_info.hdr.table_revision = fwrt->ppag_bios_rev, + .v8.ppag_config_info.value = cpu_to_le32(fwrt->ppag_flags), }; + int cmd_ver = + iwl_fw_lookup_cmd_ver(mld->fw, + WIDE_ID(PHY_OPS_GROUP, + PER_PLATFORM_ANT_GAIN_CMD), 1); + int cmd_len = sizeof(cmd.v8); int ret; + BUILD_BUG_ON(offsetof(typeof(cmd), v8.ppag_config_info.hdr) != + offsetof(typeof(cmd), v7.ppag_config_info.hdr)); + BUILD_BUG_ON(offsetof(typeof(cmd), v8.gain) != + offsetof(typeof(cmd), v7.gain)); + + BUILD_BUG_ON(ARRAY_SIZE(cmd.v7.gain) > ARRAY_SIZE(fwrt->ppag_chains)); + BUILD_BUG_ON(ARRAY_SIZE(cmd.v7.gain[0]) > + ARRAY_SIZE(fwrt->ppag_chains[0].subbands)); + BUILD_BUG_ON(ARRAY_SIZE(cmd.v8.gain) > ARRAY_SIZE(fwrt->ppag_chains)); + BUILD_BUG_ON(ARRAY_SIZE(cmd.v8.gain[0]) > + ARRAY_SIZE(fwrt->ppag_chains[0].subbands)); + IWL_DEBUG_RADIO(fwrt, "PPAG MODE bits going to be sent: %d\n", fwrt->ppag_flags); - for (int chain = 0; chain < IWL_NUM_CHAIN_LIMITS; chain++) { - for (int subband = 0; subband < IWL_NUM_SUB_BANDS_V2; subband++) { - cmd.v7.gain[chain][subband] = - fwrt->ppag_chains[chain].subbands[subband]; - IWL_DEBUG_RADIO(fwrt, - "PPAG table: chain[%d] band[%d]: gain = %d\n", - chain, subband, cmd.v7.gain[chain][subband]); + /* Since ver 7 will be deprecated at some point, don't bother making + * this code generic for both ver 7 and ver 8: duplicate the code. + */ + if (cmd_ver == 7) { + for (int chain = 0; chain < ARRAY_SIZE(cmd.v7.gain); chain++) { + for (int subband = 0; + subband < ARRAY_SIZE(cmd.v7.gain[0]); + subband++) { + cmd.v7.gain[chain][subband] = + fwrt->ppag_chains[chain].subbands[subband]; + IWL_DEBUG_RADIO(fwrt, + "PPAG table: chain[%d] band[%d]: gain = %d\n", + chain, subband, + cmd.v7.gain[chain][subband]); + } } + cmd_len = sizeof(cmd.v7); + } else if (cmd_ver == 8) { + for (int chain = 0; chain < ARRAY_SIZE(cmd.v8.gain); chain++) { + for (int subband = 0; + subband < ARRAY_SIZE(cmd.v8.gain[0]); + subband++) { + cmd.v8.gain[chain][subband] = + fwrt->ppag_chains[chain].subbands[subband]; + IWL_DEBUG_RADIO(fwrt, + "PPAG table: chain[%d] band[%d]: gain = %d\n", + chain, subband, + cmd.v8.gain[chain][subband]); + } + } + } else { + WARN(1, "Bad version for PER_PLATFORM_ANT_GAIN_CMD %d\n", + cmd_ver); + return -EINVAL; } IWL_DEBUG_RADIO(mld, "Sending PER_PLATFORM_ANT_GAIN_CMD\n"); ret = iwl_mld_send_cmd_pdu(mld, WIDE_ID(PHY_OPS_GROUP, PER_PLATFORM_ANT_GAIN_CMD), - &cmd, sizeof(cmd.v7)); + &cmd, cmd_len); if (ret < 0) IWL_ERR(mld, "failed to send PER_PLATFORM_ANT_GAIN_CMD (%d)\n", ret);