diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c index d4e1ab1f7c84..38f9d9adf90e 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c @@ -571,9 +571,11 @@ int iwl_uefi_get_ppag_table(struct iwl_fw_runtime *fwrt) { struct uefi_cnv_var_ppag *data; int ret = 0; + int data_sz = sizeof(*data) + sizeof(data->vals[0]) * + IWL_NUM_CHAIN_LIMITS * UEFI_PPAG_SUB_BANDS_NUM; data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_PPAG_NAME, - "PPAG", sizeof(*data), NULL); + "PPAG", data_sz, NULL); if (IS_ERR(data)) return -EINVAL; @@ -589,9 +591,22 @@ int iwl_uefi_get_ppag_table(struct iwl_fw_runtime *fwrt) fwrt->ppag_flags = iwl_bios_get_ppag_flags(data->ppag_modes, fwrt->ppag_bios_rev); - BUILD_BUG_ON(sizeof(fwrt->ppag_chains) != sizeof(data->ppag_chains)); - memcpy(&fwrt->ppag_chains, &data->ppag_chains, - sizeof(data->ppag_chains)); + /* + * Make sure fwrt has enough room to hold + * data coming from the UEFI table + */ + BUILD_BUG_ON(ARRAY_SIZE(fwrt->ppag_chains) * + ARRAY_SIZE(fwrt->ppag_chains[0].subbands) < + IWL_NUM_CHAIN_LIMITS * UEFI_PPAG_SUB_BANDS_NUM); + + for (int chain = 0; chain < IWL_NUM_CHAIN_LIMITS; chain++) { + for (int subband = 0; + subband < UEFI_PPAG_SUB_BANDS_NUM; + subband++) + fwrt->ppag_chains[chain].subbands[subband] = + data->vals[chain * UEFI_PPAG_SUB_BANDS_NUM + subband]; + } + fwrt->ppag_bios_source = BIOS_SOURCE_UEFI; out: kfree(data); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h index c6940a3c03ea..4f0ce068a589 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h @@ -77,6 +77,7 @@ struct uefi_cnv_common_step_data { } __packed; #define UEFI_SAR_MAX_SUB_BANDS_NUM 11 +#define UEFI_PPAG_SUB_BANDS_NUM 11 #define UEFI_SAR_MAX_CHAINS_PER_PROFILE 4 /* @@ -136,24 +137,19 @@ struct uefi_cnv_var_wgds { struct iwl_geo_profile geo_profiles[BIOS_GEO_MAX_PROFILE_NUM]; } __packed; -/* - * struct uefi_ppag_chain - PPAG table for a specific chain - * @subbands: the PPAG values for band - */ -struct uefi_ppag_chain { - s8 subbands[UEFI_SAR_MAX_SUB_BANDS_NUM]; -}; - /* * struct uefi_cnv_var_ppag - PPAG table as defined in UEFI * @revision: the revision of the table * @ppag_modes: values from &enum iwl_ppag_flags - * @ppag_chains: the PPAG values per chain and band + * @vals: the PPAG values per chain and band as an array. + * vals[chain * num_of_subbands + subband] will return the right value. + * num_of_subbands is %UEFI_PPAG_SUB_BANDS_NUM. + * the max number of chains is currently 2 */ struct uefi_cnv_var_ppag { u8 revision; u32 ppag_modes; - struct uefi_ppag_chain ppag_chains[IWL_NUM_CHAIN_LIMITS]; + s8 vals[]; } __packed; /* struct uefi_cnv_var_wtas - WTAS tabled as defined in UEFI