[PATCH 3/9] wifi: ath11k: Add support to the Qualcomm ath11k for ACPI WBRF

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Anson Tsao <anson.tsao@xxxxxxx>

Qualcomm wifi adapters are utilized in systems that support AMD's WBRF
interference mitigation mechanism. For this mechanism to work frequencies
utilized use must be notified to an ACPI device.

If the kernel is configured with CONFIG_ACPI_WBRF then notify this ACPI
device accordingly.

Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.23

Signed-off-by: Anson Tsao <anson.tsao@xxxxxxx>
Signed-off-by: Evan Quan <evan.quan@xxxxxxx>
Co-developed-by: Evan Quan <evan.quan@xxxxxxx>
--
v1->v2:
  - Fix possible NULL pointer dereference caused by ar->hw->conf.chandef.chan
v2->v3:
  - correct the timing for `ath11k_add_wbrf` and `ath11k_remove_wbrf`
    calling
---
 drivers/net/wireless/ath/Makefile      |  1 +
 drivers/net/wireless/ath/acpi_wbrf.c   | 45 ++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath.h         | 15 +++++++++
 drivers/net/wireless/ath/ath11k/core.c | 23 +++++++++++++
 drivers/net/wireless/ath/ath11k/core.h | 14 ++++++++
 drivers/net/wireless/ath/ath11k/mac.c  |  4 +++
 drivers/net/wireless/ath/ath11k/pci.c  |  3 ++
 7 files changed, 105 insertions(+)
 create mode 100644 drivers/net/wireless/ath/acpi_wbrf.c

diff --git a/drivers/net/wireless/ath/Makefile b/drivers/net/wireless/ath/Makefile
index 8d6e6e218d24..234e904bdfa9 100644
--- a/drivers/net/wireless/ath/Makefile
+++ b/drivers/net/wireless/ath/Makefile
@@ -21,5 +21,6 @@ ath-objs :=	main.o \
 
 ath-$(CONFIG_ATH_DEBUG) += debug.o
 ath-$(CONFIG_ATH_TRACEPOINTS) += trace.o
+ath-$(CONFIG_ACPI_WBRF) += acpi_wbrf.o
 
 CFLAGS_trace.o := -I$(src)
diff --git a/drivers/net/wireless/ath/acpi_wbrf.c b/drivers/net/wireless/ath/acpi_wbrf.c
new file mode 100644
index 000000000000..98b3416eca4d
--- /dev/null
+++ b/drivers/net/wireless/ath/acpi_wbrf.c
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: ISC
+/* Copyright (C) 2023 Advanced Micro Devices */
+
+#include <linux/wbrf.h>
+#include "ath.h"
+
+bool ath_check_wbrf_support(struct device *dev)
+{
+	struct acpi_device *acpi_dev = ACPI_COMPANION(dev);
+	bool wbrf_supported;
+
+	if (!acpi_dev) {
+		dev_dbg(dev, "ACPI companion not found\n");
+		return false;
+	}
+
+	wbrf_supported = wbrf_supported_producer(acpi_dev);
+	dev_dbg(dev, "WBRF is %s supported\n",
+		wbrf_supported ? "" : "not");
+
+	return wbrf_supported;
+}
+EXPORT_SYMBOL_GPL(ath_check_wbrf_support);
+
+int ath_add_wbrf(struct device *dev, struct cfg80211_chan_def *chandef)
+{
+	struct acpi_device *acpi_dev = ACPI_COMPANION(dev);
+
+	if (!acpi_dev)
+		return -ENODEV;
+
+	return wbrf_add_exclusion_wlan(acpi_dev, chandef);
+}
+EXPORT_SYMBOL_GPL(ath_add_wbrf);
+
+int ath_remove_wbrf(struct device *dev, struct cfg80211_chan_def *chandef)
+{
+	struct acpi_device *acpi_dev = ACPI_COMPANION(dev);
+
+	if (!acpi_dev)
+		return -ENODEV;
+
+	return wbrf_remove_exclusion_wlan(acpi_dev, chandef);
+}
+EXPORT_SYMBOL_GPL(ath_remove_wbrf);
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
index f02a308a9ffc..c9f5c9a67c0a 100644
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -334,4 +334,19 @@ static inline const char *ath_bus_type_to_string(enum ath_bus_type bustype)
 	return ath_bus_type_strings[bustype];
 }
 
