wifi: iwlwifi: read SPLC from UEFI
authorMiri Korenblit <miriam.rachel.korenblit@intel.com>
Thu, 1 Feb 2024 14:17:26 +0000 (16:17 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 2 Feb 2024 13:37:26 +0000 (14:37 +0100)
Try to read the SPLC table from UEFI first,
and if the WIFI UEFI tables are unlocked or the
table doesn't exist - try to read it from ACPI

Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Reviewed-by: Gregory Greenman <gregory.greenman@intel.com>
Link: https://msgid.link/20240201155157.3d9d835b6edb.I7ea262df9431ced787b77c87149c6d7bddb7e7d6@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/intel/iwlwifi/fw/acpi.c
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/fw/uefi.h
drivers/net/wireless/intel/iwlwifi/mvm/ops.c

index d6e7de2543b2d599ecdc9e676f7ab5e9c3f4594b..e74745f939ae060d9c4ad1c2fd0932f269eee2a6 100644 (file)
@@ -385,7 +385,6 @@ out_free:
 out:
        return ret;
 }
-IWL_EXPORT_SYMBOL(iwl_acpi_get_pwr_limit);
 
 int iwl_acpi_get_eckv(struct device *dev, u32 *extl_clk)
 {
index 4cf22e280dfcb89aecb14d48005c7e2e4349c7c6..452c7cc49c27ef555947eeebe5636d2c33b1626a 100644 (file)
@@ -35,6 +35,8 @@ IWL_BIOS_TABLE_LOADER(ewrd_table);
 IWL_BIOS_TABLE_LOADER(wgds_table);
 IWL_BIOS_TABLE_LOADER(ppag_table);
 IWL_BIOS_TABLE_LOADER_DATA(tas_table, struct iwl_tas_data);
+IWL_BIOS_TABLE_LOADER_DATA(pwr_limit, u64);
+
 
 static const struct dmi_system_id dmi_ppag_approved_list[] = {
        { .ident = "HP",
index 7719ee764c55207245207df73b84977516b75cc7..b391c6fc3bcc0bc09a59088c35b3a9c43c916a19 100644 (file)
@@ -137,4 +137,6 @@ int iwl_bios_get_ppag_table(struct iwl_fw_runtime *fwrt);
 int iwl_bios_get_tas_table(struct iwl_fw_runtime *fwrt,
                           struct iwl_tas_data *data);
 
+int iwl_bios_get_pwr_limit(struct iwl_fw_runtime *fwrt,
+                          u64 *dflt_pwr_limit);
 #endif /* __fw_regulatory_h__ */
index d6cbfe6c5a1727c72fcf3b3c45cd1769474b6e6b..5ec82205be1257ef6895eda3a32ea74d5c6bf1ec 100644 (file)
@@ -598,3 +598,26 @@ out:
        kfree(uefi_tas);
        return ret;
 }
+
+int iwl_uefi_get_pwr_limit(struct iwl_fw_runtime *fwrt,
+                          u64 *dflt_pwr_limit)
+{
+       struct uefi_cnv_var_splc *data;
+       int ret = 0;
+
+       data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_SPLC_NAME,
+                                             "SPLC", sizeof(*data), NULL);
+       if (IS_ERR(data))
+               return -EINVAL;
+
+       if (data->revision != IWL_UEFI_SPLC_REVISION) {
+               ret = -EINVAL;
+               IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI SPLC revision:%d\n",
+                               data->revision);
+               goto out;
+       }
+       *dflt_pwr_limit = data->default_pwr_limit;
+out:
+       kfree(data);
+       return ret;
+}
index f849a485d0a96542ac51cbdd09aba05e1f546324..4cf3af57692024c3bb85df242b1cc84577ca510d 100644 (file)
@@ -17,6 +17,8 @@
 #define IWL_UEFI_WGDS_NAME             L"UefiCnvWlanWGDS"
 #define IWL_UEFI_PPAG_NAME             L"UefiCnvWlanPPAG"
 #define IWL_UEFI_WTAS_NAME             L"UefiCnvWlanWTAS"
+#define IWL_UEFI_SPLC_NAME             L"UefiCnvWlanSPLC"
+
 
 #define IWL_SGOM_MAP_SIZE              339
 #define IWL_UATS_MAP_SIZE              339
@@ -27,6 +29,7 @@
 #define IWL_UEFI_MIN_PPAG_REV          1
 #define IWL_UEFI_MAX_PPAG_REV          3
 #define IWL_UEFI_WTAS_REVISION         1
+#define IWL_UEFI_SPLC_REVISION         0
 
 struct pnvm_sku_package {
        u8 rev;
@@ -130,6 +133,15 @@ struct uefi_cnv_var_wtas {
        u16 black_list[IWL_WTAS_BLACK_LIST_MAX];
 } __packed;
 
+/* struct uefi_cnv_var_splc - SPLC tabled as defined in UEFI
+ * @revision: the revision of the table
+ * @default_pwr_limit: The default maximum power per device
+ */
+struct uefi_cnv_var_splc {
+       u8 revision;
+       u32 default_pwr_limit;
+} __packed;
+
 /*
  * This is known to be broken on v4.19 and to work on v5.4.  Until we
  * figure out why this is the case and how to make it work, simply
@@ -150,6 +162,8 @@ int iwl_uefi_get_wgds_table(struct iwl_fw_runtime *fwrt);
 int iwl_uefi_get_ppag_table(struct iwl_fw_runtime *fwrt);
 int iwl_uefi_get_tas_table(struct iwl_fw_runtime *fwrt,
                           struct iwl_tas_data *data);
+int iwl_uefi_get_pwr_limit(struct iwl_fw_runtime *fwrt,
+                          u64 *dflt_pwr_limit);
 #else /* CONFIG_EFI */
 static inline void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
 {
@@ -206,6 +220,13 @@ static inline int iwl_uefi_get_tas_table(struct iwl_fw_runtime *fwrt,
 {
        return -ENOENT;
 }
+
+static inline int iwl_uefi_get_pwr_limit(struct iwl_fw_runtime *fwrt,
+                                        u64 *dflt_pwr_limit)
+{
+       *dflt_pwr_limit = 0;
+       return 0;
+}
 #endif /* CONFIG_EFI */
 
 #if defined(CONFIG_EFI) && defined(CONFIG_ACPI)
index 0e7b66a20b7c4d07ff18c7edb2c4aaaf03cf8bd7..747fc91ef8d03768a801931fc72cf48a87f0985f 100644 (file)
@@ -689,7 +689,7 @@ static u32 iwl_mvm_min_backoff(struct iwl_mvm *mvm)
        if (!backoff)
                return 0;
 
-       iwl_acpi_get_pwr_limit(&mvm->fwrt, &dflt_pwr_limit);
+       iwl_bios_get_pwr_limit(&mvm->fwrt, &dflt_pwr_limit);
 
        while (backoff->pwr) {
                if (dflt_pwr_limit >= backoff->pwr)