]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: iwlwifi: support PER_CHAIN_LIMIT_OFFSET_CMD v6
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Thu, 19 Mar 2026 18:48:52 +0000 (20:48 +0200)
committerMiri Korenblit <miriam.rachel.korenblit@intel.com>
Wed, 25 Mar 2026 09:31:56 +0000 (11:31 +0200)
This includes support for UNII-9.
Store the source of the WGDS table in the firmware runtime object to be
able to pass the information to the firmware.

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.eaff31760dd7.Ic7f56fbbe310833723094f965e7ba3f8624d0ef9@changeid
drivers/net/wireless/intel/iwlwifi/fw/acpi.c
drivers/net/wireless/intel/iwlwifi/fw/api/power.h
drivers/net/wireless/intel/iwlwifi/fw/runtime.h
drivers/net/wireless/intel/iwlwifi/fw/uefi.c
drivers/net/wireless/intel/iwlwifi/mld/regulatory.c

index 16d91c6915f083fd1e6e3086bc89fcfe62e773f1..bf0f851a907554c99e78a3039c89e220d7de9a13 100644 (file)
@@ -973,6 +973,7 @@ read_table:
        }
 
        fwrt->geo_num_profiles = num_profiles;
+       fwrt->geo_bios_source = BIOS_SOURCE_ACPI;
        fwrt->geo_enabled = true;
        ret = 0;
 out_free:
index ec923162a44bb5b6aea214721bc32f296c91af90..a3f916630df2bb03d4dd5ff906cd7c71dd6d66af 100644 (file)
@@ -457,6 +457,7 @@ struct iwl_dev_tx_power_cmd {
 #define IWL_NUM_GEO_PROFILES_V3                8
 #define IWL_NUM_BANDS_PER_CHAIN_V1     2
 #define IWL_NUM_BANDS_PER_CHAIN_V2     3
+#define IWL_NUM_BANDS_PER_CHAIN_V6     4
 
 /**
  * enum iwl_geo_per_chain_offset_operation - type of operation
@@ -538,12 +539,25 @@ struct iwl_geo_tx_power_profiles_cmd_v5 {
        __le32 table_revision;
 } __packed; /* PER_CHAIN_LIMIT_OFFSET_CMD_VER_5 */
 
+/**
+ * struct iwl_geo_tx_power_profiles_cmd_v6 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd.
+ * @ops: operations, value from &enum iwl_geo_per_chain_offset_operation
+ * @table: offset profile per band.
+ * @bios_hdr: describes the revision and the source of the BIOS
+ */
+struct iwl_geo_tx_power_profiles_cmd_v6 {
+       __le32 ops;
+       struct iwl_per_chain_offset table[IWL_NUM_GEO_PROFILES_V3][IWL_NUM_BANDS_PER_CHAIN_V6];
+       struct iwl_bios_config_hdr bios_hdr;
+} __packed; /* PER_CHAIN_LIMIT_OFFSET_CMD_VER_6 */
+
 union iwl_geo_tx_power_profiles_cmd {
        struct iwl_geo_tx_power_profiles_cmd_v1 v1;
        struct iwl_geo_tx_power_profiles_cmd_v2 v2;
        struct iwl_geo_tx_power_profiles_cmd_v3 v3;
        struct iwl_geo_tx_power_profiles_cmd_v4 v4;
        struct iwl_geo_tx_power_profiles_cmd_v5 v5;
+       struct iwl_geo_tx_power_profiles_cmd_v6 v6;
 };
 
 /**
index 411e75b45530a92444a7d791ed70de9e07d31368..d80ae610e56c3276cc881052a986ecf2e2c49472 100644 (file)
@@ -113,6 +113,7 @@ struct iwl_txf_iter_data {
  *     Only read the UEFI variables if locked.
  * @sar_profiles: sar profiles as read from WRDS/EWRD BIOS tables
  * @geo_profiles: geographic profiles as read from WGDS BIOS table
+ * @geo_bios_source: see &enum bios_source
  * @phy_filters: specific phy filters as read from WPFC BIOS table
  * @ppag_bios_rev: PPAG BIOS revision
  * @ppag_bios_source: see &enum bios_source
@@ -204,6 +205,7 @@ struct iwl_fw_runtime {
        u8 sar_chain_b_profile;
        u8 reduced_power_flags;
        struct iwl_geo_profile geo_profiles[BIOS_GEO_MAX_PROFILE_NUM];
+       enum bios_source geo_bios_source;
        u32 geo_rev;
        u32 geo_num_profiles;
        bool geo_enabled;
index f73340c7d53792cc44fbcc73c524e8b3f57f5f51..2ef0a7a920adb5e2fb87242063d763b03c7647ee 100644 (file)
@@ -644,6 +644,7 @@ int iwl_uefi_get_wgds_table(struct iwl_fw_runtime *fwrt)
        }
 
        fwrt->geo_rev = data->revision;
+       fwrt->geo_bios_source = BIOS_SOURCE_UEFI;
        profile_size = 3 * n_subbands;
        for (int prof = 0; prof < data->num_profiles; prof++) {
                const u8 *val = &data->vals[profile_size * prof];
index f009c884e6cdb0b810cae7a443f819c0a27c45fa..2486d78d6fc38e41bf17c2c8a2f543ea0de8f503 100644 (file)
@@ -73,16 +73,36 @@ static int iwl_mld_geo_sar_init(struct iwl_mld *mld)
 {
        u32 cmd_id = WIDE_ID(PHY_OPS_GROUP, PER_CHAIN_LIMIT_OFFSET_CMD);
        /* Only set to South Korea if the table revision is 1 */
-       __le32 sk = cpu_to_le32(mld->fwrt.geo_rev == 1 ? 1 : 0);
+       u8 sk = mld->fwrt.geo_rev == 1 ? 1 : 0;
        union iwl_geo_tx_power_profiles_cmd cmd = {
                .v5.ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_SET_TABLES),
-               .v5.table_revision = sk,
        };
