wifi: iwlwifi: read DSM functions from UEFI
authorMiri Korenblit <miriam.rachel.korenblit@intel.com>
Thu, 1 Feb 2024 14:17:37 +0000 (16:17 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 2 Feb 2024 13:37:27 +0000 (14:37 +0100)
For each DSM function, try to first read it from the UEFI.
If the UEFI WIFI GUID is unclocked, or the DSM function in
UEFI is invalid/unavailable - 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.27dd626ce2bd.Ib90bab74a9d56deb2362edb712294360e4ddae5b@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/debugfs.c
drivers/net/wireless/intel/iwlwifi/mvm/fw.c

index 357047223686115c4496712a2a288840fee93bdd..9afb1b1d6aea3606b82bab76e53361758b3e1b9a 100644 (file)
@@ -187,7 +187,6 @@ int iwl_acpi_get_dsm(struct iwl_fw_runtime *fwrt,
 
        return 0;
 }
-IWL_EXPORT_SYMBOL(iwl_acpi_get_dsm);
 
 static union acpi_object *
 iwl_acpi_get_wifi_pkg_range(struct device *dev,
index 3260f21fd2e0b9d2bb0139a7c5769f8737552a85..a42775141952fd0d387ae9f0a8047c6fc6328117 100644 (file)
@@ -443,7 +443,7 @@ __le32 iwl_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt)
        case IWL_CFG_RF_TYPE_HR2:
        case IWL_CFG_RF_TYPE_JF1:
        case IWL_CFG_RF_TYPE_JF2:
-               ret = iwl_acpi_get_dsm(fwrt, DSM_FUNC_ENABLE_INDONESIA_5G2,
+               ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_INDONESIA_5G2,
                                       &val);
 
                if (!ret && val == DSM_VALUE_INDONESIA_ENABLE)
@@ -454,7 +454,7 @@ __le32 iwl_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt)
                break;
        }
 
-       ret = iwl_acpi_get_dsm(fwrt, DSM_FUNC_DISABLE_SRD, &val);
+       ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_DISABLE_SRD, &val);
        if (!ret) {
                if (val == DSM_VALUE_SRD_PASSIVE)
                        config_bitmap |=
@@ -466,7 +466,7 @@ __le32 iwl_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt)
 
        if (fw_has_capa(&fwrt->fw->ucode_capa,
                        IWL_UCODE_TLV_CAPA_CHINA_22_REG_SUPPORT)) {
-               ret = iwl_acpi_get_dsm(fwrt, DSM_FUNC_REGULATORY_CONFIG,
+               ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_REGULATORY_CONFIG,
                                       &val);
                /*
                 * China 2022 enable if the BIOS object does not exist or
@@ -480,3 +480,10 @@ __le32 iwl_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt)
        return config_bitmap;
 }
 IWL_EXPORT_SYMBOL(iwl_get_lari_config_bitmap);
+
+int iwl_bios_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func,
+                    u32 *value)
+{
+       GET_BIOS_TABLE(dsm, fwrt, func, value);
+}
+IWL_EXPORT_SYMBOL(iwl_bios_get_dsm);
index da49ed7325d664245b19e4d209439dc5a301d92e..52389f82cbb9352da2b94d84aa6418174b6645c2 100644 (file)
@@ -186,4 +186,7 @@ int iwl_bios_get_mcc(struct iwl_fw_runtime *fwrt, char *mcc);
 int iwl_bios_get_eckv(struct iwl_fw_runtime *fwrt, u32 *ext_clk);
 
 __le32 iwl_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt);
+
+int iwl_bios_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func,
+                    u32 *value);
 #endif /* __fw_regulatory_h__ */
index 4454fae84d1fddd7fc2d842892767034763acdb7..fe6d0141cd5b1169ff789ab1730dd698d4b01c4c 100644 (file)
@@ -674,3 +674,36 @@ out:
        kfree(data);
        return ret;
 }
+
+int iwl_uefi_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func,
+                    u32 *value)
+{
+       struct uefi_cnv_var_general_cfg *data;
+       int ret = EINVAL;
+
+       /* Not supported function index */
+       if (func >= DSM_FUNC_NUM_FUNCS || func == 5)
+               return -EOPNOTSUPP;
+
+       data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_DSM_NAME,
+                                             "DSM", sizeof(*data), NULL);
+       if (IS_ERR(data))
+               return -EINVAL;
+
+       if (data->revision != IWL_UEFI_DSM_REVISION) {
+               IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI DSM revision:%d\n",
+                               data->revision);
+               goto out;
+       }
+
+       if (ARRAY_SIZE(data->functions) != UEFI_MAX_DSM_FUNCS) {
+               IWL_DEBUG_RADIO(fwrt, "Invalid size of DSM functions array\n");
+               goto out;
+       }
+
+       *value = data->functions[func];
+       ret = 0;
+out:
+       kfree(data);
+       return ret;
+}
index 723933b0b2f1fa76c800d7653ad159eebde03b3f..1f7c3f4c29010747e35303d73be464e98c5a8a0d 100644 (file)
@@ -20,6 +20,7 @@
 #define IWL_UEFI_SPLC_NAME             L"UefiCnvWlanSPLC"
 #define IWL_UEFI_WRDD_NAME             L"UefiCnvWlanWRDD"
 #define IWL_UEFI_ECKV_NAME             L"UefiCnvWlanECKV"
+#define IWL_UEFI_DSM_NAME              L"UefiCnvWlanGeneralCfg"
 
 
 #define IWL_SGOM_MAP_SIZE              339
@@ -34,6 +35,7 @@
 #define IWL_UEFI_SPLC_REVISION         0
 #define IWL_UEFI_WRDD_REVISION         0
 #define IWL_UEFI_ECKV_REVISION         0