+#ifdef CONFIG_ACPI_WBRF
+bool ath_check_wbrf_support(struct device *dev);
+int ath_add_wbrf(struct device *dev, struct cfg80211_chan_def *chandef);
+int ath_remove_wbrf(struct device *dev, struct cfg80211_chan_def *chandef);
+#else
+static inline
+bool ath_check_wbrf_support(struct device *dev) { return false; }
+static inline
+int ath_add_wbrf(struct device *dev,
+		 struct cfg80211_chan_def *chandef) { return 0; }
+static inline
+int ath_remove_wbrf(struct device *dev,
+		    struct cfg80211_chan_def *chandef) { return 0; }
+#endif
+
 #endif /* ATH_H */
diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
index b1b90bd34d67..1f1eed9c8ae7 100644
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -16,6 +16,7 @@
 #include "debug.h"
 #include "hif.h"
 #include "wow.h"
+#include "../ath.h"
 
 unsigned int ath11k_debug_mask;
 EXPORT_SYMBOL(ath11k_debug_mask);
@@ -2035,5 +2036,27 @@ struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size,
 }
 EXPORT_SYMBOL(ath11k_core_alloc);
 
+#if defined(CONFIG_ACPI_WBRF)
+int ath11k_add_wbrf(struct ath11k_base *ab,
+		    struct cfg80211_chan_def *chandef)
+{
+	if (!ab->wbrf)
+		return 0;
+
+	return ath_add_wbrf(ab->dev, chandef);
+}
+EXPORT_SYMBOL_GPL(ath11k_add_wbrf);
+
+int ath11k_remove_wbrf(struct ath11k_base *ab,
+		       struct cfg80211_chan_def *chandef)
+{
+	if (!ab->wbrf)
+		return 0;
+
+	return ath_remove_wbrf(ab->dev, chandef);
+}
+EXPORT_SYMBOL_GPL(ath11k_remove_wbrf);
+#endif
+
 MODULE_DESCRIPTION("Core module for Qualcomm Atheros 802.11ax wireless LAN cards.");
 MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index 0830276e5028..02975d012875 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -978,6 +978,8 @@ struct ath11k_base {
 		const struct ath11k_pci_ops *ops;
 	} pci;
 
+	bool wbrf;
+
 	/* must be last */
 	u8 drv_priv[] __aligned(sizeof(void *));
 };
@@ -1236,4 +1238,16 @@ static inline const char *ath11k_bus_str(enum ath11k_bus bus)
 	return "unknown";
 }
 
+#ifdef CONFIG_ACPI_WBRF
+int ath11k_add_wbrf(struct ath11k_base *ab, struct cfg80211_chan_def *chandef);
+int ath11k_remove_wbrf(struct ath11k_base *ab, struct cfg80211_chan_def *chandef);
+#else
+static inline
+int ath11k_add_wbrf(struct ath11k_base *ab,
+		    struct cfg80211_chan_def *chandef) { return 0; }
+static inline
+int ath11k_remove_wbrf(struct ath11k_base *ab0,
+		       struct cfg80211_chan_def *chandef) { return 0; }
+#endif /* CONFIG_ACPI_WBRF */
+
 #endif /* _CORE_H_ */
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index 1c93f1afccc5..b96e13ae816b 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -6838,6 +6838,8 @@ static int ath11k_mac_op_add_chanctx(struct ieee80211_hw *hw,
 
 	mutex_lock(&ar->conf_mutex);
 
+	ath11k_add_wbrf(ar->ab, &ctx->def);
+
 	spin_lock_bh(&ar->data_lock);
 	/* TODO: In case of multiple channel context, populate rx_channel from
 	 * Rx PPDU desc information.
@@ -6862,6 +6864,8 @@ static void ath11k_mac_op_remove_chanctx(struct ieee80211_hw *hw,
 
 	mutex_lock(&ar->conf_mutex);
 
+	ath11k_remove_wbrf(ar->ab, &ctx->def);
+
 	spin_lock_bh(&ar->data_lock);
 	/* TODO: In case of there is one more channel context left, populate
 	 * rx_channel with the channel of that remaining channel context.
diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c
index 7b33731a50ee..f648f92c7564 100644
--- a/drivers/net/wireless/ath/ath11k/pci.c
+++ b/drivers/net/wireless/ath/ath11k/pci.c
@@ -15,6 +15,7 @@
 #include "mhi.h"
 #include "debug.h"
 #include "pcic.h"
+#include "../ath.h"
 
 #define ATH11K_PCI_BAR_NUM		0
 #define ATH11K_PCI_DMA_MASK		32
@@ -891,6 +892,8 @@ static int ath11k_pci_probe(struct pci_dev *pdev,
 		goto err_irq_affinity_cleanup;
 	}
 
+	ab->wbrf = ath_check_wbrf_support(ab->dev);
+
 	ret = ath11k_core_init(ab);
 	if (ret) {
 		ath11k_err(ab, "failed to init core: %d\n", ret);
-- 
2.34.1




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux