From: Emmanuel Grumbach Date: Thu, 19 Mar 2026 18:48:41 +0000 (+0200) Subject: wifi: iwlwifi: uefi: add support for PPAG table rev5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1fd4e6478ccde5c89f47191170b6e655808e450d;p=thirdparty%2Flinux.git wifi: iwlwifi: uefi: add support for PPAG table rev5 This table has another subband for UNII-9. Add defines for the sizes of rev4 and rev5 to easily know how much data to ask from iwl_uefi_get_verified_variable. In case rev5 doesn't exist, fallback to rev4. Check that the revision advertised by the fetched table matches the size that we got. Signed-off-by: Emmanuel Grumbach Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20260319204647.b9ebcff37599.I1e8bb9cee5a028ed416b6094c0fdbf9f859c6dd8@changeid --- diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c index fba41976be6bb..84b6f8b7eda95 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c @@ -570,44 +570,66 @@ out: int iwl_uefi_get_ppag_table(struct iwl_fw_runtime *fwrt) { struct uefi_cnv_var_ppag *data; + int n_subbands; + u32 valid_rev; 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", data_sz, NULL); - if (IS_ERR(data)) - return -EINVAL; + "PPAG", UEFI_PPAG_DATA_SIZE_V5, + NULL); + if (!IS_ERR(data)) { + n_subbands = UEFI_PPAG_SUB_BANDS_NUM_REV5; + valid_rev = BIT(5); + + goto parse_table; + } + + data = iwl_uefi_get_verified_variable(fwrt->trans, + IWL_UEFI_PPAG_NAME, + "PPAG", + UEFI_PPAG_DATA_SIZE_V4, + NULL); + if (!IS_ERR(data)) { + n_subbands = UEFI_PPAG_SUB_BANDS_NUM_REV4; + /* revisions 1-4 have all the same size */ + valid_rev = BIT(1) | BIT(2) | BIT(3) | BIT(4); - if (data->revision < IWL_UEFI_MIN_PPAG_REV || - data->revision > IWL_UEFI_MAX_PPAG_REV) { + goto parse_table; + } + + return -EINVAL; + +parse_table: + if (!(BIT(data->revision) & valid_rev)) { ret = -EINVAL; - IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI PPAG revision:%d\n", + IWL_DEBUG_RADIO(fwrt, + "Unsupported UEFI PPAG revision:%d\n", data->revision); goto out; } - fwrt->ppag_bios_rev = data->revision; - fwrt->ppag_flags = iwl_bios_get_ppag_flags(data->ppag_modes, - fwrt->ppag_bios_rev); - /* * 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++) + if (WARN_ON(ARRAY_SIZE(fwrt->ppag_chains) * + ARRAY_SIZE(fwrt->ppag_chains[0].subbands) < + UEFI_PPAG_NUM_CHAINS * n_subbands)) { + ret = -EINVAL; + goto out; + } + + fwrt->ppag_bios_rev = data->revision; + fwrt->ppag_flags = iwl_bios_get_ppag_flags(data->ppag_modes, + fwrt->ppag_bios_rev); + + for (int chain = 0; chain < UEFI_PPAG_NUM_CHAINS; chain++) { + for (int subband = 0; subband < n_subbands; subband++) fwrt->ppag_chains[chain].subbands[subband] = - data->vals[chain * UEFI_PPAG_SUB_BANDS_NUM + subband]; + data->vals[chain * n_subbands + subband]; } - iwl_bios_print_ppag(fwrt, UEFI_PPAG_SUB_BANDS_NUM); + iwl_bios_print_ppag(fwrt, n_subbands); 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 4f0ce068a589d..5046b6a454199 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h @@ -34,8 +34,6 @@ #define IWL_UEFI_WRDS_REVISION 2 #define IWL_UEFI_EWRD_REVISION 2 #define IWL_UEFI_WGDS_REVISION 3 -#define IWL_UEFI_MIN_PPAG_REV 1 -#define IWL_UEFI_MAX_PPAG_REV 4 #define IWL_UEFI_MIN_WTAS_REVISION 1 #define IWL_UEFI_MAX_WTAS_REVISION 2 #define IWL_UEFI_SPLC_REVISION 0 @@ -77,7 +75,9 @@ struct uefi_cnv_common_step_data { } __packed; #define UEFI_SAR_MAX_SUB_BANDS_NUM 11 -#define UEFI_PPAG_SUB_BANDS_NUM 11 +#define UEFI_PPAG_SUB_BANDS_NUM_REV4 11 +#define UEFI_PPAG_SUB_BANDS_NUM_REV5 12 +#define UEFI_PPAG_NUM_CHAINS 2 #define UEFI_SAR_MAX_CHAINS_PER_PROFILE 4 /* @@ -143,7 +143,9 @@ struct uefi_cnv_var_wgds { * @ppag_modes: values from &enum iwl_ppag_flags * @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. + * num_of_subbands depends on the revision. For revision 5, it is + * %UEFI_PPAG_SUB_BANDS_NUM_REV5, for earlier revision it is + * %UEFI_PPAG_SUB_BANDS_NUM_REV4. * the max number of chains is currently 2 */ struct uefi_cnv_var_ppag { @@ -152,6 +154,13 @@ struct uefi_cnv_var_ppag { s8 vals[]; } __packed; +#define UEFI_PPAG_DATA_SIZE_V4 \ + (offsetof(struct uefi_cnv_var_ppag, vals) + \ + sizeof(s8) * UEFI_PPAG_NUM_CHAINS * UEFI_PPAG_SUB_BANDS_NUM_REV4) +#define UEFI_PPAG_DATA_SIZE_V5 \ + (offsetof(struct uefi_cnv_var_ppag, vals) + \ + sizeof(s8) * UEFI_PPAG_NUM_CHAINS * UEFI_PPAG_SUB_BANDS_NUM_REV5) + /* struct uefi_cnv_var_wtas - WTAS tabled as defined in UEFI * @revision: the revision of the table * @tas_selection: different options of TAS enablement.