netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH V5 0/9] Enable Wifi RFI interference mitigation feature support
@ 2023-06-30 10:32 Evan Quan
  2023-06-30 10:32 ` [PATCH V5 1/9] drivers core: Add support for Wifi band RF mitigations Evan Quan
                   ` (8 more replies)
  0 siblings, 9 replies; 28+ messages in thread
From: Evan Quan @ 2023-06-30 10:32 UTC (permalink / raw)
  To: rafael, lenb, Alexander.Deucher, Christian.Koenig, Xinhui.Pan,
	airlied, daniel, johannes, davem, edumazet, kuba, pabeni,
	Mario.Limonciello, mdaenzer, maarten.lankhorst, tzimmermann,
	hdegoede, jingyuwang_vip, Lijo.Lazar, jim.cromie, bellosilicio,
	andrealmeid, trix, jsg, arnd
  Cc: linux-kernel, linux-acpi, amd-gfx, dri-devel, linux-wireless,
	netdev, Evan Quan

Due to electrical and mechanical constraints in certain platform designs there may
be likely interference of relatively high-powered harmonics of the (G-)DDR memory
clocks with local radio module frequency bands used by Wifi 6/6e/7. To mitigate
possible RFI interference producers can advertise the frequencies in use and
consumers can use this information to avoid using these frequencies for
sensitive features.

The whole patch set is based on Linux 6.4. With some brief introductions as below:
Patch1 - 2:  Core functionality setup for WBRF feature support
Patch3 - 4:  Bring WBRF support to wifi subsystem.
Patch5 - 9:  Bring WBRF support to AMD graphics driver.

Evan Quan (9):
  drivers core: Add support for Wifi band RF mitigations
  driver core: add ACPI based WBRF mechanism introduced by AMD
  cfg80211: expose nl80211_chan_width_to_mhz for wide sharing
  wifi: mac80211: Add support for ACPI WBRF
  drm/amd/pm: update driver_if and ppsmc headers for coming wbrf feature
  drm/amd/pm: setup the framework to support Wifi RFI mitigation feature
  drm/amd/pm: add flood detection for wbrf events
  drm/amd/pm: enable Wifi RFI mitigation feature support for SMU13.0.0
  drm/amd/pm: enable Wifi RFI mitigation feature support for SMU13.0.7

 drivers/acpi/Makefile                         |   2 +
 drivers/acpi/amd_wbrf.c                       | 236 +++++++++++++++++
 drivers/base/Kconfig                          |  37 +++
 drivers/base/Makefile                         |   1 +
 drivers/base/wbrf.c                           | 250 ++++++++++++++++++
 drivers/gpu/drm/amd/amdgpu/amdgpu.h           |   1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c       |  19 ++
 drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c     | 214 +++++++++++++++
 drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h |  33 +++
 .../inc/pmfw_if/smu13_driver_if_v13_0_0.h     |  14 +-
 .../inc/pmfw_if/smu13_driver_if_v13_0_7.h     |  14 +-
 .../pm/swsmu/inc/pmfw_if/smu_v13_0_0_ppsmc.h  |   3 +-
 .../pm/swsmu/inc/pmfw_if/smu_v13_0_7_ppsmc.h  |   3 +-
 drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h  |   3 +-
 drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h  |   3 +
 .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c    |   9 +
 .../drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c  |  60 +++++
 .../drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c  |  59 +++++
 drivers/gpu/drm/amd/pm/swsmu/smu_internal.h   |   3 +
 include/linux/acpi_amd_wbrf.h                 |  38 +++
 include/linux/ieee80211.h                     |   1 +
 include/linux/wbrf.h                          |  67 +++++
 include/net/cfg80211.h                        |   8 +
 net/mac80211/Makefile                         |   2 +
 net/mac80211/chan.c                           |   9 +
 net/mac80211/ieee80211_i.h                    |  19 ++
 net/mac80211/main.c                           |   2 +
 net/mac80211/wbrf.c                           | 103 ++++++++
 net/wireless/chan.c                           |   3 +-
 29 files changed, 1210 insertions(+), 6 deletions(-)
 create mode 100644 drivers/acpi/amd_wbrf.c
 create mode 100644 drivers/base/wbrf.c
 create mode 100644 include/linux/acpi_amd_wbrf.h
 create mode 100644 include/linux/wbrf.h
 create mode 100644 net/mac80211/wbrf.c

-- 
2.34.1


^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH V5 1/9] drivers core: Add support for Wifi band RF mitigations
  2023-06-30 10:32 [PATCH V5 0/9] Enable Wifi RFI interference mitigation feature support Evan Quan
@ 2023-06-30 10:32 ` Evan Quan
  2023-06-30 13:38   ` Simon Horman
                     ` (2 more replies)
  2023-06-30 10:32 ` [PATCH V5 2/9] driver core: add ACPI based WBRF mechanism introduced by AMD Evan Quan
                   ` (7 subsequent siblings)
  8 siblings, 3 replies; 28+ messages in thread
From: Evan Quan @ 2023-06-30 10:32 UTC (permalink / raw)
  To: rafael, lenb, Alexander.Deucher, Christian.Koenig, Xinhui.Pan,
	airlied, daniel, johannes, davem, edumazet, kuba, pabeni,
	Mario.Limonciello, mdaenzer, maarten.lankhorst, tzimmermann,
	hdegoede, jingyuwang_vip, Lijo.Lazar, jim.cromie, bellosilicio,
	andrealmeid, trix, jsg, arnd
  Cc: linux-kernel, linux-acpi, amd-gfx, dri-devel, linux-wireless,
	netdev, Evan Quan, Mario Limonciello

Due to electrical and mechanical constraints in certain platform designs
there may be likely interference of relatively high-powered harmonics of
the (G-)DDR memory clocks with local radio module frequency bands used
by Wifi 6/6e/7.

To mitigate this, AMD has introduced a mechanism that devices can use to
notify active use of particular frequencies so that other devices can make
relative internal adjustments as necessary to avoid this resonance.

In order for a device to support this, the expected flow for device
driver or subsystems:

Drivers/subsystems contributing frequencies:

1) During probe, check `wbrf_supported_producer` to see if WBRF supported
   for the device.
2) If adding frequencies, then call `wbrf_add_exclusion` with the
   start and end ranges of the frequencies.
3) If removing frequencies, then call `wbrf_remove_exclusion` with
   start and end ranges of the frequencies.

Drivers/subsystems responding to frequencies:

1) During probe, check `wbrf_supported_consumer` to see if WBRF is supported
   for the device.
2) Call the `wbrf_retrieve_exclusions` to retrieve the current
   exclusions on receiving an ACPI notification for a new frequency
   change.

Co-developed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
Co-developed-by: Evan Quan <evan.quan@amd.com>
Signed-off-by: Evan Quan <evan.quan@amd.com>
--
v4->v5:
  - promote this to be a more generic solution with input argument taking
    `struct device` and provide better scalability to support non-ACPI
    scenarios(Andrew)
  - update the APIs naming and some other minor fixes(Rafael)
---
 drivers/base/Kconfig  |   8 ++
 drivers/base/Makefile |   1 +
 drivers/base/wbrf.c   | 227 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/wbrf.h  |  65 ++++++++++++
 4 files changed, 301 insertions(+)
 create mode 100644 drivers/base/wbrf.c
 create mode 100644 include/linux/wbrf.h

diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index 2b8fd6bb7da0..5b441017b225 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -242,4 +242,12 @@ config FW_DEVLINK_SYNC_STATE_TIMEOUT
 	  command line option on every system/board your kernel is expected to
 	  work on.
 
+config WBRF
+	bool "Wifi band RF mitigation mechanism"
+	default n
+	help
+	  Wifi band RF mitigation mechanism allows multiple drivers from
+	  different domains to notify the frequencies in use so that hardware
+	  can be reconfigured to avoid harmonic conflicts.
+
 endmenu
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 3079bfe53d04..c844f68a6830 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_GENERIC_MSI_IRQ) += platform-msi.o
 obj-$(CONFIG_GENERIC_ARCH_TOPOLOGY) += arch_topology.o
 obj-$(CONFIG_GENERIC_ARCH_NUMA) += arch_numa.o
 obj-$(CONFIG_ACPI) += physical_location.o
+obj-$(CONFIG_WBRF) += wbrf.o
 
 obj-y			+= test/
 
diff --git a/drivers/base/wbrf.c b/drivers/base/wbrf.c
new file mode 100644
index 000000000000..2163a8ec8a9a
--- /dev/null
+++ b/drivers/base/wbrf.c
@@ -0,0 +1,227 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Wifi Band Exclusion Interface
+ * Copyright (C) 2023 Advanced Micro Devices
+ *
+ */
+
+#include <linux/wbrf.h>
+
+static BLOCKING_NOTIFIER_HEAD(wbrf_chain_head);
+static DEFINE_MUTEX(wbrf_mutex);
+static struct exclusion_range_pool wbrf_pool;
+
+static int _wbrf_add_exclusion_ranges(struct wbrf_ranges_in *in)
+{
+	int i, j;
+
+	for (i = 0; i < ARRAY_SIZE(in->band_list); i++) {
+		if (!in->band_list[i].start &&
+		    !in->band_list[i].end)
+			continue;
+
+		for (j = 0; j < ARRAY_SIZE(wbrf_pool.band_list); j++) {
+			if (wbrf_pool.band_list[j].start == in->band_list[i].start &&
+			    wbrf_pool.band_list[j].end == in->band_list[i].end) {
+				wbrf_pool.ref_counter[j]++;
+				break;
+			}
+		}
+		if (j < ARRAY_SIZE(wbrf_pool.band_list))
+			continue;
+
+		for (j = 0; j < ARRAY_SIZE(wbrf_pool.band_list); j++) {
+			if (!wbrf_pool.band_list[j].start &&
+			    !wbrf_pool.band_list[j].end) {
+				wbrf_pool.band_list[j].start = in->band_list[i].start;
+				wbrf_pool.band_list[j].end = in->band_list[i].end;
+				wbrf_pool.ref_counter[j] = 1;
+				break;
+			}
+		}
+		if (j >= ARRAY_SIZE(wbrf_pool.band_list))
+			return -ENOSPC;
+	}
+
+	return 0;
+}
+
+static int _wbrf_remove_exclusion_ranges(struct wbrf_ranges_in *in)
+{
+	int i, j;
+
+	for (i = 0; i < ARRAY_SIZE(in->band_list); i++) {
+		if (!in->band_list[i].start &&
+		    !in->band_list[i].end)
+			continue;
+
+		for (j = 0; j < ARRAY_SIZE(wbrf_pool.band_list); j++) {
+			if (wbrf_pool.band_list[j].start == in->band_list[i].start &&
+			    wbrf_pool.band_list[j].end == in->band_list[i].end) {
+				wbrf_pool.ref_counter[j]--;
+				if (!wbrf_pool.ref_counter[j]) {
+					wbrf_pool.band_list[j].start = 0;
+					wbrf_pool.band_list[j].end = 0;
+				}
+				break;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static int _wbrf_retrieve_exclusion_ranges(struct wbrf_ranges_out *out)
+{
+	int out_idx = 0;
+	int i;
+
+	memset(out, 0, sizeof(*out));
+
+	for (i = 0; i < ARRAY_SIZE(wbrf_pool.band_list); i++) {
+		if (!wbrf_pool.band_list[i].start &&
+		    !wbrf_pool.band_list[i].end)
+			continue;
+
+		out->band_list[out_idx].start = wbrf_pool.band_list[i].start;
+		out->band_list[out_idx++].end = wbrf_pool.band_list[i].end;
+	}
+
+	return 0;
+}
+
+/**
+ * wbrf_supported_producer - Determine if the device can report frequencies
+ *
+ * @dev: device pointer
+ *
+ * WBRF is used to mitigate devices that cause harmonic interference.
+ * This function will determine if this device needs to report such frequencies.
+ */
+bool wbrf_supported_producer(struct device *dev)
+{
+	return true;
+}
+EXPORT_SYMBOL_GPL(wbrf_supported_producer);
+
+/**
+ * wbrf_add_exclusion - Add frequency ranges to the exclusion list
+ *
+ * @dev: device pointer
+ * @in: input structure containing the frequency ranges to be added
+ *
+ * Add frequencies into the exclusion list for supported consumers
+ * to react to.
+ */
+int wbrf_add_exclusion(struct device *dev,
+		       struct wbrf_ranges_in *in)
+{
+	int r;
+
+	mutex_lock(&wbrf_mutex);
+
+	r = _wbrf_add_exclusion_ranges(in);
+
+	mutex_unlock(&wbrf_mutex);
+	if (r)
+		return r;
+
+	blocking_notifier_call_chain(&wbrf_chain_head, WBRF_CHANGED, NULL);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(wbrf_add_exclusion);
+
+/**
+ * wbrf_remove_exclusion - Remove frequency ranges from the exclusion list
+ *
+ * @dev: device pointer
+ * @in: input structure containing the frequency ranges to be removed
+ *
+ * Remove frequencies from the exclusion list for supported consumers
+ * to react to.
+ */
+int wbrf_remove_exclusion(struct device *dev,
+			  struct wbrf_ranges_in *in)
+{
+	int r;
+
+	mutex_lock(&wbrf_mutex);
+
+	r = _wbrf_remove_exclusion_ranges(in);
+
+	mutex_unlock(&wbrf_mutex);
+	if (r)
+		return r;
+
+	blocking_notifier_call_chain(&wbrf_chain_head, WBRF_CHANGED, NULL);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(wbrf_remove_exclusion);
+
+/**
+ * wbrf_supported_consumer - Determine if the device can react to frequencies
+ *
+ * @dev: device pointer
+ *
+ * WBRF is used to mitigate devices that cause harmonic interference.
+ * This function will determine if this device needs to react to reports from
+ * other devices for such frequencies.
+ */
+bool wbrf_supported_consumer(struct device *dev)
+{
+	return true;
+}
+EXPORT_SYMBOL_GPL(wbrf_supported_consumer);
+
+/**
+ * wbrf_register_notifier - Register for notifications of frequency changes
+ *
+ * @nb: driver notifier block
+ *
+ * WBRF is used to mitigate devices that cause harmonic interference.
+ * This function will allow consumers to register for frequency notifications.
+ */
+int wbrf_register_notifier(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_register(&wbrf_chain_head, nb);
+}
+EXPORT_SYMBOL_GPL(wbrf_register_notifier);
+
+/**
+ * wbrf_unregister_notifier - Unregister for notifications of frequency changes
+ *
+ * @nb: driver notifier block
+ *
+ * WBRF is used to mitigate devices that cause harmonic interference.
+ * This function will allow consumers to unregister for frequency notifications.
+ */
+int wbrf_unregister_notifier(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_unregister(&wbrf_chain_head, nb);
+}
+EXPORT_SYMBOL_GPL(wbrf_unregister_notifier);
+
+/**
+ * wbrf_retrieve_exclusions - Retrieve the exclusion list
+ *
+ * @dev: device pointer
+ * @out: output structure containing the frequency ranges to be excluded
+ *
+ * Retrieve the current exclusion list
+ */
+int wbrf_retrieve_exclusions(struct device *dev,
+			     struct wbrf_ranges_out *out)
+{
+	int r;
+
+	mutex_lock(&wbrf_mutex);
+
+	r = _wbrf_retrieve_exclusion_ranges(out);
+
+	mutex_unlock(&wbrf_mutex);
+
+	return r;
+}
+EXPORT_SYMBOL_GPL(wbrf_retrieve_exclusions);
diff --git a/include/linux/wbrf.h b/include/linux/wbrf.h
new file mode 100644
index 000000000000..3ca95786cef5
--- /dev/null
+++ b/include/linux/wbrf.h
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Wifi Band Exclusion Interface
+ * Copyright (C) 2023 Advanced Micro Devices
+ */
+
+#ifndef _LINUX_WBRF_H
+#define _LINUX_WBRF_H
+
+#include <linux/device.h>
+
+/* Maximum number of wbrf ranges */
+#define MAX_NUM_OF_WBRF_RANGES		11
+
+struct exclusion_range {
+	/* start and end point of the frequency range in Hz */
+	uint64_t	start;
+	uint64_t	end;
+};
+
+struct exclusion_range_pool {
+	struct exclusion_range	band_list[MAX_NUM_OF_WBRF_RANGES];
+	uint64_t		ref_counter[MAX_NUM_OF_WBRF_RANGES];
+};
+
+struct wbrf_ranges_in {
+	/* valid entry: `start` and `end` filled with non-zero values */
+	struct exclusion_range	band_list[MAX_NUM_OF_WBRF_RANGES];
+};
+
+struct wbrf_ranges_out {
+	uint32_t		num_of_ranges;
+	struct exclusion_range	band_list[MAX_NUM_OF_WBRF_RANGES];
+} __packed;
+
+enum wbrf_notifier_actions {
+	WBRF_CHANGED,
+};
+
+#ifdef CONFIG_WBRF
+bool wbrf_supported_producer(struct device *dev);
+int wbrf_add_exclusion(struct device *adev,
+		       struct wbrf_ranges_in *in);
+int wbrf_remove_exclusion(struct device *dev,
+			  struct wbrf_ranges_in *in);
+int wbrf_retrieve_exclusions(struct device *dev,
+			     struct wbrf_ranges_out *out);
+bool wbrf_supported_consumer(struct device *dev);
+
+int wbrf_register_notifier(struct notifier_block *nb);
+int wbrf_unregister_notifier(struct notifier_block *nb);
+#else
+static inline bool wbrf_supported_producer(struct device *dev) { return false; }
+static inline int wbrf_add_exclusion(struct device *adev,
+				     struct wbrf_ranges_in *in) { return -ENODEV; }
+static inline int wbrf_remove_exclusion(struct device *dev,
+					struct wbrf_ranges_in *in) { return -ENODEV; }
+static inline int wbrf_retrieve_exclusions(struct device *dev,
+					   struct wbrf_ranges_out *out) { return -ENODEV; }
+static inline bool wbrf_supported_consumer(struct device *dev) { return false; }
+static inline int wbrf_register_notifier(struct notifier_block *nb) { return -ENODEV; }
+static inline int wbrf_unregister_notifier(struct notifier_block *nb) { return -ENODEV; }
+#endif
+
+#endif /* _LINUX_WBRF_H */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH V5 2/9] driver core: add ACPI based WBRF mechanism introduced by AMD
  2023-06-30 10:32 [PATCH V5 0/9] Enable Wifi RFI interference mitigation feature support Evan Quan
  2023-06-30 10:32 ` [PATCH V5 1/9] drivers core: Add support for Wifi band RF mitigations Evan Quan
