Skip to content

Commit 49b3b12

Browse files
Sumit GuptajamieNguyenNVIDIA
authored andcommitted
NVIDIA: SAUCE: cpufreq: CPPC: add autonomous mode boot parameter support
Add a kernel boot parameter 'cppc_cpufreq.auto_sel_mode' to enable CPPC autonomous performance selection on all CPUs at system startup. When autonomous mode is enabled, the hardware automatically adjusts CPU performance based on workload demands using Energy Performance Preference (EPP) hints. When auto_sel_mode=1: - Configure all CPUs for autonomous operation on first init - Set EPP to performance preference (0x0) - Use HW min/max_perf when available; otherwise initialize from caps - Clamp desired_perf to bounds before enabling autonomous mode - Hardware controls frequency instead of the OS governor The boot parameter is applied only during first policy initialization. Skip applying it on CPU hotplug to preserve runtime sysfs configuration. This patch depends on patch [2] ("cpufreq: Set policy->min and max as real QoS constraints") so that the policy->min/max set in cppc_cpufreq_cpu_init() are not overridden by cpufreq_set_policy() during init. Reviewed-by: Randy Dunlap <rdunlap@infradead.org> Signed-off-by: Sumit Gupta <sumitg@nvidia.com> (backported from https://lore.kernel.org/lkml/20260424201814.230071-1-sumitg@nvidia.com/) [jamien: hunk #2 (cppc_set_enable() insertion in cppc_cpufreq_cpu_init) rebased onto Pierre's v2 series, which replaced the local min/max vars with direct policy->min assignment; insertion point and code are unchanged.] Signed-off-by: Jamie Nguyen <jamien@nvidia.com>
1 parent b28cace commit 49b3b12

2 files changed

Lines changed: 97 additions & 5 deletions

File tree

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,6 +1052,19 @@ Kernel parameters
10521052
policy to use. This governor must be registered in the
10531053
kernel before the cpufreq driver probes.
10541054

1055+
cppc_cpufreq.auto_sel_mode=
1056+
[CPU_FREQ] Enable ACPI CPPC autonomous performance
1057+
selection. When enabled, hardware automatically adjusts
1058+
CPU frequency on all CPUs based on workload demands.
1059+
In Autonomous mode, Energy Performance Preference (EPP)
1060+
hints guide hardware toward performance (0x0) or energy
1061+
efficiency (0xff).
1062+
Requires ACPI CPPC autonomous selection register support.
1063+
Format: <bool>
1064+
Default: 0 (disabled)
1065+
0: use cpufreq governors
1066+
1: enable if supported by hardware
1067+
10551068
cpu_init_udelay=N
10561069
[X86,EARLY] Delay for N microsec between assert and de-assert
10571070
of APIC INIT to start processors. This delay occurs

drivers/cpufreq/cppc_cpufreq.c

Lines changed: 84 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828

2929
static struct cpufreq_driver cppc_cpufreq_driver;
3030

31+
/* Autonomous Selection boot parameter */
32+
static bool auto_sel_mode;
33+
3134
#ifdef CONFIG_ACPI_CPPC_CPUFREQ_FIE
3235
static enum {
3336
FIE_UNSET = -1,
@@ -655,6 +658,14 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
655658
caps = &cpu_data->perf_caps;
656659
policy->driver_data = cpu_data;
657660

661+
/*
662+
* Enable CPPC for both OS-driven and autonomous modes.
663+
* The Enable register is optional - some platforms may not support it
664+
*/
665+
ret = cppc_set_enable(cpu, true);
666+
if (ret && ret != -EOPNOTSUPP)
667+
pr_warn("Failed to enable CPPC for CPU%d (%d)\n", cpu, ret);
668+
658669
/*
659670
* Set min to lowest nonlinear perf to avoid any efficiency penalty (see
660671
* Section 8.4.7.1.1.5 of ACPI 6.1 spec)
@@ -707,11 +718,71 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
707718
policy->cur = cppc_perf_to_khz(caps, caps->highest_perf);
708719
cpu_data->perf_ctrls.desired_perf = caps->highest_perf;
709720

710-
ret = cppc_set_perf(cpu, &cpu_data->perf_ctrls);
711-
if (ret) {
712-
pr_debug("Err setting perf value:%d on CPU:%d. ret:%d\n",
713-
caps->highest_perf, cpu, ret);
714-
goto out;
721+
/*
722+
* Enable autonomous mode on first init if boot param is set.
723+
* Check last_governor to detect first init and skip if auto_sel
724+
* is already enabled.
725+
*/
726+
if (auto_sel_mode && policy->last_governor[0] == '\0' &&
727+
!cpu_data->perf_ctrls.auto_sel) {
728+
/* Init min/max_perf from caps if not already set by HW. */
729+
if (!cpu_data->perf_ctrls.min_perf)
730+
cpu_data->perf_ctrls.min_perf = caps->lowest_nonlinear_perf;
731+
if (!cpu_data->perf_ctrls.max_perf)
732+
cpu_data->perf_ctrls.max_perf = policy->boost_enabled ?
733+
caps->highest_perf : caps->nominal_perf;
734+
735+
cpu_data->perf_ctrls.desired_perf =
736+
clamp_t(u32, cpu_data->perf_ctrls.desired_perf,
737+
cpu_data->perf_ctrls.min_perf,
738+
cpu_data->perf_ctrls.max_perf);
739+
740+
policy->cur = cppc_perf_to_khz(caps,
741+
cpu_data->perf_ctrls.desired_perf);
742+
743+
/* EPP is optional - some platforms may not support it */
744+
ret = cppc_set_epp(cpu, CPPC_EPP_PERFORMANCE_PREF);
745+
if (ret && ret != -EOPNOTSUPP)
746+
pr_warn("Failed to set EPP for CPU%d (%d)\n", cpu, ret);
747+
else if (!ret)
748+
cpu_data->perf_ctrls.energy_perf = CPPC_EPP_PERFORMANCE_PREF;
749+
750+
/* Program min/max/desired into CPPC regs before enabling auto_sel. */
751+
ret = cppc_set_perf(cpu, &cpu_data->perf_ctrls);
752+
if (ret) {
753+
pr_debug("Err setting perf for autonomous mode CPU:%d ret:%d\n",
754+
cpu, ret);
755+
goto out;
756+
}
757+
758+
ret = cppc_set_auto_sel(cpu, true);
759+
if (ret && ret != -EOPNOTSUPP) {
760+
pr_warn("Failed autonomous config for CPU%d (%d)\n",
761+
cpu, ret);
762+
goto out;
763+
}
764+
if (!ret)
765+
cpu_data->perf_ctrls.auto_sel = true;
766+
}
767+
768+
if (cpu_data->perf_ctrls.auto_sel) {
769+
/* Sync policy limits from HW when autonomous mode is active */
770+
policy->min = cppc_perf_to_khz(caps,
771+
cpu_data->perf_ctrls.min_perf ?:
772+
caps->lowest_nonlinear_perf);
773+
policy->max = cppc_perf_to_khz(caps,
774+
cpu_data->perf_ctrls.max_perf ?:
775+
(policy->boost_enabled ?
776+
caps->highest_perf :
777+
caps->nominal_perf));
778+
} else {
779+
/* Normal mode: governors control frequency */
780+
ret = cppc_set_perf(cpu, &cpu_data->perf_ctrls);
781+
if (ret) {
782+
pr_debug("Err setting perf value:%d on CPU:%d. ret:%d\n",
783+
caps->highest_perf, cpu, ret);
784+
goto out;
785+
}
715786
}
716787

717788
cppc_cpufreq_cpu_fie_init(policy);
@@ -1031,10 +1102,18 @@ static int __init cppc_cpufreq_init(void)
10311102

10321103
static void __exit cppc_cpufreq_exit(void)
10331104
{
1105+
unsigned int cpu;
1106+
1107+
for_each_present_cpu(cpu)
1108+
cppc_set_auto_sel(cpu, false);
1109+
10341110
cpufreq_unregister_driver(&cppc_cpufreq_driver);
10351111
cppc_freq_invariance_exit();
10361112
}
10371113

1114+
module_param(auto_sel_mode, bool, 0444);
1115+
MODULE_PARM_DESC(auto_sel_mode, "Enable CPPC autonomous performance selection at boot");
1116+
10381117
module_exit(cppc_cpufreq_exit);
10391118
MODULE_AUTHOR("Ashwin Chaugule");
10401119
MODULE_DESCRIPTION("CPUFreq driver based on the ACPI CPPC v5.0+ spec");

0 commit comments

Comments
 (0)