]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: iwlwifi: acpi: cache the DSM functions
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Sun, 11 Jan 2026 17:39:20 +0000 (19:39 +0200)
committerMiri Korenblit <miriam.rachel.korenblit@intel.com>
Wed, 21 Jan 2026 12:23:02 +0000 (14:23 +0200)
Instead of reading the DSM functions on demand, just read them all
when the first DSM function is called and cache the values for all
the other DSM functions. This simplifies the flow.
Since the same will be done for UEFI in the next patch, remove the
ifdef CONFIG_ACPI around the relevant variables.

Once UEFI's cache will be implemented, we'll be able to change
iwl_bios_get_dsm to access the cache directly.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20260111193638.732ff6856796.Iff844bfbb0fea3c3d9654a53254a5b14dbaec8c1@changeid
drivers/net/wireless/intel/iwlwifi/fw/acpi.c
drivers/net/wireless/intel/iwlwifi/fw/runtime.h

index 52edc19d8cdd5cc38df32b8ab2f9ba80d717f060..3899dc3915bfb5a0db033cdfbc924fad32de5d3e 100644 (file)
@@ -156,61 +156,101 @@ out:
 }
 
 /*
- * This function receives a DSM function number, calculates its expected size
- * according to Intel BIOS spec, and fills in the value in a 32-bit field.
+ * This function loads all the DSM functions, it checks the size and populates
+ * the cache with the values in a 32-bit field.
  * In case the expected size is smaller than 32-bit, padding will be added.
  */
-int iwl_acpi_get_dsm(struct iwl_fw_runtime *fwrt,
-                    enum iwl_dsm_funcs func, u32 *value)
+static int iwl_acpi_load_dsm_values(struct iwl_fw_runtime *fwrt)
 {
-       size_t expected_size;
-       u64 tmp;
+       u64 query_func_val;
        int ret;
 
        BUILD_BUG_ON(ARRAY_SIZE(acpi_dsm_size) != DSM_FUNC_NUM_FUNCS);
 
-       if (WARN_ON(func >= ARRAY_SIZE(acpi_dsm_size) || !func))
-               return -EINVAL;
+       ret = iwl_acpi_get_dsm_integer(fwrt->dev, ACPI_DSM_REV,
+                                      DSM_FUNC_QUERY,
+                                      &iwl_guid, &query_func_val,
+                                      acpi_dsm_size[DSM_FUNC_QUERY]);
 
-       expected_size = acpi_dsm_size[func];
+       if (ret) {
+               IWL_DEBUG_RADIO(fwrt, "ACPI QUERY FUNC not valid: %d\n", ret);
+               return ret;
+       }
 
-       /* Currently all ACPI DSMs are either 8-bit or 32-bit */
-       if (expected_size != sizeof(u8) && expected_size != sizeof(u32))
-               return -EOPNOTSUPP;
+       IWL_DEBUG_RADIO(fwrt, "ACPI DSM validity bitmap 0x%x\n",
+                       (u32)query_func_val);
 
-       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;
+       /* DSM_FUNC_QUERY is 0, start from 1 */
+       for (int func = 1; func < ARRAY_SIZE(fwrt->dsm_values); func++) {
+               size_t expected_size = acpi_dsm_size[func];
+               u64 tmp;
+
+               if (!(query_func_val & BIT(func))) {
+                       IWL_DEBUG_RADIO(fwrt,
+                                       "ACPI DSM %d not indicated as valid\n",
+                                       func);
+                       continue;
                }
 
-               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);
+               /* This is an invalid function (5 for example) */
+               if (!expected_size)
+                       continue;
+
+               /* Currently all ACPI DSMs are either 8-bit or 32-bit */
+               if (expected_size != sizeof(u8) && expected_size != sizeof(u32))
+                       continue;
+
+               ret = iwl_acpi_get_dsm_integer(fwrt->dev, ACPI_DSM_REV, func,
+                                              &iwl_guid, &tmp, expected_size);
+               if (ret)
+                       continue;
+
+               if ((expected_size == sizeof(u8) && tmp != (u8)tmp) ||
+                   (expected_size == sizeof(u32) && tmp != (u32)tmp))
+                       IWL_DEBUG_RADIO(fwrt,
+                                       "DSM value overflows the expected size, truncating\n");
+               fwrt->dsm_values[func] = (u32)tmp;
+               fwrt->dsm_funcs_valid |= BIT(func);
        }
 
-       if (!(fwrt->acpi_dsm_funcs_valid & BIT(func))) {
+       return 0;
+}
+
+/*
+ * This function receives a DSM function number, calculates its expected size
+ * according to Intel BIOS spec, and fills in the value in a 32-bit field.
+ * In case the expected size is smaller than 32-bit, padding will be added.
+ */
+int iwl_acpi_get_dsm(struct iwl_fw_runtime *fwrt,
+                    enum iwl_dsm_funcs func, u32 *value)
+{
+       if (!fwrt->dsm_funcs_valid) {
+               int ret = iwl_acpi_load_dsm_values(fwrt);
+
+               /*
+                * Always set the valid bit for DSM_FUNC_QUERY so that even if
+                * DSM_FUNC_QUERY returns 0 (no DSM function is valid), we will
+                * still consider the cache as valid.
+                */
+               fwrt->dsm_funcs_valid |= BIT(DSM_FUNC_QUERY);
+
+               if (ret)
+                       return ret;
+       }
+
+       BUILD_BUG_ON(ARRAY_SIZE(fwrt->dsm_values) != DSM_FUNC_NUM_FUNCS);
+       BUILD_BUG_ON(BITS_PER_TYPE(fwrt->dsm_funcs_valid) < DSM_FUNC_NUM_FUNCS);
+
+       if (WARN_ON(func >= ARRAY_SIZE(fwrt->dsm_values) || !func))
+               return -EINVAL;
+
+       if (!(fwrt->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)
-               return ret;
-
-       if ((expected_size == sizeof(u8) && tmp != (u8)tmp) ||
-           (expected_size == sizeof(u32) && tmp != (u32)tmp))
-               IWL_DEBUG_RADIO(fwrt,
-                               "DSM value overflows the expected size, truncating\n");
-       *value = (u32)tmp;
+       *value = fwrt->dsm_values[func];
 
        return 0;
 }
index 57570ff15622e790da31f77356d21d0ea1b94f80..b9e5f8ea8f9477360fcc75b45b181ffe7c95e536 100644 (file)
@@ -116,10 +116,14 @@ 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,
+ * @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
+ *     bitmap and is always supported.
+ *     If the bit is set for a specific function, then the corresponding
+ *     entry in &dsm_values is valid.
+ * @dsm_values: cache of the DSM values. The validity of each entry is
+ *     determined by &dsm_funcs_valid.
  * @geo_enabled: WGDS table is present
  * @geo_num_profiles: number of geo profiles
  * @geo_rev: geo profiles table revision
@@ -213,7 +217,8 @@ struct iwl_fw_runtime {
        struct iwl_phy_specific_cfg phy_filters;
 
 #ifdef CONFIG_ACPI
-       u32 acpi_dsm_funcs_valid;
+       u32 dsm_funcs_valid;
+       u32 dsm_values[DSM_FUNC_NUM_FUNCS];
 #endif
 };