@ 2023-06-30 10:32 ` Evan Quan
  2023-07-01  0:51   ` Andrew Lunn
  2023-06-30 10:32 ` [PATCH V5 3/9] cfg80211: expose nl80211_chan_width_to_mhz for wide sharing Evan Quan
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 28+ messages in thread
From: Evan Quan @ 2023-06-30 10:32 UTC (permalink / raw)
  To: rafael, lenb, Alexander.Deucher, Christian.Koenig, Xinhui.Pan,
	airlied, daniel, johannes, davem, edumazet, kuba, pabeni,
	Mario.Limonciello, mdaenzer, maarten.lankhorst, tzimmermann,
	hdegoede, jingyuwang_vip, Lijo.Lazar, jim.cromie, bellosilicio,
	andrealmeid, trix, jsg, arnd
  Cc: linux-kernel, linux-acpi, amd-gfx, dri-devel, linux-wireless,
	netdev, Evan Quan, Mario Limonciello

AMD has introduced an ACPI based mechanism to support WBRF for some
platforms with AMD dGPU + WLAN. This needs support from BIOS equipped
with necessary AML implementations and dGPU firmwares.

For those systems without the ACPI mechanism and developing solutions,
user can use the generic WBRF solution for diagnosing potential
interference issues.

Co-developed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
Co-developed-by: Evan Quan <evan.quan@amd.com>
Signed-off-by: Evan Quan <evan.quan@amd.com>
--
v4->v5:
  - promote this to be a more generic solution with input argument taking
    `struct device` and provide better scalability to support non-ACPI
    scenarios(Andrew)
  - update the APIs naming and some other minor fixes(Rafael)
---
 drivers/acpi/Makefile         |   2 +
 drivers/acpi/amd_wbrf.c       | 236 ++++++++++++++++++++++++++++++++++
 drivers/base/Kconfig          |  29 +++++
 drivers/base/wbrf.c           |  35 ++++-
 include/linux/acpi_amd_wbrf.h |  38 ++++++
 include/linux/wbrf.h          |   2 +
 6 files changed, 336 insertions(+), 6 deletions(-)
 create mode 100644 drivers/acpi/amd_wbrf.c
 create mode 100644 include/linux/acpi_amd_wbrf.h

diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index feb36c0b9446..94b940ddbf88 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -131,3 +131,5 @@ obj-y				+= dptf/
 obj-$(CONFIG_ARM64)		+= arm64/
 
 obj-$(CONFIG_ACPI_VIOT)		+= viot.o
+
+obj-$(CONFIG_WBRF_AMD_ACPI)	+= amd_wbrf.o
diff --git a/drivers/acpi/amd_wbrf.c b/drivers/acpi/amd_wbrf.c
new file mode 100644
index 000000000000..44e38c97acf0
--- /dev/null
+++ b/drivers/acpi/amd_wbrf.c
@@ -0,0 +1,236 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Wifi Band Exclusion Interface (AMD ACPI Implementation)
+ * Copyright (C) 2023 Advanced Micro Devices
+ *
+ */
+
+#include <linux/acpi.h>
+#include <linux/acpi_amd_wbrf.h>
+
+/* functions */
+#define WBRF_RECORD		0x1
+#define WBRF_RETRIEVE		0x2
+
+/* record actions */
+#define WBRF_RECORD_ADD		0x0
+#define WBRF_RECORD_REMOVE	0x1
+
+#define WBRF_REVISION		0x1
+
+static const guid_t wifi_acpi_dsm_guid =
+	GUID_INIT(0x7b7656cf, 0xdc3d, 0x4c1c,
+		  0x83, 0xe9, 0x66, 0xe7, 0x21, 0xde, 0x30, 0x70);
+
+static int wbrf_dsm(struct acpi_device *adev, u8 fn,
+		    union acpi_object *argv4,
+		    union acpi_object **out)
+{
+	union acpi_object *obj;
+	int rc;
+
+	obj = acpi_evaluate_dsm(adev->handle, &wifi_acpi_dsm_guid,
+				WBRF_REVISION, fn, argv4);
+	if (!obj)
+		return -ENXIO;
+
+	switch (obj->type) {
+	case ACPI_TYPE_BUFFER:
+		*out = obj;
+		return 0;
+
+	case ACPI_TYPE_INTEGER:
+		rc =  obj->integer.value ? -EINVAL : 0;
+		break;
+
+	default:
+		rc = -EOPNOTSUPP;
+	}
+
+	ACPI_FREE(obj);
+
+	return rc;
+}
+
+static int wbrf_record(struct acpi_device *adev, uint8_t action,
+		       struct wbrf_ranges_in *in)
+{
+	union acpi_object *argv4;
+	uint32_t num_of_ranges = 0;
+	uint32_t arg_idx = 0;
+	uint32_t loop_idx;
+	int ret;
+
+	if (!in)
+		return -EINVAL;
+
+	for (loop_idx = 0; loop_idx < ARRAY_SIZE(in->band_list);
+	     loop_idx++)
+		if (in->band_list[loop_idx].start &&
+		    in->band_list[loop_idx].end)
+			num_of_ranges++;
+
+	argv4 = kzalloc(sizeof(*argv4) * (2 * num_of_ranges + 2 + 1), GFP_KERNEL);
+	if (!argv4)
+		return -ENOMEM;
+
+	argv4[arg_idx].package.type = ACPI_TYPE_PACKAGE;
+	argv4[arg_idx].package.count = 2 + 2 * num_of_ranges;
+	argv4[arg_idx++].package.elements = &argv4[1];
+	argv4[arg_idx].integer.type = ACPI_TYPE_INTEGER;
+	argv4[arg_idx++].integer.value = num_of_ranges;
+	argv4[arg_idx].integer.type = ACPI_TYPE_INTEGER;
+	argv4[arg_idx++].integer.value = action;
+
+	for (loop_idx = 0; loop_idx < ARRAY_SIZE(in->band_list);
+	     loop_idx++) {
+		if (!in->band_list[loop_idx].start ||
+		    !in->band_list[loop_idx].end)
+			continue;
+
+		argv4[arg_idx].integer.type = ACPI_TYPE_INTEGER;
+		argv4[arg_idx++].integer.value = in->band_list[loop_idx].start;
+		argv4[arg_idx].integer.type = ACPI_TYPE_INTEGER;
+		argv4[arg_idx++].integer.value = in->band_list[loop_idx].end;
+	}
+
+	ret = wbrf_dsm(adev, WBRF_RECORD, argv4, NULL);
+
+	kfree(argv4);
+
+	return ret;
+}
+
+int acpi_amd_wbrf_add_exclusion(struct device *dev,
+				struct wbrf_ranges_in *in)
+{
+	struct acpi_device *adev = ACPI_COMPANION(dev);
+
+	if (!adev)
+		return -ENODEV;
+
+	return wbrf_record(adev, WBRF_RECORD_ADD, in);
+}
+
+int acpi_amd_wbrf_remove_exclusion(struct device *dev,
+				   struct wbrf_ranges_in *in)
+{
+	struct acpi_device *adev = ACPI_COMPANION(dev);
+
+	if (!adev)
+		return -ENODEV;
+
+	return wbrf_record(adev, WBRF_RECORD_REMOVE, in);
+}
+
+bool acpi_amd_wbrf_supported_producer(struct device *dev)
+{
+	struct acpi_device *adev = ACPI_COMPANION(dev);
+
+	if (!adev)
+		return false;
+
+	return acpi_check_dsm(adev->handle, &wifi_acpi_dsm_guid,
+			      WBRF_REVISION,
+			      BIT(WBRF_RECORD));
+}
+
+static union acpi_object *
+acpi_evaluate_wbrf(acpi_handle handle, u64 rev, u64 func)
+{
+	acpi_status ret;
+	struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
+	union acpi_object params[4];
+	struct acpi_object_list input = {
+		.count = 4,
+		.pointer = params,
+	};
+
+	params[0].type = ACPI_TYPE_INTEGER;
+	params[0].integer.value = rev;
+	params[1].type = ACPI_TYPE_INTEGER;
+	params[1].integer.value = func;
+	params[2].type = ACPI_TYPE_PACKAGE;
+	params[2].package.count = 0;
+	params[2].package.elements = NULL;
+	params[3].type = ACPI_TYPE_STRING;
+	params[3].string.length = 0;
+	params[3].string.pointer = NULL;
+
+	ret = acpi_evaluate_object(handle, "WBRF", &input, &buf);
+	if (ACPI_SUCCESS(ret))
+		return (union acpi_object *)buf.pointer;
+
+	return NULL;
+}
+
+static bool check_acpi_wbrf(acpi_handle handle, u64 rev, u64 funcs)
+{
+	int i;
+	u64 mask = 0;
+	union acpi_object *obj;
+
+	if (funcs == 0)
+		return false;
+
+	obj = acpi_evaluate_wbrf(handle, rev, 0);
+	if (!obj)
+		return false;
+
+	if (obj->type != ACPI_TYPE_BUFFER)
+		return false;
+
+	/*
+	 * Bit vector providing supported functions information.
+	 * Each bit marks support for one specific function of the WBRF method.
+	 */
+	for (i = 0; i < obj->buffer.length && i < 8; i++)
+		mask |= (((u64)obj->buffer.pointer[i]) << (i * 8));
+
+	ACPI_FREE(obj);
+
+	/*
+	 * Bit 0 indicates whether there's support for any functions other than
+	 * function 0.
+	 */
+	if ((mask & 0x1) && (mask & funcs) == funcs)
+		return true;
+
+	return false;
+}
+
+bool acpi_amd_wbrf_supported_consumer(struct device *dev)
+{
+	struct acpi_device *adev = ACPI_COMPANION(dev);
+
+	if (!adev)
+		return false;
+
+	return check_acpi_wbrf(adev->handle,
+			       WBRF_REVISION,
+			       BIT(WBRF_RETRIEVE));
+}
+
+int acpi_amd_wbrf_retrieve_exclusions(struct device *dev,
+				      struct wbrf_ranges_out *out)
+{
+	struct acpi_device *adev = ACPI_COMPANION(dev);
+	union acpi_object *obj;
+
+	if (!adev)
+		return -ENODEV;
+
+	obj = acpi_evaluate_wbrf(adev->handle,
+				 WBRF_REVISION,
+				 WBRF_RETRIEVE);
+	if (!obj)
+		return -EINVAL;
+
+	WARN(obj->buffer.length != sizeof(*out),
+		"Unexpected buffer length");
+	memcpy(out, obj->buffer.pointer, obj->buffer.length);
+
+	ACPI_FREE(obj);
+
+	return 0;
+}
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index 5b441017b225..cbf0b2358c17 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -250,4 +250,33 @@ config WBRF
 	  different domains to notify the frequencies in use so that hardware
 	  can be reconfigured to avoid harmonic conflicts.
 
+config WBRF_AMD_ACPI
+	bool "Use the ACPI mechanism introduced by AMD to support WBRF"
+	default n
+	depends on ACPI
+	select WBRF
+	help
+	  AMD has introduced an ACPI based mechanism to support WBRF for some
+	  platforms with AMD dGPU and WLAN. This needs support from BIOS equipped
+	  with necessary AML implementations and dGPU firmwares.
+
+	  Say Y to enable this ACPI based mechanism. It is suggested to confirm
+	  with the hardware designer/provider first whether your platform
+	  equipped with necessary BIOS and firmwares.
+
+config WBRF_GENERIC
+	bool "Use the generic WBRF solution"
+	default n
+	depends on !WBRF_AMD_ACPI
+	select WBRF
+	help
+	  Ideally it is the hardware designer/provider who should provide a
+	  solution for the possible RF interference issue. Since they know
+	  well whether there could be RF interference issue with their
+	  platforms.
+
+	  Say Y to enable this generic WBRF solution for diagnosing potential
+	  interference issues on systems without the ACPI mechanism and
+	  developing solutions.
+
 endmenu
diff --git a/drivers/base/wbrf.c b/drivers/base/wbrf.c
index 2163a8ec8a9a..d9fab9f3045e 100644
--- a/drivers/base/wbrf.c
+++ b/drivers/base/wbrf.c
@@ -6,9 +6,12 @@
  */
 
 #include <linux/wbrf.h>
+#include <linux/acpi_amd_wbrf.h>
 
 static BLOCKING_NOTIFIER_HEAD(wbrf_chain_head);
 static DEFINE_MUTEX(wbrf_mutex);
+
+#if defined(CONFIG_WBRF_GENERIC)
 static struct exclusion_range_pool wbrf_pool;
 
 static int _wbrf_add_exclusion_ranges(struct wbrf_ranges_in *in)
@@ -89,6 +92,7 @@ static int _wbrf_retrieve_exclusion_ranges(struct wbrf_ranges_out *out)
 
 	return 0;
 }
+#endif
 
 /**
  * wbrf_supported_producer - Determine if the device can report frequencies
@@ -100,7 +104,12 @@ static int _wbrf_retrieve_exclusion_ranges(struct wbrf_ranges_out *out)
  */
 bool wbrf_supported_producer(struct device *dev)
 {
+#ifdef CONFIG_WBRF_AMD_ACPI
+	return acpi_amd_wbrf_supported_producer(dev);
+#elif defined(CONFIG_WBRF_GENERIC)
 	return true;
+#endif
+	return false;
 }
 EXPORT_SYMBOL_GPL(wbrf_supported_producer);
 
@@ -116,12 +125,15 @@ EXPORT_SYMBOL_GPL(wbrf_supported_producer);
 int wbrf_add_exclusion(struct device *dev,
 		       struct wbrf_ranges_in *in)
 {
-	int r;
+	int r = -ENODEV;
 
 	mutex_lock(&wbrf_mutex);
 
+#ifdef CONFIG_WBRF_AMD_ACPI
+	r = acpi_amd_wbrf_add_exclusion(dev, in);
+#elif defined(CONFIG_WBRF_GENERIC)
 	r = _wbrf_add_exclusion_ranges(in);
-
+#endif
 	mutex_unlock(&wbrf_mutex);
 	if (r)
 		return r;
@@ -144,12 +156,15 @@ EXPORT_SYMBOL_GPL(wbrf_add_exclusion);
 int wbrf_remove_exclusion(struct device *dev,
 			  struct wbrf_ranges_in *in)
 {
-	int r;
+	int r = -ENODEV;
 
 	mutex_lock(&wbrf_mutex);
 
+#ifdef CONFIG_WBRF_AMD_ACPI
+	r  = acpi_amd_wbrf_remove_exclusion(dev, in);
+#elif defined(CONFIG_WBRF_GENERIC)
 	r = _wbrf_remove_exclusion_ranges(in);
-
+#endif
 	mutex_unlock(&wbrf_mutex);
 	if (r)
 		return r;
@@ -171,7 +186,12 @@ EXPORT_SYMBOL_GPL(wbrf_remove_exclusion);
  */
 bool wbrf_supported_consumer(struct device *dev)
 {
+#ifdef CONFIG_WBRF_AMD_ACPI
+	return acpi_amd_wbrf_supported_consumer(dev);
+#elif defined(CONFIG_WBRF_GENERIC)
 	return true;
+#endif
+	return false;
 }
 EXPORT_SYMBOL_GPL(wbrf_supported_consumer);
 
@@ -214,12 +234,15 @@ EXPORT_SYMBOL_GPL(wbrf_unregister_notifier);
 int wbrf_retrieve_exclusions(struct device *dev,
 			     struct wbrf_ranges_out *out)
 {
-	int r;
+	int r = -ENODEV;
 
 	mutex_lock(&wbrf_mutex);
 
+#ifdef CONFIG_WBRF_AMD_ACPI
+	r = acpi_amd_wbrf_retrieve_exclusions(dev, out);
+#elif defined(CONFIG_WBRF_GENERIC)
 	r = _wbrf_retrieve_exclusion_ranges(out);
-
+#endif
 	mutex_unlock(&wbrf_mutex);
 
 	return r;
diff --git a/include/linux/acpi_amd_wbrf.h b/include/linux/acpi_amd_wbrf.h
new file mode 100644
index 000000000000..c274093972e3
--- /dev/null
+++ b/include/linux/acpi_amd_wbrf.h
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Wifi Band Exclusion Interface (AMD ACPI Implementation)
+ * Copyright (C) 2023 Advanced Micro Devices
+ *
+ */
+
+#ifndef _ACPI_AMD_WBRF_H
+#define _ACPI_AMD_WBRF_H
+
+#include <linux/wbrf.h>
+
+#ifdef CONFIG_WBRF_AMD_ACPI
+bool acpi_amd_wbrf_supported_consumer(struct device *dev);
+bool acpi_amd_wbrf_supported_producer(struct device *dev);
+int acpi_amd_wbrf_remove_exclusion(struct device *dev,
+				   struct wbrf_ranges_in *in);
+int acpi_amd_wbrf_add_exclusion(struct device *dev,
+				struct wbrf_ranges_in *in);
+int acpi_amd_wbrf_retrieve_exclusions(struct device *dev,
+				      struct wbrf_ranges_out *out);
+#else
+static inline bool
+acpi_amd_wbrf_supported_consumer(struct device *dev) { return false; }
+static inline bool
+acpi_amd_wbrf_supported_producer(struct device *dev) {return false; }
+static inline int
+acpi_amd_wbrf_remove_exclusion(struct device *dev,
+			       struct wbrf_ranges_in *in) { return -ENODEV; }
+static inline int
+acpi_amd_wbrf_add_exclusion(struct device *dev,
+			    struct wbrf_ranges_in *in) { return -ENODEV; }
+static inline int
+acpi_amd_wbrf_retrieve_exclusions(struct device *dev,
+				  struct wbrf_ranges_out *out) { return -ENODEV; }
+#endif
+
+#endif /* _ACPI_AMD_WBRF_H */
diff --git a/include/linux/wbrf.h b/include/linux/wbrf.h
index 3ca95786cef5..f71ac2343b29 100644
--- a/include/linux/wbrf.h
+++ b/include/linux/wbrf.h
@@ -18,10 +18,12 @@ struct exclusion_range {
 	uint64_t	end;
 };
 
+#if defined(CONFIG_WBRF_GENERIC)
 struct exclusion_range_pool {
 	struct exclusion_range	band_list[MAX_NUM_OF_WBRF_RANGES];
 	uint64_t		ref_counter[MAX_NUM_OF_WBRF_RANGES];
 };
+#endif
 
 struct wbrf_ranges_in {
 	/* valid entry: `start` and `end` filled with non-zero values */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH V5 3/9] cfg80211: expose nl80211_chan_width_to_mhz for wide sharing
  2023-06-30 10:32 [PATCH V5 0/9] Enable Wifi RFI interference mitigation feature support Evan Quan
  2023-06-30 10:32 ` [PATCH V5 1/9] drivers core: Add support for Wifi band RF mitigations Evan Quan
  2023-06-30 10:32 ` [PATCH V5 2/9] driver core: add ACPI based WBRF mechanism introduced by AMD Evan Quan
@ 2023-06-30 10:32 ` Evan Quan
  2023-06-30 10:32 ` [PATCH V5 4/9] wifi: mac80211: Add support for ACPI WBRF Evan Quan
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 28+ messages in thread
From: Evan Quan @ 2023-06-30 10:32 UTC (permalink / raw)
  To: rafael, lenb, Alexander.Deucher, Christian.Koenig, Xinhui.Pan,
	airlied, daniel, johannes, davem, edumazet, kuba, pabeni,
	Mario.Limonciello, mdaenzer, maarten.lankhorst, tzimmermann,
	hdegoede, jingyuwang_vip, Lijo.Lazar, jim.cromie, bellosilicio,
	andrealmeid, trix, jsg, arnd
  Cc: linux-kernel, linux-acpi, amd-gfx, dri-devel, linux-wireless,
	netdev, Evan Quan

The newly added WBRF feature needs this interface for channel
width calculation.

Signed-off-by: Evan Quan <evan.quan@amd.com>
---
 include/net/cfg80211.h | 8 ++++++++
 net/wireless/chan.c    | 3 ++-
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 9e04f69712b1..c6dc337eafce 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -920,6 +920,14 @@ const struct cfg80211_chan_def *
 cfg80211_chandef_compatible(const struct cfg80211_chan_def *chandef1,
 			    const struct cfg80211_chan_def *chandef2);
 
+/**
+ * nl80211_chan_width_to_mhz - get the channel width in Mhz
+ * @chan_width: the channel width from &enum nl80211_chan_width
+ * Return: channel width in Mhz if the chan_width from &enum nl80211_chan_width
+ * is valid. -1 otherwise.
+ */
+int nl80211_chan_width_to_mhz(enum nl80211_chan_width chan_width);
+
 /**
  * cfg80211_chandef_valid - check if a channel definition is valid
  * @chandef: the channel definition to check
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 0b7e81db383d..227db04eac42 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -141,7 +141,7 @@ static bool cfg80211_edmg_chandef_valid(const struct cfg80211_chan_def *chandef)
 	return true;
 }
 
-static int nl80211_chan_width_to_mhz(enum nl80211_chan_width chan_width)
+int nl80211_chan_width_to_mhz(enum nl80211_chan_width chan_width)
 {
 	int mhz;
 
@@ -190,6 +190,7 @@ static int nl80211_chan_width_to_mhz(enum nl80211_chan_width chan_width)
 	}
 	return mhz;
 }
+EXPORT_SYMBOL(nl80211_chan_width_to_mhz);
 
 static int cfg80211_chandef_get_width(const struct cfg80211_chan_def *c)
 {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH V5 4/9] wifi: mac80211: Add support for ACPI WBRF
  2023-06-30 10:32 [PATCH V5 0/9] Enable Wifi RFI interference mitigation feature support Evan Quan
                   ` (2 preceding siblings ...)
  2023-06-30 10:32 ` [PATCH V5 3/9] cfg80211: expose nl80211_chan_width_to_mhz for wide sharing Evan Quan
@ 2023-06-30 10:32 ` Evan Quan
  2023-06-30 14:08   ` kernel test robot
  2023-07-01  1:02   ` Andrew Lunn
  2023-06-30 10:32 ` [PATCH V5 5/9] drm/amd/pm: update driver_if and ppsmc headers for coming wbrf feature Evan Quan
                   ` (4 subsequent siblings)
  8 siblings, 2 replies; 28+ messages in thread
From: Evan Quan @ 2023-06-30 10:32 UTC (permalink / raw)
  To: rafael, lenb, Alexander.Deucher, Christian.Koenig, Xinhui.Pan,
	airlied, daniel, johannes, davem, edumazet, kuba, pabeni,
	Mario.Limonciello, mdaenzer, maarten.lankhorst, tzimmermann,
	hdegoede, jingyuwang_vip, Lijo.Lazar, jim.cromie, bellosilicio,
	andrealmeid, trix, jsg, arnd
  Cc: linux-kernel, linux-acpi, amd-gfx, dri-devel, linux-wireless,
	netdev, Evan Quan, Mario Limonciello

To support AMD's WBRF interference mitigation mechanism, Wifi adapters
utilized in the system must register the frequencies in use(or unregister
those frequencies no longer used) via the dedicated APCI calls. So that,
other drivers responding to the frequencies can take proper actions to
mitigate possible interference.

Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
Co-developed-by: Evan Quan <evan.quan@amd.com>
Signed-off-by: Evan Quan <evan.quan@amd.com>
--
v1->v2:
  - place the new added member(`wbrf_supported`) in
    ieee80211_local(Johannes)
  - handle chandefs change scenario properly(Johannes)
  - some minor fixes around code sharing and possible invalid input
    checks(Johannes)
v2->v3:
  - drop unnecessary input checks and intermediate APIs(Mario)
  - Separate some mac80211 common code(Mario, Johannes)
v3->v4:
  - some minor fixes around return values(Johannes)
---
 include/linux/ieee80211.h  |   1 +
 net/mac80211/Makefile      |   2 +
 net/mac80211/chan.c        |   9 ++++
 net/mac80211/ieee80211_i.h |  19 +++++++
 net/mac80211/main.c        |   2 +
 net/mac80211/wbrf.c        | 103 +++++++++++++++++++++++++++++++++++++
 6 files changed, 136 insertions(+)
 create mode 100644 net/mac80211/wbrf.c

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index c4cf296e7eaf..0703921547f5 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -4319,6 +4319,7 @@ static inline int ieee80211_get_tdls_action(struct sk_buff *skb, u32 hdr_size)
 /* convert frequencies */
 #define MHZ_TO_KHZ(freq) ((freq) * 1000)
 #define KHZ_TO_MHZ(freq) ((freq) / 1000)
+#define KHZ_TO_HZ(freq)  ((freq) * 1000)
 #define PR_KHZ(f) KHZ_TO_MHZ(f), f % 1000
 #define KHZ_F "%d.%03d"
 
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
index b8de44da1fb8..8f8ac567e7c8 100644
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -65,4 +65,6 @@ rc80211_minstrel-$(CONFIG_MAC80211_DEBUGFS) += \
 
 mac80211-$(CONFIG_MAC80211_RC_MINSTREL) += $(rc80211_minstrel-y)
 
+mac80211-$(CONFIG_WBRF) += wbrf.o
+
 ccflags-y += -DDEBUG
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index 77c90ed8f5d7..9887471028dc 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -506,11 +506,16 @@ static void _ieee80211_change_chanctx(struct ieee80211_local *local,
 
 	WARN_ON(!cfg80211_chandef_compatible(&ctx->conf.def, chandef));
 
+	ieee80211_remove_wbrf(local, &ctx->conf.def);
+
 	ctx->conf.def = *chandef;
 
 	/* check if min chanctx also changed */
 	changed = IEEE80211_CHANCTX_CHANGE_WIDTH |
 		  _ieee80211_recalc_chanctx_min_def(local, ctx, rsvd_for);
+
+	ieee80211_add_wbrf(local, &ctx->conf.def);
+
 	drv_change_chanctx(local, ctx, changed);
 
 	if (!local->use_chanctx) {
@@ -668,6 +673,8 @@ static int ieee80211_add_chanctx(struct ieee80211_local *local,
 	lockdep_assert_held(&local->mtx);
 	lockdep_assert_held(&local->chanctx_mtx);
 
+	ieee80211_add_wbrf(local, &ctx->conf.def);
+
 	if (!local->use_chanctx)
 		local->hw.conf.radar_enabled = ctx->conf.radar_enabled;
 
@@ -748,6 +755,8 @@ static void ieee80211_del_chanctx(struct ieee80211_local *local,
 	}
 
 	ieee80211_recalc_idle(local);
+
+	ieee80211_remove_wbrf(local, &ctx->conf.def);
 }
 
 static void ieee80211_free_chanctx(struct ieee80211_local *local,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 4159fb65038b..ffe00c55304e 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1591,6 +1591,10 @@ struct ieee80211_local {
 
 	/* extended capabilities provided by mac80211 */
 	u8 ext_capa[8];
+
+#ifdef CONFIG_WBRF
+	bool wbrf_supported;
+#endif
 };
 
 static inline struct ieee80211_sub_if_data *
@@ -2615,4 +2619,19 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(struct ieee80211_sub_if_data *sdata,
 				    const struct ieee80211_eht_cap_elem *eht_cap_ie_elem,
 				    u8 eht_cap_len,
 				    struct link_sta_info *link_sta);
+
+#ifdef CONFIG_WBRF
+void ieee80211_check_wbrf_support(struct ieee80211_local *local);
+void ieee80211_add_wbrf(struct ieee80211_local *local,
+			struct cfg80211_chan_def *chandef);
+void ieee80211_remove_wbrf(struct ieee80211_local *local,
+			   struct cfg80211_chan_def *chandef);
+#else
+static inline void ieee80211_check_wbrf_support(struct ieee80211_local *local) { }
+static inline void ieee80211_add_wbrf(struct ieee80211_local *local,
+				      struct cfg80211_chan_def *chandef) { return 0; }
+static inline void ieee80211_remove_wbrf(struct ieee80211_local *local,
+					 struct cfg80211_chan_def *chandef) { }
+#endif /* CONFIG_WBRF */
+
 #endif /* IEEE80211_I_H */
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 55cdfaef0f5d..0a55626b1546 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -1395,6 +1395,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 	debugfs_hw_add(local);
 	rate_control_add_debugfs(local);
 
+	ieee80211_check_wbrf_support(local);
+
 	rtnl_lock();
 	wiphy_lock(hw->wiphy);
 
diff --git a/net/mac80211/wbrf.c b/net/mac80211/wbrf.c
new file mode 100644
index 000000000000..7ddb29d128b1
--- /dev/null
+++ b/net/mac80211/wbrf.c
@@ -0,0 +1,103 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Wifi Band Exclusion Interface for WWAN
+ * Copyright (C) 2023 Advanced Micro Devices
+ *
+ */
+
+#include <linux/wbrf.h>
+#include <net/cfg80211.h>
+#include "ieee80211_i.h"
+
+void ieee80211_check_wbrf_support(struct ieee80211_local *local)
+{
+	struct wiphy *wiphy = local->hw.wiphy;
+	struct device *dev;
+
+	if (!wiphy)
+		return;
+
+	dev = wiphy->dev.parent;
+	if (!dev)
+		return;
+
+	local->wbrf_supported = wbrf_supported_producer(dev);
+	dev_dbg(dev, "WBRF is %s supported\n",
+		local->wbrf_supported ? "" : "not");
+}
+
+static void get_chan_freq_boundary(u32 center_freq,
+				   u32 bandwidth,
+				   u64 *start,
+				   u64 *end)
+{
+	bandwidth = MHZ_TO_KHZ(bandwidth);
+	center_freq = MHZ_TO_KHZ(center_freq);
+
+	*start = center_freq - bandwidth / 2;
+	*end = center_freq + bandwidth / 2;
+
+	/* Frequency in HZ is expected */
+	*start = KHZ_TO_HZ(*start);
+	*end = KHZ_TO_HZ(*end);
+}
+
+static void wbrf_get_ranges_from_chandef(struct cfg80211_chan_def *chandef,
+					 struct wbrf_ranges_in *ranges_in)
+{
+	u64 start_freq1, end_freq1;
+	u64 start_freq2, end_freq2;
+	int bandwidth;
+
+	bandwidth = nl80211_chan_width_to_mhz(chandef->width);
+
+	get_chan_freq_boundary(chandef->center_freq1,
+			       bandwidth,
+			       &start_freq1,
+			       &end_freq1);
+
+	ranges_in->band_list[0].start = start_freq1;
+	ranges_in->band_list[0].end = end_freq1;
+
+	if (chandef->width == NL80211_CHAN_WIDTH_80P80) {
+		get_chan_freq_boundary(chandef->center_freq2,
+				       bandwidth,
+				       &start_freq2,
+				       &end_freq2);
+
+		ranges_in->band_list[1].start = start_freq2;
+		ranges_in->band_list[1].end = end_freq2;
+	}
+}
+
+void ieee80211_add_wbrf(struct ieee80211_local *local,
+			struct cfg80211_chan_def *chandef)
+{
+	struct wbrf_ranges_in ranges_in = {0};
+	struct device *dev;
+
+	if (!local->wbrf_supported)
+		return;
+
+	dev = local->hw.wiphy->dev.parent;
+
+	wbrf_get_ranges_from_chandef(chandef, &ranges_in);
+
+	wbrf_add_exclusion(dev, &ranges_in);
+}
+
+void ieee80211_remove_wbrf(struct ieee80211_local *local,
+			   struct cfg80211_chan_def *chandef)
+{
+	struct wbrf_ranges_in ranges_in = {0};
+	struct device *dev;
+
+	if (!local->wbrf_supported)
+		return;
+
+	dev = local->hw.wiphy->dev.parent;
+
+	wbrf_get_ranges_from_chandef(chandef, &ranges_in);
+
+	wbrf_remove_exclusion(dev, &ranges_in);
+}
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH V5 5/9] drm/amd/pm: update driver_if and ppsmc headers for coming wbrf feature
  2023-06-30 10:32 [PATCH V5 0/9] Enable Wifi RFI interference mitigation feature support Evan Quan
                   ` (3 preceding siblings ...)
  2023-06-30 10:32 ` [PATCH V5 4/9] wifi: mac80211: Add support for ACPI WBRF Evan Quan
@ 2023-06-30 10:32 ` Evan Quan
  2023-06-30 10:32 ` [PATCH V5 6/9] drm/amd/pm: setup the framework to support Wifi RFI mitigation feature Evan Quan
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 28+ messages in thread
From: Evan Quan @ 2023-06-30 10:32 UTC (permalink / raw)
  To: rafael, lenb, Alexander.Deucher, Christian.Koenig, Xinhui.Pan,
	airlied, daniel, johannes, davem, edumazet, kuba, pabeni,
	Mario.Limonciello, mdaenzer, maarten.lankhorst, tzimmermann,
	hdegoede, jingyuwang_vip, Lijo.Lazar, jim.cromie, bellosilicio,
	andrealmeid, trix, jsg, arnd
  Cc: linux-kernel, linux-acpi, amd-gfx, dri-devel, linux-wireless,
	netdev, Evan Quan, Mario Limonciello

Add those data structures to support Wifi RFI mitigation feature.

Signed-off-by: Evan Quan <evan.quan@amd.com>
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
---
 .../pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_0.h | 14 +++++++++++++-
 .../pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_7.h | 14 +++++++++++++-
 .../amd/pm/swsmu/inc/pmfw_if/smu_v13_0_0_ppsmc.h   |  3 ++-
 .../amd/pm/swsmu/inc/pmfw_if/smu_v13_0_7_ppsmc.h   |  3 ++-
 4 files changed, 30 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_0.h
index b686fb68a6e7..d64188fb5839 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_0.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_0.h
@@ -388,6 +388,17 @@ typedef struct {
   EccInfo_t  EccInfo[24];
 } EccInfoTable_t;
 
+typedef struct {
+  uint16_t     LowFreq;
+  uint16_t     HighFreq;
+} WifiOneBand_t;
+
+typedef struct {
+  uint32_t         WifiBandEntryNum;
+  WifiOneBand_t    WifiBandEntry[11];
+  uint32_t         MmHubPadding[8];
+} WifiBandEntryTable_t;
+
 //D3HOT sequences
 typedef enum {
   BACO_SEQUENCE,
@@ -1592,7 +1603,8 @@ typedef struct {
 #define TABLE_I2C_COMMANDS            9
 #define TABLE_DRIVER_INFO             10
 #define TABLE_ECCINFO                 11
-#define TABLE_COUNT                   12
+#define TABLE_WIFIBAND                12
+#define TABLE_COUNT                   13
 
 //IH Interupt ID
 #define IH_INTERRUPT_ID_TO_DRIVER                   0xFE
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_7.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_7.h
index 4c46a0392451..77483e8485e7 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_7.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_7.h
@@ -392,6 +392,17 @@ typedef struct {
   EccInfo_t  EccInfo[24];
 } EccInfoTable_t;
 
+typedef struct {
+  uint16_t     LowFreq;
+  uint16_t     HighFreq;
+} WifiOneBand_t;
+
+typedef struct {
+  uint32_t         WifiBandEntryNum;
+  WifiOneBand_t    WifiBandEntry[11];
+  uint32_t         MmHubPadding[8];
+} WifiBandEntryTable_t;
+
 //D3HOT sequences
 typedef enum {
   BACO_SEQUENCE,
@@ -1624,7 +1635,8 @@ typedef struct {
 #define TABLE_I2C_COMMANDS            9
 #define TABLE_DRIVER_INFO             10
 #define TABLE_ECCINFO                 11
-#define TABLE_COUNT                   12
+#define TABLE_WIFIBAND                12
+#define TABLE_COUNT                   13
 
 //IH Interupt ID
 #define IH_INTERRUPT_ID_TO_DRIVER                   0xFE
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_0_ppsmc.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_0_ppsmc.h
index 10cff75b44d5..c98cc32d11bd 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_0_ppsmc.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_0_ppsmc.h
@@ -138,7 +138,8 @@
 #define PPSMC_MSG_SetBadMemoryPagesRetiredFlagsPerChannel 0x4A
 #define PPSMC_MSG_SetPriorityDeltaGain           0x4B
 #define PPSMC_MSG_AllowIHHostInterrupt           0x4C
-#define PPSMC_Message_Count                      0x4D
+#define PPSMC_MSG_EnableUCLKShadow               0x51
+#define PPSMC_Message_Count                      0x52
 
 //Debug Dump Message
 #define DEBUGSMC_MSG_TestMessage                    0x1
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_7_ppsmc.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_7_ppsmc.h
index 6aaefca9b595..a6bf9cdd130e 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_7_ppsmc.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_7_ppsmc.h
@@ -134,6 +134,7 @@
 #define PPSMC_MSG_SetBadMemoryPagesRetiredFlagsPerChannel 0x4A
 #define PPSMC_MSG_SetPriorityDeltaGain           0x4B
 #define PPSMC_MSG_AllowIHHostInterrupt           0x4C
-#define PPSMC_Message_Count                      0x4D
+#define PPSMC_MSG_EnableUCLKShadow               0x51
+#define PPSMC_Message_Count                      0x52
 
 #endif
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH V5 6/9] drm/amd/pm: setup the framework to support Wifi RFI mitigation feature
  2023-06-30 10:32 [PATCH V5 0/9] Enable Wifi RFI interference mitigation feature support Evan Quan
                   ` (4 preceding siblings ...)
  2023-06-30 10:32 ` [PATCH V5 5/9] drm/amd/pm: update driver_if and ppsmc headers for coming wbrf feature Evan Quan
@ 2023-06-30 10:32 ` Evan Quan
  2023-06-30 10:32 ` [PATCH V5 7/9] drm/amd/pm: add flood detection for wbrf events Evan Quan
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 28+ messages in thread
From: Evan Quan @ 2023-06-30 10:32 UTC (permalink / raw)
  To: rafael, lenb, Alexander.Deucher, Christian.Koenig, Xinhui.Pan,
	airlied, daniel, johannes, davem, edumazet, kuba, pabeni,
	Mario.Limonciello, mdaenzer, maarten.lankhorst, tzimmermann,
	hdegoede, jingyuwang_vip, Lijo.Lazar, jim.cromie, bellosilicio,
	andrealmeid, trix, jsg, arnd
  Cc: linux-kernel, linux-acpi, amd-gfx, dri-devel, linux-wireless,
	netdev, Evan Quan, Mario Limonciello

With WBRF feature supported, as a driver responding to the frequencies,
amdgpu driver is able to do shadow pstate switching to mitigate possible
interference(between its (G-)DDR memory clocks and local radio module
frequency bands used by Wifi 6/6e/7).

Signed-off-by: Evan Quan <evan.quan@amd.com>
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
--
v1->v2:
  - update the prompt for feature support(Lijo)
---
 drivers/gpu/drm/amd/amdgpu/amdgpu.h           |   1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c       |  19 ++
 drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c     | 194 ++++++++++++++++++
 drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h |  23 +++
 drivers/gpu/drm/amd/pm/swsmu/smu_internal.h   |   3 +
 5 files changed, 240 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 02b827785e39..785d9b43f0c4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -241,6 +241,7 @@ extern int amdgpu_num_kcq;
 #define AMDGPU_VCNFW_LOG_SIZE (32 * 1024)
 extern int amdgpu_vcnfw_log;
 extern int amdgpu_sg_display;
+extern int amdgpu_wbrf;
 
 #define AMDGPU_VM_MAX_NUM_CTX			4096
 #define AMDGPU_SG_THRESHOLD			(256*1024*1024)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 393b6fb7a71d..6c08a0cf8381 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -191,6 +191,7 @@ int amdgpu_smartshift_bias;
 int amdgpu_use_xgmi_p2p = 1;
 int amdgpu_vcnfw_log;
 int amdgpu_sg_display = -1; /* auto */
+int amdgpu_wbrf = -1;
 
 static void amdgpu_drv_delayed_reset_work_handler(struct work_struct *work);
 
@@ -948,6 +949,24 @@ MODULE_PARM_DESC(smu_pptable_id,
 	"specify pptable id to be used (-1 = auto(default) value, 0 = use pptable from vbios, > 0 = soft pptable id)");
 module_param_named(smu_pptable_id, amdgpu_smu_pptable_id, int, 0444);
 
+#ifdef CONFIG_WBRF
+/**
+ * DOC: wbrf (int)
+ * Enable Wifi RFI interference mitigation feature.
+ * Due to electrical and mechanical constraints there may be likely interference of
+ * relatively high-powered harmonics of the (G-)DDR memory clocks with local radio
+ * module frequency bands used by Wifi 6/6e/7. To mitigate the possible RFI interference,
+ * with this feature enabled, PMFW will use either “shadowed P-State” or “P-State” based
+ * on active list of frequencies in-use (to be avoided) as part of initial setting or
+ * P-state transition. However, there may be potential performance impact with this
+ * feature enabled.
+ * (0 = disabled, 1 = enabled, -1 = auto (default setting, will be enabled if supported))
+ */
+MODULE_PARM_DESC(wbrf,
+	"Enable Wifi RFI interference mitigation (0 = disabled, 1 = enabled, -1 = auto(default)");
+module_param_named(wbrf, amdgpu_wbrf, int, 0444);
+#endif
+
 /* These devices are not supported by amdgpu.
  * They are supported by the mach64, r128, radeon drivers
  */
diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
index 2ddf5198e5c4..83d428e890df 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
@@ -1188,6 +1188,173 @@ static int smu_get_thermal_temperature_range(struct smu_context *smu)
 	return ret;
 }
 
+/**
+ * smu_wbrf_handle_exclusion_ranges - consume the wbrf exclusion ranges
+ *
+ * @smu: smu_context pointer
+ *
+ * Retrieve the wbrf exclusion ranges and send them to PMFW for proper handling.
+ * Returns 0 on success, error on failure.
+ */
+static int smu_wbrf_handle_exclusion_ranges(struct smu_context *smu)
+{
+	struct wbrf_ranges_out wbrf_exclusion = {0};
+	struct exclusion_range *wifi_bands = wbrf_exclusion.band_list;
+	struct amdgpu_device *adev = smu->adev;
+	uint64_t start, end;
+	int ret, i, j;
+
+	ret = wbrf_retrieve_exclusions(adev->dev, &wbrf_exclusion);
+	if (ret) {
+		dev_err(adev->dev, "Failed to retrieve exclusion ranges!\n");
+		return ret;
+	}
+
+	/*
+	 * The exclusion ranges array we got might be filled with holes and duplicate
+	 * entries. For example:
+	 * {(2400, 2500), (0, 0), (6882, 6962), (2400, 2500), (0, 0), (6117, 6189), (0, 0)...}
+	 * We need to do some sortups to eliminate those holes and duplicate entries.
+	 * Expected output: {(2400, 2500), (6117, 6189), (6882, 6962), (0, 0)...}
+	 */
+	for (i = 0; i < MAX_NUM_OF_WBRF_RANGES; i++) {
+		start = wifi_bands[i].start;
+		end = wifi_bands[i].end;
+
+		/* get the last valid entry to fill the intermediate hole */
+		if (!start && !end) {
+			for (j = MAX_NUM_OF_WBRF_RANGES - 1; j > i; j--)
+				if (wifi_bands[j].start &&
+				    wifi_bands[j].end)
+					break;
+
+			if (j > i) {
+				wifi_bands[i].start = wifi_bands[j].start;
+				wifi_bands[i].end = wifi_bands[j].end;
+				wifi_bands[j].start = 0;
+				wifi_bands[j].end = 0;
+			}
+
+			continue;
+		}
+
+		/* eliminate duplicate entries */
+		for (j = i + 1; j < MAX_NUM_OF_WBRF_RANGES; j++) {
+			if ((wifi_bands[j].start == start) &&
+			     (wifi_bands[j].end == end)) {
+				wifi_bands[j].start = 0;
+				wifi_bands[j].end = 0;
+				continue;
+			}
+		}
+	}
+
+	/* Send the sorted wifi_bands to PMFW */
+	ret = smu_set_wbrf_exclusion_ranges(smu, wifi_bands);
+	/* Give it another chance */
+	if (unlikely(ret == -EBUSY)) {
+		mdelay(5);
+		ret = smu_set_wbrf_exclusion_ranges(smu, wifi_bands);
+	}
+
+	return ret;
+}
+
+/**
+ * smu_wbrf_event_handler - handle notify events
+ *
+ * @nb: notifier block
+ * @action: event type
+ * @data: event data
+ *
+ * Calls relevant amdgpu function in response to wbrf event
+ * notification from kernel.
+ */
+static int smu_wbrf_event_handler(struct notifier_block *nb,
+				  unsigned long action, void *_arg)
+{
+	struct smu_context *smu = container_of(nb, struct smu_context,
+					       wbrf_notifier);
+
+	switch (action) {
+	case WBRF_CHANGED:
+		smu_wbrf_handle_exclusion_ranges(smu);
+		break;
+	default:
+		return NOTIFY_DONE;
+	};
+
+	return NOTIFY_OK;
+}
+
+/**
+ * smu_wbrf_support_check - check wbrf support
+ *
+ * @smu: smu_context pointer
+ *
+ * Verifies the ACPI interface whether wbrf is supported.
+ */
+static void smu_wbrf_support_check(struct smu_context *smu)
+{
+	struct amdgpu_device *adev = smu->adev;
+
+	smu->wbrf_supported = smu_is_asic_wbrf_supported(smu) &&
+			      !!amdgpu_wbrf &&
+			      wbrf_supported_consumer(adev->dev);
+
+	if (smu->wbrf_supported)
+		dev_info(adev->dev, "RF interference mitigation is supported\n");
+}
+
+/**
+ * smu_wbrf_init - init driver wbrf support
+ *
+ * @smu: smu_context pointer
+ *
+ * Verifies the AMD ACPI interfaces and registers with the wbrf
+ * notifier chain if wbrf feature is supported.
+ * Returns 0 on success, error on failure.
+ */
+static int smu_wbrf_init(struct smu_context *smu)
+{
+	struct amdgpu_device *adev = smu->adev;
+	int ret;
+
+	if (!smu->wbrf_supported)
+		return 0;
+
+	smu->wbrf_notifier.notifier_call = smu_wbrf_event_handler;
+	ret = wbrf_register_notifier(&smu->wbrf_notifier);
+	if (ret)
+		return ret;
+
+	/*
+	 * Some wifiband exclusion ranges may be already there
+	 * before our driver loaded. To make sure our driver
+	 * is awared of those exclusion ranges.
+	 */
+	ret = smu_wbrf_handle_exclusion_ranges(smu);
+	if (ret)
+		dev_err(adev->dev, "Failed to handle wbrf exclusion ranges\n");
+
+	return ret;
+}
+
+/**
+ * smu_wbrf_fini - tear down driver wbrf support
+ *
+ * @smu: smu_context pointer
+ *
+ * Unregisters with the wbrf notifier chain.
+ */
+static void smu_wbrf_fini(struct smu_context *smu)
+{
+	if (!smu->wbrf_supported)
+		return;
+
+	wbrf_unregister_notifier(&smu->wbrf_notifier);
+}
+
 static int smu_smc_hw_setup(struct smu_context *smu)
 {
 	struct smu_feature *feature = &smu->smu_feature;
@@ -1280,6 +1447,15 @@ static int smu_smc_hw_setup(struct smu_context *smu)
 	if (ret)
 		return ret;
 
+	/* Enable UclkShadow on wbrf supported */
+	if (smu->wbrf_supported) {
+		ret = smu_enable_uclk_shadow(smu, true);
+		if (ret) {
+			dev_err(adev->dev, "Failed to enable UclkShadow feature to support wbrf!\n");
+			return ret;
+		}
+	}
+
 	/*
 	 * With SCPM enabled, these actions(and relevant messages) are
 	 * not needed and permitted.
@@ -1376,6 +1552,15 @@ static int smu_smc_hw_setup(struct smu_context *smu)
 	 */
 	ret = smu_set_min_dcef_deep_sleep(smu,
 					  smu->smu_table.boot_values.dcefclk / 100);
+	if (ret) {
+		dev_err(adev->dev, "Error setting min deepsleep dcefclk\n");
+		return ret;
+	}
+
+	/* Init wbrf support. Properly setup the notifier */
+	ret = smu_wbrf_init(smu);
+	if (ret)
+		dev_err(adev->dev, "Error during wbrf init call\n");
 
 	return ret;
 }
@@ -1431,6 +1616,13 @@ static int smu_hw_init(void *handle)
 		return ret;
 	}
 
+	/*
+	 * Check whether wbrf is supported. This needs to be done
+	 * before SMU setup starts since part of SMU configuration
+	 * relies on this.
+	 */
+	smu_wbrf_support_check(smu);
+
 	if (smu->is_apu) {
 		ret = smu_set_gfx_imu_enable(smu);
 		if (ret)
@@ -1583,6 +1775,8 @@ static int smu_smc_hw_cleanup(struct smu_context *smu)
 	struct amdgpu_device *adev = smu->adev;
 	int ret = 0;
 
+	smu_wbrf_fini(smu);
+
 	cancel_work_sync(&smu->throttling_logging_work);
 	cancel_work_sync(&smu->interrupt_work);
 
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
index 09469c750a96..5b2343cfc69b 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
@@ -22,6 +22,8 @@
 #ifndef __AMDGPU_SMU_H__
 #define __AMDGPU_SMU_H__
 
+#include <linux/wbrf.h>
+
 #include "amdgpu.h"
 #include "kgd_pp_interface.h"
 #include "dm_pp_interface.h"
@@ -573,6 +575,10 @@ struct smu_context
 	u32 debug_param_reg;
 	u32 debug_msg_reg;
 	u32 debug_resp_reg;
+
+	/* data structures for wbrf feature support */
+	bool				wbrf_supported;
+	struct notifier_block		wbrf_notifier;
 };
 
 struct i2c_adapter;
@@ -1354,6 +1360,23 @@ struct pptable_funcs {
 	 * @init_pptable_microcode: Prepare the pptable microcode to upload via PSP
 	 */
 	int (*init_pptable_microcode)(struct smu_context *smu);
+
+	/**
+	 * @is_asic_wbrf_supported: check whether PMFW supports the wbrf feature
+	 */
+	bool (*is_asic_wbrf_supported)(struct smu_context *smu);
+
+	/**
+	 * @enable_uclk_shadow: Enable the uclk shadow feature on wbrf supported
+	 */
+	int (*enable_uclk_shadow)(struct smu_context *smu,
+				  bool enablement);
+
+	/**
+	 * @set_wbrf_exclusion_ranges: notify SMU the wifi bands occupied
+	 */
+	int (*set_wbrf_exclusion_ranges)(struct smu_context *smu,
+					 struct exclusion_range *exclusion_ranges);
 };
 
 typedef enum {
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h
index ceb13c838067..67d7495ab49e 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h
@@ -97,6 +97,9 @@
 #define smu_get_default_config_table_settings(smu, config_table)	smu_ppt_funcs(get_default_config_table_settings, -EOPNOTSUPP, smu, config_table)
 #define smu_set_config_table(smu, config_table)				smu_ppt_funcs(set_config_table, -EOPNOTSUPP, smu, config_table)
 #define smu_init_pptable_microcode(smu)					smu_ppt_funcs(init_pptable_microcode, 0, smu)
+#define smu_is_asic_wbrf_supported(smu)					smu_ppt_funcs(is_asic_wbrf_supported, false, smu)
+#define smu_enable_uclk_shadow(smu, enablement)				smu_ppt_funcs(enable_uclk_shadow, 0, smu, enablement)
+#define smu_set_wbrf_exclusion_ranges(smu, exclusion_ranges)		smu_ppt_funcs(set_wbrf_exclusion_ranges, -EOPNOTSUPP, smu, exclusion_ranges)
 
 #endif
 #endif
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH V5 7/9] drm/amd/pm: add flood detection for wbrf events
  2023-06-30 10:32 [PATCH V5 0/9] Enable Wifi RFI interference mitigation feature support Evan Quan
                   ` (5 preceding siblings ...)
  2023-06-30 10:32 ` [PATCH V5 6/9] drm/amd/pm: setup the framework to support Wifi RFI mitigation feature Evan Quan
@ 2023-06-30 10:32 ` Evan Quan
  2023-06-30 14:29   ` kernel test robot
  2023-06-30 10:32 ` [PATCH V5 8/9] drm/amd/pm: enable Wifi RFI mitigation feature support for SMU13.0.0 Evan Quan
  2023-06-30 10:32 ` [PATCH V5 9/9] drm/amd/pm: enable Wifi RFI mitigation feature support for SMU13.0.7 Evan Quan
  8 siblings, 1 reply; 28+ messages in thread
From: Evan Quan @ 2023-06-30 10:32 UTC (permalink / raw)
  To: rafael, lenb, Alexander.Deucher, Christian.Koenig, Xinhui.Pan,
	airlied, daniel, johannes, davem, edumazet, kuba, pabeni,
	Mario.Limonciello, mdaenzer, maarten.lankhorst, tzimmermann,
	hdegoede, jingyuwang_vip, Lijo.Lazar, jim.cromie, bellosilicio,
	andrealmeid, trix, jsg, arnd
  Cc: linux-kernel, linux-acpi, amd-gfx, dri-devel, linux-wireless,
	netdev, Evan Quan, Mario Limonciello

To protect PMFW from being overloaded.

Signed-off-by: Evan Quan <evan.quan@amd.com>
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
---
 drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c     | 30 +++++++++++++++----
 drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h |  7 +++++
 2 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
index 83d428e890df..a4cfaf8a6f59 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
@@ -1278,7 +1278,8 @@ static int smu_wbrf_event_handler(struct notifier_block *nb,
 
 	switch (action) {
 	case WBRF_CHANGED:
-		smu_wbrf_handle_exclusion_ranges(smu);
+		schedule_delayed_work(&smu->wbrf_delayed_work,
+				      msecs_to_jiffies(SMU_WBRF_EVENT_HANDLING_PACE));
 		break;
 	default:
 		return NOTIFY_DONE;
@@ -1287,6 +1288,21 @@ static int smu_wbrf_event_handler(struct notifier_block *nb,
 	return NOTIFY_OK;
 }
 
+/**
+ * smu_wbrf_delayed_work_handler - callback on delayed work timer expired
+ *
+ * @work: struct work_struct pointer
+ *
+ * Flood is over and driver will consume the latest exclusion ranges.
+ */
+static void smu_wbrf_delayed_work_handler(struct work_struct *work)
+{
+	struct smu_context *smu =
+		container_of(work, struct smu_context, wbrf_delayed_work.work);
+
+	smu_wbrf_handle_exclusion_ranges(smu);
+}
+
 /**
  * smu_wbrf_support_check - check wbrf support
  *
@@ -1323,6 +1339,9 @@ static int smu_wbrf_init(struct smu_context *smu)
 	if (!smu->wbrf_supported)
 		return 0;
 
+	INIT_DELAYED_WORK(&smu->wbrf_delayed_work,
+			  smu_wbrf_delayed_work_handler);
+
 	smu->wbrf_notifier.notifier_call = smu_wbrf_event_handler;
 	ret = wbrf_register_notifier(&smu->wbrf_notifier);
 	if (ret)
@@ -1333,11 +1352,10 @@ static int smu_wbrf_init(struct smu_context *smu)
 	 * before our driver loaded. To make sure our driver
 	 * is awared of those exclusion ranges.
 	 */
-	ret = smu_wbrf_handle_exclusion_ranges(smu);
-	if (ret)
-		dev_err(adev->dev, "Failed to handle wbrf exclusion ranges\n");
+	schedule_delayed_work(&smu->wbrf_delayed_work,
+			      msecs_to_jiffies(SMU_WBRF_EVENT_HANDLING_PACE));
 
-	return ret;
+	return 0;
 }
 
 /**
@@ -1353,6 +1371,8 @@ static void smu_wbrf_fini(struct smu_context *smu)
 		return;
 
 	wbrf_unregister_notifier(&smu->wbrf_notifier);
+
+	cancel_delayed_work_sync(&smu->wbrf_delayed_work);
 }
 
 static int smu_smc_hw_setup(struct smu_context *smu)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
index 5b2343cfc69b..5df28d4a8c30 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
@@ -480,6 +480,12 @@ struct stb_context {
 
 #define WORKLOAD_POLICY_MAX 7
 
+/*
+ * Configure wbrf event handling pace as there can be only one
+ * event processed every SMU_WBRF_EVENT_HANDLING_PACE ms.
+ */
+#define SMU_WBRF_EVENT_HANDLING_PACE	10
+
 struct smu_context
 {
 	struct amdgpu_device            *adev;
@@ -579,6 +585,7 @@ struct smu_context
 	/* data structures for wbrf feature support */
 	bool				wbrf_supported;
 	struct notifier_block		wbrf_notifier;
+	struct delayed_work		wbrf_delayed_work;
 };
 
 struct i2c_adapter;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH V5 8/9] drm/amd/pm: enable Wifi RFI mitigation feature support for SMU13.0.0
  2023-06-30 10:32 [PATCH V5 0/9] Enable Wifi RFI interference mitigation feature support Evan Quan
                   ` (6 preceding siblings ...)
  2023-06-30 10:32 ` [PATCH V5 7/9] drm/amd/pm: add flood detection for wbrf events Evan Quan
@ 2023-06-30 10:32 ` Evan Quan
  2023-06-30 10:32 ` [PATCH V5 9/9] drm/amd/pm: enable Wifi RFI mitigation feature support for SMU13.0.7 Evan Quan
  8 siblings, 0 replies; 28+ messages in thread
From: Evan Quan @ 2023-06-30 10:32 UTC (permalink / raw)
  To: rafael, lenb, Alexander.Deucher, Christian.Koenig, Xinhui.Pan,
	airlied, daniel, johannes, davem, edumazet, kuba, pabeni,
	Mario.Limonciello, mdaenzer, maarten.lankhorst, tzimmermann,
	hdegoede, jingyuwang_vip, Lijo.Lazar, jim.cromie, bellosilicio,
	andrealmeid, trix, jsg, arnd
  Cc: linux-kernel, linux-acpi, amd-gfx, dri-devel, linux-wireless,
	netdev, Evan Quan, Mario Limonciello

Fulfill the SMU13.0.0 support for Wifi RFI mitigation feature.

Signed-off-by: Evan Quan <evan.quan@amd.com>
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
---
 drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h |  3 +
 drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h  |  3 +-
 drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h  |  3 +
 .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c    |  9 +++
 .../drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c  | 60 +++++++++++++++++++
 5 files changed, 77 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
index 5df28d4a8c30..32764c509ba8 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
@@ -325,6 +325,7 @@ enum smu_table_id
 	SMU_TABLE_PACE,
 	SMU_TABLE_ECCINFO,
 	SMU_TABLE_COMBO_PPTABLE,
+	SMU_TABLE_WIFIBAND,
 	SMU_TABLE_COUNT,
 };
 
@@ -1499,6 +1500,8 @@ enum smu_baco_seq {
 			 __dst_size);					   \
 })
 
+#define HZ_IN_MHZ		1000000U
+
 #if !defined(SWSMU_CODE_LAYER_L2) && !defined(SWSMU_CODE_LAYER_L3) && !defined(SWSMU_CODE_LAYER_L4)
 int smu_get_power_limit(void *handle,
 			uint32_t *limit,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
index 297b70b9388f..5bbb60289a79 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
@@ -245,7 +245,8 @@
 	__SMU_DUMMY_MAP(AllowGpo),	\
 	__SMU_DUMMY_MAP(Mode2Reset),	\
 	__SMU_DUMMY_MAP(RequestI2cTransaction), \
-	__SMU_DUMMY_MAP(GetMetricsTable),
+	__SMU_DUMMY_MAP(GetMetricsTable), \
+	__SMU_DUMMY_MAP(EnableUCLKShadow),
 
 #undef __SMU_DUMMY_MAP
 #define __SMU_DUMMY_MAP(type)	SMU_MSG_##type
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h
index df3baaab0037..b6fae9b92303 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h
@@ -303,5 +303,8 @@ int smu_v13_0_get_pptable_from_firmware(struct smu_context *smu,
 					uint32_t *size,
 					uint32_t pptable_id);
 
+int smu_v13_0_enable_uclk_shadow(struct smu_context *smu,
+				 bool enablement);
+
 #endif
 #endif
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
index ca379181081c..7cb24c862720 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
@@ -2453,3 +2453,12 @@ int smu_v13_0_mode1_reset(struct smu_context *smu)
 
 	return ret;
 }
+
+int smu_v13_0_enable_uclk_shadow(struct smu_context *smu,
+				 bool enablement)
+{
+	return smu_cmn_send_smc_msg_with_param(smu,
+					       SMU_MSG_EnableUCLKShadow,
+					       enablement,
+					       NULL);
+}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
index 08577d1b84ec..3e864bd2c5a4 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
@@ -155,6 +155,7 @@ static struct cmn2asic_msg_mapping smu_v13_0_0_message_map[SMU_MSG_MAX_COUNT] =
 	MSG_MAP(AllowGpo,			PPSMC_MSG_SetGpoAllow,           0),
 	MSG_MAP(AllowIHHostInterrupt,		PPSMC_MSG_AllowIHHostInterrupt,       0),
 	MSG_MAP(ReenableAcDcInterrupt,		PPSMC_MSG_ReenableAcDcInterrupt,       0),
+	MSG_MAP(EnableUCLKShadow,		PPSMC_MSG_EnableUCLKShadow,            0),
 };
 
 static struct cmn2asic_mapping smu_v13_0_0_clk_map[SMU_CLK_COUNT] = {
@@ -235,6 +236,7 @@ static struct cmn2asic_mapping smu_v13_0_0_table_map[SMU_TABLE_COUNT] = {
 	TAB_MAP(DRIVER_SMU_CONFIG),
 	TAB_MAP(ACTIVITY_MONITOR_COEFF),
 	[SMU_TABLE_COMBO_PPTABLE] = {1, TABLE_COMBO_PPTABLE},
+	TAB_MAP(WIFIBAND),
 	TAB_MAP(I2C_COMMANDS),
 	TAB_MAP(ECCINFO),
 };
@@ -472,6 +474,9 @@ static int smu_v13_0_0_tables_init(struct smu_context *smu)
 			PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
 	SMU_TABLE_INIT(tables, SMU_TABLE_ECCINFO, sizeof(EccInfoTable_t),
 			PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+	SMU_TABLE_INIT(tables, SMU_TABLE_WIFIBAND,
+		       sizeof(WifiBandEntryTable_t), PAGE_SIZE,
+		       AMDGPU_GEM_DOMAIN_VRAM);
 
 	smu_table->metrics_table = kzalloc(sizeof(SmuMetricsExternal_t), GFP_KERNEL);
 	if (!smu_table->metrics_table)
@@ -2141,6 +2146,58 @@ static ssize_t smu_v13_0_0_get_ecc_info(struct smu_context *smu,
 	return ret;
 }
 
+static bool smu_v13_0_0_wbrf_support_check(struct smu_context *smu)
+{
+	struct amdgpu_device *adev = smu->adev;
+
+	switch (adev->ip_versions[MP1_HWIP][0]) {
+	case IP_VERSION(13, 0, 0):
+		return smu->smc_fw_version >= 0x004e6300;
+	case IP_VERSION(13, 0, 10):
+		return smu->smc_fw_version >= 0x00503300;
+	default:
+		return false;
+	}
+}
+
+static int smu_v13_0_0_set_wbrf_exclusion_ranges(struct smu_context *smu,
+						 struct exclusion_range *exclusion_ranges)
+{
+	WifiBandEntryTable_t wifi_bands;
+	int valid_entries = 0;
+	int ret, i;
+
+	memset(&wifi_bands, 0, sizeof(wifi_bands));
+	for (i = 0; i < ARRAY_SIZE(wifi_bands.WifiBandEntry); i++) {
+		if (!exclusion_ranges[i].start &&
+		    !exclusion_ranges[i].end)
+			break;
+
+		/* PMFW expects the inputs to be in Mhz unit */
+		wifi_bands.WifiBandEntry[valid_entries].LowFreq =
+			DIV_ROUND_DOWN_ULL(exclusion_ranges[i].start, HZ_IN_MHZ);
+		wifi_bands.WifiBandEntry[valid_entries++].HighFreq =
+			DIV_ROUND_UP_ULL(exclusion_ranges[i].end, HZ_IN_MHZ);
+	}
+	wifi_bands.WifiBandEntryNum = valid_entries;
+
+	/*
+	 * Per confirm with PMFW team, WifiBandEntryNum = 0
+	 * is a valid setting. So, there should be no direct
+	 * return on that.
+	 */
+
+	ret = smu_cmn_update_table(smu,
+				   SMU_TABLE_WIFIBAND,
+				   0,
+				   (void *)(&wifi_bands),
+				   true);
+	if (ret)
+		dev_err(smu->adev->dev, "Failed to set wifiband!");
+
+	return ret;
+}
+
 static const struct pptable_funcs smu_v13_0_0_ppt_funcs = {
 	.get_allowed_feature_mask = smu_v13_0_0_get_allowed_feature_mask,
 	.set_default_dpm_table = smu_v13_0_0_set_default_dpm_table,
@@ -2217,6 +2274,9 @@ static const struct pptable_funcs smu_v13_0_0_ppt_funcs = {
 	.send_hbm_bad_channel_flag = smu_v13_0_0_send_bad_mem_channel_flag,
 	.gpo_control = smu_v13_0_gpo_control,
 	.get_ecc_info = smu_v13_0_0_get_ecc_info,
+	.is_asic_wbrf_supported = smu_v13_0_0_wbrf_support_check,
+	.enable_uclk_shadow = smu_v13_0_enable_uclk_shadow,
+	.set_wbrf_exclusion_ranges = smu_v13_0_0_set_wbrf_exclusion_ranges,
 };
 
 void smu_v13_0_0_set_ppt_funcs(struct smu_context *smu)
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH V5 9/9] drm/amd/pm: enable Wifi RFI mitigation feature support for SMU13.0.7
  2023-06-30 10:32 [PATCH V5 0/9] Enable Wifi RFI interference mitigation feature support Evan Quan
                   ` (7 preceding siblings ...)
  2023-06-30 10:32 ` [PATCH V5 8/9] drm/amd/pm: enable Wifi RFI mitigation feature support for SMU13.0.0 Evan Quan
@ 2023-06-30 10:32 ` Evan Quan
  8 siblings, 0 replies; 28+ messages in thread
From: Evan Quan @ 2023-06-30 10:32 UTC (permalink / raw)
  To: rafael, lenb, Alexander.Deucher, Christian.Koenig, Xinhui.Pan,
	airlied, daniel, johannes, davem, edumazet, kuba, pabeni,
	Mario.Limonciello, mdaenzer, maarten.lankhorst, tzimmermann,
	hdegoede, jingyuwang_vip, Lijo.Lazar, jim.cromie, bellosilicio,
	andrealmeid, trix, jsg, arnd
  Cc: linux-kernel, linux-acpi, amd-gfx, dri-devel, linux-wireless,
	netdev, Evan Quan, Mario Limonciello

Fulfill the SMU13.0.7 support for Wifi RFI mitigation feature.

Signed-off-by: Evan Quan <evan.quan@amd.com>
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
---
 .../drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c  | 59 +++++++++++++++++++
 1 file changed, 59 insertions(+)

diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
index bba621615abf..4a680756208b 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
@@ -126,6 +126,7 @@ static struct cmn2asic_msg_mapping smu_v13_0_7_message_map[SMU_MSG_MAX_COUNT] =
 	MSG_MAP(AllowGpo,			PPSMC_MSG_SetGpoAllow,           0),
 	MSG_MAP(GetPptLimit,			PPSMC_MSG_GetPptLimit,                 0),
 	MSG_MAP(NotifyPowerSource,		PPSMC_MSG_NotifyPowerSource,           0),
+	MSG_MAP(EnableUCLKShadow,		PPSMC_MSG_EnableUCLKShadow,            0),
 };
 
 static struct cmn2asic_mapping smu_v13_0_7_clk_map[SMU_CLK_COUNT] = {
@@ -206,6 +207,7 @@ static struct cmn2asic_mapping smu_v13_0_7_table_map[SMU_TABLE_COUNT] = {
 	TAB_MAP(DRIVER_SMU_CONFIG),
 	TAB_MAP(ACTIVITY_MONITOR_COEFF),
 	[SMU_TABLE_COMBO_PPTABLE] = {1, TABLE_COMBO_PPTABLE},
+	TAB_MAP(WIFIBAND),
 };
 
 static struct cmn2asic_mapping smu_v13_0_7_pwr_src_map[SMU_POWER_SOURCE_COUNT] = {
@@ -488,6 +490,9 @@ static int smu_v13_0_7_tables_init(struct smu_context *smu)
 	               AMDGPU_GEM_DOMAIN_VRAM);
 	SMU_TABLE_INIT(tables, SMU_TABLE_COMBO_PPTABLE, MP0_MP1_DATA_REGION_SIZE_COMBOPPTABLE,
 			PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+	SMU_TABLE_INIT(tables, SMU_TABLE_WIFIBAND,
+		       sizeof(WifiBandEntryTable_t), PAGE_SIZE,
+		       AMDGPU_GEM_DOMAIN_VRAM);
 
 	smu_table->metrics_table = kzalloc(sizeof(SmuMetricsExternal_t), GFP_KERNEL);
 	if (!smu_table->metrics_table)
@@ -1722,6 +1727,57 @@ static int smu_v13_0_7_set_df_cstate(struct smu_context *smu,
 					       NULL);
 }
 
+static bool smu_v13_0_7_wbrf_support_check(struct smu_context *smu)
+{
+	return smu->smc_fw_version > 0x00524600;
+}
+
+static int smu_v13_0_7_set_wbrf_exclusion_ranges(struct smu_context *smu,
+						 struct exclusion_range *exclusion_ranges)
+{
+	WifiBandEntryTable_t wifi_bands;
+	int valid_entries = 0;
+	int ret, i;
+
+	memset(&wifi_bands, 0, sizeof(wifi_bands));
+	for (i = 0; i < ARRAY_SIZE(wifi_bands.WifiBandEntry); i++) {
+		if (!exclusion_ranges[i].start &&
+		    !exclusion_ranges[i].end)
+			break;
+
+		/* PMFW expects the inputs to be in Mhz unit */
+		wifi_bands.WifiBandEntry[valid_entries].LowFreq =
+			DIV_ROUND_DOWN_ULL(exclusion_ranges[i].start, HZ_IN_MHZ);
+		wifi_bands.WifiBandEntry[valid_entries++].HighFreq =
+			DIV_ROUND_UP_ULL(exclusion_ranges[i].end, HZ_IN_MHZ);
+	}
+	wifi_bands.WifiBandEntryNum = valid_entries;
+
+	/*
+	 * Per confirm with PMFW team, WifiBandEntryNum = 0 is a valid setting.
+	 * Considering the scenarios below:
+	 * - At first the wifi device adds an exclusion range e.g. (2400,2500) to
+	 *   BIOS and our driver gets notified. We will set WifiBandEntryNum = 1
+	 *   and pass the WifiBandEntry (2400, 2500) to PMFW.
+	 *
+	 * - Later the wifi device removes the wifiband list added above and
+	 *   our driver gets notified again. At this time, driver will set
+	 *   WifiBandEntryNum = 0 and pass an empty WifiBandEntry list to PMFW.
+	 *   - PMFW may still need to do some uclk shadow update(e.g. switching
+	 *     from shadow clock back to primary clock) on receiving this.
+	 */
+
+	ret = smu_cmn_update_table(smu,
+				   SMU_TABLE_WIFIBAND,
+				   0,
+				   (void *)(&wifi_bands),
+				   true);
+	if (ret)
+		dev_err(smu->adev->dev, "Failed to set wifiband!");
+
+	return ret;
+}
+
 static const struct pptable_funcs smu_v13_0_7_ppt_funcs = {
 	.get_allowed_feature_mask = smu_v13_0_7_get_allowed_feature_mask,
 	.set_default_dpm_table = smu_v13_0_7_set_default_dpm_table,
@@ -1787,6 +1843,9 @@ static const struct pptable_funcs smu_v13_0_7_ppt_funcs = {
 	.set_mp1_state = smu_v13_0_7_set_mp1_state,
 	.set_df_cstate = smu_v13_0_7_set_df_cstate,
 	.gpo_control = smu_v13_0_gpo_control,
+	.is_asic_wbrf_supported = smu_v13_0_7_wbrf_support_check,
+	.enable_uclk_shadow = smu_v13_0_enable_uclk_shadow,
+	.set_wbrf_exclusion_ranges = smu_v13_0_7_set_wbrf_exclusion_ranges,
 };
 
 void smu_v13_0_7_set_ppt_funcs(struct smu_context *smu)
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* Re: [PATCH V5 1/9] drivers core: Add support for Wifi band RF mitigations
  2023-06-30 10:32 ` [PATCH V5 1/9] drivers core: Add support for Wifi band RF mitigations Evan Quan
@ 2023-06-30 13:38   ` Simon Horman
  2023-07-04  3:41     ` Quan, Evan
  2023-06-30 16:40   ` Limonciello, Mario
  2023-07-01  0:19   ` Andrew Lunn
  2 siblings, 1 reply; 28+ messages in thread
From: Simon Horman @ 2023-06-30 13:38 UTC (permalink / raw)
  To: Evan Quan
  Cc: rafael, lenb, Alexander.Deucher, Christian.Koenig, Xinhui.Pan,
	airlied, daniel, johannes, davem, edumazet, kuba, pabeni,
	Mario.Limonciello, mdaenzer, maarten.lankhorst, tzimmermann,
	hdegoede, jingyuwang_vip, Lijo.Lazar, jim.cromie, bellosilicio,
	andrealmeid, trix, jsg, arnd, linux-kernel, linux-acpi, amd-gfx,
	dri-devel, linux-wireless, netdev

On Fri, Jun 30, 2023 at 06:32:32PM +0800, Evan Quan wrote:

...

> diff --git a/include/linux/wbrf.h b/include/linux/wbrf.h
> new file mode 100644
> index 000000000000..3ca95786cef5
> --- /dev/null
> +++ b/include/linux/wbrf.h
> @@ -0,0 +1,65 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Wifi Band Exclusion Interface
> + * Copyright (C) 2023 Advanced Micro Devices
> + */
> +
> +#ifndef _LINUX_WBRF_H
> +#define _LINUX_WBRF_H
> +
> +#include <linux/device.h>
> +
> +/* Maximum number of wbrf ranges */
> +#define MAX_NUM_OF_WBRF_RANGES		11
> +
> +struct exclusion_range {
> +	/* start and end point of the frequency range in Hz */
> +	uint64_t	start;
> +	uint64_t	end;
> +};
> +
> +struct exclusion_range_pool {
> +	struct exclusion_range	band_list[MAX_NUM_OF_WBRF_RANGES];
> +	uint64_t		ref_counter[MAX_NUM_OF_WBRF_RANGES];
> +};
> +
> +struct wbrf_ranges_in {
> +	/* valid entry: `start` and `end` filled with non-zero values */
> +	struct exclusion_range	band_list[MAX_NUM_OF_WBRF_RANGES];
> +};
> +
> +struct wbrf_ranges_out {
> +	uint32_t		num_of_ranges;
> +	struct exclusion_range	band_list[MAX_NUM_OF_WBRF_RANGES];
> +} __packed;
> +
> +enum wbrf_notifier_actions {
> +	WBRF_CHANGED,
> +};

Hi Evan,

checkpatch suggests that u64 and u32 might be more appropriate types here,
as they are Kernel types, whereas the ones use are user-space types.

...

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH V5 4/9] wifi: mac80211: Add support for ACPI WBRF
  2023-06-30 10:32 ` [PATCH V5 4/9] wifi: mac80211: Add support for ACPI WBRF Evan Quan
@ 2023-06-30 14:08   ` kernel test robot
  2023-07-01  1:02   ` Andrew Lunn
  1 sibling, 0 replies; 28+ messages in thread
From: kernel test robot @ 2023-06-30 14:08 UTC (permalink / raw)
  To: Evan Quan, rafael, lenb, Alexander.Deucher, Christian.Koenig,
	Xinhui.Pan, airlied, daniel, johannes, davem, edumazet, kuba,
	pabeni, Mario.Limonciello, mdaenzer, maarten.lankhorst,
	tzimmermann, hdegoede, jingyuwang_vip, Lijo.Lazar, jim.cromie,
	bellosilicio, andrealmeid, trix, jsg, arnd
  Cc: llvm, oe-kbuild-all, netdev, linux-wireless, linux-kernel,
	dri-devel, linux-acpi

Hi Evan,

kernel test robot noticed the following build errors:

[auto build test ERROR on wireless-next/main]
[also build test ERROR on wireless/main linus/master v6.4]
[cannot apply to drm-misc/drm-misc-next next-20230630]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Evan-Quan/drivers-core-Add-support-for-Wifi-band-RF-mitigations/20230630-183633
base:   https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git main
patch link:    https://lore.kernel.org/r/20230630103240.1557100-5-evan.quan%40amd.com
patch subject: [PATCH V5 4/9] wifi: mac80211: Add support for ACPI WBRF
config: powerpc-randconfig-r025-20230630 (https://download.01.org/0day-ci/archive/20230630/202306302133.Px6k3Lmq-lkp@intel.com/config)
compiler: clang version 17.0.0 (https://github.com/llvm/llvm-project.git 4a5ac14ee968ff0ad5d2cc1ffa0299048db4c88a)
reproduce: (https://download.01.org/0day-ci/archive/20230630/202306302133.Px6k3Lmq-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202306302133.Px6k3Lmq-lkp@intel.com/

All errors (new ones prefixed by >>):

         |                 ^~~~~~~~~~~~~~
   <scratch space>:87:1: note: expanded from here
      87 | __do_insw
         | ^
   arch/powerpc/include/asm/io.h:615:56: note: expanded from macro '__do_insw'
     615 | #define __do_insw(p, b, n)      readsw((PCI_IO_ADDR)_IO_BASE+(p), (b), (n))
         |                                        ~~~~~~~~~~~~~~~~~~~~~^
   In file included from net/mac80211/rx.c:15:
   In file included from include/linux/skbuff.h:17:
   In file included from include/linux/bvec.h:10:
   In file included from include/linux/highmem.h:12:
   In file included from include/linux/hardirq.h:11:
   In file included from arch/powerpc/include/asm/hardirq.h:6:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/powerpc/include/asm/io.h:677:
   arch/powerpc/include/asm/io-defs.h:47:1: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
      47 | DEF_PCI_AC_NORET(insl, (unsigned long p, void *b, unsigned long c),
         | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      48 |                  (p, b, c), pio, p)
         |                  ~~~~~~~~~~~~~~~~~~
   arch/powerpc/include/asm/io.h:674:3: note: expanded from macro 'DEF_PCI_AC_NORET'
     674 |                 __do_##name al;                                 \
         |                 ^~~~~~~~~~~~~~
   <scratch space>:89:1: note: expanded from here
      89 | __do_insl
         | ^
   arch/powerpc/include/asm/io.h:616:56: note: expanded from macro '__do_insl'
     616 | #define __do_insl(p, b, n)      readsl((PCI_IO_ADDR)_IO_BASE+(p), (b), (n))
         |                                        ~~~~~~~~~~~~~~~~~~~~~^
   In file included from net/mac80211/rx.c:15:
   In file included from include/linux/skbuff.h:17:
   In file included from include/linux/bvec.h:10:
   In file included from include/linux/highmem.h:12:
   In file included from include/linux/hardirq.h:11:
   In file included from arch/powerpc/include/asm/hardirq.h:6:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/powerpc/include/asm/io.h:677:
   arch/powerpc/include/asm/io-defs.h:49:1: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
      49 | DEF_PCI_AC_NORET(outsb, (unsigned long p, const void *b, unsigned long c),
         | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      50 |                  (p, b, c), pio, p)
         |                  ~~~~~~~~~~~~~~~~~~
   arch/powerpc/include/asm/io.h:674:3: note: expanded from macro 'DEF_PCI_AC_NORET'
     674 |                 __do_##name al;                                 \
         |                 ^~~~~~~~~~~~~~
   <scratch space>:91:1: note: expanded from here
      91 | __do_outsb
         | ^
   arch/powerpc/include/asm/io.h:617:58: note: expanded from macro '__do_outsb'
     617 | #define __do_outsb(p, b, n)     writesb((PCI_IO_ADDR)_IO_BASE+(p),(b),(n))
         |                                         ~~~~~~~~~~~~~~~~~~~~~^
   In file included from net/mac80211/rx.c:15:
   In file included from include/linux/skbuff.h:17:
   In file included from include/linux/bvec.h:10:
   In file included from include/linux/highmem.h:12:
   In file included from include/linux/hardirq.h:11:
   In file included from arch/powerpc/include/asm/hardirq.h:6:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/powerpc/include/asm/io.h:677:
   arch/powerpc/include/asm/io-defs.h:51:1: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
      51 | DEF_PCI_AC_NORET(outsw, (unsigned long p, const void *b, unsigned long c),
         | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      52 |                  (p, b, c), pio, p)
         |                  ~~~~~~~~~~~~~~~~~~
   arch/powerpc/include/asm/io.h:674:3: note: expanded from macro 'DEF_PCI_AC_NORET'
     674 |                 __do_##name al;                                 \
         |                 ^~~~~~~~~~~~~~
   <scratch space>:93:1: note: expanded from here
      93 | __do_outsw
         | ^
   arch/powerpc/include/asm/io.h:618:58: note: expanded from macro '__do_outsw'
     618 | #define __do_outsw(p, b, n)     writesw((PCI_IO_ADDR)_IO_BASE+(p),(b),(n))
         |                                         ~~~~~~~~~~~~~~~~~~~~~^
   In file included from net/mac80211/rx.c:15:
   In file included from include/linux/skbuff.h:17:
   In file included from include/linux/bvec.h:10:
   In file included from include/linux/highmem.h:12:
   In file included from include/linux/hardirq.h:11:
   In file included from arch/powerpc/include/asm/hardirq.h:6:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/powerpc/include/asm/io.h:677:
   arch/powerpc/include/asm/io-defs.h:53:1: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
      53 | DEF_PCI_AC_NORET(outsl, (unsigned long p, const void *b, unsigned long c),
         | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      54 |                  (p, b, c), pio, p)
         |                  ~~~~~~~~~~~~~~~~~~
   arch/powerpc/include/asm/io.h:674:3: note: expanded from macro 'DEF_PCI_AC_NORET'
     674 |                 __do_##name al;                                 \
         |                 ^~~~~~~~~~~~~~
   <scratch space>:95:1: note: expanded from here
      95 | __do_outsl
         | ^
   arch/powerpc/include/asm/io.h:619:58: note: expanded from macro '__do_outsl'
     619 | #define __do_outsl(p, b, n)     writesl((PCI_IO_ADDR)_IO_BASE+(p),(b),(n))
         |                                         ~~~~~~~~~~~~~~~~~~~~~^
   In file included from net/mac80211/rx.c:26:
>> net/mac80211/ieee80211_i.h:2655:48: error: void function 'ieee80211_add_wbrf' should not return a value [-Wreturn-type]
    2655 |                                       struct cfg80211_chan_def *chandef) { return 0; }
         |                                                                            ^      ~
   6 warnings and 1 error generated.
--
   In file included from include/net/net_namespace.h:43:
   In file included from include/linux/skbuff.h:17:
   In file included from include/linux/bvec.h:10:
   In file included from include/linux/highmem.h:12:
   In file included from include/linux/hardirq.h:11:
   In file included from arch/powerpc/include/asm/hardirq.h:6:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/powerpc/include/asm/io.h:677:
   arch/powerpc/include/asm/io-defs.h:47:1: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
      47 | DEF_PCI_AC_NORET(insl, (unsigned long p, void *b, unsigned long c),
         | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      48 |                  (p, b, c), pio, p)
         |                  ~~~~~~~~~~~~~~~~~~
   arch/powerpc/include/asm/io.h:674:3: note: expanded from macro 'DEF_PCI_AC_NORET'
     674 |                 __do_##name al;                                 \
         |                 ^~~~~~~~~~~~~~
   <scratch space>:87:1: note: expanded from here
      87 | __do_insl
         | ^
   arch/powerpc/include/asm/io.h:616:56: note: expanded from macro '__do_insl'
     616 | #define __do_insl(p, b, n)      readsl((PCI_IO_ADDR)_IO_BASE+(p), (b), (n))
         |                                        ~~~~~~~~~~~~~~~~~~~~~^
   In file included from net/mac80211/rc80211_minstrel_ht.c:6:
   In file included from include/linux/netdevice.h:38:
   In file included from include/net/net_namespace.h:43:
   In file included from include/linux/skbuff.h:17:
   In file included from include/linux/bvec.h:10:
   In file included from include/linux/highmem.h:12:
   In file included from include/linux/hardirq.h:11:
   In file included from arch/powerpc/include/asm/hardirq.h:6:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/powerpc/include/asm/io.h:677:
   arch/powerpc/include/asm/io-defs.h:49:1: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
      49 | DEF_PCI_AC_NORET(outsb, (unsigned long p, const void *b, unsigned long c),
         | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      50 |                  (p, b, c), pio, p)
         |                  ~~~~~~~~~~~~~~~~~~
   arch/powerpc/include/asm/io.h:674:3: note: expanded from macro 'DEF_PCI_AC_NORET'
     674 |                 __do_##name al;                                 \
         |                 ^~~~~~~~~~~~~~
   <scratch space>:89:1: note: expanded from here
      89 | __do_outsb
         | ^
   arch/powerpc/include/asm/io.h:617:58: note: expanded from macro '__do_outsb'
     617 | #define __do_outsb(p, b, n)     writesb((PCI_IO_ADDR)_IO_BASE+(p),(b),(n))
         |                                         ~~~~~~~~~~~~~~~~~~~~~^
   In file included from net/mac80211/rc80211_minstrel_ht.c:6:
   In file included from include/linux/netdevice.h:38:
   In file included from include/net/net_namespace.h:43:
   In file included from include/linux/skbuff.h:17:
   In file included from include/linux/bvec.h:10:
   In file included from include/linux/highmem.h:12:
   In file included from include/linux/hardirq.h:11:
   In file included from arch/powerpc/include/asm/hardirq.h:6:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/powerpc/include/asm/io.h:677:
   arch/powerpc/include/asm/io-defs.h:51:1: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
      51 | DEF_PCI_AC_NORET(outsw, (unsigned long p, const void *b, unsigned long c),
         | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      52 |                  (p, b, c), pio, p)
         |                  ~~~~~~~~~~~~~~~~~~
   arch/powerpc/include/asm/io.h:674:3: note: expanded from macro 'DEF_PCI_AC_NORET'
     674 |                 __do_##name al;                                 \
         |                 ^~~~~~~~~~~~~~
   <scratch space>:91:1: note: expanded from here
      91 | __do_outsw
         | ^
   arch/powerpc/include/asm/io.h:618:58: note: expanded from macro '__do_outsw'
     618 | #define __do_outsw(p, b, n)     writesw((PCI_IO_ADDR)_IO_BASE+(p),(b),(n))
         |                                         ~~~~~~~~~~~~~~~~~~~~~^
   In file included from net/mac80211/rc80211_minstrel_ht.c:6:
   In file included from include/linux/netdevice.h:38:
   In file included from include/net/net_namespace.h:43:
   In file included from include/linux/skbuff.h:17:
   In file included from include/linux/bvec.h:10:
   In file included from include/linux/highmem.h:12:
   In file included from include/linux/hardirq.h:11:
   In file included from arch/powerpc/include/asm/hardirq.h:6:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/powerpc/include/asm/io.h:677:
   arch/powerpc/include/asm/io-defs.h:53:1: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
      53 | DEF_PCI_AC_NORET(outsl, (unsigned long p, const void *b, unsigned long c),
         | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      54 |                  (p, b, c), pio, p)
         |                  ~~~~~~~~~~~~~~~~~~
   arch/powerpc/include/asm/io.h:674:3: note: expanded from macro 'DEF_PCI_AC_NORET'
     674 |                 __do_##name al;                                 \
         |                 ^~~~~~~~~~~~~~
   <scratch space>:93:1: note: expanded from here
      93 | __do_outsl
         | ^
   arch/powerpc/include/asm/io.h:619:58: note: expanded from macro '__do_outsl'
     619 | #define __do_outsl(p, b, n)     writesl((PCI_IO_ADDR)_IO_BASE+(p),(b),(n))
         |                                         ~~~~~~~~~~~~~~~~~~~~~^
   In file included from net/mac80211/rc80211_minstrel_ht.c:15:
   In file included from net/mac80211/rate.h:16:
>> net/mac80211/ieee80211_i.h:2655:48: error: void function 'ieee80211_add_wbrf' should not return a value [-Wreturn-type]
    2655 |                                       struct cfg80211_chan_def *chandef) { return 0; }
         |                                                                            ^      ~
   6 warnings and 1 error generated.
--
   In file included from include/linux/ieee80211.h:19:
   In file included from include/linux/if_ether.h:19:
   In file included from include/linux/skbuff.h:17:
   In file included from include/linux/bvec.h:10:
   In file included from include/linux/highmem.h:12:
   In file included from include/linux/hardirq.h:11:
   In file included from arch/powerpc/include/asm/hardirq.h:6:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/powerpc/include/asm/io.h:677:
   arch/powerpc/include/asm/io-defs.h:47:1: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
      47 | DEF_PCI_AC_NORET(insl, (unsigned long p, void *b, unsigned long c),
         | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      48 |                  (p, b, c), pio, p)
         |                  ~~~~~~~~~~~~~~~~~~
   arch/powerpc/include/asm/io.h:674:3: note: expanded from macro 'DEF_PCI_AC_NORET'
     674 |                 __do_##name al;                                 \
         |                 ^~~~~~~~~~~~~~
   <scratch space>:126:1: note: expanded from here
     126 | __do_insl
         | ^
   arch/powerpc/include/asm/io.h:616:56: note: expanded from macro '__do_insl'
     616 | #define __do_insl(p, b, n)      readsl((PCI_IO_ADDR)_IO_BASE+(p), (b), (n))
         |                                        ~~~~~~~~~~~~~~~~~~~~~^
   In file included from net/mac80211/ht.c:15:
   In file included from include/linux/ieee80211.h:19:
   In file included from include/linux/if_ether.h:19:
   In file included from include/linux/skbuff.h:17:
   In file included from include/linux/bvec.h:10:
   In file included from include/linux/highmem.h:12:
   In file included from include/linux/hardirq.h:11:
   In file included from arch/powerpc/include/asm/hardirq.h:6:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/powerpc/include/asm/io.h:677:
   arch/powerpc/include/asm/io-defs.h:49:1: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
      49 | DEF_PCI_AC_NORET(outsb, (unsigned long p, const void *b, unsigned long c),
         | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      50 |                  (p, b, c), pio, p)
         |                  ~~~~~~~~~~~~~~~~~~
   arch/powerpc/include/asm/io.h:674:3: note: expanded from macro 'DEF_PCI_AC_NORET'
     674 |                 __do_##name al;                                 \
         |                 ^~~~~~~~~~~~~~
   <scratch space>:128:1: note: expanded from here
     128 | __do_outsb
         | ^
   arch/powerpc/include/asm/io.h:617:58: note: expanded from macro '__do_outsb'
     617 | #define __do_outsb(p, b, n)     writesb((PCI_IO_ADDR)_IO_BASE+(p),(b),(n))
         |                                         ~~~~~~~~~~~~~~~~~~~~~^
   In file included from net/mac80211/ht.c:15:
   In file included from include/linux/ieee80211.h:19:
   In file included from include/linux/if_ether.h:19:
   In file included from include/linux/skbuff.h:17:
   In file included from include/linux/bvec.h:10:
   In file included from include/linux/highmem.h:12:
   In file included from include/linux/hardirq.h:11:
   In file included from arch/powerpc/include/asm/hardirq.h:6:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/powerpc/include/asm/io.h:677:
   arch/powerpc/include/asm/io-defs.h:51:1: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
      51 | DEF_PCI_AC_NORET(outsw, (unsigned long p, const void *b, unsigned long c),
         | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      52 |                  (p, b, c), pio, p)
         |                  ~~~~~~~~~~~~~~~~~~
   arch/powerpc/include/asm/io.h:674:3: note: expanded from macro 'DEF_PCI_AC_NORET'
     674 |                 __do_##name al;                                 \
         |                 ^~~~~~~~~~~~~~
   <scratch space>:130:1: note: expanded from here
     130 | __do_outsw
         | ^
   arch/powerpc/include/asm/io.h:618:58: note: expanded from macro '__do_outsw'
     618 | #define __do_outsw(p, b, n)     writesw((PCI_IO_ADDR)_IO_BASE+(p),(b),(n))
         |                                         ~~~~~~~~~~~~~~~~~~~~~^
   In file included from net/mac80211/ht.c:15:
   In file included from include/linux/ieee80211.h:19:
   In file included from include/linux/if_ether.h:19:
   In file included from include/linux/skbuff.h:17:
   In file included from include/linux/bvec.h:10:
   In file included from include/linux/highmem.h:12:
   In file included from include/linux/hardirq.h:11:
   In file included from arch/powerpc/include/asm/hardirq.h:6:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/powerpc/include/asm/io.h:677:
   arch/powerpc/include/asm/io-defs.h:53:1: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
      53 | DEF_PCI_AC_NORET(outsl, (unsigned long p, const void *b, unsigned long c),
         | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      54 |                  (p, b, c), pio, p)
         |                  ~~~~~~~~~~~~~~~~~~
   arch/powerpc/include/asm/io.h:674:3: note: expanded from macro 'DEF_PCI_AC_NORET'
     674 |                 __do_##name al;                                 \
         |                 ^~~~~~~~~~~~~~
   <scratch space>:132:1: note: expanded from here
     132 | __do_outsl
         | ^
   arch/powerpc/include/asm/io.h:619:58: note: expanded from macro '__do_outsl'
     619 | #define __do_outsl(p, b, n)     writesl((PCI_IO_ADDR)_IO_BASE+(p),(b),(n))
         |                                         ~~~~~~~~~~~~~~~~~~~~~^
   In file included from net/mac80211/ht.c:18:
>> net/mac80211/ieee80211_i.h:2655:48: error: void function 'ieee80211_add_wbrf' should not return a value [-Wreturn-type]
    2655 |                                       struct cfg80211_chan_def *chandef) { return 0; }
         |                                                                            ^      ~
   6 warnings and 1 error generated.
..


vim +/ieee80211_add_wbrf +2655 net/mac80211/ieee80211_i.h

  2630	
  2631	u8 ieee80211_ie_len_eht_cap(struct ieee80211_sub_if_data *sdata, u8 iftype);
  2632	u8 *ieee80211_ie_build_eht_cap(u8 *pos,
  2633				       const struct ieee80211_sta_he_cap *he_cap,
  2634				       const struct ieee80211_sta_eht_cap *eht_cap,
  2635				       u8 *end,
  2636				       bool for_ap);
  2637	
  2638	void
  2639	ieee80211_eht_cap_ie_to_sta_eht_cap(struct ieee80211_sub_if_data *sdata,
  2640					    struct ieee80211_supported_band *sband,
  2641					    const u8 *he_cap_ie, u8 he_cap_len,
  2642					    const struct ieee80211_eht_cap_elem *eht_cap_ie_elem,
  2643					    u8 eht_cap_len,
  2644					    struct link_sta_info *link_sta);
  2645	
  2646	#ifdef CONFIG_WBRF
  2647	void ieee80211_check_wbrf_support(struct ieee80211_local *local);
  2648	void ieee80211_add_wbrf(struct ieee80211_local *local,
  2649				struct cfg80211_chan_def *chandef);
  2650	void ieee80211_remove_wbrf(struct ieee80211_local *local,
  2651				   struct cfg80211_chan_def *chandef);
  2652	#else
  2653	static inline void ieee80211_check_wbrf_support(struct ieee80211_local *local) { }
  2654	static inline void ieee80211_add_wbrf(struct ieee80211_local *local,
> 2655					      struct cfg80211_chan_def *chandef) { return 0; }
  2656	static inline void ieee80211_remove_wbrf(struct ieee80211_local *local,
  2657						 struct cfg80211_chan_def *chandef) { }
  2658	#endif /* CONFIG_WBRF */
  2659	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH V5 7/9] drm/amd/pm: add flood detection for wbrf events
  2023-06-30 10:32 ` [PATCH V5 7/9] drm/amd/pm: add flood detection for wbrf events Evan Quan
@ 2023-06-30 14:29   ` kernel test robot
  0 siblings, 0 replies; 28+ messages in thread
From: kernel test robot @ 2023-06-30 14:29 UTC (permalink / raw)
  To: Evan Quan, rafael, lenb, Alexander.Deucher, Christian.Koenig,
	Xinhui.Pan, airlied, daniel, johannes, davem, edumazet, kuba,
	pabeni, Mario.Limonciello, mdaenzer, maarten.lankhorst,
	tzimmermann, hdegoede, jingyuwang_vip, Lijo.Lazar, jim.cromie,
	bellosilicio, andrealmeid, trix, jsg, arnd
  Cc: oe-kbuild-all, netdev, linux-wireless, linux-kernel, dri-devel,
	linux-acpi

Hi Evan,

kernel test robot noticed the following build warnings:

[auto build test WARNING on wireless-next/main]
[also build test WARNING on wireless/main v6.4]
[cannot apply to drm-misc/drm-misc-next linus/master next-20230630]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Evan-Quan/drivers-core-Add-support-for-Wifi-band-RF-mitigations/20230630-183633
base:   https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git main
patch link:    https://lore.kernel.org/r/20230630103240.1557100-8-evan.quan%40amd.com
patch subject: [PATCH V5 7/9] drm/amd/pm: add flood detection for wbrf events
config: x86_64-buildonly-randconfig-r003-20230630 (https://download.01.org/0day-ci/archive/20230630/202306302258.ZdzWnrmF-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce: (https://download.01.org/0day-ci/archive/20230630/202306302258.ZdzWnrmF-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202306302258.ZdzWnrmF-lkp@intel.com/

All warnings (new ones prefixed by >>):

   drivers/gpu/drm/amd/amdgpu/../pm/swsmu/amdgpu_smu.c: In function 'smu_wbrf_init':
>> drivers/gpu/drm/amd/amdgpu/../pm/swsmu/amdgpu_smu.c:1336:31: warning: unused variable 'adev' [-Wunused-variable]
    1336 |         struct amdgpu_device *adev = smu->adev;
         |                               ^~~~


vim +/adev +1336 drivers/gpu/drm/amd/amdgpu/../pm/swsmu/amdgpu_smu.c

19fbe240b2627a Evan Quan 2023-06-30  1324  
19fbe240b2627a Evan Quan 2023-06-30  1325  /**
19fbe240b2627a Evan Quan 2023-06-30  1326   * smu_wbrf_init - init driver wbrf support
19fbe240b2627a Evan Quan 2023-06-30  1327   *
19fbe240b2627a Evan Quan 2023-06-30  1328   * @smu: smu_context pointer
19fbe240b2627a Evan Quan 2023-06-30  1329   *
19fbe240b2627a Evan Quan 2023-06-30  1330   * Verifies the AMD ACPI interfaces and registers with the wbrf
19fbe240b2627a Evan Quan 2023-06-30  1331   * notifier chain if wbrf feature is supported.
19fbe240b2627a Evan Quan 2023-06-30  1332   * Returns 0 on success, error on failure.
19fbe240b2627a Evan Quan 2023-06-30  1333   */
19fbe240b2627a Evan Quan 2023-06-30  1334  static int smu_wbrf_init(struct smu_context *smu)
19fbe240b2627a Evan Quan 2023-06-30  1335  {
19fbe240b2627a Evan Quan 2023-06-30 @1336  	struct amdgpu_device *adev = smu->adev;
19fbe240b2627a Evan Quan 2023-06-30  1337  	int ret;
19fbe240b2627a Evan Quan 2023-06-30  1338  
19fbe240b2627a Evan Quan 2023-06-30  1339  	if (!smu->wbrf_supported)
19fbe240b2627a Evan Quan 2023-06-30  1340  		return 0;
19fbe240b2627a Evan Quan 2023-06-30  1341  
0b8224d2686865 Evan Quan 2023-06-30  1342  	INIT_DELAYED_WORK(&smu->wbrf_delayed_work,
0b8224d2686865 Evan Quan 2023-06-30  1343  			  smu_wbrf_delayed_work_handler);
0b8224d2686865 Evan Quan 2023-06-30  1344  
19fbe240b2627a Evan Quan 2023-06-30  1345  	smu->wbrf_notifier.notifier_call = smu_wbrf_event_handler;
19fbe240b2627a Evan Quan 2023-06-30  1346  	ret = wbrf_register_notifier(&smu->wbrf_notifier);
19fbe240b2627a Evan Quan 2023-06-30  1347  	if (ret)
19fbe240b2627a Evan Quan 2023-06-30  1348  		return ret;
19fbe240b2627a Evan Quan 2023-06-30  1349  
19fbe240b2627a Evan Quan 2023-06-30  1350  	/*
19fbe240b2627a Evan Quan 2023-06-30  1351  	 * Some wifiband exclusion ranges may be already there
19fbe240b2627a Evan Quan 2023-06-30  1352  	 * before our driver loaded. To make sure our driver
19fbe240b2627a Evan Quan 2023-06-30  1353  	 * is awared of those exclusion ranges.
19fbe240b2627a Evan Quan 2023-06-30  1354  	 */
0b8224d2686865 Evan Quan 2023-06-30  1355  	schedule_delayed_work(&smu->wbrf_delayed_work,
0b8224d2686865 Evan Quan 2023-06-30  1356  			      msecs_to_jiffies(SMU_WBRF_EVENT_HANDLING_PACE));
19fbe240b2627a Evan Quan 2023-06-30  1357  
0b8224d2686865 Evan Quan 2023-06-30  1358  	return 0;
19fbe240b2627a Evan Quan 2023-06-30  1359  }
19fbe240b2627a Evan Quan 2023-06-30  1360  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH V5 1/9] drivers core: Add support for Wifi band RF mitigations
  2023-06-30 10:32 ` [PATCH V5 1/9] drivers core: Add support for Wifi band RF mitigations Evan Quan
  2023-06-30 13:38   ` Simon Horman
@ 2023-06-30 16:40   ` Limonciello, Mario
  2023-07-01  0:25     ` Andrew Lunn
  2023-07-04  3:40     ` Quan, Evan
  2023-07-01  0:19   ` Andrew Lunn
  2 siblings, 2 replies; 28+ messages in thread
From: Limonciello, Mario @ 2023-06-30 16:40 UTC (permalink / raw)
  To: Evan Quan, rafael, lenb, Alexander.Deucher, Christian.Koenig,
	Xinhui.Pan, airlied, daniel, johannes, davem, edumazet, kuba,
	pabeni, mdaenzer, maarten.lankhorst, tzimmermann, hdegoede,
	jingyuwang_vip, Lijo.Lazar, jim.cromie, bellosilicio,
	andrealmeid, trix, jsg, arnd
  Cc: linux-kernel, linux-acpi, amd-gfx, dri-devel, linux-wireless, netdev

On 6/30/2023 05:32, Evan Quan wrote:
> Due to electrical and mechanical constraints in certain platform designs
> there may be likely interference of relatively high-powered harmonics of
> the (G-)DDR memory clocks with local radio module frequency bands used
> by Wifi 6/6e/7.
> 
> To mitigate this, AMD has introduced a mechanism that devices can use to
> notify active use of particular frequencies so that other devices can make
> relative internal adjustments as necessary to avoid this resonance.
> 
> In order for a device to support this, the expected flow for device
> driver or subsystems:
> 
> Drivers/subsystems contributing frequencies:
> 
> 1) During probe, check `wbrf_supported_producer` to see if WBRF supported
>     for the device.
> 2) If adding frequencies, then call `wbrf_add_exclusion` with the
>     start and end ranges of the frequencies.
> 3) If removing frequencies, then call `wbrf_remove_exclusion` with
>     start and end ranges of the frequencies.
> 
> Drivers/subsystems responding to frequencies:
> 
> 1) During probe, check `wbrf_supported_consumer` to see if WBRF is supported
>     for the device.
> 2) Call the `wbrf_retrieve_exclusions` to retrieve the current
>     exclusions on receiving an ACPI notification for a new frequency
>     change.
> 
> Co-developed-by: Mario Limonciello <mario.limonciello@amd.com>
> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
> Co-developed-by: Evan Quan <evan.quan@amd.com>
> Signed-off-by: Evan Quan <evan.quan@amd.com>
> --
> v4->v5:
>    - promote this to be a more generic solution with input argument taking
>      `struct device` and provide better scalability to support non-ACPI
>      scenarios(Andrew)
>    - update the APIs naming and some other minor fixes(Rafael)
> ---
>   drivers/base/Kconfig  |   8 ++
>   drivers/base/Makefile |   1 +
>   drivers/base/wbrf.c   | 227 ++++++++++++++++++++++++++++++++++++++++++
>   include/linux/wbrf.h  |  65 ++++++++++++
>   4 files changed, 301 insertions(+)
>   create mode 100644 drivers/base/wbrf.c
>   create mode 100644 include/linux/wbrf.h
> 
> diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
> index 2b8fd6bb7da0..5b441017b225 100644
> --- a/drivers/base/Kconfig
> +++ b/drivers/base/Kconfig
> @@ -242,4 +242,12 @@ config FW_DEVLINK_SYNC_STATE_TIMEOUT
>   	  command line option on every system/board your kernel is expected to
>   	  work on.
>   
> +config WBRF
> +	bool "Wifi band RF mitigation mechanism"
> +	default n
> +	help
> +	  Wifi band RF mitigation mechanism allows multiple drivers from
> +	  different domains to notify the frequencies in use so that hardware
> +	  can be reconfigured to avoid harmonic conflicts.
> +
>   endmenu
> diff --git a/drivers/base/Makefile b/drivers/base/Makefile
> index 3079bfe53d04..c844f68a6830 100644
> --- a/drivers/base/Makefile
> +++ b/drivers/base/Makefile
> @@ -26,6 +26,7 @@ obj-$(CONFIG_GENERIC_MSI_IRQ) += platform-msi.o
>   obj-$(CONFIG_GENERIC_ARCH_TOPOLOGY) += arch_topology.o
>   obj-$(CONFIG_GENERIC_ARCH_NUMA) += arch_numa.o
>   obj-$(CONFIG_ACPI) += physical_location.o
> +obj-$(CONFIG_WBRF) += wbrf.o
>   
>   obj-y			+= test/
>   
> diff --git a/drivers/base/wbrf.c b/drivers/base/wbrf.c
> new file mode 100644
> index 000000000000..2163a8ec8a9a
> --- /dev/null
> +++ b/drivers/base/wbrf.c
> @@ -0,0 +1,227 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Wifi Band Exclusion Interface
> + * Copyright (C) 2023 Advanced Micro Devices
> + *
> + */
> +
> +#include <linux/wbrf.h>
> +
> +static BLOCKING_NOTIFIER_HEAD(wbrf_chain_head);
> +static DEFINE_MUTEX(wbrf_mutex);
> +static struct exclusion_range_pool wbrf_pool;
> +
> +static int _wbrf_add_exclusion_ranges(struct wbrf_ranges_in *in)
> +{
> +	int i, j;
> +
> +	for (i = 0; i < ARRAY_SIZE(in->band_list); i++) {
> +		if (!in->band_list[i].start &&
> +		    !in->band_list[i].end)
> +			continue;
> +
> +		for (j = 0; j < ARRAY_SIZE(wbrf_pool.band_list); j++) {
> +			if (wbrf_pool.band_list[j].start == in->band_list[i].start &&
> +			    wbrf_pool.band_list[j].end == in->band_list[i].end) {
> +				wbrf_pool.ref_counter[j]++;
> +				break;
> +			}
> +		}
> +		if (j < ARRAY_SIZE(wbrf_pool.band_list))
> +			continue;
> +
> +		for (j = 0; j < ARRAY_SIZE(wbrf_pool.band_list); j++) {
> +			if (!wbrf_pool.band_list[j].start &&
> +			    !wbrf_pool.band_list[j].end) {
> +				wbrf_pool.band_list[j].start = in->band_list[i].start;
> +				wbrf_pool.band_list[j].end = in->band_list[i].end;
> +				wbrf_pool.ref_counter[j] = 1;
> +				break;
> +			}
> +		}
> +		if (j >= ARRAY_SIZE(wbrf_pool.band_list))
> +			return -ENOSPC;
> +	}
> +
> +	return 0;
> +}
> +
> +static int _wbrf_remove_exclusion_ranges(struct wbrf_ranges_in *in)
> +{
> +	int i, j;
> +
> +	for (i = 0; i < ARRAY_SIZE(in->band_list); i++) {
> +		if (!in->band_list[i].start &&
> +		    !in->band_list[i].end)
> +			continue;
> +
> +		for (j = 0; j < ARRAY_SIZE(wbrf_pool.band_list); j++) {
> +			if (wbrf_pool.band_list[j].start == in->band_list[i].start &&
> +			    wbrf_pool.band_list[j].end == in->band_list[i].end) {
> +				wbrf_pool.ref_counter[j]--;
> +				if (!wbrf_pool.ref_counter[j]) {
> +					wbrf_pool.band_list[j].start = 0;
> +					wbrf_pool.band_list[j].end = 0;
> +				}
> +				break;
> +			}
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static int _wbrf_retrieve_exclusion_ranges(struct wbrf_ranges_out *out)
> +{
> +	int out_idx = 0;
> +	int i;
> +
> +	memset(out, 0, sizeof(*out));
> +
> +	for (i = 0; i < ARRAY_SIZE(wbrf_pool.band_list); i++) {
> +		if (!wbrf_pool.band_list[i].start &&
> +		    !wbrf_pool.band_list[i].end)
> +			continue;
> +
> +		out->band_list[out_idx].start = wbrf_pool.band_list[i].start;
> +		out->band_list[out_idx++].end = wbrf_pool.band_list[i].end;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * wbrf_supported_producer - Determine if the device can report frequencies
> + *
> + * @dev: device pointer
> + *
> + * WBRF is used to mitigate devices that cause harmonic interference.
> + * This function will determine if this device needs to report such frequencies.
> + */
> +bool wbrf_supported_producer(struct device *dev)
> +{
> +	return true;
> +}
> +EXPORT_SYMBOL_GPL(wbrf_supported_producer);
> +
> +/**
> + * wbrf_add_exclusion - Add frequency ranges to the exclusion list
> + *
> + * @dev: device pointer
> + * @in: input structure containing the frequency ranges to be added
> + *
> + * Add frequencies into the exclusion list for supported consumers
> + * to react to.
> + */
> +int wbrf_add_exclusion(struct device *dev,
> +		       struct wbrf_ranges_in *in)
> +{
> +	int r;
> +
> +	mutex_lock(&wbrf_mutex);
> +
> +	r = _wbrf_add_exclusion_ranges(in);
> +
> +	mutex_unlock(&wbrf_mutex);
> +	if (r)
> +		return r;
> +
> +	blocking_notifier_call_chain(&wbrf_chain_head, WBRF_CHANGED, NULL);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(wbrf_add_exclusion);
> +
> +/**
> + * wbrf_remove_exclusion - Remove frequency ranges from the exclusion list
> + *
> + * @dev: device pointer
> + * @in: input structure containing the frequency ranges to be removed
> + *
> + * Remove frequencies from the exclusion list for supported consumers
> + * to react to.
> + */
> +int wbrf_remove_exclusion(struct device *dev,
> +			  struct wbrf_ranges_in *in)
> +{
> +	int r;
> +
> +	mutex_lock(&wbrf_mutex);
> +
> +	r = _wbrf_remove_exclusion_ranges(in);
> +
> +	mutex_unlock(&wbrf_mutex);
> +	if (r)
> +		return r;
> +
> +	blocking_notifier_call_chain(&wbrf_chain_head, WBRF_CHANGED, NULL);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(wbrf_remove_exclusion);
> +
> +/**
> + * wbrf_supported_consumer - Determine if the device can react to frequencies
> + *
> + * @dev: device pointer
> + *
> + * WBRF is used to mitigate devices that cause harmonic interference.
> + * This function will determine if this device needs to react to reports from
> + * other devices for such frequencies.
> + */
> +bool wbrf_supported_consumer(struct device *dev)
> +{
> +	return true;
> +}
> +EXPORT_SYMBOL_GPL(wbrf_supported_consumer);
> +
> +/**
> + * wbrf_register_notifier - Register for notifications of frequency changes
> + *
> + * @nb: driver notifier block
> + *
> + * WBRF is used to mitigate devices that cause harmonic interference.
> + * This function will allow consumers to register for frequency notifications.
> + */
> +int wbrf_register_notifier(struct notifier_block *nb)
> +{
> +	return blocking_notifier_chain_register(&wbrf_chain_head, nb);
> +}
> +EXPORT_SYMBOL_GPL(wbrf_register_notifier);
> +
> +/**
> + * wbrf_unregister_notifier - Unregister for notifications of frequency changes
> + *
> + * @nb: driver notifier block
> + *
> + * WBRF is used to mitigate devices that cause harmonic interference.
> + * This function will allow consumers to unregister for frequency notifications.
> + */
> +int wbrf_unregister_notifier(struct notifier_block *nb)
> +{
> +	return blocking_notifier_chain_unregister(&wbrf_chain_head, nb);
> +}
> +EXPORT_SYMBOL_GPL(wbrf_unregister_notifier);
> +
> +/**
> + * wbrf_retrieve_exclusions - Retrieve the exclusion list
> + *
> + * @dev: device pointer
> + * @out: output structure containing the frequency ranges to be excluded
> + *
> + * Retrieve the current exclusion list
> + */
> +int wbrf_retrieve_exclusions(struct device *dev,
> +			     struct wbrf_ranges_out *out)
> +{
> +	int r;
> +
> +	mutex_lock(&wbrf_mutex);
> +
> +	r = _wbrf_retrieve_exclusion_ranges(out);
> +
> +	mutex_unlock(&wbrf_mutex);
> +
> +	return r;
> +}
> +EXPORT_SYMBOL_GPL(wbrf_retrieve_exclusions);
> diff --git a/include/linux/wbrf.h b/include/linux/wbrf.h
> new file mode 100644
> index 000000000000..3ca95786cef5
> --- /dev/null
> +++ b/include/linux/wbrf.h
> @@ -0,0 +1,65 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Wifi Band Exclusion Interface
> + * Copyright (C) 2023 Advanced Micro Devices
> + */
> +
> +#ifndef _LINUX_WBRF_H
> +#define _LINUX_WBRF_H
> +
> +#include <linux/device.h>
> +
> +/* Maximum number of wbrf ranges */
> +#define MAX_NUM_OF_WBRF_RANGES		11
> +
> +struct exclusion_range {
> +	/* start and end point of the frequency range in Hz */
> +	uint64_t	start;
> +	uint64_t	end;
> +};
> +
> +struct exclusion_range_pool {
> +	struct exclusion_range	band_list[MAX_NUM_OF_WBRF_RANGES];
> +	uint64_t		ref_counter[MAX_NUM_OF_WBRF_RANGES];
> +};
> +
> +struct wbrf_ranges_in {
> +	/* valid entry: `start` and `end` filled with non-zero values */
> +	struct exclusion_range	band_list[MAX_NUM_OF_WBRF_RANGES];
> +};
> +
> +struct wbrf_ranges_out {
> +	uint32_t		num_of_ranges;
> +	struct exclusion_range	band_list[MAX_NUM_OF_WBRF_RANGES];
> +} __packed;
> +
> +enum wbrf_notifier_actions {
> +	WBRF_CHANGED,
> +};
> +
> +#ifdef CONFIG_WBRF
> +bool wbrf_supported_producer(struct device *dev);
> +int wbrf_add_exclusion(struct device *adev,
> +		       struct wbrf_ranges_in *in);
> +int wbrf_remove_exclusion(struct device *dev,
> +			  struct wbrf_ranges_in *in);
> +int wbrf_retrieve_exclusions(struct device *dev,
> +			     struct wbrf_ranges_out *out);
> +bool wbrf_supported_consumer(struct device *dev);
> +
> +int wbrf_register_notifier(struct notifier_block *nb);
> +int wbrf_unregister_notifier(struct notifier_block *nb);
> +#else
> +static inline bool wbrf_supported_producer(struct device *dev) { return false; }
> +static inline int wbrf_add_exclusion(struct device *adev,
> +				     struct wbrf_ranges_in *in) { return -ENODEV; }
> +static inline int wbrf_remove_exclusion(struct device *dev,
> +					struct wbrf_ranges_in *in) { return -ENODEV; }
> +static inline int wbrf_retrieve_exclusions(struct device *dev,
> +					   struct wbrf_ranges_out *out) { return -ENODEV; }
> +static inline bool wbrf_supported_consumer(struct device *dev) { return false; }
> +static inline int wbrf_register_notifier(struct notifier_block *nb) { return -ENODEV; }
> +static inline int wbrf_unregister_notifier(struct notifier_block *nb) { return -ENODEV; }
> +#endif
> +

Right now there are stubs for non CONFIG_WBRF as well as other patches 
are using #ifdef CONFIG_WBRF or having their own stubs.  Like mac80211 
patch looks for #ifdef CONFIG_WBRF.

I think we should pick one or the other.

Having other subsystems #ifdef CONFIG_WBRF will make the series easier 
to land through multiple trees; so I have a slight leaning in that 
direction.

> +#endif /* _LINUX_WBRF_H */


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH V5 1/9] drivers core: Add support for Wifi band RF mitigations
  2023-06-30 10:32 ` [PATCH V5 1/9] drivers core: Add support for Wifi band RF mitigations Evan Quan
  2023-06-30 13:38   ` Simon Horman
  2023-06-30 16:40   ` Limonciello, Mario
@ 2023-07-01  0:19   ` Andrew Lunn
  2023-07-04  3:30     ` Quan, Evan
  2 siblings, 1 reply; 28+ messages in thread
From: Andrew Lunn @ 2023-07-01  0:19 UTC (permalink / raw)
  To: Evan Quan
  Cc: rafael, lenb, Alexander.Deucher, Christian.Koenig, Xinhui.Pan,
	airlied, daniel, johannes, davem, edumazet, kuba, pabeni,
	Mario.Limonciello, mdaenzer, maarten.lankhorst, tzimmermann,
	hdegoede, jingyuwang_vip, Lijo.Lazar, jim.cromie, bellosilicio,
	andrealmeid, trix, jsg, arnd, linux-kernel, linux-acpi, amd-gfx,
	dri-devel, linux-wireless, netdev

> Drivers/subsystems contributing frequencies:
> 
> 1) During probe, check `wbrf_supported_producer` to see if WBRF supported
>    for the device.

