From: Christian Loehle <christian.loehle@arm.com>
To: Sumit Gupta <sumitg@nvidia.com>,
rafael@kernel.org, viresh.kumar@linaro.org,
zhanjie9@hisilicon.com, zhenglifeng1@huawei.com,
pierre.gondois@arm.com, ionela.voinescu@arm.com,
mario.limonciello@amd.com, maciej.wieczor-retman@intel.com,
pawel.chmielewski@intel.com, lenb@kernel.org, corbet@lwn.net,
skhan@linuxfoundation.org, rdunlap@infradead.org,
linux-pm@vger.kernel.org, linux-acpi@vger.kernel.org,
acpica-devel@lists.linux.dev, linux-tegra@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org
Cc: treding@nvidia.com, jonathanh@nvidia.com, vsethi@nvidia.com,
ksitaraman@nvidia.com, sanjayc@nvidia.com, mochs@nvidia.com,
bbasu@nvidia.com
Subject: Re: [PATCH v6 RESEND] cpufreq: CPPC: Add autonomous mode boot parameter support
Date: Thu, 12 Nov 2026 13:14:16 +0000 [thread overview]
Message-ID: <8d335175-7d1e-4e12-b28b-d6f2ee13edee@arm.com> (raw)
In-Reply-To: <20261112080442.4007723-1-sumitg@nvidia.com>
On 11/12/26 08:04, Sumit Gupta wrote:
> Configuring autonomous selection and Energy Performance Preference (EPP)
> at every boot currently requires per-policy sysfs writes.
>
> Add the 'cppc_cpufreq.auto_sel_mode' boot parameter to enable autonomous
> selection during policy initialization and optionally set EPP. In
> autonomous mode, the platform selects the performance level within the
> MIN and MAX limits, which the driver sets from the policy limits. The EPP
> hint guides that selection.
>
> The parameter accepts:
> - performance: enable autonomous selection and set EPP to 0x00
> - balance_performance: enable it and set EPP to 0x80
> - balance_power: enable it and set EPP to 0xc0
> - power: enable it and set EPP to 0xff
> - default_epp: enable it and preserve firmware EPP
> - disabled: preserve the firmware configuration (default)
>
> Warn about unrecognized values and ignore them.
>
> Skip policies without autonomous-selection support. The driver enables
> autonomous selection before writing EPP, as the platform may ignore EPP
> while autonomous selection is disabled.
>
> Record successful writes so the existing online and resume paths reapply
> the requested values. The offline and suspend paths restore the saved
> firmware values, including during driver unload.
>
> Signed-off-by: Sumit Gupta <sumitg@nvidia.com>
> ---
> Resending v6 with base-commit info and Pierre added to Cc.
> No changes to the code or commit message.
>
> This is based on the "Preserve OSPM-set registers" [1] and
> "ospm_nominal_perf" [2] series, which are applied for 7.5.
I've sent out
https://lore.kernel.org/lkml/20261112113204.778904-1-christian.loehle@arm.com/
as a follow up, if it looks sound to you, feel free to pick it up
as a series to go in before $SUBJECT?
>
> v5 -> v6:
> - Split "Set CPPC Enable register in cpu_init" into a separate fix [3].
> - Accept strings only (Pierre [4]).
> - Move the setup into cppc_cpufreq_setup_auto_sel_mode() and check
> autonomous selection support first (Pierre [4]).
> - Drop the last_governor check, as init() now runs only for a new
> policy (Pierre [4]).
> - Drop the MIN/MAX seeding, Desired hint and policy->min/max override,
> as init() and the governor already set valid values (Pierre [4]).
> - Apply the parameter at the end of init(), after the usual
> performance controls write.
> - Save auto_sel and EPP through the saved-register code from [1]
> (Sashiko [5]).
> - Drop the cppc_cpufreq_exit() loop that cleared auto_sel on all
> present CPUs (Pierre [4], Sashiko [5]).
> - Enable autonomous selection before writing EPP.
> - Set EPP also when firmware has already enabled autonomous selection.
> - Add the balance_power (0xc0) and power (0xff) modes.
> - Ignore an unrecognized value instead of treating it as disabled.
>
> v5: https://lore.kernel.org/lkml/20260623080652.3353386-1-sumitg@nvidia.com/
> [1] https://lore.kernel.org/lkml/20261106193304.3347374-1-sumitg@nvidia.com/
> [2] https://lore.kernel.org/lkml/20261109195400.3600561-1-sumitg@nvidia.com/
> [3] https://lore.kernel.org/lkml/20261110101246.3665797-1-sumitg@nvidia.com/
> [4] https://lore.kernel.org/lkml/f61f592a-bc9c-4a83-bde1-e999c8101c36@nvidia.com/
> [5] https://sashiko.dev/#/patchset/20260623080652.3353386-1-sumitg@nvidia.com
>
> .../admin-guide/kernel-parameters.txt | 26 ++++
> drivers/cpufreq/cppc_cpufreq.c | 120 ++++++++++++++++++
> include/acpi/cppc_acpi.h | 2 +
> 3 files changed, 148 insertions(+)
>
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> index 0b3c140babd9..5714c0d30fce 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -1015,6 +1015,32 @@ Kernel parameters
> Format:
> <first_slot>,<last_slot>,<port>,<enum_bit>[,<debug>]
>
> + cppc_cpufreq.auto_sel_mode=
> + [ACPI,CPU_FREQ] Enable ACPI CPPC autonomous performance
> + selection on all CPUs at boot. In autonomous mode, the
> + platform selects the performance level within the CPPC
> + Minimum and Maximum Performance limits. The driver sets
> + these limits from scaling_min_freq and scaling_max_freq.
> + The Energy Performance Preference (EPP) hint guides the
> + platform toward performance (0x00) or energy efficiency
> + (0xff).
> + Requires the ACPI CPPC Autonomous Selection Enable
> + register. EPP is set only if the platform implements it.
> + Format: <string>
> + performance:
> + enable autonomous selection, set EPP to 0x00
> + balance_performance:
> + enable autonomous selection, set EPP to 0x80
> + balance_power:
> + enable autonomous selection, set EPP to 0xc0
> + power:
> + enable autonomous selection, set EPP to 0xff
> + default_epp:
> + enable autonomous selection, keep firmware EPP
> + disabled:
> + keep the firmware configuration (default)
> + An unrecognized value is ignored with a warning.
> +
> cpuidle.off=1 [CPU_IDLE]
> disable the cpuidle sub-system
>
> diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
> index a62589c0674f..c9bed93cf0c9 100644
> --- a/drivers/cpufreq/cppc_cpufreq.c
> +++ b/drivers/cpufreq/cppc_cpufreq.c
> @@ -238,6 +238,58 @@ static void cppc_cpufreq_apply_saved_regs(struct cpufreq_policy *policy,
> saved_type);
> }
>
> +/* Autonomous Selection boot parameter modes */
> +enum {
> + AUTO_SEL_MODE_DISABLED,
> + AUTO_SEL_MODE_PERFORMANCE,
> + AUTO_SEL_MODE_BALANCE_PERFORMANCE,
> + AUTO_SEL_MODE_BALANCE_POWER,
> + AUTO_SEL_MODE_POWER,
> + AUTO_SEL_MODE_DEFAULT_EPP,
> +};
> +
> +static const char * const auto_sel_mode_names[] = {
> + [AUTO_SEL_MODE_DISABLED] = "disabled",
> + [AUTO_SEL_MODE_PERFORMANCE] = "performance",
> + [AUTO_SEL_MODE_BALANCE_PERFORMANCE] = "balance_performance",
> + [AUTO_SEL_MODE_BALANCE_POWER] = "balance_power",
> + [AUTO_SEL_MODE_POWER] = "power",
> + [AUTO_SEL_MODE_DEFAULT_EPP] = "default_epp",
> +};
> +
> +static int auto_sel_mode;
> +
> +static int auto_sel_mode_set(const char *val, const struct kernel_param *kp)
> +{
> + int *mode = kp->arg;
> + int ret;
> +
> + ret = sysfs_match_string(auto_sel_mode_names, val);
> + if (ret < 0) {
> + pr_warn("Invalid auto_sel_mode \"%s\", ignoring it\n", val);
> + return 0;
> + }
> +
> + *mode = ret;
> + return 0;
> +}
> +
> +static int auto_sel_mode_get(char *buffer, const struct kernel_param *kp)
> +{
> + int *mode = kp->arg;
> +
> + return sysfs_emit(buffer, "%s\n", auto_sel_mode_names[*mode]);
> +}
> +
> +static const struct kernel_param_ops auto_sel_mode_ops = {
> + .set = auto_sel_mode_set,
> + .get = auto_sel_mode_get,
> +};
> +
> +module_param_cb(auto_sel_mode, &auto_sel_mode_ops, &auto_sel_mode, 0444);
> +MODULE_PARM_DESC(auto_sel_mode,
> + "Autonomous selection mode: performance, balance_performance, balance_power, power, default_epp, disabled");
> +
> #ifdef CONFIG_ACPI_CPPC_CPUFREQ_FIE
> static enum {
> FIE_UNSET = -1,
> @@ -938,6 +990,72 @@ static u32 cppc_cpufreq_effective_nominal(struct cpufreq_policy *policy)
> return (u32)ospm_nominal;
> }
>
> +/*
> + * Apply the auto_sel_mode boot parameter in init(). Enable autonomous
> + * selection unless it is already enabled. Then set EPP for the selected mode.
> + *
> + * Enable auto_sel before writing EPP, as the platform may ignore EPP while
> + * autonomous selection is disabled. Save each value written, so that online()
> + * and resume() write it again.
> + */
> +static void cppc_cpufreq_setup_auto_sel_mode(struct cpufreq_policy *policy)
> +{
> + struct cppc_policy_state *st = cppc_cpufreq_policy_state(policy);
> + struct cppc_cpudata *cpu_data = policy->driver_data;
> + unsigned int cpu = policy->cpu;
> + u64 auto_sel, epp;
> + int ret;
> +
> + if (auto_sel_mode == AUTO_SEL_MODE_DISABLED)
> + return;
> +
> + /* U64_MAX means the platform does not implement the register. */
> + auto_sel = st->regs[CPPC_SAVED_AUTO_SEL][CPPC_SAVED_FIRMWARE];
> + if (auto_sel == U64_MAX) {
> + pr_info_once("Autonomous selection is not supported, ignoring auto_sel_mode\n");
> + return;
> + }
> +
> + if (!auto_sel) {
> + ret = cppc_set_auto_sel(cpu, true);
> + if (ret) {
> + pr_warn("Failed to enable auto_sel for CPU%u (%d)\n",
> + cpu, ret);
> + return;
> + }
> + cppc_cpufreq_save_requested(policy, CPPC_SAVED_AUTO_SEL, true);
> + }
> + cpu_data->perf_ctrls.auto_sel = true;
> +
> + switch (auto_sel_mode) {
> + case AUTO_SEL_MODE_PERFORMANCE:
> + epp = CPPC_EPP_PERFORMANCE_PREF;
> + break;
> + case AUTO_SEL_MODE_BALANCE_PERFORMANCE:
> + epp = CPPC_EPP_BALANCE_PERFORMANCE_PREF;
> + break;
> + case AUTO_SEL_MODE_BALANCE_POWER:
> + epp = CPPC_EPP_BALANCE_POWER_PREF;
> + break;
> + case AUTO_SEL_MODE_POWER:
> + epp = CPPC_EPP_ENERGY_EFFICIENCY_PREF;
> + break;
> + default:
> + /* default_epp keeps the EPP value set by firmware. */
> + return;
> + }
> +
> + /* EPP is optional. */
> + ret = cppc_set_epp(cpu, epp);
> + if (ret) {
> + if (ret != -EOPNOTSUPP)
> + pr_warn("Failed to set EPP for CPU%u (%d)\n", cpu, ret);
> + return;
> + }
> + cpu_data->perf_ctrls.energy_perf = epp;
So EPP is also allowed to be 4 or 6 bits wide and we might wanna account
for that either here or in acpi-cppc.
That being said that's already not working, I usually think all these
technically compliant platforms should just be filtered out on
acpi-cppc probe and we don't support EPP then and not worry about it.
That being said amd-pstate requires EPP for active mode and in this case
just handling the read/writes seems the pass of less resistance:
https://lore.kernel.org/all/20261112131316.827708-1-christian.loehle@arm.com/
> + cppc_cpufreq_save_requested(policy, CPPC_SAVED_EPP, epp);
> +}
> +
> static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
> {
> unsigned int cpu = policy->cpu;
> @@ -1058,6 +1176,8 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
> }
> cpu_data->perf_limits_valid = true;
>
> + cppc_cpufreq_setup_auto_sel_mode(policy);
> +
> cppc_cpufreq_cpu_fie_init(policy);
> return 0;
>
> diff --git a/include/acpi/cppc_acpi.h b/include/acpi/cppc_acpi.h
> index 2cec54b4d2e2..3d47c07f494b 100644
> --- a/include/acpi/cppc_acpi.h
> +++ b/include/acpi/cppc_acpi.h
> @@ -42,6 +42,8 @@
> #define CPPC_AUTO_ACT_WINDOW_SIG_CARRY_THRESH 129
>
> #define CPPC_EPP_PERFORMANCE_PREF 0x00
> +#define CPPC_EPP_BALANCE_PERFORMANCE_PREF 0x80
> +#define CPPC_EPP_BALANCE_POWER_PREF 0xC0
> #define CPPC_EPP_ENERGY_EFFICIENCY_PREF 0xFF
>
> #define CPPC_PERF_LIMITED_DESIRED_EXCURSION BIT(0)
>
> base-commit: a917b5968c17196b98b514158de800194d09e505
Actual $SUBJECT looks okay to me, I'd wait with the R-b for the
series, though.
prev parent reply other threads:[~2026-11-12 13:14 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-12 8:04 [PATCH v6 RESEND] cpufreq: CPPC: Add autonomous mode boot parameter support Sumit Gupta
2026-11-12 13:14 ` Christian Loehle [this message]
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=8d335175-7d1e-4e12-b28b-d6f2ee13edee@arm.com \
--to=christian.loehle@arm.com \
--cc=acpica-devel@lists.linux.dev \
--cc=bbasu@nvidia.com \
--cc=corbet@lwn.net \
--cc=ionela.voinescu@arm.com \
--cc=jonathanh@nvidia.com \
--cc=ksitaraman@nvidia.com \
--cc=lenb@kernel.org \
--cc=linux-acpi@vger.kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=linux-tegra@vger.kernel.org \
--cc=maciej.wieczor-retman@intel.com \
--cc=mario.limonciello@amd.com \
--cc=mochs@nvidia.com \
--cc=pawel.chmielewski@intel.com \
--cc=pierre.gondois@arm.com \
--cc=rafael@kernel.org \
--cc=rdunlap@infradead.org \
--cc=sanjayc@nvidia.com \
--cc=skhan@linuxfoundation.org \
--cc=sumitg@nvidia.com \
--cc=treding@nvidia.com \
--cc=viresh.kumar@linaro.org \
--cc=vsethi@nvidia.com \
--cc=zhanjie9@hisilicon.com \
--cc=zhenglifeng1@huawei.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