+       u32 cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw, cmd_id, 0);
+       int n_subbands;
+       int cmd_size;
        int ret;
 
-       ret = iwl_sar_geo_fill_table(&mld->fwrt, &cmd.v5.table[0][0],
-                                    ARRAY_SIZE(cmd.v5.table[0]),
-                                    BIOS_GEO_MAX_PROFILE_NUM);
+       switch (cmd_ver) {
+       case 5:
+               n_subbands = ARRAY_SIZE(cmd.v5.table[0]);
+               cmd.v5.table_revision = cpu_to_le32(sk);
+               cmd_size = sizeof(cmd.v5);
+               break;
+       case 6:
+               n_subbands = ARRAY_SIZE(cmd.v6.table[0]);
+               cmd.v6.bios_hdr.table_revision = mld->fwrt.geo_rev;
+               cmd.v6.bios_hdr.table_source = mld->fwrt.geo_bios_source;
+               cmd_size = sizeof(cmd.v6);
+               break;
+       default:
+               WARN(false, "unsupported version: %d", cmd_ver);
+               return -EINVAL;
+       }
+
+       BUILD_BUG_ON(offsetof(typeof(cmd), v6.table) !=
+                    offsetof(typeof(cmd), v5.table));
+       ret = iwl_sar_geo_fill_table(&mld->fwrt, &cmd.v6.table[0][0],
+                                    n_subbands, BIOS_GEO_MAX_PROFILE_NUM);
 
        /* It is a valid scenario to not support SAR, or miss wgds table,
         * but in that case there is no need to send the command.
@@ -90,7 +110,7 @@ static int iwl_mld_geo_sar_init(struct iwl_mld *mld)
        if (ret)
                return 0;
 
-       return iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd, sizeof(cmd.v5));
+       return iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd, cmd_size);
 }
 
 int iwl_mld_config_sar_profile(struct iwl_mld *mld, int prof_a, int prof_b)