What is the purpose of this stage? Why would it not be supported for
this device?

> +#ifdef CONFIG_WBRF
> +bool wbrf_supported_producer(struct device *dev);
> +int wbrf_add_exclusion(struct device *adev,
> +		       struct wbrf_ranges_in *in);
> +int wbrf_remove_exclusion(struct device *dev,
> +			  struct wbrf_ranges_in *in);
> +int wbrf_retrieve_exclusions(struct device *dev,
> +			     struct wbrf_ranges_out *out);
> +bool wbrf_supported_consumer(struct device *dev);
> +
> +int wbrf_register_notifier(struct notifier_block *nb);
> +int wbrf_unregister_notifier(struct notifier_block *nb);
> +#else
> +static inline bool wbrf_supported_producer(struct device *dev) { return false; }
> +static inline int wbrf_add_exclusion(struct device *adev,
> +				     struct wbrf_ranges_in *in) { return -ENODEV; }
> +static inline int wbrf_remove_exclusion(struct device *dev,
> +					struct wbrf_ranges_in *in) { return -ENODEV; }

The normal aim of stubs is that so long as it is not expected to be
fatal if the functionality is missing, the caller should not care if
it is missing. So i would expect these to return 0, indicating
everything worked as expected.

> +static inline int wbrf_retrieve_exclusions(struct device *dev,
> +					   struct wbrf_ranges_out *out) { return -ENODEV; }

