@@ -1248,3 +1248,40 @@ bool iwl_acpi_is_ppag_approved(struct iwl_fw_runtime *fwrt)
return true;
}
IWL_EXPORT_SYMBOL(iwl_acpi_is_ppag_approved);
+
+void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt,
+ struct iwl_phy_specific_cfg *filters)
+{
+ struct iwl_phy_specific_cfg tmp = {};
+ union acpi_object *wifi_pkg, *data;
+ int tbl_rev, i;
+
+ data = iwl_acpi_get_object(fwrt->dev, ACPI_WPFC_METHOD);
+ if (IS_ERR(data))
+ return;
+
+ /* try to read wtas table revision 1 or revision 0*/
+ wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
+ ACPI_WPFC_WIFI_DATA_SIZE,
+ &tbl_rev);
+ if (IS_ERR(wifi_pkg))
+ goto out_free;
+
+ if (tbl_rev != 0)
+ goto out_free;
+
+ BUILD_BUG_ON(ARRAY_SIZE(filters->filter_cfg_chains) != ACPI_WPFC_WIFI_DATA_SIZE);
+
+ for (i = 0; i < ARRAY_SIZE(filters->filter_cfg_chains); i++) {
+ if (wifi_pkg->package.elements[i].type != ACPI_TYPE_INTEGER)
+ return;
+ tmp.filter_cfg_chains[i] =
+ cpu_to_le32(wifi_pkg->package.elements[i].integer.value);
+ }
+
+ IWL_DEBUG_RADIO(fwrt, "Loaded WPFC filter config from ACPI\n");
+ *filters = tmp;
+out_free:
+ kfree(data);
+}
+IWL_EXPORT_SYMBOL(iwl_acpi_get_phy_filters);
@@ -11,6 +11,7 @@
#include "fw/api/power.h"
#include "fw/api/phy.h"
#include "fw/api/nvm-reg.h"
+#include "fw/api/config.h"
#include "fw/img.h"
#include "iwl-trans.h"
@@ -23,6 +24,7 @@
#define ACPI_ECKV_METHOD "ECKV"
#define ACPI_PPAG_METHOD "PPAG"
#define ACPI_WTAS_METHOD "WTAS"
+#define ACPI_WPFC_METHOD "WPFC"
#define ACPI_WIFI_DOMAIN (0x07)
@@ -54,6 +56,7 @@
#define ACPI_EWRD_WIFI_DATA_SIZE_REV2 ((ACPI_SAR_PROFILE_NUM - 1) * \
ACPI_SAR_NUM_CHAINS_REV2 * \
ACPI_SAR_NUM_SUB_BANDS_REV2 + 3)
+#define ACPI_WPFC_WIFI_DATA_SIZE 4 /* 4 filter config words */
/* revision 0 and 1 are identical, except for the semantics in the FW */
#define ACPI_GEO_NUM_BANDS_REV0 2
@@ -225,6 +228,9 @@ int iwl_read_ppag_table(struct iwl_fw_runtime *fwrt, union iwl_ppag_table_cmd *c
bool iwl_acpi_is_ppag_approved(struct iwl_fw_runtime *fwrt);
+void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt,
+ struct iwl_phy_specific_cfg *filters);
+
#else /* CONFIG_ACPI */
static inline void *iwl_acpi_get_dsm_object(struct device *dev, int rev,
@@ -314,6 +320,11 @@ static inline bool iwl_acpi_is_ppag_approved(struct iwl_fw_runtime *fwrt)
return false;
}
+static inline void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt,
+ struct iwl_phy_specific_cfg *filters)
+{
+}
+
#endif /* CONFIG_ACPI */
#endif /* __iwl_fw_acpi__ */
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
- * Copyright (C) 2012-2014, 2018-2019 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2019, 2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -67,17 +67,12 @@ enum iwl_calib_cfg {
* Sent as part of the phy configuration command (v3) to configure specific FW
* defined PHY filters that can be applied to each antenna.
*
- * @filter_cfg_chain_a: filter config id for LMAC1 chain A
- * @filter_cfg_chain_b: filter config id for LMAC1 chain B
- * @filter_cfg_chain_c: filter config id for LMAC2 chain A
- * @filter_cfg_chain_d: filter config id for LMAC2 chain B
- * values: 0 - no filter; 0xffffffff - reserved; otherwise - filter id
+ * @filter_cfg_chains: filter config id for LMAC1 chain A, LMAC1 chain B,
+ * LMAC2 chain A, LMAC2 chain B (in that order)
+ * values: 0: no filter; 0xffffffff: reserved; otherwise: filter id
*/
struct iwl_phy_specific_cfg {
- __le32 filter_cfg_chain_a;
- __le32 filter_cfg_chain_b;
- __le32 filter_cfg_chain_c;
- __le32 filter_cfg_chain_d;
+ __le32 filter_cfg_chains[4];
} __packed; /* PHY_SPECIFIC_CONFIGURATION_API_VER_1*/
/**
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
- * Copyright (C) 2013-2014, 2018-2021 Intel Corporation
+ * Copyright (C) 2013-2014, 2018-2023 Intel Corporation
* Copyright (C) 2015 Intel Deutschland GmbH
*/
#ifndef __MVM_CONSTANTS_H
@@ -109,10 +109,6 @@
#define IWL_MVM_USE_TWT true
#define IWL_MVM_AMPDU_CONSEC_DROPS_DELBA 20
#define IWL_MVM_USE_NSSN_SYNC 0
-#define IWL_MVM_PHY_FILTER_CHAIN_A 0
-#define IWL_MVM_PHY_FILTER_CHAIN_B 0
-#define IWL_MVM_PHY_FILTER_CHAIN_C 0
-#define IWL_MVM_PHY_FILTER_CHAIN_D 0
#define IWL_MVM_FTM_INITIATOR_ENABLE_SMOOTH false
#define IWL_MVM_FTM_INITIATOR_SMOOTH_ALPHA 40
/* 20016 pSec is 6 meter RTT, meaning 3 meter range */
@@ -478,40 +478,13 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
return 0;
}
-#ifdef CONFIG_ACPI
static void iwl_mvm_phy_filter_init(struct iwl_mvm *mvm,
struct iwl_phy_specific_cfg *phy_filters)
{
- /*
- * TODO: read specific phy config from BIOS
- * ACPI table for this feature has not been defined yet,
- * so for now we use hardcoded values.
- */
-
- if (IWL_MVM_PHY_FILTER_CHAIN_A) {
- phy_filters->filter_cfg_chain_a =
- cpu_to_le32(IWL_MVM_PHY_FILTER_CHAIN_A);
- }
- if (IWL_MVM_PHY_FILTER_CHAIN_B) {
- phy_filters->filter_cfg_chain_b =
- cpu_to_le32(IWL_MVM_PHY_FILTER_CHAIN_B);
- }
- if (IWL_MVM_PHY_FILTER_CHAIN_C) {
- phy_filters->filter_cfg_chain_c =
- cpu_to_le32(IWL_MVM_PHY_FILTER_CHAIN_C);
- }
- if (IWL_MVM_PHY_FILTER_CHAIN_D) {
- phy_filters->filter_cfg_chain_d =
- cpu_to_le32(IWL_MVM_PHY_FILTER_CHAIN_D);
- }
-}
-#else /* CONFIG_ACPI */
-
-static void iwl_mvm_phy_filter_init(struct iwl_mvm *mvm,
- struct iwl_phy_specific_cfg *phy_filters)
-{
-}
+#ifdef CONFIG_ACPI
+ *phy_filters = mvm->phy_filters;
#endif /* CONFIG_ACPI */
+}
#if defined(CONFIG_ACPI) && defined(CONFIG_EFI)
static int iwl_mvm_sgom_init(struct iwl_mvm *mvm)
@@ -560,7 +533,6 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
u32 cmd_id = PHY_CONFIGURATION_CMD;
struct iwl_phy_cfg_cmd_v3 phy_cfg_cmd;
enum iwl_ucode_type ucode_type = mvm->fwrt.cur_fw_img;
- struct iwl_phy_specific_cfg phy_filters = {};
u8 cmd_ver;
size_t cmd_size;
@@ -591,11 +563,8 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id,
IWL_FW_CMD_VER_UNKNOWN);
- if (cmd_ver == 3) {
- iwl_mvm_phy_filter_init(mvm, &phy_filters);
- memcpy(&phy_cfg_cmd.phy_specific_cfg, &phy_filters,
- sizeof(struct iwl_phy_specific_cfg));
- }
+ if (cmd_ver >= 3)
+ iwl_mvm_phy_filter_init(mvm, &phy_cfg_cmd.phy_specific_cfg);
IWL_DEBUG_INFO(mvm, "Sending Phy CFG command: 0x%x\n",
phy_cfg_cmd.phy_cfg);
@@ -1380,6 +1349,8 @@ void iwl_mvm_get_acpi_tables(struct iwl_mvm *mvm)
/* we don't fail if the table is not available */
}
}
+
+ iwl_acpi_get_phy_filters(&mvm->fwrt, &mvm->phy_filters);
}
#else /* CONFIG_ACPI */
@@ -1182,6 +1182,10 @@ struct iwl_mvm {
__le16 cur_aid;
u8 cur_bssid[ETH_ALEN];
+#ifdef CONFIG_ACPI
+ struct iwl_phy_specific_cfg phy_filters;
+#endif
+
unsigned long last_6ghz_passive_scan_jiffies;
unsigned long last_reset_or_resume_time_jiffies;