Re: [PATCH v3 1/4] cpufreq: CPPC: Keep the policy across CPU hotplug

From: Sumit Gupta

Date: Wed Jul 29 2026 - 13:20:00 EST



On 28/07/26 14:11, zhenglifeng (A) wrote:
External email: Use caution opening links or attachments


On 7/25/2026 5:59 AM, Sumit Gupta wrote:
Without online()/offline() callbacks, the cpufreq core fully tears
down a policy during exit() when its last online CPU is offlined, and
rebuilds it during init() when it comes back.

Add lightweight online()/offline() callbacks so the core instead keeps
the policy live and reuses the driver's cpu_data across CPU hotplug.
This avoids re-reading the CPPC capabilities on every offline/online,
making CPU hotplug faster.

From online(), re-enable CPPC, as the platform may have disabled it
while the CPU was offline. Since the policy is no longer rebuilt via
init(), online() also reprograms the CPPC performance controls
(desired/min/max).

Signed-off-by: Sumit Gupta <sumitg@xxxxxxxxxx>
---
drivers/cpufreq/cppc_cpufreq.c | 44 ++++++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)

diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
index f6cea0c54dd9..6dc59f99d880 100644
--- a/drivers/cpufreq/cppc_cpufreq.c
+++ b/drivers/cpufreq/cppc_cpufreq.c
@@ -722,6 +722,48 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
return ret;
}

+/*
+ * With offline() defined, the cpufreq core keeps the policy alive when
+ * a CPU is hotplugged out.
+ */
+static int cppc_cpufreq_cpu_offline(struct cpufreq_policy *policy)
+{
+ return 0;
+}
I am not sure if doing nothing here will cause issues. In my view, to be safe,
we should perform the actions found in cppc_cpufreq_cpu_exit() here, except
cppc_cpufreq_put_cpu_data().

Agreed regarding the performance request. Since exit() previously set
desired_perf to lowest_perf during hotplug, I will do the same in
offline().
I will keep FIE registered across the lightweight tear down, as clearing
it on every hotplug would add tear down cost with no benefit. It does
need the feedback counter snapshots refreshed, as init() no longer runs,
so I will do that for the online CPUs from online().

Thanks,
Sumit



+
+/*
+ * Re-enable CPPC when the policy's CPU comes back online, since the platform
+ * may have disabled it while the CPU was offline.
+ */
+static int cppc_cpufreq_cpu_online(struct cpufreq_policy *policy)
+{
+ struct cppc_cpudata *cpu_data = policy->driver_data;
+ unsigned int cpu = policy->cpu;
+ int ret;
+
+ ret = cppc_set_enable(cpu, true);
+ if (ret && ret != -EOPNOTSUPP)
+ pr_warn("Failed to re-enable CPPC for CPU%d (%d)\n", cpu, ret);
+
+ /*
+ * The platform may reset the controls while the CPU is offline, so
+ * recompute min/max, clamp desired_perf into range, and reprogram them.
+ */
+ cppc_cpufreq_update_perf_limits(cpu_data, policy);
+
+ cpu_data->perf_ctrls.desired_perf =
+ clamp_t(u32, cpu_data->perf_ctrls.desired_perf,
+ cpu_data->perf_ctrls.min_perf,
+ cpu_data->perf_ctrls.max_perf);
+
+ ret = cppc_set_perf(cpu, &cpu_data->perf_ctrls);
+ if (ret)
+ pr_debug("Failed to reapply perf request on CPU%d (%d)\n",
+ cpu, ret);
+
+ return 0;
+}
+
static void cppc_cpufreq_cpu_exit(struct cpufreq_policy *policy)
{
struct cppc_cpudata *cpu_data = policy->driver_data;
@@ -1034,6 +1076,8 @@ static struct cpufreq_driver cppc_cpufreq_driver = {
.fast_switch = cppc_cpufreq_fast_switch,
.init = cppc_cpufreq_cpu_init,
.exit = cppc_cpufreq_cpu_exit,
+ .online = cppc_cpufreq_cpu_online,
+ .offline = cppc_cpufreq_cpu_offline,
.set_boost = cppc_cpufreq_set_boost,
.attr = cppc_cpufreq_attr,
.name = "cppc_cpufreq",