This is more complex. Ideally you want to return an empty set, so
there is nothing to do. So i think the stub probably wants to do a
memset and then return 0.

> +static inline bool wbrf_supported_consumer(struct device *dev) { return false; }
> +static inline int wbrf_register_notifier(struct notifier_block *nb) { return -ENODEV; }
> +static inline int wbrf_unregister_notifier(struct notifier_block *nb) { return -ENODEV; }

And these can just return 0.

    Andrew

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH V5 1/9] drivers core: Add support for Wifi band RF mitigations
  2023-06-30 16:40   ` Limonciello, Mario
@ 2023-07-01  0:25     ` Andrew Lunn
  2023-07-04  3:25       ` Quan, Evan
  2023-07-04  3:40     ` Quan, Evan
  1 sibling, 1 reply; 28+ messages in thread
From: Andrew Lunn @ 2023-07-01  0:25 UTC (permalink / raw)
  To: Limonciello, Mario
  Cc: Evan Quan, rafael, lenb, Alexander.Deucher, Christian.Koenig,
	Xinhui.Pan, airlied, daniel, johannes, davem, edumazet, kuba,
	pabeni, mdaenzer, maarten.lankhorst, tzimmermann, hdegoede,
	jingyuwang_vip, Lijo.Lazar, jim.cromie, bellosilicio,
	andrealmeid, trix, jsg, arnd, linux-kernel, linux-acpi, amd-gfx,
	dri-devel, linux-wireless, netdev

> Right now there are stubs for non CONFIG_WBRF as well as other patches are
> using #ifdef CONFIG_WBRF or having their own stubs.  Like mac80211 patch
> looks for #ifdef CONFIG_WBRF.
> 
> I think we should pick one or the other.
> 
> Having other subsystems #ifdef CONFIG_WBRF will make the series easier to
> land through multiple trees; so I have a slight leaning in that direction.

#ifdef in C files is generally not liked because it makes build
testing harder. There are more permutations to build. It is better to use

if (IS_ENABLED(CONFIG_WBTR)) {
}

so that the code is compiled, and them throw away because
IS_ENABLED(CONFIG_WBTR) evaluates to false.

However, if the stubs are done correctly, the driver should not
care. I doubt this is used in any sort of hot path where every
instruction counts.

	Andrew

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH V5 2/9] driver core: add ACPI based WBRF mechanism introduced by AMD
  2023-06-30 10:32 ` [PATCH V5 2/9] driver core: add ACPI based WBRF mechanism introduced by AMD Evan Quan
@ 2023-07-01  0:51   ` Andrew Lunn
  2023-07-04  3:24     ` Quan, Evan
  0 siblings, 1 reply; 28+ messages in thread
From: Andrew Lunn @ 2023-07-01  0:51 UTC (permalink / raw)
  To: Evan Quan
  Cc: rafael, lenb, Alexander.Deucher, Christian.Koenig, Xinhui.Pan,
	airlied, daniel, johannes, davem, edumazet, kuba, pabeni,
	Mario.Limonciello, mdaenzer, maarten.lankhorst, tzimmermann,
	hdegoede, jingyuwang_vip, Lijo.Lazar, jim.cromie, bellosilicio,
	andrealmeid, trix, jsg, arnd, linux-kernel, linux-acpi, amd-gfx,
	dri-devel, linux-wireless, netdev

> +	argv4 = kzalloc(sizeof(*argv4) * (2 * num_of_ranges + 2 + 1), GFP_KERNEL);
> +	if (!argv4)
> +		return -ENOMEM;
> +
> +	argv4[arg_idx].package.type = ACPI_TYPE_PACKAGE;
> +	argv4[arg_idx].package.count = 2 + 2 * num_of_ranges;
> +	argv4[arg_idx++].package.elements = &argv4[1];
> +	argv4[arg_idx].integer.type = ACPI_TYPE_INTEGER;
> +	argv4[arg_idx++].integer.value = num_of_ranges;
> +	argv4[arg_idx].integer.type = ACPI_TYPE_INTEGER;
> +	argv4[arg_idx++].integer.value = action;

There is a lot of magic numbers in that kzalloc. It is being used as
an array, kcalloc() would be a good start to make it more readable.
Can some #define's be used to explain what the other numbers mean?

> +	/*
> +	 * Bit 0 indicates whether there's support for any functions other than
> +	 * function 0.
> +	 */

Please make use of the BIT macro to give the different bits
informative names.

> +	if ((mask & 0x1) && (mask & funcs) == funcs)
> +		return true;
> +
> +	return false;
> +}
> +

> +int acpi_amd_wbrf_retrieve_exclusions(struct device *dev,
> +				      struct wbrf_ranges_out *out)
> +{
> +	struct acpi_device *adev = ACPI_COMPANION(dev);
> +	union acpi_object *obj;
> +
> +	if (!adev)
> +		return -ENODEV;
> +
> +	obj = acpi_evaluate_wbrf(adev->handle,
> +				 WBRF_REVISION,
> +				 WBRF_RETRIEVE);
> +	if (!obj)
> +		return -EINVAL;
> +
> +	WARN(obj->buffer.length != sizeof(*out),
> +		"Unexpected buffer length");
> +	memcpy(out, obj->buffer.pointer, obj->buffer.length);

You WARN, and then overwrite whatever i passed the end of out?  Please
at least use min(obj->buffer.length, sizeof(*out)), but better still:

   if (obj->buffer.length != sizeof(*out)) {
         dev_err(dev, "BIOS FUBAR, ignoring wrong sized WBRT information");
	 return -EINVAL;
   }

> +#if defined(CONFIG_WBRF_GENERIC)
>  static struct exclusion_range_pool wbrf_pool;
>  
>  static int _wbrf_add_exclusion_ranges(struct wbrf_ranges_in *in)
> @@ -89,6 +92,7 @@ static int _wbrf_retrieve_exclusion_ranges(struct wbrf_ranges_out *out)
>  
>  	return 0;
>  }
> +#endif

I was expecting you would keep these tables, and then call into the
BIOS as well. Having this table in debugfs seems like a useful thing
to have for debugging the BIOS.

> +#ifdef CONFIG_WBRF_AMD_ACPI
> +#else
> +static inline bool
> +acpi_amd_wbrf_supported_consumer(struct device *dev) { return false; }
> +static inline bool
> +acpi_amd_wbrf_supported_producer(struct device *dev) {return false; }
> +static inline int
> +acpi_amd_wbrf_remove_exclusion(struct device *dev,
> +			       struct wbrf_ranges_in *in) { return -ENODEV; }
> +static inline int
> +acpi_amd_wbrf_add_exclusion(struct device *dev,
> +			    struct wbrf_ranges_in *in) { return -ENODEV; }
> +static inline int
> +acpi_amd_wbrf_retrieve_exclusions(struct device *dev,
> +				  struct wbrf_ranges_out *out) { return -ENODEV; }

Do you actually need these stub versions?

	Andrew

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH V5 4/9] wifi: mac80211: Add support for ACPI WBRF
  2023-06-30 10:32 ` [PATCH V5 4/9] wifi: mac80211: Add support for ACPI WBRF Evan Quan
  2023-06-30 14:08   ` kernel test robot
@ 2023-07-01  1:02   ` Andrew Lunn
  2023-07-04  3:12     ` Quan, Evan
  1 sibling, 1 reply; 28+ messages in thread
From: Andrew Lunn @ 2023-07-01  1:02 UTC (permalink / raw)
  To: Evan Quan
  Cc: rafael, lenb, Alexander.Deucher, Christian.Koenig, Xinhui.Pan,
	airlied, daniel, johannes, davem, edumazet, kuba, pabeni,
	Mario.Limonciello, mdaenzer, maarten.lankhorst, tzimmermann,
	hdegoede, jingyuwang_vip, Lijo.Lazar, jim.cromie, bellosilicio,
	andrealmeid, trix, jsg, arnd, linux-kernel, linux-acpi, amd-gfx,
	dri-devel, linux-wireless, netdev

> +static void get_chan_freq_boundary(u32 center_freq,
> +				   u32 bandwidth,
> +				   u64 *start,
> +				   u64 *end)
> +{
> +	bandwidth = MHZ_TO_KHZ(bandwidth);
> +	center_freq = MHZ_TO_KHZ(center_freq);
> +
> +	*start = center_freq - bandwidth / 2;
> +	*end = center_freq + bandwidth / 2;
> +
> +	/* Frequency in HZ is expected */
> +	*start = KHZ_TO_HZ(*start);
> +	*end = KHZ_TO_HZ(*end);
> +}

This seems pretty generic, so maybe it should be moved into the shared
code? It can then become a NOP when the functionality if disabled.

      Andrew


^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [PATCH V5 4/9] wifi: mac80211: Add support for ACPI WBRF
  2023-07-01  1:02   ` Andrew Lunn
@ 2023-07-04  3:12     ` Quan, Evan
  0 siblings, 0 replies; 28+ messages in thread
From: Quan, Evan @ 2023-07-04  3:12 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: rafael, lenb, Deucher, Alexander, Koenig, Christian, Pan, Xinhui,
	airlied, daniel, johannes, davem, edumazet, kuba, pabeni,
	Limonciello, Mario, mdaenzer, maarten.lankhorst, tzimmermann,
	hdegoede, jingyuwang_vip, Lazar, Lijo, jim.cromie, bellosilicio,
	andrealmeid, trix, jsg, arnd, linux-kernel, linux-acpi, amd-gfx,
	dri-devel, linux-wireless, netdev

[AMD Official Use Only - General]

Hi Andrew,

> -----Original Message-----
> From: Andrew Lunn <andrew@lunn.ch>
> Sent: Saturday, July 1, 2023 9:02 AM
> To: Quan, Evan <Evan.Quan@amd.com>
> Cc: rafael@kernel.org; lenb@kernel.org; Deucher, Alexander
> <Alexander.Deucher@amd.com>; Koenig, Christian
> <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>;
> airlied@gmail.com; daniel@ffwll.ch; johannes@sipsolutions.net;
> davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
> pabeni@redhat.com; Limonciello, Mario <Mario.Limonciello@amd.com>;
> mdaenzer@redhat.com; maarten.lankhorst@linux.intel.com;
> tzimmermann@suse.de; hdegoede@redhat.com; jingyuwang_vip@163.com;
> Lazar, Lijo <Lijo.Lazar@amd.com>; jim.cromie@gmail.com;
> bellosilicio@gmail.com; andrealmeid@igalia.com; trix@redhat.com;
> jsg@jsg.id.au; arnd@arndb.de; linux-kernel@vger.kernel.org; linux-
> acpi@vger.kernel.org; amd-gfx@lists.freedesktop.org; dri-
> devel@lists.freedesktop.org; linux-wireless@vger.kernel.org;
> netdev@vger.kernel.org
> Subject: Re: [PATCH V5 4/9] wifi: mac80211: Add support for ACPI WBRF
>
> > +static void get_chan_freq_boundary(u32 center_freq,
> > +                              u32 bandwidth,
> > +                              u64 *start,
> > +                              u64 *end)
> > +{
> > +   bandwidth = MHZ_TO_KHZ(bandwidth);
> > +   center_freq = MHZ_TO_KHZ(center_freq);
> > +
> > +   *start = center_freq - bandwidth / 2;
> > +   *end = center_freq + bandwidth / 2;
> > +
> > +   /* Frequency in HZ is expected */
> > +   *start = KHZ_TO_HZ(*start);
> > +   *end = KHZ_TO_HZ(*end);
> > +}
>
> This seems pretty generic, so maybe it should be moved into the shared code?
> It can then become a NOP when the functionality if disabled.
The shared code you mean is some place around mac80211?
Actually, there are two similar variants existed already: cfg80211_get_start_freq and cfg80211_get_end_freq.
The outputs of them are really what most mac80211 logics care.
The new API here is unlikely to be shared by other mac80211 part.
So, I suppose placing it here(only in wbrf.c) seems proper.
How do you think?

Evan
>
>       Andrew


^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [PATCH V5 2/9] driver core: add ACPI based WBRF mechanism introduced by AMD
  2023-07-01  0:51   ` Andrew Lunn
@ 2023-07-04  3:24     ` Quan, Evan
  0 siblings, 0 replies; 28+ messages in thread
From: Quan, Evan @ 2023-07-04  3:24 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: rafael, lenb, Deucher, Alexander, Koenig, Christian, Pan, Xinhui,
	airlied, daniel, johannes, davem, edumazet, kuba, pabeni,
	Limonciello, Mario, mdaenzer, maarten.lankhorst, tzimmermann,
	hdegoede, jingyuwang_vip, Lazar, Lijo, jim.cromie, bellosilicio,
	andrealmeid, trix, jsg, arnd, linux-kernel, linux-acpi, amd-gfx,
	dri-devel, linux-wireless, netdev

[AMD Official Use Only - General]

> -----Original Message-----
> From: Andrew Lunn <andrew@lunn.ch>
> Sent: Saturday, July 1, 2023 8:51 AM
> To: Quan, Evan <Evan.Quan@amd.com>
> Cc: rafael@kernel.org; lenb@kernel.org; Deucher, Alexander
> <Alexander.Deucher@amd.com>; Koenig, Christian
> <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>;
> airlied@gmail.com; daniel@ffwll.ch; johannes@sipsolutions.net;
> davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
> pabeni@redhat.com; Limonciello, Mario <Mario.Limonciello@amd.com>;
> mdaenzer@redhat.com; maarten.lankhorst@linux.intel.com;
> tzimmermann@suse.de; hdegoede@redhat.com; jingyuwang_vip@163.com;
> Lazar, Lijo <Lijo.Lazar@amd.com>; jim.cromie@gmail.com;
> bellosilicio@gmail.com; andrealmeid@igalia.com; trix@redhat.com;
> jsg@jsg.id.au; arnd@arndb.de; linux-kernel@vger.kernel.org; linux-
> acpi@vger.kernel.org; amd-gfx@lists.freedesktop.org; dri-
> devel@lists.freedesktop.org; linux-wireless@vger.kernel.org;
> netdev@vger.kernel.org
> Subject: Re: [PATCH V5 2/9] driver core: add ACPI based WBRF mechanism
> introduced by AMD
>
> > +   argv4 = kzalloc(sizeof(*argv4) * (2 * num_of_ranges + 2 + 1),
> GFP_KERNEL);
> > +   if (!argv4)
> > +           return -ENOMEM;
> > +
> > +   argv4[arg_idx].package.type = ACPI_TYPE_PACKAGE;
> > +   argv4[arg_idx].package.count = 2 + 2 * num_of_ranges;
> > +   argv4[arg_idx++].package.elements = &argv4[1];
> > +   argv4[arg_idx].integer.type = ACPI_TYPE_INTEGER;
> > +   argv4[arg_idx++].integer.value = num_of_ranges;
> > +   argv4[arg_idx].integer.type = ACPI_TYPE_INTEGER;
> > +   argv4[arg_idx++].integer.value = action;
>
> There is a lot of magic numbers in that kzalloc. It is being used as an array,
> kcalloc() would be a good start to make it more readable.
> Can some #define's be used to explain what the other numbers mean?
Sure, will update accordingly.
>
> > +   /*
> > +    * Bit 0 indicates whether there's support for any functions other than
> > +    * function 0.
> > +    */
>
> Please make use of the BIT macro to give the different bits informative names.
Sure.
>
> > +   if ((mask & 0x1) && (mask & funcs) == funcs)
> > +           return true;
> > +
> > +   return false;
> > +}
> > +
>
> > +int acpi_amd_wbrf_retrieve_exclusions(struct device *dev,
> > +                                 struct wbrf_ranges_out *out) {
> > +   struct acpi_device *adev = ACPI_COMPANION(dev);
> > +   union acpi_object *obj;
> > +
> > +   if (!adev)
> > +           return -ENODEV;
> > +
> > +   obj = acpi_evaluate_wbrf(adev->handle,
> > +                            WBRF_REVISION,
> > +                            WBRF_RETRIEVE);
> > +   if (!obj)
> > +           return -EINVAL;
> > +
> > +   WARN(obj->buffer.length != sizeof(*out),
> > +           "Unexpected buffer length");
> > +   memcpy(out, obj->buffer.pointer, obj->buffer.length);
>
> You WARN, and then overwrite whatever i passed the end of out?  Please at
> least use min(obj->buffer.length, sizeof(*out)), but better still:
>
>    if (obj->buffer.length != sizeof(*out)) {
>          dev_err(dev, "BIOS FUBAR, ignoring wrong sized WBRT information");
>        return -EINVAL;
>    }
OK. Sounds reasonable. Will update as suggested.
>
> > +#if defined(CONFIG_WBRF_GENERIC)
> >  static struct exclusion_range_pool wbrf_pool;
> >
> >  static int _wbrf_add_exclusion_ranges(struct wbrf_ranges_in *in) @@
> > -89,6 +92,7 @@ static int _wbrf_retrieve_exclusion_ranges(struct
> > wbrf_ranges_out *out)
> >
> >     return 0;
> >  }
> > +#endif
>
> I was expecting you would keep these tables, and then call into the BIOS as
> well. Having this table in debugfs seems like a useful thing to have for
> debugging the BIOS.
I'm not sure. Since these interfaces what we designed now kind of serve as a library.
When and where the debugfs should be created will be quite tricky.
>
> > +#ifdef CONFIG_WBRF_AMD_ACPI
> > +#else
> > +static inline bool
> > +acpi_amd_wbrf_supported_consumer(struct device *dev) { return false;
> > +} static inline bool acpi_amd_wbrf_supported_producer(struct device
> > +*dev) {return false; } static inline int
> > +acpi_amd_wbrf_remove_exclusion(struct device *dev,
> > +                          struct wbrf_ranges_in *in) { return -ENODEV; }
> static
> > +inline int acpi_amd_wbrf_add_exclusion(struct device *dev,
> > +                       struct wbrf_ranges_in *in) { return -ENODEV; } static
> inline
> > +int acpi_amd_wbrf_retrieve_exclusions(struct device *dev,
> > +                             struct wbrf_ranges_out *out) { return -
> ENODEV; }
>
> Do you actually need these stub versions?
Yes, these can be dropped. Let me update accordingly.

Evan
>
>       Andrew

^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [PATCH V5 1/9] drivers core: Add support for Wifi band RF mitigations
  2023-07-01  0:25     ` Andrew Lunn
@ 2023-07-04  3:25       ` Quan, Evan
  0 siblings, 0 replies; 28+ messages in thread
From: Quan, Evan @ 2023-07-04  3:25 UTC (permalink / raw)
  To: Andrew Lunn, Limonciello, Mario
  Cc: rafael, lenb, Deucher, Alexander, Koenig, Christian, Pan, Xinhui,
	airlied, daniel, johannes, davem, edumazet, kuba, pabeni,
	mdaenzer, maarten.lankhorst, tzimmermann, hdegoede,
	jingyuwang_vip, Lazar, Lijo, jim.cromie, bellosilicio,
	andrealmeid, trix, jsg, arnd, linux-kernel, linux-acpi, amd-gfx,
	dri-devel, linux-wireless, netdev

[AMD Official Use Only - General]

> -----Original Message-----
> From: Andrew Lunn <andrew@lunn.ch>
> Sent: Saturday, July 1, 2023 8:25 AM
> To: Limonciello, Mario <Mario.Limonciello@amd.com>
> Cc: Quan, Evan <Evan.Quan@amd.com>; rafael@kernel.org; lenb@kernel.org;
> Deucher, Alexander <Alexander.Deucher@amd.com>; Koenig, Christian
> <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>;
> airlied@gmail.com; daniel@ffwll.ch; johannes@sipsolutions.net;
> davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
> pabeni@redhat.com; mdaenzer@redhat.com;
> maarten.lankhorst@linux.intel.com; tzimmermann@suse.de;
> hdegoede@redhat.com; jingyuwang_vip@163.com; Lazar, Lijo
> <Lijo.Lazar@amd.com>; jim.cromie@gmail.com; bellosilicio@gmail.com;
> andrealmeid@igalia.com; trix@redhat.com; jsg@jsg.id.au; arnd@arndb.de;
> linux-kernel@vger.kernel.org; linux-acpi@vger.kernel.org; amd-
> gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org; linux-
> wireless@vger.kernel.org; netdev@vger.kernel.org
> Subject: Re: [PATCH V5 1/9] drivers core: Add support for Wifi band RF
> mitigations
>
> > Right now there are stubs for non CONFIG_WBRF as well as other patches
> > are using #ifdef CONFIG_WBRF or having their own stubs.  Like mac80211
> > patch looks for #ifdef CONFIG_WBRF.
> >
> > I think we should pick one or the other.
> >
> > Having other subsystems #ifdef CONFIG_WBRF will make the series easier
> > to land through multiple trees; so I have a slight leaning in that direction.
>
> #ifdef in C files is generally not liked because it makes build testing harder.
> There are more permutations to build. It is better to use
>
> if (IS_ENABLED(CONFIG_WBTR)) {
> }
>
> so that the code is compiled, and them throw away because
> IS_ENABLED(CONFIG_WBTR) evaluates to false.
>
> However, if the stubs are done correctly, the driver should not care. I doubt
> this is used in any sort of hot path where every instruction counts.
OK, will update as suggested.

Evan
>
>       Andrew

^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [PATCH V5 1/9] drivers core: Add support for Wifi band RF mitigations
  2023-07-01  0:19   ` Andrew Lunn
@ 2023-07-04  3:30     ` Quan, Evan
  2023-07-04 13:07       ` Andrew Lunn
  0 siblings, 1 reply; 28+ messages in thread
From: Quan, Evan @ 2023-07-04  3:30 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: rafael, lenb, Deucher, Alexander, Koenig, Christian, Pan, Xinhui,
	airlied, daniel, johannes, davem, edumazet, kuba, pabeni,
	Limonciello, Mario, mdaenzer, maarten.lankhorst, tzimmermann,
	hdegoede, jingyuwang_vip, Lazar, Lijo, jim.cromie, bellosilicio,
	andrealmeid, trix, jsg, arnd, linux-kernel, linux-acpi, amd-gfx,
	dri-devel, linux-wireless, netdev

[AMD Official Use Only - General]

> -----Original Message-----
> From: Andrew Lunn <andrew@lunn.ch>
> Sent: Saturday, July 1, 2023 8:20 AM
> To: Quan, Evan <Evan.Quan@amd.com>
> Cc: rafael@kernel.org; lenb@kernel.org; Deucher, Alexander
> <Alexander.Deucher@amd.com>; Koenig, Christian
> <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>;
> airlied@gmail.com; daniel@ffwll.ch; johannes@sipsolutions.net;
> davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
> pabeni@redhat.com; Limonciello, Mario <Mario.Limonciello@amd.com>;
> mdaenzer@redhat.com; maarten.lankhorst@linux.intel.com;
> tzimmermann@suse.de; hdegoede@redhat.com; jingyuwang_vip@163.com;
> Lazar, Lijo <Lijo.Lazar@amd.com>; jim.cromie@gmail.com;
> bellosilicio@gmail.com; andrealmeid@igalia.com; trix@redhat.com;
> jsg@jsg.id.au; arnd@arndb.de; linux-kernel@vger.kernel.org; linux-
> acpi@vger.kernel.org; amd-gfx@lists.freedesktop.org; dri-
> devel@lists.freedesktop.org; linux-wireless@vger.kernel.org;
> netdev@vger.kernel.org
> Subject: Re: [PATCH V5 1/9] drivers core: Add support for Wifi band RF
> mitigations
>
> > Drivers/subsystems contributing frequencies:
> >
> > 1) During probe, check `wbrf_supported_producer` to see if WBRF
> supported
> >    for the device.
>
> What is the purpose of this stage? Why would it not be supported for this
> device?
This is needed for wbrf support via ACPI mechanism. If BIOS(AML code) does not support the wbrf adding/removing for some device,
it should speak that out so that the device can be aware of that.
>
> > +#ifdef CONFIG_WBRF
> > +bool wbrf_supported_producer(struct device *dev); int
> > +wbrf_add_exclusion(struct device *adev,
> > +                  struct wbrf_ranges_in *in);
> > +int wbrf_remove_exclusion(struct device *dev,
> > +                     struct wbrf_ranges_in *in);
> > +int wbrf_retrieve_exclusions(struct device *dev,
> > +                        struct wbrf_ranges_out *out); bool
> > +wbrf_supported_consumer(struct device *dev);
> > +
> > +int wbrf_register_notifier(struct notifier_block *nb); int
> > +wbrf_unregister_notifier(struct notifier_block *nb); #else static
> > +inline bool wbrf_supported_producer(struct device *dev) { return
> > +false; } static inline int wbrf_add_exclusion(struct device *adev,
> > +                                struct wbrf_ranges_in *in) { return -
> ENODEV; } static inline
> > +int wbrf_remove_exclusion(struct device *dev,
> > +                                   struct wbrf_ranges_in *in) { return -
> ENODEV; }
>
> The normal aim of stubs is that so long as it is not expected to be fatal if the
> functionality is missing, the caller should not care if it is missing. So i would
> expect these to return 0, indicating everything worked as expected.
Sure, that makes sense.
>
> > +static inline int wbrf_retrieve_exclusions(struct device *dev,
> > +                                      struct wbrf_ranges_out *out)
> { return -ENODEV; }
>
> This is more complex. Ideally you want to return an empty set, so there is
> nothing to do. So i think the stub probably wants to do a memset and then
> return 0.
Right, will update it accordingly.
>
> > +static inline bool wbrf_supported_consumer(struct device *dev) {
> > +return false; } static inline int wbrf_register_notifier(struct
> > +notifier_block *nb) { return -ENODEV; } static inline int
> > +wbrf_unregister_notifier(struct notifier_block *nb) { return -ENODEV;
> > +}
>
> And these can just return 0.
Will update it.

