* [PATCH v6] cpufreq: CPPC: Add autonomous mode boot parameter support
@ 2026-11-11 22:08 Sumit Gupta
0 siblings, 0 replies; only message in thread
From: Sumit Gupta @ 2026-11-11 22:08 UTC (permalink / raw)
To: rafael, viresh.kumar, zhanjie9, zhenglifeng1, christian.loehle,
maciej.wieczor-retman, pawel.chmielewski, lenb, corbet, skhan,
rdunlap, linux-pm, linux-acpi, acpica-devel, linux-tegra,
linux-kernel, linux-doc
Cc: treding, jonathanh, vsethi, ksitaraman, sanjayc, mochs, bbasu, sumitg
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>
---
This is based on the "Preserve OSPM-set registers" [1] and
"ospm_nominal_perf" [2] series, which are applied for 7.5.
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;
+ 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)
--
2.34.1
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-11-11 22:08 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-11 22:08 [PATCH v6] cpufreq: CPPC: Add autonomous mode boot parameter support Sumit Gupta
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®