]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: iwlwifi: uefi: add support for PPAG table rev5
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Thu, 19 Mar 2026 18:48:41 +0000 (20:48 +0200)
committerMiri Korenblit <miriam.rachel.korenblit@intel.com>
Wed, 25 Mar 2026 09:31:56 +0000 (11:31 +0200)
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 <emmanuel.grumbach@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20260319204647.b9ebcff37599.I1e8bb9cee5a028ed416b6094c0fdbf9f859c6dd8@changeid
drivers/net/wireless/intel/iwlwifi/fw/uefi.c
drivers/net/wireless/intel/iwlwifi/fw/uefi.h

index fba41976be6bb8328be37deecd4f6e14206470e9..84b6f8b7eda95fe0f269c624efe6ed5686026230 100644 (file)
@@ -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);
index 4f0ce068a589d822d1bb3be8449fb281f03e55c8..5046b6a454199c39a2f21f9e207ccf8e975d2f42 100644 (file)
@@ -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.