[PATCH v6 2/3] cpufreq: cppc: Refactor autonomous perf bounds into helper
From: Xueqin Luo
Date: Wed Nov 11 2026 - 04:09:30 EST
Extract the autonomous selection performance bounds programming from
store_auto_select() into a reusable cppc_cpufreq_set_autonomous_perf()
helper. The helper saves and restores MIN/MAX performance on failure,
keeping the rollback logic co-located with the programming sequence.
Reuse the helper in cppc_cpufreq_update_limits() so that when
Highest Performance changes at runtime, the autonomous MIN/MAX
envelope is re-programmed against the updated capability. Add a
pr_debug message on failure for diagnostics.
Signed-off-by: Xueqin Luo <luoxueqin@xxxxxxxxxx>
---
drivers/cpufreq/cppc_cpufreq.c | 49 +++++++++++++++++++++++++---------
1 file changed, 36 insertions(+), 13 deletions(-)
diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
index 3bca30f5c0d5..7dab6e046b9f 100644
--- a/drivers/cpufreq/cppc_cpufreq.c
+++ b/drivers/cpufreq/cppc_cpufreq.c
@@ -868,6 +868,29 @@ static int cppc_cpufreq_set_boost(struct cpufreq_policy *policy, int state)
return 0;
}
+/*
+ * Program the autonomous MIN/MAX_PERF bounds from the current policy
+ * limits, restoring the previous bounds if the write fails.
+ */
+static int cppc_cpufreq_set_autonomous_perf(struct cpufreq_policy *policy)
+{
+ struct cppc_cpudata *cpu_data = policy->driver_data;
+ u32 old_min_perf = cpu_data->perf_ctrls.min_perf;
+ u32 old_max_perf = cpu_data->perf_ctrls.max_perf;
+ int ret;
+
+ cppc_cpufreq_update_perf_limits(cpu_data, policy);
+
+ ret = cppc_set_perf(policy->cpu, &cpu_data->perf_ctrls);
+ if (ret) {
+ cpu_data->perf_ctrls.min_perf = old_min_perf;
+ cpu_data->perf_ctrls.max_perf = old_max_perf;
+ return ret;
+ }
+
+ return 0;
+}
+
/*
* Boost being off is enforced through the boost_freq_req QoS request
* (capping policy->max) rather than by hiding the hardware maximum in
@@ -961,6 +984,18 @@ static void cppc_cpufreq_update_limits(struct cpufreq_policy *policy)
refresh_frequency_limits(policy);
+ /*
+ * Autonomous selection mode uses MIN/MAX performance as runtime
+ * hardware control bounds. Re-program them when highest_perf
+ * changes so that the platform uses the updated bounds.
+ */
+ if (cpu_data->perf_ctrls.auto_sel) {
+ ret = cppc_cpufreq_set_autonomous_perf(policy);
+ if (ret)
+ pr_debug("CPU%d: failed to update autonomous perf: %d\n",
+ policy->cpu, ret);
+ }
+
pr_debug("CPU%d: highest_perf updated %llu -> %llu\n",
policy->cpu, prev_highest_perf, highest_perf);
}
@@ -1008,20 +1043,8 @@ static ssize_t store_auto_select(struct cpufreq_policy *policy,
cpu_data->perf_ctrls.auto_sel = val;
if (val) {
- u32 old_min_perf = cpu_data->perf_ctrls.min_perf;
- u32 old_max_perf = cpu_data->perf_ctrls.max_perf;
-
- /*
- * When enabling autonomous selection, program MIN_PERF and
- * MAX_PERF from current policy limits so that the platform
- * uses the correct performance bounds immediately.
- */
- cppc_cpufreq_update_perf_limits(cpu_data, policy);
-
- ret = cppc_set_perf(policy->cpu, &cpu_data->perf_ctrls);
+ ret = cppc_cpufreq_set_autonomous_perf(policy);
if (ret) {
- cpu_data->perf_ctrls.min_perf = old_min_perf;
- cpu_data->perf_ctrls.max_perf = old_max_perf;
cppc_set_auto_sel(policy->cpu, old_auto_sel);
cpu_data->perf_ctrls.auto_sel = old_auto_sel;
return ret;
--
2.43.0