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 3570472..9afb1b1 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 3260f21..a427751 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 da49ed7..52389f8 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 4454fae..fe6d014 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 723933b..1f7c3f4 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 6f33f79..1ba3a55 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 a05a5f4..738e90a 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);