]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: iwlwifi: regulatory: support a new command for PPAG
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Thu, 19 Mar 2026 09:09:25 +0000 (11:09 +0200)
committerMiri Korenblit <miriam.rachel.korenblit@intel.com>
Wed, 25 Mar 2026 09:31:56 +0000 (11:31 +0200)
Per Platform Antenna Gain is getting support for UNII-9.
Add a new version of PER_PLATFORM_ANT_GAIN_CMD.
This requires to increase the number of subbands in the firmware runtime
object.
Pass the number of subbands to iwl_bios_print_ppag to avoid printing
invalid values.

Introduce BIOS_PPAG_MAX_SUB_BANDS_NUM to avoid impacting
BIOS_SAR_MAX_SUB_BANDS_NUM which was used until now for PPAG as well.
SAR will get support for the new subband in future patches.

While at it, print the PPAG table as it was read from BIOS.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20260319110722.2e577236d3c9.I042697a73893d79ef761796354b5d1dd8522f734@changeid
drivers/net/wireless/intel/iwlwifi/fw/acpi.c
drivers/net/wireless/intel/iwlwifi/fw/api/power.h
drivers/net/wireless/intel/iwlwifi/fw/regulatory.c
drivers/net/wireless/intel/iwlwifi/fw/regulatory.h
drivers/net/wireless/intel/iwlwifi/fw/uefi.c
drivers/net/wireless/intel/iwlwifi/mld/regulatory.c

index b64abb8439b71cc5a0ac01b4ebfce13a09fa3e25..d00191e84f202b25cccf2ceb2b47086eb7e94149 100644 (file)
@@ -981,6 +981,7 @@ read_table:
                }
        }
 
+       iwl_bios_print_ppag(fwrt, num_sub_bands);
        fwrt->ppag_bios_source = BIOS_SOURCE_ACPI;
        ret = 0;
 
index 0cd8a12e0f7c01abdb6b6df8d5222106135c65d7..118c08f9564952d0f112c6368568639753c49589 100644 (file)
@@ -269,6 +269,7 @@ enum iwl_dev_tx_power_cmd_mode {
 #define IWL_NUM_CHAIN_LIMITS   2
 #define IWL_NUM_SUB_BANDS_V1   5
 #define IWL_NUM_SUB_BANDS_V2   11
+#define IWL_NUM_SUB_BANDS_V3   12
 
 /**
  * struct iwl_dev_tx_power_common - Common part of the TX power reduction cmd
@@ -573,6 +574,7 @@ enum iwl_ppag_flags {
  * @v1: command version 1 structure.
  * @v5: command version 5 structure.
  * @v7: command version 7 structure.
+ * @v8: command version 8 structure.
  * @v1.flags: values from &enum iwl_ppag_flags
  * @v1.gain: table of antenna gain values per chain and sub-band
  * @v1.reserved: reserved
@@ -581,6 +583,8 @@ enum iwl_ppag_flags {
  * @v7.ppag_config_info: see @struct bios_value_u32
  * @v7.gain: table of antenna gain values per chain and sub-band
  * @v7.reserved: reserved
+ * @v8.ppag_config_info: see @struct bios_value_u32
+ * @v8.gain: table of antenna gain values per chain and sub-band
  */
 union iwl_ppag_table_cmd {
        struct {
@@ -598,6 +602,10 @@ union iwl_ppag_table_cmd {
                s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2];
                s8 reserved[2];
        } __packed v7; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_7 */
+       struct {
+               struct bios_value_u32 ppag_config_info;
+               s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V3];
+       } __packed v8; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_8 */
 } __packed;
 
 #define IWL_PPAG_CMD_V1_MASK (IWL_PPAG_ETSI_MASK | IWL_PPAG_CHINA_MASK)
index 9e834cc1b0545edd417eb5f00ca161f6fd90bcb5..55128caac7ed9fa400dc149ade17723d98ad7714 100644 (file)
@@ -318,6 +318,27 @@ bool iwl_is_ppag_approved(struct iwl_fw_runtime *fwrt)
 }
 IWL_EXPORT_SYMBOL(iwl_is_ppag_approved);
 