Evan
>
>     Andrew

^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [PATCH V5 1/9] drivers core: Add support for Wifi band RF mitigations
  2023-06-30 16:40   ` Limonciello, Mario
  2023-07-01  0:25     ` Andrew Lunn
@ 2023-07-04  3:40     ` Quan, Evan
  2023-07-04  3:53       ` Mario Limonciello
  1 sibling, 1 reply; 28+ messages in thread
From: Quan, Evan @ 2023-07-04  3:40 UTC (permalink / raw)
  To: Limonciello, Mario, rafael, lenb, Deucher, Alexander, Koenig,
	Christian, Pan, Xinhui, airlied, daniel, johannes, davem,
	edumazet, kuba, pabeni, mdaenzer, maarten.lankhorst, tzimmermann,
	hdegoede, jingyuwang_vip, Lazar, Lijo, jim.cromie, bellosilicio,
	andrealmeid, trix, jsg, arnd
  Cc: linux-kernel, linux-acpi, amd-gfx, dri-devel, linux-wireless, netdev

[AMD Official Use Only - General]

> -----Original Message-----
> From: Limonciello, Mario <Mario.Limonciello@amd.com>
> Sent: Saturday, July 1, 2023 12:41 AM
> To: Quan, Evan <Evan.Quan@amd.com>; rafael@kernel.org; lenb@kernel.org;
> Deucher, Alexander <Alexander.Deucher@amd.com>; Koenig, Christian
> <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>;
> airlied@gmail.com; daniel@ffwll.ch; johannes@sipsolutions.net;
> davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
> pabeni@redhat.com; mdaenzer@redhat.com;
> maarten.lankhorst@linux.intel.com; tzimmermann@suse.de;
> hdegoede@redhat.com; jingyuwang_vip@163.com; Lazar, Lijo
> <Lijo.Lazar@amd.com>; jim.cromie@gmail.com; bellosilicio@gmail.com;
> andrealmeid@igalia.com; trix@redhat.com; jsg@jsg.id.au; arnd@arndb.de
> Cc: linux-kernel@vger.kernel.org; linux-acpi@vger.kernel.org; amd-
> gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org; linux-
> wireless@vger.kernel.org; netdev@vger.kernel.org
> Subject: Re: [PATCH V5 1/9] drivers core: Add support for Wifi band RF
> mitigations
>
> On 6/30/2023 05:32, Evan Quan wrote:
> > Due to electrical and mechanical constraints in certain platform
> > designs there may be likely interference of relatively high-powered
> > harmonics of the (G-)DDR memory clocks with local radio module
> > frequency bands used by Wifi 6/6e/7.
> >
> > To mitigate this, AMD has introduced a mechanism that devices can use
> > to notify active use of particular frequencies so that other devices
> > can make relative internal adjustments as necessary to avoid this resonance.
> >
> > In order for a device to support this, the expected flow for device
> > driver or subsystems:
> >
> > Drivers/subsystems contributing frequencies:
> >
> > 1) During probe, check `wbrf_supported_producer` to see if WBRF
> supported
> >     for the device.
> > 2) If adding frequencies, then call `wbrf_add_exclusion` with the
> >     start and end ranges of the frequencies.
> > 3) If removing frequencies, then call `wbrf_remove_exclusion` with
> >     start and end ranges of the frequencies.
> >
> > Drivers/subsystems responding to frequencies:
> >
> > 1) During probe, check `wbrf_supported_consumer` to see if WBRF is
> supported
> >     for the device.
> > 2) Call the `wbrf_retrieve_exclusions` to retrieve the current
> >     exclusions on receiving an ACPI notification for a new frequency
> >     change.
> >
> > Co-developed-by: Mario Limonciello <mario.limonciello@amd.com>
> > Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
> > Co-developed-by: Evan Quan <evan.quan@amd.com>
> > Signed-off-by: Evan Quan <evan.quan@amd.com>
> > --
> > v4->v5:
> >    - promote this to be a more generic solution with input argument taking
> >      `struct device` and provide better scalability to support non-ACPI
> >      scenarios(Andrew)
> >    - update the APIs naming and some other minor fixes(Rafael)
> > ---
> >   drivers/base/Kconfig  |   8 ++
> >   drivers/base/Makefile |   1 +
> >   drivers/base/wbrf.c   | 227
> ++++++++++++++++++++++++++++++++++++++++++
> >   include/linux/wbrf.h  |  65 ++++++++++++
> >   4 files changed, 301 insertions(+)
> >   create mode 100644 drivers/base/wbrf.c
> >   create mode 100644 include/linux/wbrf.h
> >
> > diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index
> > 2b8fd6bb7da0..5b441017b225 100644
> > --- a/drivers/base/Kconfig
> > +++ b/drivers/base/Kconfig
> > @@ -242,4 +242,12 @@ config FW_DEVLINK_SYNC_STATE_TIMEOUT
> >       command line option on every system/board your kernel is expected
> to
> >       work on.
> >
> > +config WBRF
> > +   bool "Wifi band RF mitigation mechanism"
> > +   default n
> > +   help
> > +     Wifi band RF mitigation mechanism allows multiple drivers from
> > +     different domains to notify the frequencies in use so that hardware
> > +     can be reconfigured to avoid harmonic conflicts.
> > +
> >   endmenu
> > diff --git a/drivers/base/Makefile b/drivers/base/Makefile index
> > 3079bfe53d04..c844f68a6830 100644
> > --- a/drivers/base/Makefile
> > +++ b/drivers/base/Makefile
> > @@ -26,6 +26,7 @@ obj-$(CONFIG_GENERIC_MSI_IRQ) += platform-msi.o
> >   obj-$(CONFIG_GENERIC_ARCH_TOPOLOGY) += arch_topology.o
> >   obj-$(CONFIG_GENERIC_ARCH_NUMA) += arch_numa.o
> >   obj-$(CONFIG_ACPI) += physical_location.o
> > +obj-$(CONFIG_WBRF) += wbrf.o
> >
> >   obj-y                     += test/
> >
> > diff --git a/drivers/base/wbrf.c b/drivers/base/wbrf.c new file mode
> > 100644 index 000000000000..2163a8ec8a9a
> > --- /dev/null
> > +++ b/drivers/base/wbrf.c
> > @@ -0,0 +1,227 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Wifi Band Exclusion Interface
> > + * Copyright (C) 2023 Advanced Micro Devices
> > + *
> > + */
> > +
> > +#include <linux/wbrf.h>
> > +
> > +static BLOCKING_NOTIFIER_HEAD(wbrf_chain_head);
> > +static DEFINE_MUTEX(wbrf_mutex);
> > +static struct exclusion_range_pool wbrf_pool;
> > +
> > +static int _wbrf_add_exclusion_ranges(struct wbrf_ranges_in *in) {
> > +   int i, j;
> > +
> > +   for (i = 0; i < ARRAY_SIZE(in->band_list); i++) {
> > +           if (!in->band_list[i].start &&
> > +               !in->band_list[i].end)
> > +                   continue;
> > +
> > +           for (j = 0; j < ARRAY_SIZE(wbrf_pool.band_list); j++) {
> > +                   if (wbrf_pool.band_list[j].start == in-
> >band_list[i].start &&
> > +                       wbrf_pool.band_list[j].end == in->band_list[i].end) {
> > +                           wbrf_pool.ref_counter[j]++;
> > +                           break;
> > +                   }
> > +           }
> > +           if (j < ARRAY_SIZE(wbrf_pool.band_list))
> > +                   continue;
> > +
> > +           for (j = 0; j < ARRAY_SIZE(wbrf_pool.band_list); j++) {
> > +                   if (!wbrf_pool.band_list[j].start &&
> > +                       !wbrf_pool.band_list[j].end) {
> > +                           wbrf_pool.band_list[j].start = in-
> >band_list[i].start;
> > +                           wbrf_pool.band_list[j].end = in-
> >band_list[i].end;
> > +                           wbrf_pool.ref_counter[j] = 1;
> > +                           break;
> > +                   }
> > +           }
> > +           if (j >= ARRAY_SIZE(wbrf_pool.band_list))
> > +                   return -ENOSPC;
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> > +static int _wbrf_remove_exclusion_ranges(struct wbrf_ranges_in *in) {
> > +   int i, j;
> > +
> > +   for (i = 0; i < ARRAY_SIZE(in->band_list); i++) {
> > +           if (!in->band_list[i].start &&
> > +               !in->band_list[i].end)
> > +                   continue;
> > +
> > +           for (j = 0; j < ARRAY_SIZE(wbrf_pool.band_list); j++) {
> > +                   if (wbrf_pool.band_list[j].start == in-
> >band_list[i].start &&
> > +                       wbrf_pool.band_list[j].end == in->band_list[i].end) {
> > +                           wbrf_pool.ref_counter[j]--;
> > +                           if (!wbrf_pool.ref_counter[j]) {
> > +                                   wbrf_pool.band_list[j].start = 0;
> > +                                   wbrf_pool.band_list[j].end = 0;
> > +                           }
> > +                           break;
> > +                   }
> > +           }
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> > +static int _wbrf_retrieve_exclusion_ranges(struct wbrf_ranges_out
> > +*out) {
> > +   int out_idx = 0;
> > +   int i;
> > +
> > +   memset(out, 0, sizeof(*out));
> > +
> > +   for (i = 0; i < ARRAY_SIZE(wbrf_pool.band_list); i++) {
> > +           if (!wbrf_pool.band_list[i].start &&
> > +               !wbrf_pool.band_list[i].end)
> > +                   continue;
> > +
> > +           out->band_list[out_idx].start = wbrf_pool.band_list[i].start;
> > +           out->band_list[out_idx++].end = wbrf_pool.band_list[i].end;
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> > +/**
> > + * wbrf_supported_producer - Determine if the device can report
> > +frequencies
> > + *
> > + * @dev: device pointer
> > + *
> > + * WBRF is used to mitigate devices that cause harmonic interference.
> > + * This function will determine if this device needs to report such
> frequencies.
> > + */
> > +bool wbrf_supported_producer(struct device *dev) {
> > +   return true;
> > +}
> > +EXPORT_SYMBOL_GPL(wbrf_supported_producer);
> > +
> > +/**
> > + * wbrf_add_exclusion - Add frequency ranges to the exclusion list
> > + *
> > + * @dev: device pointer
> > + * @in: input structure containing the frequency ranges to be added
> > + *
> > + * Add frequencies into the exclusion list for supported consumers
> > + * to react to.
> > + */
> > +int wbrf_add_exclusion(struct device *dev,
> > +                  struct wbrf_ranges_in *in)
> > +{
> > +   int r;
> > +
> > +   mutex_lock(&wbrf_mutex);
> > +
> > +   r = _wbrf_add_exclusion_ranges(in);
> > +
> > +   mutex_unlock(&wbrf_mutex);
> > +   if (r)
> > +           return r;
> > +
> > +   blocking_notifier_call_chain(&wbrf_chain_head, WBRF_CHANGED,
> NULL);
> > +
> > +   return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(wbrf_add_exclusion);
> > +
> > +/**
> > + * wbrf_remove_exclusion - Remove frequency ranges from the exclusion
> > +list
> > + *
> > + * @dev: device pointer
> > + * @in: input structure containing the frequency ranges to be removed
> > + *
> > + * Remove frequencies from the exclusion list for supported consumers
> > + * to react to.
> > + */
> > +int wbrf_remove_exclusion(struct device *dev,
> > +                     struct wbrf_ranges_in *in)
> > +{
> > +   int r;
> > +
> > +   mutex_lock(&wbrf_mutex);
> > +
> > +   r = _wbrf_remove_exclusion_ranges(in);
> > +
> > +   mutex_unlock(&wbrf_mutex);
> > +   if (r)
> > +           return r;
> > +
> > +   blocking_notifier_call_chain(&wbrf_chain_head, WBRF_CHANGED,
> NULL);
> > +
> > +   return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(wbrf_remove_exclusion);
> > +
> > +/**
> > + * wbrf_supported_consumer - Determine if the device can react to
> > +frequencies
> > + *
> > + * @dev: device pointer
> > + *
> > + * WBRF is used to mitigate devices that cause harmonic interference.
> > + * This function will determine if this device needs to react to
> > +reports from
> > + * other devices for such frequencies.
> > + */
> > +bool wbrf_supported_consumer(struct device *dev) {
> > +   return true;
> > +}
> > +EXPORT_SYMBOL_GPL(wbrf_supported_consumer);
> > +
> > +/**
> > + * wbrf_register_notifier - Register for notifications of frequency
> > +changes
> > + *
> > + * @nb: driver notifier block
> > + *
> > + * WBRF is used to mitigate devices that cause harmonic interference.
> > + * This function will allow consumers to register for frequency notifications.
> > + */
> > +int wbrf_register_notifier(struct notifier_block *nb) {
> > +   return blocking_notifier_chain_register(&wbrf_chain_head, nb); }
> > +EXPORT_SYMBOL_GPL(wbrf_register_notifier);
> > +
> > +/**
> > + * wbrf_unregister_notifier - Unregister for notifications of
> > +frequency changes
> > + *
> > + * @nb: driver notifier block
> > + *
> > + * WBRF is used to mitigate devices that cause harmonic interference.
> > + * This function will allow consumers to unregister for frequency
> notifications.
> > + */
> > +int wbrf_unregister_notifier(struct notifier_block *nb) {
> > +   return blocking_notifier_chain_unregister(&wbrf_chain_head, nb); }
> > +EXPORT_SYMBOL_GPL(wbrf_unregister_notifier);
> > +
> > +/**
> > + * wbrf_retrieve_exclusions - Retrieve the exclusion list
> > + *
> > + * @dev: device pointer
> > + * @out: output structure containing the frequency ranges to be
> > +excluded
> > + *
> > + * Retrieve the current exclusion list  */ int
> > +wbrf_retrieve_exclusions(struct device *dev,
> > +                        struct wbrf_ranges_out *out)
> > +{
> > +   int r;
> > +
> > +   mutex_lock(&wbrf_mutex);
> > +
> > +   r = _wbrf_retrieve_exclusion_ranges(out);
> > +
> > +   mutex_unlock(&wbrf_mutex);
> > +
> > +   return r;
> > +}
> > +EXPORT_SYMBOL_GPL(wbrf_retrieve_exclusions);
> > diff --git a/include/linux/wbrf.h b/include/linux/wbrf.h new file mode
> > 100644 index 000000000000..3ca95786cef5
> > --- /dev/null
> > +++ b/include/linux/wbrf.h
> > @@ -0,0 +1,65 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Wifi Band Exclusion Interface
> > + * Copyright (C) 2023 Advanced Micro Devices  */
> > +
> > +#ifndef _LINUX_WBRF_H
> > +#define _LINUX_WBRF_H
> > +
> > +#include <linux/device.h>
> > +
> > +/* Maximum number of wbrf ranges */
> > +#define MAX_NUM_OF_WBRF_RANGES             11
> > +
> > +struct exclusion_range {
> > +   /* start and end point of the frequency range in Hz */
> > +   uint64_t        start;
> > +   uint64_t        end;
> > +};
> > +
> > +struct exclusion_range_pool {
> > +   struct exclusion_range  band_list[MAX_NUM_OF_WBRF_RANGES];
> > +   uint64_t
>       ref_counter[MAX_NUM_OF_WBRF_RANGES];
> > +};
> > +
> > +struct wbrf_ranges_in {
> > +   /* valid entry: `start` and `end` filled with non-zero values */
> > +   struct exclusion_range  band_list[MAX_NUM_OF_WBRF_RANGES];
> > +};
> > +
> > +struct wbrf_ranges_out {
> > +   uint32_t                num_of_ranges;
> > +   struct exclusion_range  band_list[MAX_NUM_OF_WBRF_RANGES];
> > +} __packed;
> > +
> > +enum wbrf_notifier_actions {
> > +   WBRF_CHANGED,
> > +};
> > +
> > +#ifdef CONFIG_WBRF
> > +bool wbrf_supported_producer(struct device *dev); int
> > +wbrf_add_exclusion(struct device *adev,
> > +                  struct wbrf_ranges_in *in);
> > +int wbrf_remove_exclusion(struct device *dev,
> > +                     struct wbrf_ranges_in *in);
> > +int wbrf_retrieve_exclusions(struct device *dev,
> > +                        struct wbrf_ranges_out *out); bool
> > +wbrf_supported_consumer(struct device *dev);
> > +
> > +int wbrf_register_notifier(struct notifier_block *nb); int
> > +wbrf_unregister_notifier(struct notifier_block *nb); #else static
> > +inline bool wbrf_supported_producer(struct device *dev) { return
> > +false; } static inline int wbrf_add_exclusion(struct device *adev,
> > +                                struct wbrf_ranges_in *in) { return -
> ENODEV; } static inline
> > +int wbrf_remove_exclusion(struct device *dev,
> > +                                   struct wbrf_ranges_in *in) { return -
> ENODEV; } static inline int
> > +wbrf_retrieve_exclusions(struct device *dev,
> > +                                      struct wbrf_ranges_out *out)
> { return -ENODEV; } static
> > +inline bool wbrf_supported_consumer(struct device *dev) { return
> > +false; } static inline int wbrf_register_notifier(struct
> > +notifier_block *nb) { return -ENODEV; } static inline int
> > +wbrf_unregister_notifier(struct notifier_block *nb) { return -ENODEV;
> > +} #endif
> > +
>
> Right now there are stubs for non CONFIG_WBRF as well as other patches are
> using #ifdef CONFIG_WBRF or having their own stubs.  Like mac80211 patch
> looks for #ifdef CONFIG_WBRF.
>
> I think we should pick one or the other.
Right..
>
> Having other subsystems #ifdef CONFIG_WBRF will make the series easier to
> land through multiple trees; so I have a slight leaning in that direction.
I kind of expecting to use the other way. That is to make CONFIG_WBRF agnostic to other subsystems or drivers.
They (other subsystems or drivers) can always assume those wbrf_xxxxx interfaces are available.
What they need to care only are the return values of those interfaces.
How do you think?

Evan
>
> > +#endif /* _LINUX_WBRF_H */


^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [PATCH V5 1/9] drivers core: Add support for Wifi band RF mitigations
  2023-06-30 13:38   ` Simon Horman
@ 2023-07-04  3:41     ` Quan, Evan
  0 siblings, 0 replies; 28+ messages in thread
From: Quan, Evan @ 2023-07-04  3:41 UTC (permalink / raw)
  To: Simon Horman
  Cc: rafael, lenb, Deucher, Alexander, Koenig, Christian, Pan, Xinhui,
	airlied, daniel, johannes, davem, edumazet, kuba, pabeni,
	Limonciello, Mario, mdaenzer, maarten.lankhorst, tzimmermann,
	hdegoede, jingyuwang_vip, Lazar, Lijo, jim.cromie, bellosilicio,
	andrealmeid, trix, jsg, arnd, linux-kernel, linux-acpi, amd-gfx,
	dri-devel, linux-wireless, netdev

[AMD Official Use Only - General]

> -----Original Message-----
> From: Simon Horman <simon.horman@corigine.com>
> Sent: Friday, June 30, 2023 9:39 PM
> To: Quan, Evan <Evan.Quan@amd.com>
> Cc: rafael@kernel.org; lenb@kernel.org; Deucher, Alexander
> <Alexander.Deucher@amd.com>; Koenig, Christian
> <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>;
> airlied@gmail.com; daniel@ffwll.ch; johannes@sipsolutions.net;
> davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
> pabeni@redhat.com; Limonciello, Mario <Mario.Limonciello@amd.com>;
> mdaenzer@redhat.com; maarten.lankhorst@linux.intel.com;
> tzimmermann@suse.de; hdegoede@redhat.com; jingyuwang_vip@163.com;
> Lazar, Lijo <Lijo.Lazar@amd.com>; jim.cromie@gmail.com;
> bellosilicio@gmail.com; andrealmeid@igalia.com; trix@redhat.com;
> jsg@jsg.id.au; arnd@arndb.de; linux-kernel@vger.kernel.org; linux-
> acpi@vger.kernel.org; amd-gfx@lists.freedesktop.org; dri-
> devel@lists.freedesktop.org; linux-wireless@vger.kernel.org;
> netdev@vger.kernel.org
> Subject: Re: [PATCH V5 1/9] drivers core: Add support for Wifi band RF
> mitigations
>
> On Fri, Jun 30, 2023 at 06:32:32PM +0800, Evan Quan wrote:
>
> ...
>
> > diff --git a/include/linux/wbrf.h b/include/linux/wbrf.h
> > new file mode 100644
> > index 000000000000..3ca95786cef5
> > --- /dev/null
> > +++ b/include/linux/wbrf.h
> > @@ -0,0 +1,65 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Wifi Band Exclusion Interface
> > + * Copyright (C) 2023 Advanced Micro Devices
> > + */
> > +
> > +#ifndef _LINUX_WBRF_H
> > +#define _LINUX_WBRF_H
> > +
> > +#include <linux/device.h>
> > +
> > +/* Maximum number of wbrf ranges */
> > +#define MAX_NUM_OF_WBRF_RANGES             11
> > +
> > +struct exclusion_range {
> > +   /* start and end point of the frequency range in Hz */
> > +   uint64_t        start;
> > +   uint64_t        end;
> > +};
> > +
> > +struct exclusion_range_pool {
> > +   struct exclusion_range  band_list[MAX_NUM_OF_WBRF_RANGES];
> > +   uint64_t
>       ref_counter[MAX_NUM_OF_WBRF_RANGES];
> > +};
> > +
> > +struct wbrf_ranges_in {
> > +   /* valid entry: `start` and `end` filled with non-zero values */
> > +   struct exclusion_range  band_list[MAX_NUM_OF_WBRF_RANGES];
> > +};
> > +
> > +struct wbrf_ranges_out {
> > +   uint32_t                num_of_ranges;
> > +   struct exclusion_range  band_list[MAX_NUM_OF_WBRF_RANGES];
> > +} __packed;
> > +
> > +enum wbrf_notifier_actions {
> > +   WBRF_CHANGED,
> > +};
>
> Hi Evan,
>
> checkpatch suggests that u64 and u32 might be more appropriate types here,
> as they are Kernel types, whereas the ones use are user-space types.
Thanks for pointing this out. Will update them accordingly.

Evan
>
> ...

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH V5 1/9] drivers core: Add support for Wifi band RF mitigations
  2023-07-04  3:40     ` Quan, Evan
@ 2023-07-04  3:53       ` Mario Limonciello
  0 siblings, 0 replies; 28+ messages in thread
From: Mario Limonciello @ 2023-07-04  3:53 UTC (permalink / raw)
  To: Quan, Evan, rafael, lenb, Deucher, Alexander, Koenig, Christian,
	Pan, Xinhui, airlied, daniel, johannes, davem, edumazet, kuba,
	pabeni, mdaenzer, maarten.lankhorst, tzimmermann, hdegoede,
	jingyuwang_vip, Lazar, Lijo, jim.cromie, bellosilicio,
	andrealmeid, trix, jsg, arnd
  Cc: linux-kernel, linux-acpi, amd-gfx, dri-devel, linux-wireless, netdev

On 7/3/23 22:40, Quan, Evan wrote:
> [AMD Official Use Only - General]
> 
>> -----Original Message-----
>> From: Limonciello, Mario <Mario.Limonciello@amd.com>
>> Sent: Saturday, July 1, 2023 12:41 AM
>> To: Quan, Evan <Evan.Quan@amd.com>; rafael@kernel.org; lenb@kernel.org;
>> Deucher, Alexander <Alexander.Deucher@amd.com>; Koenig, Christian
>> <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>;
>> airlied@gmail.com; daniel@ffwll.ch; johannes@sipsolutions.net;
>> davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
>> pabeni@redhat.com; mdaenzer@redhat.com;
>> maarten.lankhorst@linux.intel.com; tzimmermann@suse.de;
>> hdegoede@redhat.com; jingyuwang_vip@163.com; Lazar, Lijo
>> <Lijo.Lazar@amd.com>; jim.cromie@gmail.com; bellosilicio@gmail.com;
>> andrealmeid@igalia.com; trix@redhat.com; jsg@jsg.id.au; arnd@arndb.de
>> Cc: linux-kernel@vger.kernel.org; linux-acpi@vger.kernel.org; amd-
>> gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org; linux-
>> wireless@vger.kernel.org; netdev@vger.kernel.org
>> Subject: Re: [PATCH V5 1/9] drivers core: Add support for Wifi band RF
>> mitigations
>>
>> On 6/30/2023 05:32, Evan Quan wrote:
>>> Due to electrical and mechanical constraints in certain platform
>>> designs there may be likely interference of relatively high-powered
>>> harmonics of the (G-)DDR memory clocks with local radio module
>>> frequency bands used by Wifi 6/6e/7.
>>>
>>> To mitigate this, AMD has introduced a mechanism that devices can use
>>> to notify active use of particular frequencies so that other devices
>>> can make relative internal adjustments as necessary to avoid this resonance.
>>>
>>> In order for a device to support this, the expected flow for device
>>> driver or subsystems:
>>>
>>> Drivers/subsystems contributing frequencies:
>>>
>>> 1) During probe, check `wbrf_supported_producer` to see if WBRF
>> supported
>>>      for the device.
>>> 2) If adding frequencies, then call `wbrf_add_exclusion` with the
>>>      start and end ranges of the frequencies.
>>> 3) If removing frequencies, then call `wbrf_remove_exclusion` with
>>>      start and end ranges of the frequencies.
>>>
>>> Drivers/subsystems responding to frequencies:
>>>
>>> 1) During probe, check `wbrf_supported_consumer` to see if WBRF is
>> supported
>>>      for the device.
>>> 2) Call the `wbrf_retrieve_exclusions` to retrieve the current
>>>      exclusions on receiving an ACPI notification for a new frequency
>>>      change.
>>>
>>> Co-developed-by: Mario Limonciello <mario.limonciello@amd.com>
>>> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
>>> Co-developed-by: Evan Quan <evan.quan@amd.com>
>>> Signed-off-by: Evan Quan <evan.quan@amd.com>
>>> --
>>> v4->v5:
>>>     - promote this to be a more generic solution with input argument taking
>>>       `struct device` and provide better scalability to support non-ACPI
>>>       scenarios(Andrew)
>>>     - update the APIs naming and some other minor fixes(Rafael)
>>> ---
>>>    drivers/base/Kconfig  |   8 ++
>>>    drivers/base/Makefile |   1 +
>>>    drivers/base/wbrf.c   | 227
>> ++++++++++++++++++++++++++++++++++++++++++
>>>    include/linux/wbrf.h  |  65 ++++++++++++
>>>    4 files changed, 301 insertions(+)
>>>    create mode 100644 drivers/base/wbrf.c
>>>    create mode 100644 include/linux/wbrf.h
>>>
>>> diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index
>>> 2b8fd6bb7da0..5b441017b225 100644
>>> --- a/drivers/base/Kconfig
>>> +++ b/drivers/base/Kconfig
>>> @@ -242,4 +242,12 @@ config FW_DEVLINK_SYNC_STATE_TIMEOUT
>>>        command line option on every system/board your kernel is expected
>> to
>>>        work on.
>>>
>>> +config WBRF
>>> +   bool "Wifi band RF mitigation mechanism"
>>> +   default n
>>> +   help
>>> +     Wifi band RF mitigation mechanism allows multiple drivers from
>>> +     different domains to notify the frequencies in use so that hardware
>>> +     can be reconfigured to avoid harmonic conflicts.
>>> +
>>>    endmenu
>>> diff --git a/drivers/base/Makefile b/drivers/base/Makefile index
>>> 3079bfe53d04..c844f68a6830 100644
>>> --- a/drivers/base/Makefile
>>> +++ b/drivers/base/Makefile
>>> @@ -26,6 +26,7 @@ obj-$(CONFIG_GENERIC_MSI_IRQ) += platform-msi.o
>>>    obj-$(CONFIG_GENERIC_ARCH_TOPOLOGY) += arch_topology.o
>>>    obj-$(CONFIG_GENERIC_ARCH_NUMA) += arch_numa.o
>>>    obj-$(CONFIG_ACPI) += physical_location.o
>>> +obj-$(CONFIG_WBRF) += wbrf.o
>>>
>>>    obj-y                     += test/
>>>
>>> diff --git a/drivers/base/wbrf.c b/drivers/base/wbrf.c new file mode
>>> 100644 index 000000000000..2163a8ec8a9a
>>> --- /dev/null
>>> +++ b/drivers/base/wbrf.c
>>> @@ -0,0 +1,227 @@
>>> +// SPDX-License-Identifier: GPL-2.0
>>> +/*
>>> + * Wifi Band Exclusion Interface
>>> + * Copyright (C) 2023 Advanced Micro Devices
>>> + *
>>> + */
>>> +
>>> +#include <linux/wbrf.h>
>>> +
>>> +static BLOCKING_NOTIFIER_HEAD(wbrf_chain_head);
>>> +static DEFINE_MUTEX(wbrf_mutex);
>>> +static struct exclusion_range_pool wbrf_pool;
>>> +
>>> +static int _wbrf_add_exclusion_ranges(struct wbrf_ranges_in *in) {
>>> +   int i, j;
>>> +
>>> +   for (i = 0; i < ARRAY_SIZE(in->band_list); i++) {
>>> +           if (!in->band_list[i].start &&
>>> +               !in->band_list[i].end)
>>> +                   continue;
>>> +
>>> +           for (j = 0; j < ARRAY_SIZE(wbrf_pool.band_list); j++) {
>>> +                   if (wbrf_pool.band_list[j].start == in-
>>> band_list[i].start &&
>>> +                       wbrf_pool.band_list[j].end == in->band_list[i].end) {
>>> +                           wbrf_pool.ref_counter[j]++;
>>> +                           break;
>>> +                   }
>>> +           }
>>> +           if (j < ARRAY_SIZE(wbrf_pool.band_list))
>>> +                   continue;
>>> +
>>> +           for (j = 0; j < ARRAY_SIZE(wbrf_pool.band_list); j++) {
>>> +                   if (!wbrf_pool.band_list[j].start &&
>>> +                       !wbrf_pool.band_list[j].end) {
>>> +                           wbrf_pool.band_list[j].start = in-
>>> band_list[i].start;
>>> +                           wbrf_pool.band_list[j].end = in-
>>> band_list[i].end;
>>> +                           wbrf_pool.ref_counter[j] = 1;
>>> +                           break;
>>> +                   }
>>> +           }
>>> +           if (j >= ARRAY_SIZE(wbrf_pool.band_list))
>>> +                   return -ENOSPC;
>>> +   }
>>> +
>>> +   return 0;
>>> +}
>>> +
>>> +static int _wbrf_remove_exclusion_ranges(struct wbrf_ranges_in *in) {
>>> +   int i, j;
>>> +
>>> +   for (i = 0; i < ARRAY_SIZE(in->band_list); i++) {
>>> +           if (!in->band_list[i].start &&
>>> +               !in->band_list[i].end)
>>> +                   continue;
>>> +
>>> +           for (j = 0; j < ARRAY_SIZE(wbrf_pool.band_list); j++) {
>>> +                   if (wbrf_pool.band_list[j].start == in-
>>> band_list[i].start &&
>>> +                       wbrf_pool.band_list[j].end == in->band_list[i].end) {
>>> +                           wbrf_pool.ref_counter[j]--;
>>> +                           if (!wbrf_pool.ref_counter[j]) {
>>> +                                   wbrf_pool.band_list[j].start = 0;
>>> +                                   wbrf_pool.band_list[j].end = 0;
>>> +                           }
>>> +                           break;
>>> +                   }
>>> +           }
>>> +   }
>>> +
>>> +   return 0;
>>> +}
>>> +
>>> +static int _wbrf_retrieve_exclusion_ranges(struct wbrf_ranges_out
>>> +*out) {
>>> +   int out_idx = 0;
>>> +   int i;
>>> +
>>> +   memset(out, 0, sizeof(*out));
>>> +
>>> +   for (i = 0; i < ARRAY_SIZE(wbrf_pool.band_list); i++) {
>>> +           if (!wbrf_pool.band_list[i].start &&
>>> +               !wbrf_pool.band_list[i].end)
>>> +                   continue;
>>> +
>>> +           out->band_list[out_idx].start = wbrf_pool.band_list[i].start;
>>> +           out->band_list[out_idx++].end = wbrf_pool.band_list[i].end;
>>> +   }
>>> +
>>> +   return 0;
>>> +}
>>> +
>>> +/**
>>> + * wbrf_supported_producer - Determine if the device can report
>>> +frequencies
>>> + *
>>> + * @dev: device pointer
>>> + *
>>> + * WBRF is used to mitigate devices that cause harmonic interference.
>>> + * This function will determine if this device needs to report such
>> frequencies.
>>> + */
>>> +bool wbrf_supported_producer(struct device *dev) {
>>> +   return true;
>>> +}
>>> +EXPORT_SYMBOL_GPL(wbrf_supported_producer);
>>> +
>>> +/**
>>> + * wbrf_add_exclusion - Add frequency ranges to the exclusion list
>>> + *
>>> + * @dev: device pointer
>>> + * @in: input structure containing the frequency ranges to be added
>>> + *
>>> + * Add frequencies into the exclusion list for supported consumers
>>> + * to react to.
>>> + */
>>> +int wbrf_add_exclusion(struct device *dev,
>>> +                  struct wbrf_ranges_in *in)
>>> +{
>>> +   int r;
>>> +
>>> +   mutex_lock(&wbrf_mutex);
>>> +
>>> +   r = _wbrf_add_exclusion_ranges(in);
>>> +
>>> +   mutex_unlock(&wbrf_mutex);
>>> +   if (r)
>>> +           return r;
>>> +
>>> +   blocking_notifier_call_chain(&wbrf_chain_head, WBRF_CHANGED,
>> NULL);
>>> +
>>> +   return 0;
>>> +}
>>> +EXPORT_SYMBOL_GPL(wbrf_add_exclusion);
>>> +
>>> +/**
>>> + * wbrf_remove_exclusion - Remove frequency ranges from the exclusion
>>> +list
>>> + *
>>> + * @dev: device pointer
>>> + * @in: input structure containing the frequency ranges to be removed
>>> + *
>>> + * Remove frequencies from the exclusion list for supported consumers
>>> + * to react to.
>>> + */
>>> +int wbrf_remove_exclusion(struct device *dev,
>>> +                     struct wbrf_ranges_in *in)
>>> +{
>>> +   int r;
>>> +
>>> +   mutex_lock(&wbrf_mutex);
>>> +
>>> +   r = _wbrf_remove_exclusion_ranges(in);
>>> +
>>> +   mutex_unlock(&wbrf_mutex);
>>> +   if (r)
>>> +           return r;
>>> +
>>> +   blocking_notifier_call_chain(&wbrf_chain_head, WBRF_CHANGED,
>> NULL);
>>> +
>>> +   return 0;
>>> +}
>>> +EXPORT_SYMBOL_GPL(wbrf_remove_exclusion);
>>> +
>>> +/**
>>> + * wbrf_supported_consumer - Determine if the device can react to
>>> +frequencies
>>> + *
>>> + * @dev: device pointer
>>> + *
>>> + * WBRF is used to mitigate devices that cause harmonic interference.
>>> + * This function will determine if this device needs to react to
>>> +reports from
>>> + * other devices for such frequencies.
>>> + */
>>> +bool wbrf_supported_consumer(struct device *dev) {
>>> +   return true;
>>> +}
>>> +EXPORT_SYMBOL_GPL(wbrf_supported_consumer);
>>> +
>>> +/**
>>> + * wbrf_register_notifier - Register for notifications of frequency
>>> +changes
>>> + *
>>> + * @nb: driver notifier block
>>> + *
>>> + * WBRF is used to mitigate devices that cause harmonic interference.
>>> + * This function will allow consumers to register for frequency notifications.
>>> + */
>>> +int wbrf_register_notifier(struct notifier_block *nb) {
>>> +   return blocking_notifier_chain_register(&wbrf_chain_head, nb); }
>>> +EXPORT_SYMBOL_GPL(wbrf_register_notifier);
>>> +
>>> +/**
>>> + * wbrf_unregister_notifier - Unregister for notifications of
>>> +frequency changes
>>> + *
>>> + * @nb: driver notifier block
>>> + *
>>> + * WBRF is used to mitigate devices that cause harmonic interference.
>>> + * This function will allow consumers to unregister for frequency
>> notifications.
>>> + */
>>> +int wbrf_unregister_notifier(struct notifier_block *nb) {
>>> +   return blocking_notifier_chain_unregister(&wbrf_chain_head, nb); }
>>> +EXPORT_SYMBOL_GPL(wbrf_unregister_notifier);
>>> +
>>> +/**
>>> + * wbrf_retrieve_exclusions - Retrieve the exclusion list
>>> + *
>>> + * @dev: device pointer
>>> + * @out: output structure containing the frequency ranges to be
>>> +excluded
>>> + *
>>> + * Retrieve the current exclusion list  */ int
>>> +wbrf_retrieve_exclusions(struct device *dev,
>>> +                        struct wbrf_ranges_out *out)
>>> +{
>>> +   int r;
>>> +
>>> +   mutex_lock(&wbrf_mutex);
>>> +
>>> +   r = _wbrf_retrieve_exclusion_ranges(out);
>>> +
>>> +   mutex_unlock(&wbrf_mutex);
>>> +
>>> +   return r;
>>> +}
>>> +EXPORT_SYMBOL_GPL(wbrf_retrieve_exclusions);
>>> diff --git a/include/linux/wbrf.h b/include/linux/wbrf.h new file mode
>>> 100644 index 000000000000..3ca95786cef5
>>> --- /dev/null
>>> +++ b/include/linux/wbrf.h
>>> @@ -0,0 +1,65 @@
>>> +/* SPDX-License-Identifier: GPL-2.0 */
>>> +/*
>>> + * Wifi Band Exclusion Interface
>>> + * Copyright (C) 2023 Advanced Micro Devices  */
>>> +
>>> +#ifndef _LINUX_WBRF_H
>>> +#define _LINUX_WBRF_H
>>> +
>>> +#include <linux/device.h>
>>> +
>>> +/* Maximum number of wbrf ranges */
>>> +#define MAX_NUM_OF_WBRF_RANGES             11
>>> +
>>> +struct exclusion_range {
>>> +   /* start and end point of the frequency range in Hz */
>>> +   uint64_t        start;
>>> +   uint64_t        end;
>>> +};
>>> +
>>> +struct exclusion_range_pool {
>>> +   struct exclusion_range  band_list[MAX_NUM_OF_WBRF_RANGES];
>>> +   uint64_t
>>        ref_counter[MAX_NUM_OF_WBRF_RANGES];
>>> +};
>>> +
>>> +struct wbrf_ranges_in {
>>> +   /* valid entry: `start` and `end` filled with non-zero values */
>>> +   struct exclusion_range  band_list[MAX_NUM_OF_WBRF_RANGES];
>>> +};
>>> +
>>> +struct wbrf_ranges_out {
>>> +   uint32_t                num_of_ranges;
>>> +   struct exclusion_range  band_list[MAX_NUM_OF_WBRF_RANGES];
>>> +} __packed;
>>> +
>>> +enum wbrf_notifier_actions {
>>> +   WBRF_CHANGED,
>>> +};
>>> +
>>> +#ifdef CONFIG_WBRF
>>> +bool wbrf_supported_producer(struct device *dev); int
>>> +wbrf_add_exclusion(struct device *adev,
>>> +                  struct wbrf_ranges_in *in);
>>> +int wbrf_remove_exclusion(struct device *dev,
>>> +                     struct wbrf_ranges_in *in);
>>> +int wbrf_retrieve_exclusions(struct device *dev,
>>> +                        struct wbrf_ranges_out *out); bool
>>> +wbrf_supported_consumer(struct device *dev);
>>> +
>>> +int wbrf_register_notifier(struct notifier_block *nb); int
>>> +wbrf_unregister_notifier(struct notifier_block *nb); #else static
>>> +inline bool wbrf_supported_producer(struct device *dev) { return
>>> +false; } static inline int wbrf_add_exclusion(struct device *adev,
>>> +                                struct wbrf_ranges_in *in) { return -
>> ENODEV; } static inline
>>> +int wbrf_remove_exclusion(struct device *dev,
>>> +                                   struct wbrf_ranges_in *in) { return -
>> ENODEV; } static inline int
>>> +wbrf_retrieve_exclusions(struct device *dev,
>>> +                                      struct wbrf_ranges_out *out)
>> { return -ENODEV; } static
>>> +inline bool wbrf_supported_consumer(struct device *dev) { return
>>> +false; } static inline int wbrf_register_notifier(struct
>>> +notifier_block *nb) { return -ENODEV; } static inline int
>>> +wbrf_unregister_notifier(struct notifier_block *nb) { return -ENODEV;
>>> +} #endif
>>> +
>>
>> Right now there are stubs for non CONFIG_WBRF as well as other patches are
>> using #ifdef CONFIG_WBRF or having their own stubs.  Like mac80211 patch
>> looks for #ifdef CONFIG_WBRF.
>>
>> I think we should pick one or the other.
> Right..
>>
>> Having other subsystems #ifdef CONFIG_WBRF will make the series easier to
>> land through multiple trees; so I have a slight leaning in that direction.
> I kind of expecting to use the other way. That is to make CONFIG_WBRF agnostic to other subsystems or drivers.
> They (other subsystems or drivers) can always assume those wbrf_xxxxx interfaces are available.
> What they need to care only are the return values of those interfaces.
> How do you think?

That's fine, thanks.

> 
> Evan
>>
>>> +#endif /* _LINUX_WBRF_H */
> 


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH V5 1/9] drivers core: Add support for Wifi band RF mitigations
  2023-07-04  3:30     ` Quan, Evan
@ 2023-07-04 13:07       ` Andrew Lunn
  2023-07-06  2:58         ` Quan, Evan
  0 siblings, 1 reply; 28+ messages in thread
From: Andrew Lunn @ 2023-07-04 13:07 UTC (permalink / raw)
  To: Quan, Evan
  Cc: rafael, lenb, Deucher, Alexander, Koenig, Christian, Pan, Xinhui,
	airlied, daniel, johannes, davem, edumazet, kuba, pabeni,
	Limonciello, Mario, mdaenzer, maarten.lankhorst, tzimmermann,
	hdegoede, jingyuwang_vip, Lazar, Lijo, jim.cromie, bellosilicio,
	andrealmeid, trix, jsg, arnd, linux-kernel, linux-acpi, amd-gfx,
	dri-devel, linux-wireless, netdev

> > What is the purpose of this stage? Why would it not be supported for this
> > device?
> This is needed for wbrf support via ACPI mechanism. If BIOS(AML code) does not support the wbrf adding/removing for some device,
> it should speak that out so that the device can be aware of that.

How much overhead is this adding? How deep do you need to go to find
the BIOS does not support it? And how often is this called?

Where do we want to add complexity? In the generic API? Or maybe a
little deeper in the ACPI specific code?

       Andrew


^ permalink raw reply	[flat|nested] 28+ messages in thread

* RE: [PATCH V5 1/9] drivers core: Add support for Wifi band RF mitigations
  2023-07-04 13:07       ` Andrew Lunn
@ 2023-07-06  2:58         ` Quan, Evan
  2023-07-06  3:09           ` Mario Limonciello
  0 siblings, 1 reply; 28+ messages in thread
From: Quan, Evan @ 2023-07-06  2:58 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: rafael, lenb, Deucher, Alexander, Koenig, Christian, Pan, Xinhui,
	airlied, daniel, johannes, davem, edumazet, kuba, pabeni,
	Limonciello, Mario, mdaenzer, maarten.lankhorst, tzimmermann,
	hdegoede, jingyuwang_vip, Lazar, Lijo, jim.cromie, bellosilicio,
	andrealmeid, trix, jsg, arnd, linux-kernel, linux-acpi, amd-gfx,
	dri-devel, linux-wireless, netdev

[AMD Official Use Only - General]

Hi Andrew,

I discussed with Mario about your proposal/concerns here.
We believe some changes below might address your concerns.
- place/move the wbrf_supported_producer check inside acpi_amd_wbrf_add_exclusion and acpi_amd_wbrf_add_exclusion
- place the wbrf_supported_consumer check inside acpi_amd_wbrf_retrieve_exclusions
So that the wbrf_supported_producer and wbrf_supported_consumer can be dropped.
We made some prototypes and even performed some tests which showed technically it is absolutely practicable.

However, we found several issues with that.
- The overhead caused by the extra _producer/_consumer check on every calling of wbrf_add/remove/retrieve_ecxclusion.
  Especially when you consider there might be multiple producers and consumers in the system at the same time. And some of
  them might do in-use band/frequency switching frequently.
- Some extra costs caused by the "know it only at the last minute". For example, to support WBRF, amdgpu driver needs some preparations: install the notification hander,
  setup the delay workqueue(to handle possible events flooding) and even notify firmware engine to be ready. However, only on the 1st notification receiving,
  it is realized(reported by wbrf_supported_consumer check) the WBRF feature is actually not supported. All those extra costs can be actually avoided if we can know the WBRF is not supported at first.
  This could happen to other consumers and producers too.

After a careful consideration, we think the changes do not benefit us much. It does not deserve us to spend extra efforts.
Thus we would like to stick with original implementations. That is to have wbrf_supported_producer and wbrf_supported_consumer interfaces exposed.
Then other drivers/subsystems can do necessary wbrf support check in advance and coordinate their actions accordingly.
Please let us know your thoughts.

BR,
Evan
> -----Original Message-----
> From: Andrew Lunn <andrew@lunn.ch>
> Sent: Tuesday, July 4, 2023 9:07 PM
> To: Quan, Evan <Evan.Quan@amd.com>
> Cc: rafael@kernel.org; lenb@kernel.org; Deucher, Alexander
> <Alexander.Deucher@amd.com>; Koenig, Christian
> <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>;
> airlied@gmail.com; daniel@ffwll.ch; johannes@sipsolutions.net;
> davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
> pabeni@redhat.com; Limonciello, Mario <Mario.Limonciello@amd.com>;
> mdaenzer@redhat.com; maarten.lankhorst@linux.intel.com;
> tzimmermann@suse.de; hdegoede@redhat.com; jingyuwang_vip@163.com;
> Lazar, Lijo <Lijo.Lazar@amd.com>; jim.cromie@gmail.com;
> bellosilicio@gmail.com; andrealmeid@igalia.com; trix@redhat.com;
> jsg@jsg.id.au; arnd@arndb.de; linux-kernel@vger.kernel.org; linux-
> acpi@vger.kernel.org; amd-gfx@lists.freedesktop.org; dri-
> devel@lists.freedesktop.org; linux-wireless@vger.kernel.org;
> netdev@vger.kernel.org
> Subject: Re: [PATCH V5 1/9] drivers core: Add support for Wifi band RF
> mitigations
>
> > > What is the purpose of this stage? Why would it not be supported for
> > > this device?
> > This is needed for wbrf support via ACPI mechanism. If BIOS(AML code)
> > does not support the wbrf adding/removing for some device, it should
> speak that out so that the device can be aware of that.
>
> How much overhead is this adding? How deep do you need to go to find the
> BIOS does not support it? And how often is this called?
>
> Where do we want to add complexity? In the generic API? Or maybe a little
> deeper in the ACPI specific code?
>
>        Andrew


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH V5 1/9] drivers core: Add support for Wifi band RF mitigations
  2023-07-06  2:58         ` Quan, Evan
@ 2023-07-06  3:09           ` Mario Limonciello
  0 siblings, 0 replies; 28+ messages in thread
