From: Zhongqiu Han <zhongqiu.han@oss.qualcomm.com>
To: Ananthu C V <ananthu.cv@oss.qualcomm.com>,
Vincent Guittot <vincent.guittot@linaro.org>,
Sudeep Holla <sudeep.holla@kernel.org>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
"Rafael J. Wysocki" <rafael@kernel.org>,
Danilo Krummrich <dakr@kernel.org>,
Viresh Kumar <viresh.kumar@linaro.org>,
Jie Zhan <zhanjie9@hisilicon.com>,
Pierre Gondois <pierre.gondois@arm.com>
Cc: linux-kernel@vger.kernel.org, driver-core@lists.linux.dev,
linux-pm@vger.kernel.org,
"Rafael J. Wysocki" <rafael.j.wysocki@intel.com>,
Oleg Keri <okerixx@gmail.com>,
zhongqiu.han@oss.qualcomm.com
Subject: Re: [PATCH v3 1/2] arch_topology: seed capacity_freq_ref with highest available frequency
Date: Sun, 11 Oct 2026 22:16:37 +0800 [thread overview]
Message-ID: <fbd7fe35-5e14-4589-a072-909e49a92e76@oss.qualcomm.com> (raw)
In-Reply-To: <20260929-schedutil-boost-frequency-handling-v3-1-68de169498c7@oss.qualcomm.com>
On 9/29/2026 7:38 PM, Ananthu C V 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 isn't enabled yet at boot, max_freq reflects only 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.
>
> Seed capacity_freq_ref with the highest available frequency regardless
> of whether boost is enabled. Runtime enforcement, still handled by
> policy->max, is unaffected.
>
> Suggested-by: Vincent Guittot <vincent.guittot@linaro.org>
> Signed-off-by: Ananthu C V <ananthu.cv@oss.qualcomm.com>
> ---
> drivers/base/arch_topology.c | 3 ++-
> include/linux/cpufreq.h | 13 +++++++++++++
> 2 files changed, 15 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c
> index 8c5e47c28d9a..92966be712d5 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,
> + cpufreq_frequency_table_max(policy));
> freq_inv_set_max_ratio(cpu,
> per_cpu(capacity_freq_ref, cpu) * HZ_PER_KHZ);
> }
> diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
> index 35ce665edfd8..f048c925fd98 100644
> --- a/include/linux/cpufreq.h
> +++ b/include/linux/cpufreq.h
> @@ -1107,6 +1107,19 @@ static inline int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
> return idx;
> }
>
> +static inline unsigned int cpufreq_frequency_table_max(struct cpufreq_policy *policy)
> +{
> + int idx;
> +
> + if (!policy->freq_table)
> + return policy->cpuinfo.max_freq;
> +
> + idx = cpufreq_frequency_table_target(policy, UINT_MAX, 0, UINT_MAX,
> + CPUFREQ_RELATION_H);
> +
> + return policy->freq_table[idx].frequency;
> +}
> +
The current implementation looks correct and works well. That said, we
might be able to optimize it with a simpler implementation as shown
below:
+/**
+ * cpufreq_frequency_table_max - Get the highest frequency in a
policy's table
+ * @policy: the &struct cpufreq_policy to inspect
+ *
+ * Boost entries (%CPUFREQ_BOOST_FREQ) are taken into account regardless of
+ * whether or not boost is currently enabled.
+ *
+ * Return: the highest valid frequency in @policy->freq_table, or 0 if
there
+ * is no frequency table.
+ */
+static inline unsigned int
+cpufreq_frequency_table_max(const struct cpufreq_policy *policy)
+{
+ struct cpufreq_frequency_table *pos;
+ unsigned int max_freq = 0;
+
+ if (!policy->freq_table)
+ return 0;
+
+ cpufreq_for_each_valid_entry(pos, policy->freq_table)
+ max_freq = max(max_freq, pos->frequency);
+
+ return max_freq;
+}
+
> static inline int cpufreq_table_count_valid_entries(const struct cpufreq_policy *policy)
> {
> struct cpufreq_frequency_table *pos;
>
Besides, could you comment patch v2 Dietmar's comments? It seems that
patch 1/2 exposes a pre-existing ordering issue. On DT systems,
cpu_scale is normalized only from the CPUFREQ_CREATE_POLICY notification
of the last policy, so the cpufreq pressure of every other policy is
computed in cpufreq_init_policy() from the raw, not yet normalized,
capacity, and stays cached until the next cpufreq_set_policy() for that
policy. So far this was harmless because capacity_freq_ref ==
policy->max at boot, so the pressure was 0 regardless of the capacity.
With 1/2, capacity_freq_ref covers the boost frequencies while boost is
disabled at boot, so policy->max < capacity_freq_ref becomes the common
case and the stale value becomes visible (102 vs 79 on Juno R0, as
reported by Dietmar). Perhaps the limits of all policies could be
refreshed once from parsing_done_workfn(), after the capacities have
been normalized?
--- a/drivers/base/arch_topology.c
+++ b/drivers/base/arch_topology.c
@@ -454,9 +454,27 @@ core_initcall(register_cpufreq_notifier);
static void parsing_done_workfn(struct work_struct *work)
{
+ int cpu;
+
cpufreq_unregister_notifier(&init_cpu_capacity_notifier,
CPUFREQ_POLICY_NOTIFIER);
free_cpumask_var(cpus_to_visit);
+
+ /*
+ * The cpufreq pressure of all policies but the last one has been
+ * computed before topology_normalize_cpu_scale(), so refresh it now
+ * that cpu_scale is final.
+ */
+ for_each_possible_cpu(cpu) {
+ struct cpufreq_policy *policy __free(put_cpufreq_policy) =
+ cpufreq_cpu_get(cpu);
+
+ if (!policy || cpu != policy->cpu)
+ continue;
+
+ guard(cpufreq_policy_write)(policy);
+ refresh_frequency_limits(policy);
+ }
--
Thx and BRs,
Zhongqiu Han
next prev parent reply other threads:[~2026-10-11 14:16 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-29 11:38 [PATCH v3 0/2] sched/cpufreq: fix schedutil's boost frequency handling Ananthu C V
2026-09-29 11:38 ` [PATCH v3 1/2] arch_topology: seed capacity_freq_ref with highest available frequency Ananthu C V
2026-10-11 14:16 ` Zhongqiu Han [this message]
2026-09-29 11:38 ` [PATCH v3 2/2] cpufreq: fix policy max not returning to non-boost freq on boost disable Ananthu C V
2026-10-11 14:17 ` Zhongqiu Han
2026-10-11 23:42 ` Dietmar Eggemann
2026-09-30 9:10 ` [PATCH v3 0/2] sched/cpufreq: fix schedutil's boost frequency handling Oleg Keri
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=fbd7fe35-5e14-4589-a072-909e49a92e76@oss.qualcomm.com \
--to=zhongqiu.han@oss.qualcomm.com \
--cc=ananthu.cv@oss.qualcomm.com \
--cc=dakr@kernel.org \
--cc=driver-core@lists.linux.dev \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=okerixx@gmail.com \
--cc=pierre.gondois@arm.com \
--cc=rafael.j.wysocki@intel.com \
--cc=rafael@kernel.org \
--cc=sudeep.holla@kernel.org \
--cc=vincent.guittot@linaro.org \
--cc=viresh.kumar@linaro.org \
--cc=zhanjie9@hisilicon.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®