[PATCH v4 2/2] arch_topology: use the boost frequencies for capacity_freq_ref

From: Oleg Keri

Date: Thu Sep 17 2026 - 09:21:25 EST


capacity_freq_ref is latched from policy->cpuinfo.max_freq by
init_cpu_capacity_callback() on CPUFREQ_CREATE_POLICY.
cpufreq_frequency_table_cpuinfo() excludes CPUFREQ_BOOST_FREQ entries
while boost is disabled, so on a system that boots with boost off the
reference is the non-boost maximum and stays there.

Once boost is enabled the CPU runs above its reference. On arm64, where
the AMU drives frequency invariance, amu_scale_freq_tick() caps the scale
at SCHED_CAPACITY_SCALE, so the scheduler cannot tell a boosted CPU from
one at the sustained maximum, and arch_freq_get_on_cpu() cannot report
above the reference, so cpuinfo_avg_freq is pinned to it.

CPPC based systems do not have the problem: their reference comes from
highest_perf, and a disabled boost shows up as cpufreq pressure. Do the
same for frequency table drivers and take the highest valid table entry,
boost entries included, as the reference. With boost off
cpufreq_update_pressure() then reports the difference as pressure.

On a Snapdragon X2 Elite (Glymur) laptop with a 4032000 kHz sustained
and a 4723200 kHz boost OPP this moves the reference of the big cores
from 4032000 to 4723200 kHz.

Signed-off-by: Oleg Keri <okerixx@xxxxxxxxx>
---
drivers/base/arch_topology.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c
index 8c5e47c28d9a..300f64ffea2f 100644
--- a/drivers/base/arch_topology.c
+++ b/drivers/base/arch_topology.c
@@ -386,6 +386,20 @@ static cpumask_var_t cpus_to_visit;
static void parsing_done_workfn(struct work_struct *work);
static DECLARE_WORK(parsing_done_work, parsing_done_workfn);

+static unsigned int topology_policy_max_freq(struct cpufreq_policy *policy)
+{
+ unsigned int max_freq = policy->cpuinfo.max_freq;
+ struct cpufreq_frequency_table *pos;
+
+ if (!policy->freq_table)
+ return max_freq;
+
+ cpufreq_for_each_valid_entry(pos, policy->freq_table)
+ max_freq = max(max_freq, pos->frequency);
+
+ return max_freq;
+}
+
static int
init_cpu_capacity_callback(struct notifier_block *nb,
unsigned long val,
@@ -404,7 +418,7 @@ init_cpu_capacity_callback(struct notifier_block *nb,
cpumask_andnot(cpus_to_visit, cpus_to_visit, policy->related_cpus);

for_each_cpu(cpu, policy->related_cpus) {
- per_cpu(capacity_freq_ref, cpu) = policy->cpuinfo.max_freq;
+ per_cpu(capacity_freq_ref, cpu) = topology_policy_max_freq(policy);
freq_inv_set_max_ratio(cpu,
per_cpu(capacity_freq_ref, cpu) * HZ_PER_KHZ);
}
--
2.55.0