+#define IWL_UEFI_DSM_REVISION          4
 
 struct pnvm_sku_package {
        u8 rev;
@@ -166,6 +168,17 @@ struct uefi_cnv_var_eckv {
        u32 ext_clock_valid;
 } __packed;
 
+#define UEFI_MAX_DSM_FUNCS 32
+
+/* struct uefi_cnv_var_general_cfg - DSM-like table as defined in UEFI
+ * @revision: the revision of the table
+ * @functions: payload of the different DSM functions
+ */
+struct uefi_cnv_var_general_cfg {
+       u8 revision;
+       u32 functions[UEFI_MAX_DSM_FUNCS];
+} __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
@@ -190,6 +203,8 @@ int iwl_uefi_get_pwr_limit(struct iwl_fw_runtime *fwrt,
                           u64 *dflt_pwr_limit);
 int iwl_uefi_get_mcc(struct iwl_fw_runtime *fwrt, char *mcc);
 int iwl_uefi_get_eckv(struct iwl_fw_runtime *fwrt, u32 *extl_clk);
+int iwl_uefi_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func,
+                    u32 *value);
 #else /* CONFIG_EFI */
 static inline void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len)
 {
@@ -263,6 +278,12 @@ static inline int iwl_uefi_get_eckv(struct iwl_fw_runtime *fwrt, u32 *extl_clk)
 {
        return -ENOENT;
 }
+
+static inline int iwl_uefi_get_dsm(struct iwl_fw_runtime *fwrt,
+                                  enum iwl_dsm_funcs func, u32 *value)
+{
+       return -ENOENT;
+}
 #endif /* CONFIG_EFI */
 
 #if defined(CONFIG_EFI) && defined(CONFIG_ACPI)
index 6f33f791648e6bc5ba874b457717e34fedf2d66d..1ba3a559c1d62cdca43c1f47856e2378533e3f2e 100644 (file)
@@ -391,7 +391,7 @@ static ssize_t iwl_dbgfs_wifi_6e_enable_read(struct file *file,
        char buf[12];
        u32 value;
 
-       err = iwl_acpi_get_dsm(&mvm->fwrt, DSM_FUNC_ENABLE_6E, &value);
+       err = iwl_bios_get_dsm(&mvm->fwrt, DSM_FUNC_ENABLE_6E, &value);
        if (err)
                return err;
 
index a05a5f403ae5eb767b96420a8c9f3301a509188a..738e90a4fe2f4ec55087030d2ad1215578316699 100644 (file)
@@ -1206,7 +1206,7 @@ static bool iwl_mvm_eval_dsm_rfi(struct iwl_mvm *mvm)
        u32 value = 0;
        /* default behaviour is disabled */
        bool bios_enable_rfi = false;
-       int ret = iwl_acpi_get_dsm(&mvm->fwrt, DSM_FUNC_RFI_CONFIG, &value);
+       int ret = iwl_bios_get_dsm(&mvm->fwrt, DSM_FUNC_RFI_CONFIG, &value);
 
 
        if (ret < 0) {
@@ -1244,31 +1244,31 @@ static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm)
 
        cmd.config_bitmap = iwl_get_lari_config_bitmap(&mvm->fwrt);
 
-       ret = iwl_acpi_get_dsm(&mvm->fwrt, DSM_FUNC_11AX_ENABLEMENT, &value);
+       ret = iwl_bios_get_dsm(&mvm->fwrt, DSM_FUNC_11AX_ENABLEMENT, &value);
        if (!ret)
                cmd.oem_11ax_allow_bitmap = cpu_to_le32(value);
 
-       ret = iwl_acpi_get_dsm(&mvm->fwrt, DSM_FUNC_ENABLE_UNII4_CHAN, &value);
+       ret = iwl_bios_get_dsm(&mvm->fwrt, DSM_FUNC_ENABLE_UNII4_CHAN, &value);
        if (!ret)
                cmd.oem_unii4_allow_bitmap = cpu_to_le32(value);
 
-       ret = iwl_acpi_get_dsm(&mvm->fwrt, DSM_FUNC_ACTIVATE_CHANNEL, &value);
+       ret = iwl_bios_get_dsm(&mvm->fwrt, DSM_FUNC_ACTIVATE_CHANNEL, &value);
        if (!ret) {
                if (cmd_ver < 8)
                        value &= ~ACTIVATE_5G2_IN_WW_MASK;
                cmd.chan_state_active_bitmap = cpu_to_le32(value);
        }
 
-       ret = iwl_acpi_get_dsm(&mvm->fwrt, DSM_FUNC_ENABLE_6E, &value);
+       ret = iwl_bios_get_dsm(&mvm->fwrt, DSM_FUNC_ENABLE_6E, &value);
        if (!ret)
                cmd.oem_uhb_allow_bitmap = cpu_to_le32(value);
 
-       ret = iwl_acpi_get_dsm(&mvm->fwrt, DSM_FUNC_FORCE_DISABLE_CHANNELS,
+       ret = iwl_bios_get_dsm(&mvm->fwrt, DSM_FUNC_FORCE_DISABLE_CHANNELS,
                               &value);
        if (!ret)
                cmd.force_disable_channels_bitmap = cpu_to_le32(value);
 
-       ret = iwl_acpi_get_dsm(&mvm->fwrt, DSM_FUNC_ENERGY_DETECTION_THRESHOLD,
+       ret = iwl_bios_get_dsm(&mvm->fwrt, DSM_FUNC_ENERGY_DETECTION_THRESHOLD,
                               &value);
        if (!ret)
                cmd.edt_bitmap = cpu_to_le32(value);