+/* Print the PPAG table as read from BIOS */
+void iwl_bios_print_ppag(struct iwl_fw_runtime *fwrt, int n_subbands)
+{
+       int i, j;
+
+       IWL_DEBUG_RADIO(fwrt, "PPAG table as read from BIOS:\n");
+       IWL_DEBUG_RADIO(fwrt, "PPAG revision = %d\n", fwrt->ppag_bios_rev);
+       IWL_DEBUG_RADIO(fwrt, "PPAG flags = 0x%x\n", fwrt->ppag_flags);
+
+       if (WARN_ON_ONCE(n_subbands >
+                        ARRAY_SIZE(fwrt->ppag_chains[0].subbands)))
+               return;
+
+       for (i = 0; i < ARRAY_SIZE(fwrt->ppag_chains); i++)
+               for (j = 0; j < n_subbands; j++)
+                       IWL_DEBUG_RADIO(fwrt,
+                                       "ppag_chains[%d].subbands[%d] = %d\n",
+                                       i, j,
+                                       fwrt->ppag_chains[i].subbands[j]);
+}
+
 bool iwl_is_tas_approved(void)
 {
        return dmi_check_system(dmi_tas_approved_list);
index 8e04b0e2d50751633c94a762be3a01cf6d0cfc03..446c8a2c4f9d68bb6f1b432dc2ac9f19ceb5a770 100644 (file)
@@ -22,6 +22,7 @@
 #define BIOS_SAR_MAX_CHAINS_PER_PROFILE 4
 #define BIOS_SAR_NUM_CHAINS             2
 #define BIOS_SAR_MAX_SUB_BANDS_NUM      11
+#define BIOS_PPAG_MAX_SUB_BANDS_NUM     12
 
 #define BIOS_GEO_NUM_CHAINS            2
 #define BIOS_GEO_MAX_NUM_BANDS         3
@@ -100,7 +101,7 @@ struct iwl_geo_profile {
 
 /* Same thing as with SAR, all revisions fit in revision 2 */
 struct iwl_ppag_chain {
-       s8 subbands[BIOS_SAR_MAX_SUB_BANDS_NUM];
+       s8 subbands[BIOS_PPAG_MAX_SUB_BANDS_NUM];
 };
 
 struct iwl_tas_data {
@@ -180,6 +181,9 @@ enum iwl_dsm_masks_reg {
 
 struct iwl_fw_runtime;
 
+/* Print the PPAG table as read from BIOS */
+void iwl_bios_print_ppag(struct iwl_fw_runtime *fwrt, int n_subbands);
+
 bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt);
 
 int iwl_sar_geo_fill_table(struct iwl_fw_runtime *fwrt,
index 38f9d9adf90ee420e73285702de04640428813dd..fba41976be6bb8328be37deecd4f6e14206470e9 100644 (file)
@@ -607,6 +607,7 @@ int iwl_uefi_get_ppag_table(struct iwl_fw_runtime *fwrt)
                                data->vals[chain * UEFI_PPAG_SUB_BANDS_NUM + subband];
        }
 
+       iwl_bios_print_ppag(fwrt, UEFI_PPAG_SUB_BANDS_NUM);
        fwrt->ppag_bios_source = BIOS_SOURCE_UEFI;
 out:
        kfree(data);
index d1a55b5658983c86dbc01dad77e4ca7a581e779f..27059ec938473d0c7fa3c44ea66b290bda762071 100644 (file)
@@ -166,30 +166,74 @@ static int iwl_mld_ppag_send_cmd(struct iwl_mld *mld)
 {
        struct iwl_fw_runtime *fwrt = &mld->fwrt;
        union iwl_ppag_table_cmd cmd = {
-               .v7.ppag_config_info.hdr.table_source = fwrt->ppag_bios_source,
-               .v7.ppag_config_info.hdr.table_revision = fwrt->ppag_bios_rev,
-               .v7.ppag_config_info.value = cpu_to_le32(fwrt->ppag_flags),
+               /* v7 and v8 have the same layout for the ppag_config_info */
+               .v8.ppag_config_info.hdr.table_source = fwrt->ppag_bios_source,
+               .v8.ppag_config_info.hdr.table_revision = fwrt->ppag_bios_rev,
+               .v8.ppag_config_info.value = cpu_to_le32(fwrt->ppag_flags),
        };
+       int cmd_ver =
+               iwl_fw_lookup_cmd_ver(mld->fw,
+                                     WIDE_ID(PHY_OPS_GROUP,
+                                             PER_PLATFORM_ANT_GAIN_CMD), 1);
+       int cmd_len = sizeof(cmd.v8);
        int ret;
 
+       BUILD_BUG_ON(offsetof(typeof(cmd), v8.ppag_config_info.hdr) !=
+                    offsetof(typeof(cmd), v7.ppag_config_info.hdr));
+       BUILD_BUG_ON(offsetof(typeof(cmd), v8.gain) !=
+                    offsetof(typeof(cmd), v7.gain));
+
+       BUILD_BUG_ON(ARRAY_SIZE(cmd.v7.gain) > ARRAY_SIZE(fwrt->ppag_chains));
+       BUILD_BUG_ON(ARRAY_SIZE(cmd.v7.gain[0]) >
+                    ARRAY_SIZE(fwrt->ppag_chains[0].subbands));
+       BUILD_BUG_ON(ARRAY_SIZE(cmd.v8.gain) > ARRAY_SIZE(fwrt->ppag_chains));
+       BUILD_BUG_ON(ARRAY_SIZE(cmd.v8.gain[0]) >
+                    ARRAY_SIZE(fwrt->ppag_chains[0].subbands));
+
        IWL_DEBUG_RADIO(fwrt,
                        "PPAG MODE bits going to be sent: %d\n",
                        fwrt->ppag_flags);
 
-       for (int chain = 0; chain < IWL_NUM_CHAIN_LIMITS; chain++) {
-               for (int subband = 0; subband < IWL_NUM_SUB_BANDS_V2; subband++) {
-                       cmd.v7.gain[chain][subband] =
-                               fwrt->ppag_chains[chain].subbands[subband];
-                       IWL_DEBUG_RADIO(fwrt,
-                                       "PPAG table: chain[%d] band[%d]: gain = %d\n",
-                                       chain, subband, cmd.v7.gain[chain][subband]);
+       /* Since ver 7 will be deprecated at some point, don't bother making
+        * this code generic for both ver 7 and ver 8: duplicate the code.
+        */
+       if (cmd_ver == 7) {
+               for (int chain = 0; chain < ARRAY_SIZE(cmd.v7.gain); chain++) {
+                       for (int subband = 0;
+                            subband < ARRAY_SIZE(cmd.v7.gain[0]);
+                            subband++) {
+                               cmd.v7.gain[chain][subband] =
+                                       fwrt->ppag_chains[chain].subbands[subband];
+                               IWL_DEBUG_RADIO(fwrt,
+                                               "PPAG table: chain[%d] band[%d]: gain = %d\n",
+                                               chain, subband,
+                                               cmd.v7.gain[chain][subband]);
+                       }
                }
+               cmd_len = sizeof(cmd.v7);
+       } else if (cmd_ver == 8) {
+               for (int chain = 0; chain < ARRAY_SIZE(cmd.v8.gain); chain++) {
+                       for (int subband = 0;
+                            subband < ARRAY_SIZE(cmd.v8.gain[0]);
+                            subband++) {
+                               cmd.v8.gain[chain][subband] =
+                                       fwrt->ppag_chains[chain].subbands[subband];
+                               IWL_DEBUG_RADIO(fwrt,
+                                               "PPAG table: chain[%d] band[%d]: gain = %d\n",
+                                               chain, subband,
+                                               cmd.v8.gain[chain][subband]);
+                       }
+               }
+       } else {
+               WARN(1, "Bad version for PER_PLATFORM_ANT_GAIN_CMD %d\n",
+                    cmd_ver);
+               return -EINVAL;
        }
 
        IWL_DEBUG_RADIO(mld, "Sending PER_PLATFORM_ANT_GAIN_CMD\n");
        ret = iwl_mld_send_cmd_pdu(mld, WIDE_ID(PHY_OPS_GROUP,
                                                PER_PLATFORM_ANT_GAIN_CMD),
-                                  &cmd, sizeof(cmd.v7));
+                                  &cmd, cmd_len);
        if (ret < 0)
                IWL_ERR(mld, "failed to send PER_PLATFORM_ANT_GAIN_CMD (%d)\n",
                        ret);