RE: [V10 1/8] ACPI: Add support for AMD ACPI based Wifi band RFI mitigation feature
[AMD Official Use Only - General] > -Original Message- > From: Simon Horman > Sent: Sunday, August 27, 2023 11:43 PM > To: Quan, Evan > Cc: l...@kernel.org; johan...@sipsolutions.net; da...@davemloft.net; > eduma...@google.com; k...@kernel.org; pab...@redhat.com; Deucher, > Alexander ; raf...@kernel.org; Lazar, Lijo > ; Limonciello, Mario ; > linux-ker...@vger.kernel.org; linux-a...@vger.kernel.org; amd- > g...@lists.freedesktop.org; dri-de...@lists.freedesktop.org; linux- > wirel...@vger.kernel.org; net...@vger.kernel.org > Subject: Re: [V10 1/8] ACPI: Add support for AMD ACPI based Wifi band RFI > mitigation feature > > On Fri, Aug 25, 2023 at 04:38:39PM +0800, 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. > > > > Signed-off-by: Evan Quan > > ... > > > diff --git a/drivers/acpi/amd_wbrf.c b/drivers/acpi/amd_wbrf.c > > ... > > > +/** > > + * acpi_amd_wbrf_add_exclusion - broadcast the frequency band the > device > > + * is using > > + * > > + * @dev: device pointer > > + * @in: input structure containing the frequency band the device is > > +using > > + * > > + * Broadcast to other consumers the frequency band the device starts > > + * to use. Underneath the surface the information is cached into an > > + * internal buffer first. Then a notification is sent to all those > > + * registered consumers. So then they can retrieve that buffer to > > + * know the latest active frequency bands. The benifit with such > > +design > > nit: ./checkpatch.pl --codespell suggests benifit -> benefit. Thanks, will fix that. Evan > > > + * is for those consumers which have not been registered yet, they > > +can > > + * still have a chance to retrieve such information later. > > + */ > > +int acpi_amd_wbrf_add_exclusion(struct device *dev, > > + struct wbrf_ranges_in_out *in) > > +{ > > + struct acpi_device *adev = ACPI_COMPANION(dev); > > + int ret; > > + > > + if (!adev) > > + return -ENODEV; > > + > > + ret = wbrf_record(adev, WBRF_RECORD_ADD, in); > > + if (ret) > > + return ret; > > + > > + blocking_notifier_call_chain(_chain_head, > > +WBRF_CHANGED, > > +NULL); > > + > > + return 0; > > +} > > +EXPORT_SYMBOL_GPL(acpi_amd_wbrf_add_exclusion); > > ...
Re: [V10 1/8] ACPI: Add support for AMD ACPI based Wifi band RFI mitigation feature
On Fri, Aug 25, 2023 at 04:38:39PM +0800, 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. > > Signed-off-by: Evan Quan ... > diff --git a/drivers/acpi/amd_wbrf.c b/drivers/acpi/amd_wbrf.c ... > +/** > + * acpi_amd_wbrf_add_exclusion - broadcast the frequency band the device > + * is using > + * > + * @dev: device pointer > + * @in: input structure containing the frequency band the device is using > + * > + * Broadcast to other consumers the frequency band the device starts > + * to use. Underneath the surface the information is cached into an > + * internal buffer first. Then a notification is sent to all those > + * registered consumers. So then they can retrieve that buffer to > + * know the latest active frequency bands. The benifit with such design nit: ./checkpatch.pl --codespell suggests benifit -> benefit. > + * is for those consumers which have not been registered yet, they can > + * still have a chance to retrieve such information later. > + */ > +int acpi_amd_wbrf_add_exclusion(struct device *dev, > + struct wbrf_ranges_in_out *in) > +{ > + struct acpi_device *adev = ACPI_COMPANION(dev); > + int ret; > + > + if (!adev) > + return -ENODEV; > + > + ret = wbrf_record(adev, WBRF_RECORD_ADD, in); > + if (ret) > + return ret; > + > + blocking_notifier_call_chain(_chain_head, > + WBRF_CHANGED, > + NULL); > + > + return 0; > +} > +EXPORT_SYMBOL_GPL(acpi_amd_wbrf_add_exclusion); ...
[V10 1/8] ACPI: Add support for AMD ACPI based Wifi band RFI mitigation feature
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. Signed-off-by: Evan Quan --- drivers/acpi/Kconfig | 17 ++ drivers/acpi/Makefile | 2 + drivers/acpi/amd_wbrf.c | 414 ++ include/linux/acpi_amd_wbrf.h | 140 4 files changed, 573 insertions(+) create mode 100644 drivers/acpi/amd_wbrf.c create mode 100644 include/linux/acpi_amd_wbrf.h diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 00dd309b6682..a092ea72d152 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -594,6 +594,23 @@ config ACPI_PRMT substantially increase computational overhead related to the initialization of some server systems. +config WBRF_AMD_ACPI + bool "ACPI based WBRF mechanism introduced by AMD" + depends on ACPI + default n + help + Wifi band RFI mitigation mechanism allows multiple drivers from + different domains to notify the frequencies in use so that hardware + can be reconfigured to avoid harmonic conflicts. + + 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. + + Before enabling this ACPI based mechanism, it is suggested to confirm + with the hardware designer/provider first whether your platform + equipped with necessary BIOS and firmwares. + endif # ACPI config X86_PM_TIMER diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 3fc5a0d54f6e..9185d16e4495 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -133,3 +133,5 @@ obj-$(CONFIG_ARM64) += arm64/ obj-$(CONFIG_ACPI_VIOT)+= viot.o obj-$(CONFIG_RISCV)+= riscv/ + +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 ..98663b2bfd54 --- /dev/null +++ b/drivers/acpi/amd_wbrf.c @@ -0,0 +1,414 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Wifi Band Exclusion Interface (AMD ACPI Implementation) + * Copyright (C) 2023 Advanced Micro Devices + * + */ + +#include +#include + +#define ACPI_AMD_WBRF_METHOD "\\WBRF" + +/* + * Functions bit vector for WBRF method + * + * Bit 0: Supported for any functions other than function 0. + * Bit 1: Function 1 (Add / Remove frequency) is supported. + * Bit 2: Function 2 (Get frequency list) is supported. + */ +#define WBRF_ENABLED 0x0 +#define WBRF_RECORD0x1 +#define WBRF_RETRIEVE 0x2 + +/* record actions */ +#define WBRF_RECORD_ADD0x0 +#define WBRF_RECORD_REMOVE 0x1 + +#define WBRF_REVISION 0x1 + +/* + * The data structure used for WBRF_RETRIEVE is not naturally aligned. + * And unfortunately the design has been settled down. + */ +struct amd_wbrf_ranges_out { + u32 num_of_ranges; + struct exclusion_range band_list[MAX_NUM_OF_WBRF_RANGES]; +} __packed; + +static const guid_t wifi_acpi_dsm_guid = + GUID_INIT(0x7b7656cf, 0xdc3d, 0x4c1c, + 0x83, 0xe9, 0x66, 0xe7, 0x21, 0xde, 0x30, 0x70); + +static BLOCKING_NOTIFIER_HEAD(wbrf_chain_head); + +static int wbrf_dsm(struct acpi_device *adev, + u8 fn, + union acpi_object *argv4) +{ + union acpi_object *obj; + int rc; + + obj = acpi_evaluate_dsm(adev->handle, _acpi_dsm_guid, + WBRF_REVISION, fn, argv4); + if (!obj) + return -ENXIO; + + switch (obj->type) { + 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_out *in) +{ + union acpi_object argv4; + union acpi_object *tmp; + u32 num_of_ranges = 0; + u32 num_of_elements; + u32 arg_idx = 0; + u32 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++; + + /* +* The valid entry counter does not