From: Mario Limonciello <mario.limonciello@amd.com>
To: Evan Quan <evan.quan@amd.com>
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, rafael@kernel.org,
lenb@kernel.org, Alexander.Deucher@amd.com,
Christian.Koenig@amd.com, Xinhui.Pan@amd.com, airlied@gmail.com,
daniel@ffwll.ch, kvalo@kernel.org, nbd@nbd.name,
lorenzo@kernel.org, ryder.lee@mediatek.com,
shayne.chen@mediatek.com, sean.wang@mediatek.com,
matthias.bgg@gmail.com, angelogioacchino.delregno@collabora.com,
Lijo.Lazar@amd.com
Subject: Re: [PATCH V3 1/7] drivers/acpi: Add support for Wifi band RF mitigations
Date: Sun, 18 Jun 2023 21:04:29 -0500 [thread overview]
Message-ID: <fc055de3-3ff4-c0dc-f48a-9f30a60bfcbf@amd.com> (raw)
In-Reply-To: <20230616065757.1054422-2-evan.quan@amd.com>
On 6/16/23 01:57, Evan Quan wrote:
> From: Mario Limonciello <mario.limonciello@amd.com>
>
> 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 an ACPI based mechanism that
> devices can use to notify active use of particular frequencies so
> that 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.
>
> 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:
> - move those wlan specific implementations to net/mac80211(Mario)
> ---
> drivers/acpi/Kconfig | 7 ++
> drivers/acpi/Makefile | 2 +
> drivers/acpi/acpi_wbrf.c | 215 +++++++++++++++++++++++++++++++++++++++
> include/linux/wbrf.h | 55 ++++++++++
> 4 files changed, 279 insertions(+)
> create mode 100644 drivers/acpi/acpi_wbrf.c
> create mode 100644 include/linux/wbrf.h
>
> diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
> index ccbeab9500ec..9ee7c7dcc3e6 100644
> --- a/drivers/acpi/Kconfig
> +++ b/drivers/acpi/Kconfig
> @@ -611,3 +611,10 @@ config X86_PM_TIMER
>
> You should nearly always say Y here because many modern
> systems require this timer.
> +
> +config ACPI_WBRF
> + bool "ACPI Wifi band RF mitigation mechanism"
> + 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.
> \ No newline at end of file
There should be a newline at the end of the Kconfig file.
> diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
> index feb36c0b9446..be173e76aa62 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_ACPI_WBRF) += acpi_wbrf.o
> \ No newline at end of file
> diff --git a/drivers/acpi/acpi_wbrf.c b/drivers/acpi/acpi_wbrf.c
> new file mode 100644
> index 000000000000..8c275998ac29
> --- /dev/null
> +++ b/drivers/acpi/acpi_wbrf.c
> @@ -0,0 +1,215 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * AMD Wifi Band Exclusion Interface
> + * Copyright (C) 2023 Advanced Micro Devices
> + *
> + */
> +
> +#include <linux/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:
> + if (!*out) {
> + rc = -EINVAL;
> + break;
> + }
> + *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 wbrf_add_exclusion(struct acpi_device *adev,
> + struct wbrf_ranges_in *in)
> +{
> + return wbrf_record(adev, WBRF_RECORD_ADD, in);
> +}
> +EXPORT_SYMBOL_GPL(wbrf_add_exclusion);
> +
> +int wbrf_remove_exclusion(struct acpi_device *adev,
> + struct wbrf_ranges_in *in)
> +{
> + return wbrf_record(adev, WBRF_RECORD_REMOVE, in);
> +}
> +EXPORT_SYMBOL_GPL(wbrf_remove_exclusion);
> +
> +bool wbrf_supported_producer(struct acpi_device *adev)
> +{
> + return acpi_check_dsm(adev->handle, &wifi_acpi_dsm_guid,
> + WBRF_REVISION,
> + (1ULL << WBRF_RECORD) | (1ULL << WBRF_RETRIEVE));
> +}
> +EXPORT_SYMBOL_GPL(wbrf_supported_producer);
> +
> +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;
> +
> + if (ret != AE_NOT_FOUND)
> + acpi_handle_warn(handle,
> + "failed to evaluate WBRF(0x%x)\n", ret);
> +
> + 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;
> +
> + 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 wbrf_supported_consumer(struct acpi_device *adev)
> +{
> + return check_acpi_wbrf(adev->handle,
> + WBRF_REVISION,
> + 1ULL << WBRF_RETRIEVE);
> +}
> +EXPORT_SYMBOL_GPL(wbrf_supported_consumer);
> +
> +int wbrf_retrieve_exclusions(struct acpi_device *adev,
> + struct wbrf_ranges_out *exclusions_out)
> +{
> + union acpi_object *obj;
> +
> + obj = acpi_evaluate_wbrf(adev->handle,
> + WBRF_REVISION,
> + WBRF_RETRIEVE);
> + if (!obj)
> + return -EINVAL;
> +
> + memcpy(exclusions_out, obj->buffer.pointer, obj->buffer.length);
> +
> + ACPI_FREE(obj);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(wbrf_retrieve_exclusions);
> diff --git a/include/linux/wbrf.h b/include/linux/wbrf.h
> new file mode 100644
> index 000000000000..e4c99b69f1d2
> --- /dev/null
> +++ b/include/linux/wbrf.h
> @@ -0,0 +1,55 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * AMD Wifi Band Exclusion Interface
> + * Copyright (C) 2023 Advanced Micro Devices
> + */
> +
> +#ifndef _LINUX_WBRF_H
> +#define _LINUX_WBRF_H
> +
> +#include <linux/acpi.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 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];
> +} __attribute__((packed));
> +
> +/**
> + * APIs needed by drivers/subsystems for contributing frequencies:
> + * During probe, check `wbrf_supported_producer` to see if WBRF is supported.
> + * If adding frequencies, then call `wbrf_add_exclusion` with the
> + * start and end points specified for the frequency ranges added.
> + * If removing frequencies, then call `wbrf_remove_exclusion` with
> + * start and end points specified for the frequency ranges added.
> + */
> +bool wbrf_supported_producer(struct acpi_device *adev);
> +int wbrf_add_exclusion(struct acpi_device *adev,
> + struct wbrf_ranges_in *in);
> +int wbrf_remove_exclusion(struct acpi_device *adev,
> + struct wbrf_ranges_in *in);
> +
> +/**
> + * APIs needed by drivers/subsystems responding to frequencies:
> + * During probe, check `wbrf_supported_consumer` to see if WBRF is supported.
> + * When receiving an ACPI notification for some frequencies change, run
> + * `wbrf_retrieve_exclusions` to retrieve the latest frequencies ranges.
> + */
> +int wbrf_retrieve_exclusions(struct acpi_device *adev,
> + struct wbrf_ranges_out *out);
> +bool wbrf_supported_consumer(struct acpi_device *adev);
> +
> +#endif /* _LINUX_WBRF_H */
next prev parent reply other threads:[~2023-06-19 2:04 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-06-16 6:57 [PATCH V3 0/7] Support Wifi RFI interference mitigation feature Evan Quan
2023-06-16 6:57 ` [PATCH V3 1/7] drivers/acpi: Add support for Wifi band RF mitigations Evan Quan
2023-06-19 2:04 ` Mario Limonciello [this message]
2023-06-21 1:26 ` Quan, Evan
2023-06-16 6:57 ` [PATCH V3 2/7] wifi: mac80211: Add support for ACPI WBRF Evan Quan
2023-06-19 2:17 ` Mario Limonciello
2023-06-19 8:24 ` Johannes Berg
2023-06-21 1:04 ` Quan, Evan
2023-06-21 1:24 ` Quan, Evan
2023-06-16 6:57 ` [PATCH V3 3/7] drm/amd/pm: update driver_if and ppsmc headers for coming wbrf feature Evan Quan
2023-06-19 2:18 ` Mario Limonciello
2023-06-16 6:57 ` [PATCH V3 4/7] drm/amd/pm: setup the framework to support Wifi RFI mitigation feature Evan Quan
2023-06-19 2:22 ` Mario Limonciello
2023-06-19 14:54 ` Lazar, Lijo
2023-06-21 0:34 ` Quan, Evan
2023-06-16 6:57 ` [PATCH V3 5/7] drm/amd/pm: add flood detection for wbrf events Evan Quan
2023-06-19 2:22 ` Mario Limonciello
2023-06-16 6:57 ` [PATCH V3 6/7] drm/amd/pm: enable Wifi RFI mitigation feature support for SMU13.0.0 Evan Quan
2023-06-19 2:26 ` Mario Limonciello
2023-06-16 6:57 ` [PATCH V3 7/7] drm/amd/pm: enable Wifi RFI mitigation feature support for SMU13.0.7 Evan Quan
2023-06-19 2:27 ` Mario Limonciello
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=fc055de3-3ff4-c0dc-f48a-9f30a60bfcbf@amd.com \
--to=mario.limonciello@amd.com \
--cc=Alexander.Deucher@amd.com \
--cc=Christian.Koenig@amd.com \
--cc=Lijo.Lazar@amd.com \
--cc=Xinhui.Pan@amd.com \
--cc=airlied@gmail.com \
--cc=amd-gfx@lists.freedesktop.org \
--cc=angelogioacchino.delregno@collabora.com \
--cc=daniel@ffwll.ch \
--cc=dri-devel@lists.freedesktop.org \
--cc=evan.quan@amd.com \
--cc=kvalo@kernel.org \
--cc=lenb@kernel.org \
--cc=linux-acpi@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-wireless@vger.kernel.org \
--cc=lorenzo@kernel.org \
--cc=matthias.bgg@gmail.com \
--cc=nbd@nbd.name \
--cc=rafael@kernel.org \
--cc=ryder.lee@mediatek.com \
--cc=sean.wang@mediatek.com \
--cc=shayne.chen@mediatek.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox