[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID:
<CAGwozwFjo4uSFpCAXRKivK+VoeYz-Qftmw+iLtOrVnyhn3xpfA@mail.gmail.com>
Date: Thu, 19 Dec 2024 14:12:37 +0100
From: Antheas Kapenekakis <lkml@...heas.dev>
To: Mario Limonciello <superm1@...nel.org>
Cc: Shyam Sundar S K <Shyam-sundar.S-k@....com>,
"Rafael J . Wysocki" <rafael@...nel.org>,
Hans de Goede <hdegoede@...hat.com>,
Ilpo Järvinen <ilpo.jarvinen@...ux.intel.com>,
"Luke D . Jones" <luke@...nes.dev>, Mark Pearson <mpearson-lenovo@...ebb.ca>,
"open list:AMD PMF DRIVER" <platform-driver-x86@...r.kernel.org>,
open list <linux-kernel@...r.kernel.org>,
"open list:ACPI" <linux-acpi@...r.kernel.org>,
"Derek J . Clark" <derekjohn.clark@...il.com>,
me@...egospodneti.ch, Denis Benato <benato.denis96@...il.com>,
Mario Limonciello <mario.limonciello@....com>
Subject: Re: [RFC 2/2] platform/x86/amd: pmf: Add manual control support
Hi Mario,
given that there is a Legion Go driver in the works, and Asus already
has a driver, the only thing that would be left for locking down ACPI
access is manufacturers w/o vendor APIs.
So, can we restart the conversation about this driver? It would be
nice to get to a place where we can lock down /dev/mem and ACPI by
spring.
Moreover, since the other two proposed drivers use the
firmware_attributes API, should this be used here as well?
By the way, you were right about needing a taint for this. Strix Point
fails to enter a lower power state during sleep if you set it to lower
than 10W. This is not ideal, as hawk point could go down to 5 while
still showing a power difference, but I am unsure where this bug
should be reported. This is both through ryzenadj/ALIB
Antheas
On Thu, 26 Sept 2024 at 05:00, Mario Limonciello <superm1@...nel.org> wrote:
>
> From: Mario Limonciello <mario.limonciello@....com>
>
> A number of users resort to using reverse engineered software like
> ryzenadj to manipulate debugging interfaces for modifying APU settings.
>
> At a glance these tools are useful, but the problem is they break
> state machines in other software such as the PMF driver or the OEM
> EC.
>
> Offer a knob for PMF to allow 'manual control' which will users can
> directly change things like fPPT and sPPT. As this can be harmful for
> a system to try to push limits outside of a thermal design, taint the
> kernel and show a critical message when in use.
>
> Signed-off-by: Mario Limonciello <mario.limonciello@....com>
> ---
> Documentation/ABI/testing/sysfs-amd-pmf | 10 +++
> drivers/platform/x86/amd/pmf/Makefile | 1 +
> drivers/platform/x86/amd/pmf/core.c | 9 +++
> drivers/platform/x86/amd/pmf/manual.c | 88 +++++++++++++++++++++++++
> drivers/platform/x86/amd/pmf/pmf.h | 5 ++
> drivers/platform/x86/amd/pmf/sps.c | 4 ++
> 6 files changed, 117 insertions(+)
> create mode 100644 drivers/platform/x86/amd/pmf/manual.c
>
> diff --git a/Documentation/ABI/testing/sysfs-amd-pmf b/Documentation/ABI/testing/sysfs-amd-pmf
> index 7fc0e1c2b76b..6f3d5cbf443f 100644
> --- a/Documentation/ABI/testing/sysfs-amd-pmf
> +++ b/Documentation/ABI/testing/sysfs-amd-pmf
> @@ -11,3 +11,13 @@ Description: Reading this file tells if the AMD Platform Management(PMF)
> To turn off CnQF user can write "off" to the sysfs node.
> Note: Systems that support auto mode will not have this sysfs file
> available.
> +
> +What: /sys/devices/platform/*/{spl, fppt, sppt, sppt_apu_only, stt_min, stt_limit_apu, stt_skip_temp}
> +Date: December 2024
> +Contact: Mario Limonciello <mario.limonciello@....com>
> +Description: Manual control of AMD PMF APU coefficients
> + .
> + These files are used to manually control the APU coefficients.
> + In order to write to these files the module most be
> + loaded with manual_control=1 and the user must write "custom"
> + to the ACPI platform profile.
> diff --git a/drivers/platform/x86/amd/pmf/Makefile b/drivers/platform/x86/amd/pmf/Makefile
> index 7d6079b02589..81444d6f4428 100644
> --- a/drivers/platform/x86/amd/pmf/Makefile
> +++ b/drivers/platform/x86/amd/pmf/Makefile
> @@ -7,4 +7,5 @@
> obj-$(CONFIG_AMD_PMF) += amd-pmf.o
> amd-pmf-objs := core.o acpi.o sps.o \
> auto-mode.o cnqf.o \
> + manual.o \
> tee-if.o spc.o pmf-quirks.o
> diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
> index d6af0ca036f1..52a68ca094be 100644
> --- a/drivers/platform/x86/amd/pmf/core.c
> +++ b/drivers/platform/x86/amd/pmf/core.c
> @@ -53,6 +53,10 @@ static bool force_load;
> module_param(force_load, bool, 0444);
> MODULE_PARM_DESC(force_load, "Force load this driver on supported older platforms (experimental)");
>
> +bool pmf_manual_control;
> +module_param_named(manual_control, pmf_manual_control, bool, 0444);
> +MODULE_PARM_DESC(manual_control, "Expose manual control knobs (experimental)");
> +
> static int amd_pmf_pwr_src_notify_call(struct notifier_block *nb, unsigned long event, void *data)
> {
> struct amd_pmf_dev *pmf = container_of(nb, struct amd_pmf_dev, pwr_src_notifier);
> @@ -349,6 +353,10 @@ static void amd_pmf_init_features(struct amd_pmf_dev *dev)
> dev_dbg(dev->dev, "SPS enabled and Platform Profiles registered\n");
> }
>
> + if (pmf_manual_control) {
> + amd_pmf_init_manual_control(dev);
> + return;
> + }
> amd_pmf_init_smart_pc(dev);
> if (dev->smart_pc_enabled) {
> dev_dbg(dev->dev, "Smart PC Solution Enabled\n");
> @@ -485,6 +493,7 @@ static void amd_pmf_remove(struct platform_device *pdev)
>
> static const struct attribute_group *amd_pmf_driver_groups[] = {
> &cnqf_feature_attribute_group,
> + &manual_attribute_group,
> NULL,
> };
>
> diff --git a/drivers/platform/x86/amd/pmf/manual.c b/drivers/platform/x86/amd/pmf/manual.c
> new file mode 100644
> index 000000000000..b33fc3cd8d61
> --- /dev/null
> +++ b/drivers/platform/x86/amd/pmf/manual.c
> @@ -0,0 +1,88 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * AMD Platform Management Framework Driver
> + *
> + * Copyright (c) 2024, Advanced Micro Devices, Inc.
> + * All Rights Reserved.
> + *
> + * Author: Mario Limonciello <mario.limonciello@....com>
> + */
> +
> +#include "pmf.h"
> +
> +#define pmf_manual_attribute(_name, _set_command, _get_command) \
> +static ssize_t _name##_store(struct device *d, \
> + struct device_attribute *attr, \
> + const char *buf, size_t count) \
> +{ \
> + struct amd_pmf_dev *dev = dev_get_drvdata(d); \
> + uint val; \
> + \
> + if (dev->current_profile != PLATFORM_PROFILE_CUSTOM) { \
> + dev_warn_once(dev->dev, \
> + "Manual control is disabled, please set " \
> + "platform profile to custom.\n"); \
> + return -EINVAL; \
> + } \
> + \
> + if (kstrtouint(buf, 10, &val) < 0) \
> + return -EINVAL; \
> + \
> + amd_pmf_send_cmd(dev, _set_command, false, val, NULL); \
> + \
> + return count; \
> +} \
> +static ssize_t _name##_show(struct device *d, \
> + struct device_attribute *attr, \
> + char *buf) \
> +{ \
> + struct amd_pmf_dev *dev = dev_get_drvdata(d); \
> + uint val; \
> + \
> + amd_pmf_send_cmd(dev, _get_command, true, ARG_NONE, &val); \
> + \
> + return sysfs_emit(buf, "%u\n", val); \
> +}
> +
> +pmf_manual_attribute(spl, SET_SPL, GET_SPL);
> +static DEVICE_ATTR_RW(spl);
> +pmf_manual_attribute(fppt, SET_FPPT, GET_FPPT);
> +static DEVICE_ATTR_RW(fppt);
> +pmf_manual_attribute(sppt, SET_SPPT, GET_SPPT);
> +static DEVICE_ATTR_RW(sppt);
> +pmf_manual_attribute(sppt_apu_only, SET_SPPT_APU_ONLY, GET_SPPT_APU_ONLY);
> +static DEVICE_ATTR_RW(sppt_apu_only);
> +pmf_manual_attribute(stt_min, SET_STT_MIN_LIMIT, GET_STT_MIN_LIMIT);
> +static DEVICE_ATTR_RW(stt_min);
> +pmf_manual_attribute(stt_limit_apu, SET_STT_LIMIT_APU, GET_STT_LIMIT_APU);
> +static DEVICE_ATTR_RW(stt_limit_apu);
> +pmf_manual_attribute(stt_skin_temp, SET_STT_LIMIT_HS2, GET_STT_LIMIT_HS2);
> +static DEVICE_ATTR_RW(stt_skin_temp);
> +
> +static umode_t manual_attr_is_visible(struct kobject *kobj, struct attribute *attr, int idx)
> +{
> + return pmf_manual_control ? 0660 : 0;
> +}
> +
> +static struct attribute *manual_attrs[] = {
> + &dev_attr_spl.attr,
> + &dev_attr_fppt.attr,
> + &dev_attr_sppt.attr,
> + &dev_attr_sppt_apu_only.attr,
> + &dev_attr_stt_min.attr,
> + &dev_attr_stt_limit_apu.attr,
> + &dev_attr_stt_skin_temp.attr,
> + NULL,
> +};
> +
> +const struct attribute_group manual_attribute_group = {
> + .attrs = manual_attrs,
> + .is_visible = manual_attr_is_visible,
> +};
> +
> +void amd_pmf_init_manual_control(struct amd_pmf_dev *dev)
> +{
> + add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
> + pr_crit("Manual PMF control is enabled, please disable it before "
> + "reporting any bugs unrelated to PMF.\n");
> +}
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index 8ce8816da9c1..ca3df63cf190 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -798,4 +798,9 @@ void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *
> /* Quirk infrastructure */
> void amd_pmf_quirks_init(struct amd_pmf_dev *dev);
>
> +/* Manual configuration */
> +extern bool pmf_manual_control;
> +extern const struct attribute_group manual_attribute_group;
> +void amd_pmf_init_manual_control(struct amd_pmf_dev *dev);
> +
> #endif /* PMF_H */
> diff --git a/drivers/platform/x86/amd/pmf/sps.c b/drivers/platform/x86/amd/pmf/sps.c
> index 92f7fb22277d..6db88e523a86 100644
> --- a/drivers/platform/x86/amd/pmf/sps.c
> +++ b/drivers/platform/x86/amd/pmf/sps.c
> @@ -305,6 +305,8 @@ int amd_pmf_get_pprof_modes(struct amd_pmf_dev *pmf)
> case PLATFORM_PROFILE_LOW_POWER:
> mode = POWER_MODE_POWER_SAVER;
> break;
> + case PLATFORM_PROFILE_CUSTOM:
> + return 0;
> default:
> dev_err(pmf->dev, "Unknown Platform Profile.\n");
> return -EOPNOTSUPP;
> @@ -412,6 +414,8 @@ int amd_pmf_init_sps(struct amd_pmf_dev *dev)
> set_bit(PLATFORM_PROFILE_LOW_POWER, dev->pprof.choices);
> set_bit(PLATFORM_PROFILE_BALANCED, dev->pprof.choices);
> set_bit(PLATFORM_PROFILE_PERFORMANCE, dev->pprof.choices);
> + if (pmf_manual_control)
> + set_bit(PLATFORM_PROFILE_CUSTOM, dev->pprof.choices);
>
> /* Create platform_profile structure and register */
> err = platform_profile_register(&dev->pprof);
> --
> 2.43.0
>
Powered by blists - more mailing lists