wifi: iwlwifi: implement WPFC ACPI table loading
authorJohannes Berg <johannes.berg@intel.com>
Wed, 14 Jun 2023 09:41:33 +0000 (12:41 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 19 Jun 2023 10:05:26 +0000 (12:05 +0200)
We skipped this in the past, but now we will need it for some
platforms. Implement loading the PHY filter configuration IDs
from the WPFC ACPI table. Note that the firmware must also be
aware of the right filter configuration IDs (they're just the
IDs of a filter configuration, not the actual configuration).

Remove the useless hardcoded zeroes while at it.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230614123447.035026ea3169.I3a1fc1fe644fefa0d818ee1926c5fc331d68e8a3@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/intel/iwlwifi/fw/acpi.c
drivers/net/wireless/intel/iwlwifi/fw/acpi.h
drivers/net/wireless/intel/iwlwifi/fw/api/config.h
drivers/net/wireless/intel/iwlwifi/mvm/constants.h
drivers/net/wireless/intel/iwlwifi/mvm/fw.c
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h

index 6345ac4..dfe8357 100644 (file)
@@ -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);
index e9c533c..c36c62d 100644 (file)
@@ -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__ */
index 087354b..4419631 100644 (file)
@@ -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*/
 
 /**
index c604f9f..243eccc 100644 (file)
@@ -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
 #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 */
index 8d8277d..77cdfb4 100644 (file)
@@ -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 */
 
index bcfe4af..ee2a526 100644 (file)
@@ -1179,6 +1179,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;