Re: [PATCH v2 1/2] arch_topology: seed capacity_freq_ref with boost-aware max freq

From: Rafael J. Wysocki (Intel)

Date: Fri Sep 18 2026 - 09:50:31 EST


On Fri, Sep 18, 2026 at 2:36 PM Vincent Guittot
<vincent.guittot@xxxxxxxxxx> wrote:
>
> On Fri, 18 Sept 2026 at 14:05, Rafael J. Wysocki (Intel)
> <rafael@xxxxxxxxxx> wrote:
> >
> > On Fri, Sep 18, 2026 at 8:24 AM Vincent Guittot
> > <vincent.guittot@xxxxxxxxxx> wrote:
> > >
> > > On Thu, 17 Sept 2026 at 21:07, Rafael J. Wysocki (Intel)
> > > <rafael@xxxxxxxxxx> wrote:
> > > >
> > > > On Tue, Sep 8, 2026 at 10:31 AM Ananthu C V <ananthu.cv@xxxxxxxxxxxxxxxx> wrote:
> > > > >
> > > > > capacity_freq_ref, the per-CPU frequency-invariance reference used by
> > > > > schedutil, is seeded from policy->cpuinfo.max_freq at policy creation.
> > > > > If boost frequencies are filtered out of the frequency table because
> > > > > boost isn't yet enabled at boot, max_freq only reflects the non-boost
> > > > > ceiling, so capacity_freq_ref never learns about boost frequencies for
> > > > > the policy's lifetime. Enabling boost later raises policy->max, but
> > > > > capacity_freq_ref stays stale, leaving schedutil unable to scale
> > > > > utilization or target a frequency above the non-boost maximum.
> > > > >
> > > > > Track the highest frequency in the table regardless of boost state
> > > > > (max_table_freq) and seed capacity_freq_ref with max(cpuinfo.max_freq,
> > > > > max_table_freq), so the invariance reference is boost-aware from boot
> > > > > regardless of whether boost is currently enabled. Runtime enforcement,
> > > > > still handled by policy->max, is unaffected.
> > > > >
> > > > > Suggested-by: Vincent Guittot <vincent.guittot@xxxxxxxxxx>
> > > > > Signed-off-by: Ananthu C V <ananthu.cv@xxxxxxxxxxxxxxxx>
> > > > > ---
> > > > > drivers/base/arch_topology.c | 3 ++-
> > > > > drivers/cpufreq/freq_table.c | 6 ++++++
> > > > > include/linux/cpufreq.h | 1 +
> > > > > 3 files changed, 9 insertions(+), 1 deletion(-)
> > > > >
> > > > > diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c
> > > > > index 8c5e47c28d9a..da94f77441da 100644
> > > > > --- a/drivers/base/arch_topology.c
> > > > > +++ b/drivers/base/arch_topology.c
> > > > > @@ -404,7 +404,8 @@ 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) = max(policy->cpuinfo.max_freq,
> > > > > + policy->cpuinfo.max_table_freq);
> > > >
> > > > So isn't capacity_freq_ref supposed to correspond to the CPU capacity
> > > > returned by arch_scale_cpu_capacity()?
> > >
> > > capacity_freq_ref is the frequency that has been used when computing
> > > the capacity at boot
> >
> > I get it, and so it is what I wrote above: The frequency of the CPU
> > when running at the arch_scale_cpu_capacity() performance level.
> > Isn't it?
>
> Original it was not strictly tight to arch_scale_cpu_capacity but to a
> ref capacity but it ended up being arch_scale_cpu_capacity

OK

> >
> > > and it should not change at runtime wether the
> > > boost is enabled or not, otherwise you will have some fluctuation on
> > > the system capacity that will create issue with PELT and scheduler
> >
> > So the capacity should be constant and consequently, capacity_freq_ref
> > should be constant.
> >
> > Also, if boost is not enabled when capacity_freq_ref is set and there
> > are frequency levels marked as "boost" in the table, it cannot be the
> > maximum frequency in the table because that's not what is used for
> > computing the capacity.
>
> I'm not sure I follow your last point above. It's not because boost
> isn't enabled at boot time that we can't the highest boost OPP in the
> table as a ref freq to compute arch_scale_cpu_capacity. In this case,
> the CPU will have a pressure on its capacity until the boost is
> enabled. Do I miss something ?

Well, I'm not sure if my understanding is correct.

Suppose that the cpufreq driver has a frequency table which is
processed by cpufreq_table_validate_and_sort(), right after the
driver's ->init() has returned.

That function calls cpufreq_frequency_table_cpuinfo() for the first
time and policy->cpuinfo.max_freq is set. However, if boost is not
enabled (that is, cpufreq_boost_enabled() returns false or
policy->boost_enabled is false), it only takes frequency table entries
without CPUFREQ_BOOST_FREQ into account, so policy->cpuinfo.max_freq
is one of those frequencies.

I would think that the CPU capacity has already been set at this point
and now the question arises whether or not it corresponds to
policy->cpuinfo.max_freq because that is what is assumed by
init_cpu_capacity_callback() invoked subsequently (via the
cpufreq_policy_notifier_list chain).

The $subject patch seems to suggest that the answer is "no" and the
capacity really corresponds to the highest frequency in the table
which may be flagged with CPUFREQ_BOOST_FREQ. Is that always the case
though and if not, then how can we tell?

> Can the boost OPP be added later?

Not really. It is already there in the frequency table, but the
question is if that's the capacity OPP. I guess we need to assume so?

> We keep taking the max between freq table and cpuinfo.max_freq fo the
> case where the boost freq is not listed is the freq table or there
> isno freq table. Or there is another way to get teh boost freq in thsi
> later case ?

No, I think it's the only way.

So init_cpu_capacity_callback() should find the highest frequency in
the table (regardless of whether or not the "boost" flag is set) and
set capacity_freq_ref to that one for each CPU UUIC.

That's roughly what the patch does, but it can get away without adding
a new field to struct cpufreq_policy.

And the changelog needs to be rewritten to tell the true story.