wifi: iwlwifi: read PPAG table from UEFI
authorMiri Korenblit <miriam.rachel.korenblit@intel.com>
Wed, 31 Jan 2024 08:24:43 +0000 (10:24 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 2 Feb 2024 13:15:15 +0000 (14:15 +0100)
Try to read the PPAG 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/20240131091413.6516da09aec1.I0dcaf0b6d8857417ba1318467a28da5d0d7d7f27@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/runtime.h
drivers/net/wireless/intel/iwlwifi/fw/uefi.c
drivers/net/wireless/intel/iwlwifi/fw/uefi.h
drivers/net/wireless/intel/iwlwifi/mvm/fw.c

index b029e88501a11be97c68920317eca54ac9574e4d..c150a66eed07f232be75ac2ec64fee2a6dc89961 100644 (file)
@@ -968,7 +968,6 @@ out_free:
        kfree(data);
        return ret;
 }
-IWL_EXPORT_SYMBOL(iwl_acpi_get_ppag_table);
 
 void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt,
                              struct iwl_phy_specific_cfg *filters)
index 3d42ea1ec5fdb364ce51edaf51d2e079de16eacf..fb4df1ff061d0e5ccd99d30c98b9e386cc291c4c 100644 (file)
@@ -24,6 +24,7 @@ IWL_EXPORT_SYMBOL(iwl_bios_get_ ## __name ## _table)
 IWL_BIOS_TABLE_LOADER(wrds);
 IWL_BIOS_TABLE_LOADER(ewrd);
 IWL_BIOS_TABLE_LOADER(wgds);
+IWL_BIOS_TABLE_LOADER(ppag);
 
 static const struct dmi_system_id dmi_ppag_approved_list[] = {
        { .ident = "HP",
index 63f650cb6517361671e9d19d65bd75c97330b963..954ba83d02776f6c7555c5bb1cf6dd3775aa6b9a 100644 (file)
@@ -113,4 +113,5 @@ int iwl_bios_get_ewrd_table(struct iwl_fw_runtime *fwrt);
 
 int iwl_bios_get_wgds_table(struct iwl_fw_runtime *fwrt);
 
+int iwl_bios_get_ppag_table(struct iwl_fw_runtime *fwrt);
 #endif /* __fw_regulatory_h__ */
index d129782f2be49ba8d48aac7ab855e1525907fcbe..9bcf04987d8bcda0bf095323d2902aa817b68bbb 100644 (file)
@@ -172,10 +172,10 @@ struct iwl_fw_runtime {
        u32 geo_rev;
        u32 geo_num_profiles;
        bool geo_enabled;
-#ifdef CONFIG_ACPI
        struct iwl_ppag_chain ppag_chains[IWL_NUM_CHAIN_LIMITS];
        u32 ppag_flags;
        u32 ppag_ver;
+#ifdef CONFIG_ACPI
        struct iwl_sar_offset_mapping_cmd sgom_table;
        bool sgom_enabled;
        struct iwl_uats_table_cmd uats_table;
index a777cd4c70f7c6b862aae7fc6034a554ec04e566..f8092622d9886a182218b87608d4bf63c137a1fd 100644 (file)
@@ -521,3 +521,32 @@ out:
        kfree(data);
        return ret;
 }
+
+int iwl_uefi_get_ppag_table(struct iwl_fw_runtime *fwrt)
+{
+       struct uefi_cnv_var_ppag *data;
+       int ret = 0;
+
+       data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_PPAG_NAME,
+                                             "PPAG", sizeof(*data), NULL);
+       if (IS_ERR(data))
+               return -EINVAL;
+
+       if (data->revision < IWL_UEFI_MIN_PPAG_REV ||
+           data->revision > IWL_UEFI_MAX_PPAG_REV) {
+               ret = -EINVAL;
+               IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI PPAG revision:%d\n",
+                               data->revision);
+               goto out;
+       }
+
+       fwrt->ppag_ver = data->revision;
+       fwrt->ppag_flags = data->ppag_modes & IWL_PPAG_ETSI_CHINA_MASK;
+
+       BUILD_BUG_ON(sizeof(fwrt->ppag_chains) != sizeof(data->ppag_chains));
+       memcpy(&fwrt->ppag_chains, &data->ppag_chains,
+              sizeof(data->ppag_chains));
+out:
+       kfree(data);
+       return ret;
+}
index 3141fca047c657622be940148b3e788681259488..a2e6eb21de823dc3b86b6031f4a6b4c7b7957b02 100644 (file)
@@ -15,6 +15,7 @@
 #define IWL_UEFI_WRDS_NAME             L"UefiCnvWlanWRDS"
 #define IWL_UEFI_EWRD_NAME             L"UefiCnvWlanEWRD"
 #define IWL_UEFI_WGDS_NAME             L"UefiCnvWlanWGDS"
+#define IWL_UEFI_PPAG_NAME             L"UefiCnvWlanPPAG"
 
 #define IWL_SGOM_MAP_SIZE              339
 #define IWL_UATS_MAP_SIZE              339
@@ -22,6 +23,8 @@
 #define IWL_UEFI_WRDS_REVISION         2
 #define IWL_UEFI_EWRD_REVISION         2
 #define IWL_UEFI_WGDS_REVISION         3
+#define IWL_UEFI_MIN_PPAG_REV          1
+#define IWL_UEFI_MAX_PPAG_REV          3
 
 struct pnvm_sku_package {
        u8 rev;
@@ -99,6 +102,19 @@ struct uefi_cnv_var_wgds {
        struct iwl_geo_profile geo_profiles[BIOS_GEO_MAX_PROFILE_NUM];
 } __packed;
 
+/*
+ * struct uefi_cnv_var_ppag - PPAG table as defined in UEFI
+ * @revision: the revision of the table
+ * @ppag_modes: bit 0 - PPAG is enabled/disabled in ETSI,
+ *     bit 1 - PPAG is enabled/disabled in China
+ * @ppag_chains: the PPAG values per chain and band
+ */
+struct uefi_cnv_var_ppag {
+       u8 revision;
+       u32 ppag_modes;
+       struct iwl_ppag_chain ppag_chains[IWL_NUM_CHAIN_LIMITS];
+} __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
@@ -116,6 +132,7 @@ int iwl_uefi_handle_tlv_mem_desc(struct iwl_trans *trans, const u8 *data,
 int iwl_uefi_get_wrds_table(struct iwl_fw_runtime *fwrt);
 int iwl_uefi_get_ewrd_table(struct iwl_fw_runtime *fwrt);
 int iwl_uefi_get_wgds_table(struct iwl_fw_runtime *fwrt);
+int iwl_uefi_get_ppag_table(struct iwl_fw_runtime *fwrt);
 #else /* CONFIG_EFI */
 static inline void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
 {
@@ -161,6 +178,11 @@ static inline int iwl_uefi_get_wgds_table(struct iwl_fw_runtime *fwrt)
 {
        return -ENOENT;
 }
+
+static inline int iwl_uefi_get_ppag_table(struct iwl_fw_runtime *fwrt)
+{
+       return -ENOENT;
+}
 #endif /* CONFIG_EFI */
 
 #if defined(CONFIG_EFI) && defined(CONFIG_ACPI)
index 1d759fe7d12db6be03d5f787d04f6ce9e291f01f..0a820dbeef23f989cacd987de6abcb80c9319856 100644 (file)
@@ -1078,8 +1078,6 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
        return iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, len, &cmd);
 }
 
-#ifdef CONFIG_ACPI
-
 int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm)
 {
        union iwl_ppag_table_cmd cmd;
@@ -1110,6 +1108,8 @@ static int iwl_mvm_ppag_init(struct iwl_mvm *mvm)
        return iwl_mvm_ppag_send_cmd(mvm);
 }
 
+#ifdef CONFIG_ACPI
+
 static const struct dmi_system_id dmi_tas_approved_list[] = {
        { .ident = "HP",
          .matches = {
@@ -1389,16 +1389,6 @@ static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm)
 
 #else /* CONFIG_ACPI */
 
-int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm)
-{
-       return -ENOENT;
-}
-
-static int iwl_mvm_ppag_init(struct iwl_mvm *mvm)
-{
-       return 0;
-}
-
 static void iwl_mvm_tas_init(struct iwl_mvm *mvm)
 {
 }
@@ -1426,7 +1416,7 @@ void iwl_mvm_get_bios_tables(struct iwl_mvm *mvm)
        iwl_acpi_get_guid_lock_status(&mvm->fwrt);
 
        /* read PPAG table */
-       ret = iwl_acpi_get_ppag_table(&mvm->fwrt);
+       ret = iwl_bios_get_ppag_table(&mvm->fwrt);
        if (ret < 0) {
                IWL_DEBUG_RADIO(mvm,
                                "PPAG BIOS table invalid or unavailable. (%d)\n",