wifi: iwlwifi: acpi: check DSM func validity
authorJohannes Berg <johannes.berg@intel.com>
Thu, 28 Aug 2025 06:55:27 +0000 (09:55 +0300)
committerMiri Korenblit <miriam.rachel.korenblit@intel.com>
Thu, 28 Aug 2025 11:00:45 +0000 (14:00 +0300)
The DSM func 0 (DSM_FUNC_QUERY) returns a bitmap of which
other functions contain valid data, query and check it
before returning other functions data.

Fixes: 9db93491f29e ("iwlwifi: acpi: support device specific method (DSM)")
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220085
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20250828095500.881e17ff8f6a.Ic6d92997d9d5fad127919d6e1b830cd3fe944468@changeid
drivers/net/wireless/intel/iwlwifi/fw/acpi.c
drivers/net/wireless/intel/iwlwifi/fw/runtime.h

index bee7d92293b8d69e43e5ef3892e0b9f9e9281d52..7ec22738b5d650d3f0a830e8a37c41fbebb496bb 100644 (file)
@@ -169,7 +169,7 @@ int iwl_acpi_get_dsm(struct iwl_fw_runtime *fwrt,
 
        BUILD_BUG_ON(ARRAY_SIZE(acpi_dsm_size) != DSM_FUNC_NUM_FUNCS);
 
-       if (WARN_ON(func >= ARRAY_SIZE(acpi_dsm_size)))
+       if (WARN_ON(func >= ARRAY_SIZE(acpi_dsm_size) || !func))
                return -EINVAL;
 
        expected_size = acpi_dsm_size[func];
@@ -178,6 +178,29 @@ int iwl_acpi_get_dsm(struct iwl_fw_runtime *fwrt,
        if (expected_size != sizeof(u8) && expected_size != sizeof(u32))
                return -EOPNOTSUPP;
 
+       if (!fwrt->acpi_dsm_funcs_valid) {
+               ret = iwl_acpi_get_dsm_integer(fwrt->dev, ACPI_DSM_REV,
+                                              DSM_FUNC_QUERY,
+                                              &iwl_guid, &tmp,
+                                              acpi_dsm_size[DSM_FUNC_QUERY]);
+               if (ret) {
+                       /* always indicate BIT(0) to avoid re-reading */
+                       fwrt->acpi_dsm_funcs_valid = BIT(0);
+                       return ret;
+               }
+
+               IWL_DEBUG_RADIO(fwrt, "ACPI DSM validity bitmap 0x%x\n",
+                               (u32)tmp);
+               /* always indicate BIT(0) to avoid re-reading */
+               fwrt->acpi_dsm_funcs_valid = tmp | BIT(0);
+       }
+
+       if (!(fwrt->acpi_dsm_funcs_valid & BIT(func))) {
+               IWL_DEBUG_RADIO(fwrt, "ACPI DSM %d not indicated as valid\n",
+                               func);
+               return -ENODATA;
+       }
+
        ret = iwl_acpi_get_dsm_integer(fwrt->dev, ACPI_DSM_REV, func,
                                       &iwl_guid, &tmp, expected_size);
        if (ret)
index 0444a736c2b2060db3002496b942bcc520137d7b..bd3bc2846cfa4984338819fb8a5788e2c4f89510 100644 (file)
@@ -113,6 +113,10 @@ struct iwl_txf_iter_data {
  * @phy_filters: specific phy filters as read from WPFC BIOS table
  * @ppag_bios_rev: PPAG BIOS revision
  * @ppag_bios_source: see &enum bios_source
+ * @acpi_dsm_funcs_valid: bitmap indicating which DSM values are valid,
+ *     zero (default initialization) means it hasn't been read yet,
+ *     and BIT(0) is set when it has since function 0 also has this
+ *     bitmap and is always supported
  */
 struct iwl_fw_runtime {
        struct iwl_trans *trans;
@@ -189,6 +193,10 @@ struct iwl_fw_runtime {
        bool uats_valid;
        u8 uefi_tables_lock_status;
        struct iwl_phy_specific_cfg phy_filters;
+
+#ifdef CONFIG_ACPI
+       u32 acpi_dsm_funcs_valid;
+#endif
 };
 
 void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,