Skip to content

Commit 17f54e0

Browse files
Sumit GuptajamieNguyenNVIDIA
authored andcommitted
NVIDIA: SAUCE: cpufreq: CPPC: add autonomous mode boot parameter support
Add kernel boot parameter 'cppc_cpufreq.auto_sel_mode' to enable CPPC autonomous performance selection at system startup. When autonomous mode is enabled, the hardware automatically adjusts CPU performance based on workload demands using Energy Performance Preference (EPP) hints. This parameter allows to configure the autonomous mode on all CPUs without requiring runtime sysfs manipulation if the 'auto_sel' register is present. When auto_sel_mode=1: - All CPUs are configured for autonomous operation during module init - EPP is set to performance preference (0x0) by default - Min/max performance bounds use defaults - CPU frequency scaling is handled by hardware instead of OS governor For Documentation/: Reviewed-by: Randy Dunlap <rdunlap@infradead.org> Signed-off-by: Sumit Gupta <sumitg@nvidia.com> (backported from https://lore.kernel.org/lkml/20260317151053.2361475-1-sumitg@nvidia.com/) [jamien: adapted for the upstream struct layout where auto_sel moved from cppc_perf_caps to cppc_perf_ctrls, and inlined the init-path logic previously handled by removed SAUCE helpers] Signed-off-by: Jamie Nguyen <jamien@nvidia.com>
1 parent 60ea7a2 commit 17f54e0

2 files changed

Lines changed: 108 additions & 6 deletions

File tree

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -911,6 +911,18 @@
911911
Format:
912912
<first_slot>,<last_slot>,<port>,<enum_bit>[,<debug>]
913913

914+
cppc_cpufreq.auto_sel_mode=
915+
[CPU_FREQ] Enable ACPI CPPC autonomous performance selection.
916+
When enabled, hardware automatically adjusts CPU frequency
917+
on all CPUs based on workload demands. In Autonomous mode,
918+
Energy Performance Preference(EPP) hints guide hardware
919+
toward performance(0x0) or energy efficiency (0xff).
920+
Requires ACPI CPPC autonomous selection register support.
921+
Format: <bool>
922+
Default: 0 (disabled)
923+
0: use cpufreq governors
924+
1: enable if supported by hardware
925+
914926
cpuidle.off=1 [CPU_IDLE]
915927
disable the cpuidle sub-system
916928

drivers/cpufreq/cppc_cpufreq.c

Lines changed: 96 additions & 6 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 */
32+
static bool auto_sel_mode;
33+
3134
#ifdef CONFIG_ACPI_CPPC_CPUFREQ_FIE
3235
static enum {
3336
FIE_UNSET = -1,
@@ -289,8 +292,13 @@ static int cppc_cpufreq_set_target(struct cpufreq_policy *policy,
289292
freqs.old = policy->cur;
290293
freqs.new = target_freq;
291294

295+
/*
296+
* In autonomous selection mode, hardware handles frequency scaling directly
297+
* based on workload and EPP hints. So, skip the OS frequency set requests.
298+
*/
292299
cpufreq_freq_transition_begin(policy, &freqs);
293-
ret = cppc_set_perf(cpu, &cpu_data->perf_ctrls);
300+
if (!cpu_data->perf_ctrls.auto_sel)
301+
ret = cppc_set_perf(cpu, &cpu_data->perf_ctrls);
294302
cpufreq_freq_transition_end(policy, &freqs, ret != 0);
295303

296304
if (ret)
@@ -676,11 +684,36 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
676684
policy->cur = cppc_perf_to_khz(caps, caps->highest_perf);
677685
cpu_data->perf_ctrls.desired_perf = caps->highest_perf;
678686

679-
ret = cppc_set_perf(cpu, &cpu_data->perf_ctrls);
680-
if (ret) {
681-
pr_debug("Err setting perf value:%d on CPU:%d. ret:%d\n",
682-
caps->highest_perf, cpu, ret);
683-
goto out;
687+
if (cpu_data->perf_ctrls.auto_sel) {
688+
ret = cppc_set_enable(cpu, true);
689+
if (ret) {
690+
pr_err("Failed to enable CPPC on cpu%d (%d)\n", cpu, ret);
691+
goto out;
692+
}
693+
694+
cpu_data->perf_ctrls.min_perf = cpu_data->perf_ctrls.min_perf ?
695+
cpu_data->perf_ctrls.min_perf : caps->lowest_nonlinear_perf;
696+
cpu_data->perf_ctrls.max_perf = cpu_data->perf_ctrls.max_perf ?
697+
cpu_data->perf_ctrls.max_perf : caps->nominal_perf;
698+
699+
ret = cppc_set_perf(cpu, &cpu_data->perf_ctrls);
700+
if (ret) {
701+
cppc_set_enable(cpu, false);
702+
goto out;
703+
}
704+
705+
ret = cppc_set_epp(cpu, 0);
706+
if (ret) {
707+
cppc_set_enable(cpu, false);
708+
goto out;
709+
}
710+
} else {
711+
ret = cppc_set_perf(cpu, &cpu_data->perf_ctrls);
712+
if (ret) {
713+
pr_debug("Err setting perf value:%d on CPU:%d. ret:%d\n",
714+
caps->highest_perf, cpu, ret);
715+
goto out;
716+
}
684717
}
685718

686719
cppc_cpufreq_cpu_fie_init(policy);
@@ -1018,13 +1051,61 @@ static struct cpufreq_driver cppc_cpufreq_driver = {
10181051
.name = "cppc_cpufreq",
10191052
};
10201053

1054+
static int cppc_cpufreq_set_epp_autosel_allcpus(bool auto_sel, u64 epp)
1055+
{
1056+
int cpu, ret;
1057+
1058+
for_each_present_cpu(cpu) {
1059+
ret = cppc_set_epp(cpu, epp);
1060+
if (ret) {
1061+
pr_warn("Failed to set EPP on CPU%d (%d)\n", cpu, ret);
1062+
goto disable_all;
1063+
}
1064+
1065+
ret = cppc_set_auto_sel(cpu, auto_sel);
1066+
if (ret) {
1067+
pr_warn("Failed to set auto_sel on CPU%d (%d)\n", cpu, ret);
1068+
goto disable_all;
1069+
}
1070+
}
1071+
1072+
return 0;
1073+
1074+
disable_all:
1075+
pr_warn("Disabling auto_sel for all CPUs\n");
1076+
for_each_present_cpu(cpu)
1077+
cppc_set_auto_sel(cpu, false);
1078+
1079+
return -EIO;
1080+
}
1081+
10211082
static int __init cppc_cpufreq_init(void)
10221083
{
1084+
bool auto_sel;
10231085
int ret;
10241086

10251087
if (!acpi_cpc_valid())
10261088
return -ENODEV;
10271089

1090+
if (auto_sel_mode) {
1091+
/*
1092+
* Check if autonomous selection is supported by testing CPU 0.
1093+
* If supported, enable autonomous mode on all CPUs.
1094+
*/
1095+
ret = cppc_get_auto_sel(0, &auto_sel);
1096+
if (!ret) {
1097+
pr_info("Enabling auto_sel_mode (autonomous selection mode)\n");
1098+
ret = cppc_cpufreq_set_epp_autosel_allcpus(true, 0);
1099+
if (ret) {
1100+
pr_warn("Disabling auto_sel_mode, fallback to standard\n");
1101+
auto_sel_mode = false;
1102+
}
1103+
} else {
1104+
pr_warn("Disabling auto_sel_mode as not supported by hardware\n");
1105+
auto_sel_mode = false;
1106+
}
1107+
}
1108+
10281109
cppc_freq_invariance_init();
10291110
populate_efficiency_class();
10301111

@@ -1037,10 +1118,19 @@ static int __init cppc_cpufreq_init(void)
10371118

10381119
static void __exit cppc_cpufreq_exit(void)
10391120
{
1121+
int cpu;
1122+
1123+
for_each_present_cpu(cpu)
1124+
cppc_set_auto_sel(cpu, false);
1125+
auto_sel_mode = false;
1126+
10401127
cpufreq_unregister_driver(&cppc_cpufreq_driver);
10411128
cppc_freq_invariance_exit();
10421129
}
10431130

1131+
module_param(auto_sel_mode, bool, 0000);
1132+
MODULE_PARM_DESC(auto_sel_mode, "Enable Autonomous Performance Level Selection");
1133+
10441134
module_exit(cppc_cpufreq_exit);
10451135
MODULE_AUTHOR("Ashwin Chaugule");
10461136
MODULE_DESCRIPTION("CPUFreq driver based on the ACPI CPPC v5.0+ spec");

0 commit comments

Comments
 (0)