wifi: iwlwifi: read WPFC also from UEFI
authorMiri Korenblit <miriam.rachel.korenblit@intel.com>
Wed, 30 Apr 2025 12:23:08 +0000 (15:23 +0300)
committerMiri Korenblit <miriam.rachel.korenblit@intel.com>
Tue, 6 May 2025 17:22:37 +0000 (20:22 +0300)
We are currently reading it only from ACPI, but we need to read it from
UEFI too (if exists, and if the UEFI variables are locked)

Add the reading from the UEFI and use IWL_BIOS_TABLE_LOADER to generate
the code that determines the source from which the table should be read
(ACPI/UEFI).

Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20250430151952.839a5e7dd89b.I491acbf68047874df97b3971f1ba692ebc998a52@changeid
drivers/net/wireless/intel/iwlwifi/fw/regulatory.c
drivers/net/wireless/intel/iwlwifi/fw/regulatory.h
drivers/net/wireless/intel/iwlwifi/fw/runtime.h
drivers/net/wireless/intel/iwlwifi/fw/uefi.c
drivers/net/wireless/intel/iwlwifi/fw/uefi.h

index 6adcfa6e214a0a01eeccc0cb4a0dede3f6eb310d..1444b628214b0df99ff4e8b9ac8435e5ffe1c3d8 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
 /*
- * Copyright (C) 2023 Intel Corporation
+ * Copyright (C) 2023, 2025 Intel Corporation
  */
 #include <linux/dmi.h>
 #include "iwl-drv.h"
@@ -34,6 +34,7 @@ IWL_BIOS_TABLE_LOADER(wrds_table);
 IWL_BIOS_TABLE_LOADER(ewrd_table);
 IWL_BIOS_TABLE_LOADER(wgds_table);
 IWL_BIOS_TABLE_LOADER(ppag_table);
+IWL_BIOS_TABLE_LOADER(phy_filters);
 IWL_BIOS_TABLE_LOADER_DATA(tas_table, struct iwl_tas_data);
 IWL_BIOS_TABLE_LOADER_DATA(pwr_limit, u64);
 IWL_BIOS_TABLE_LOADER_DATA(mcc, char);
index 53693314d50592e261d188e70c7ab68e224056af..46d19101b74157c3d821db9a4ecfcb7584da5712 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
 /*
- * Copyright (C) 2023-2024 Intel Corporation
+ * Copyright (C) 2023-2025 Intel Corporation
  */
 
 #ifndef __fw_regulatory_h__
@@ -236,6 +236,7 @@ bool iwl_puncturing_is_allowed_in_bios(u32 puncturing, u16 mcc);
 #define IWL_DSBR_PERMANENT_URM_MASK    BIT(9)
 
 int iwl_bios_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *value);
+int iwl_bios_get_phy_filters(struct iwl_fw_runtime *fwrt);
 
 static inline void iwl_bios_setup_step(struct iwl_trans *trans,
                                       struct iwl_fw_runtime *fwrt)
index 5753d95986cda56eca390ba23ea97592d7687c9d..a56b96003650dbc6478d0c95e9e59376d43e5ea8 100644 (file)
@@ -185,9 +185,7 @@ struct iwl_fw_runtime {
        struct iwl_mcc_allowed_ap_type_cmd uats_table;
        bool uats_valid;
        u8 uefi_tables_lock_status;
-#ifdef CONFIG_ACPI
        struct iwl_phy_specific_cfg phy_filters;
-#endif
 };
 
 void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
index 386aadbce2a2defee13dc90a3e12a05241826b2e..b0f4c217b2a5004b9251bac62662a7a97ac7d506 100644 (file)
@@ -810,3 +810,31 @@ out:
        kfree(data);
        return ret;
 }
+
+int iwl_uefi_get_phy_filters(struct iwl_fw_runtime *fwrt)
+{
+       struct uefi_cnv_wpfc_data *data __free(kfree);
+       struct iwl_phy_specific_cfg *filters = &fwrt->phy_filters;
+
+       data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_WPFC_NAME,
+                                             "WPFC", sizeof(*data), NULL);
+       if (IS_ERR(data))
+               return -EINVAL;
+
+       if (data->revision != 0) {
+               IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI WPFC revision:%d\n",
+                       data->revision);
+               return -EINVAL;
+       }
+
+       BUILD_BUG_ON(ARRAY_SIZE(filters->filter_cfg_chains) !=
+                    ARRAY_SIZE(data->chains));
+
+       for (int i = 0; i < ARRAY_SIZE(filters->filter_cfg_chains); i++) {
+               filters->filter_cfg_chains[i] = cpu_to_le32(data->chains[i]);
+               IWL_DEBUG_RADIO(fwrt, "WPFC: chain %d: %u\n", i, data->chains[i]);
+       }
+
+       IWL_DEBUG_RADIO(fwrt, "Loaded WPFC config from UEFI\n");
+       return 0;
+}
index eb3c05417da371b41c140b2877574d5f2c1cf78d..37d2ced03ce12f2ee77f317ab5964cff5fc17532 100644 (file)
@@ -24,6 +24,7 @@
 #define IWL_UEFI_WBEM_NAME             L"UefiCnvWlanWBEM"
 #define IWL_UEFI_PUNCTURING_NAME       L"UefiCnvWlanPuncturing"
 #define IWL_UEFI_DSBR_NAME             L"UefiCnvCommonDSBR"
+#define IWL_UEFI_WPFC_NAME             L"WPFC"
 
 
 #define IWL_SGOM_MAP_SIZE              339
@@ -230,6 +231,18 @@ struct uefi_cnv_wlan_dsbr_data {
        u32 config;
 } __packed;
 
+/**
+ * struct uefi_cnv_wpfc_data - BIOS Wi-Fi PHY filter Configuration
+ * @revision: the revision of the table
+ * @chains: configuration of each of the chains (a-d)
+ *
+ * specific PHY filter configuration
+ */
+struct uefi_cnv_wpfc_data {
+       u8 revision;
+       u32 chains[4];
+} __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
@@ -262,6 +275,7 @@ int iwl_uefi_get_uats_table(struct iwl_trans *trans,
                            struct iwl_fw_runtime *fwrt);
 int iwl_uefi_get_puncturing(struct iwl_fw_runtime *fwrt);
 int iwl_uefi_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *value);
+int iwl_uefi_get_phy_filters(struct iwl_fw_runtime *fwrt);
 #else /* CONFIG_EFI */
 static inline void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
 {
@@ -370,5 +384,10 @@ int iwl_uefi_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *value)
 {
        return -ENOENT;
 }
+
+static inline int iwl_uefi_get_phy_filters(struct iwl_fw_runtime *fwrt)
+{
+       return -ENOENT;
+}
 #endif /* CONFIG_EFI */
 #endif /* __iwl_fw_uefi__ */