]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: iwlwifi: uefi: open code the parsing of the WGDS table
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Thu, 19 Mar 2026 18:48:48 +0000 (20:48 +0200)
committerMiri Korenblit <miriam.rachel.korenblit@intel.com>
Wed, 25 Mar 2026 09:31:56 +0000 (11:31 +0200)
We will soon add support for UNII-9 band in the WGDS table. We need to
decouple the UEFI code from the firmware runtime code.
The firmware runtime is just a software object which will need to grow
and UEFI objects need a new revision to grow. Existing systems will keep
the same UEFI objects.

Just like PPAG and SAR, stop using structures to parse the UEFI tables
since the layout depends on the revision.
The support for the new revision will be added in the next patch, for
now, just do the ground work.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20260319204647.140706e6e91f.I83ca04932bc21aa358119890001e876ced1e1bda@changeid
drivers/net/wireless/intel/iwlwifi/fw/uefi.c
drivers/net/wireless/intel/iwlwifi/fw/uefi.h

index 3d3d698bacd0c01e5efcccb1380e5d335679cd5a..ccac503851753d50ccf9dbab6ba31d72f34bdb21 100644 (file)
@@ -593,10 +593,11 @@ out:
 int iwl_uefi_get_wgds_table(struct iwl_fw_runtime *fwrt)
 {
        struct uefi_cnv_var_wgds *data;
-       int i, ret = 0;
+       int ret = 0;
 
        data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_WGDS_NAME,
-                                             "WGDS", sizeof(*data), NULL);
+                                             "WGDS", UEFI_WGDS_TABLE_SIZE_REV3,
+                                             NULL);
        if (IS_ERR(data))
                return -EINVAL;
 
@@ -615,10 +616,32 @@ int iwl_uefi_get_wgds_table(struct iwl_fw_runtime *fwrt)
                goto out;
        }
 
+       if (WARN_ON(BIOS_GEO_MAX_PROFILE_NUM >
+                   ARRAY_SIZE(fwrt->geo_profiles) ||
+                   UEFI_GEO_NUM_BANDS_REV3 >
+                   ARRAY_SIZE(fwrt->geo_profiles[0].bands) ||
+                   BIOS_GEO_NUM_CHAINS >
+                   ARRAY_SIZE(fwrt->geo_profiles[0].bands[0].chains))) {
+               ret = -EINVAL;
+               goto out;
+       }
+
        fwrt->geo_rev = data->revision;
-       for (i = 0; i < data->num_profiles; i++)
-               memcpy(&fwrt->geo_profiles[i], &data->geo_profiles[i],
-                      sizeof(struct iwl_geo_profile));
+       for (int prof = 0; prof < data->num_profiles; prof++) {
+               const u8 *val = &data->vals[UEFI_WGDS_PROFILE_SIZE_REV3 * prof];
+               struct iwl_geo_profile *geo_prof = &fwrt->geo_profiles[prof];
+
+               for (int subband = 0;
+                    subband < UEFI_GEO_NUM_BANDS_REV3;
+                    subband++) {
+                       geo_prof->bands[subband].max = *val++;
+
+                       for (int chain = 0;
+                            chain < BIOS_GEO_NUM_CHAINS;
+                            chain++)
+                               geo_prof->bands[subband].chains[chain] = *val++;
+               }
+       }
 
        fwrt->geo_num_profiles = data->num_profiles;
        fwrt->geo_enabled = true;
index aa5a4c5a73922ee9878690692847462380f18dec..3959937242d8f2329378e70d8a87d10ecc56de0e 100644 (file)
@@ -81,6 +81,8 @@ struct uefi_cnv_common_step_data {
 
 #define UEFI_SAR_MAX_CHAINS_PER_PROFILE        4
 
+#define UEFI_GEO_NUM_BANDS_REV3                3
+
 /*
  * struct uefi_cnv_var_wrds - WRDS table as defined in UEFI
  *
@@ -145,14 +147,26 @@ struct uefi_cnv_var_ewrd {
  * @revision: the revision of the table
  * @num_profiles: the number of geo profiles we have in the table.
  *     The first 3 are mandatory, and can have up to 8.
- * @geo_profiles: a per-profile table of the offsets to add to SAR values.
+ * @vals: a per-profile table of the offsets to add to SAR values. This is an
+ *     array of profiles, each profile is an array of
+ *     &struct iwl_geo_profile_band, one for each subband.
+ *     There are %UEFI_GEO_NUM_BANDS_REV3 subbands.
  */
 struct uefi_cnv_var_wgds {
        u8 revision;
        u8 num_profiles;
-       struct iwl_geo_profile geo_profiles[BIOS_GEO_MAX_PROFILE_NUM];
+       u8 vals[];
 } __packed;
 
+/* struct iwl_geo_profile_band is 3 bytes-long, but since it is not packed,
+ * we can't use sizeof()
+ */
+#define UEFI_WGDS_PROFILE_SIZE_REV3 (sizeof(u8) * 3 * UEFI_GEO_NUM_BANDS_REV3)
+
+#define UEFI_WGDS_TABLE_SIZE_REV3                              \
+       (offsetof(struct uefi_cnv_var_wgds, vals) +             \
+        UEFI_WGDS_PROFILE_SIZE_REV3 * BIOS_GEO_MAX_PROFILE_NUM)
+
 /*
  * struct uefi_cnv_var_ppag - PPAG table as defined in UEFI
  * @revision: the revision of the table