From: Mario Limonciello @ 2023-07-06  3:09 UTC (permalink / raw)
  To: Quan, Evan, Andrew Lunn
  Cc: rafael, lenb, Deucher, Alexander, Koenig, Christian, Pan, Xinhui,
	airlied, daniel, johannes, davem, edumazet, kuba, pabeni,
	mdaenzer, maarten.lankhorst, tzimmermann, hdegoede,
	jingyuwang_vip, Lazar, Lijo, jim.cromie, bellosilicio,
	andrealmeid, trix, jsg, arnd, linux-kernel, linux-acpi, amd-gfx,
	dri-devel, linux-wireless, netdev

On 7/5/23 21:58, Quan, Evan wrote:
> [AMD Official Use Only - General]
> 
> Hi Andrew,
> 
> I discussed with Mario about your proposal/concerns here.
> We believe some changes below might address your concerns.
> - place/move the wbrf_supported_producer check inside acpi_amd_wbrf_add_exclusion and acpi_amd_wbrf_add_exclusion
> - place the wbrf_supported_consumer check inside acpi_amd_wbrf_retrieve_exclusions
> So that the wbrf_supported_producer and wbrf_supported_consumer can be dropped.
> We made some prototypes and even performed some tests which showed technically it is absolutely practicable.
> 
> However, we found several issues with that.
> - The overhead caused by the extra _producer/_consumer check on every calling of wbrf_add/remove/retrieve_ecxclusion.
>    Especially when you consider there might be multiple producers and consumers in the system at the same time. And some of
>    them might do in-use band/frequency switching frequently.

One more piece of overhead that is in this same theme that Evan didn't 
mention is the case of a system "without" AMD's ACPI WBRF but the kernel 
was configured with it enabled.  Think like a distro kernel.

Moving it into add/remove exclusion would mean that every single time 
frequency changed by a producer the _DSM would attempt to be evaluated 
and fail.  To avoid that extra call overhead after the first time would 
mean needing to keep a variable somewhere, and at that point what did 
you save?

> - Some extra costs caused by the "know it only at the last minute". For example, to support WBRF, amdgpu driver needs some preparations: install the notification hander,
>    setup the delay workqueue(to handle possible events flooding) and even notify firmware engine to be ready. However, only on the 1st notification receiving,
>    it is realized(reported by wbrf_supported_consumer check) the WBRF feature is actually not supported. All those extra costs can be actually avoided if we can know the WBRF is not supported at first.
>    This could happen to other consumers and producers too.
> 
> After a careful consideration, we think the changes do not benefit us much. It does not deserve us to spend extra efforts.
> Thus we would like to stick with original implementations. That is to have wbrf_supported_producer and wbrf_supported_consumer interfaces exposed.
> Then other drivers/subsystems can do necessary wbrf support check in advance and coordinate their actions accordingly.
> Please let us know your thoughts.
> 
> BR,
> Evan
>> -----Original Message-----
>> From: Andrew Lunn <andrew@lunn.ch>
>> Sent: Tuesday, July 4, 2023 9:07 PM
>> To: Quan, Evan <Evan.Quan@amd.com>
>> Cc: rafael@kernel.org; lenb@kernel.org; Deucher, Alexander
>> <Alexander.Deucher@amd.com>; Koenig, Christian
>> <Christian.Koenig@amd.com>; Pan, Xinhui <Xinhui.Pan@amd.com>;
>> airlied@gmail.com; daniel@ffwll.ch; johannes@sipsolutions.net;
>> davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
>> pabeni@redhat.com; Limonciello, Mario <Mario.Limonciello@amd.com>;
>> mdaenzer@redhat.com; maarten.lankhorst@linux.intel.com;
>> tzimmermann@suse.de; hdegoede@redhat.com; jingyuwang_vip@163.com;
>> Lazar, Lijo <Lijo.Lazar@amd.com>; jim.cromie@gmail.com;
>> bellosilicio@gmail.com; andrealmeid@igalia.com; trix@redhat.com;
>> jsg@jsg.id.au; arnd@arndb.de; linux-kernel@vger.kernel.org; linux-
>> acpi@vger.kernel.org; amd-gfx@lists.freedesktop.org; dri-
>> devel@lists.freedesktop.org; linux-wireless@vger.kernel.org;
>> netdev@vger.kernel.org
>> Subject: Re: [PATCH V5 1/9] drivers core: Add support for Wifi band RF
>> mitigations
>>
>>>> What is the purpose of this stage? Why would it not be supported for
>>>> this device?
>>> This is needed for wbrf support via ACPI mechanism. If BIOS(AML code)
>>> does not support the wbrf adding/removing for some device, it should
>> speak that out so that the device can be aware of that.
>>
>> How much overhead is this adding? How deep do you need to go to find the
>> BIOS does not support it? And how often is this called?
>>
>> Where do we want to add complexity? In the generic API? Or maybe a little
>> deeper in the ACPI specific code?
>>
>>         Andrew
> 


^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2023-07-06  3:09 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-30 10:32 [PATCH V5 0/9] Enable Wifi RFI interference mitigation feature support Evan Quan
2023-06-30 10:32 ` [PATCH V5 1/9] drivers core: Add support for Wifi band RF mitigations Evan Quan
2023-06-30 13:38   ` Simon Horman
2023-07-04  3:41     ` Quan, Evan
2023-06-30 16:40   ` Limonciello, Mario
2023-07-01  0:25     ` Andrew Lunn
2023-07-04  3:25       ` Quan, Evan
2023-07-04  3:40     ` Quan, Evan
2023-07-04  3:53       ` Mario Limonciello
2023-07-01  0:19   ` Andrew Lunn
2023-07-04  3:30     ` Quan, Evan
2023-07-04 13:07       ` Andrew Lunn
2023-07-06  2:58         ` Quan, Evan
2023-07-06  3:09           ` Mario Limonciello
2023-06-30 10:32 ` [PATCH V5 2/9] driver core: add ACPI based WBRF mechanism introduced by AMD Evan Quan
2023-07-01  0:51   ` Andrew Lunn
2023-07-04  3:24     ` Quan, Evan
2023-06-30 10:32 ` [PATCH V5 3/9] cfg80211: expose nl80211_chan_width_to_mhz for wide sharing Evan Quan
2023-06-30 10:32 ` [PATCH V5 4/9] wifi: mac80211: Add support for ACPI WBRF Evan Quan
2023-06-30 14:08   ` kernel test robot
2023-07-01  1:02   ` Andrew Lunn
2023-07-04  3:12     ` Quan, Evan
2023-06-30 10:32 ` [PATCH V5 5/9] drm/amd/pm: update driver_if and ppsmc headers for coming wbrf feature Evan Quan
2023-06-30 10:32 ` [PATCH V5 6/9] drm/amd/pm: setup the framework to support Wifi RFI mitigation feature Evan Quan
2023-06-30 10:32 ` [PATCH V5 7/9] drm/amd/pm: add flood detection for wbrf events Evan Quan
2023-06-30 14:29   ` kernel test robot
2023-06-30 10:32 ` [PATCH V5 8/9] drm/amd/pm: enable Wifi RFI mitigation feature support for SMU13.0.0 Evan Quan
2023-06-30 10:32 ` [PATCH V5 9/9] drm/amd/pm: enable Wifi RFI mitigation feature support for SMU13.0.7 Evan Quan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).