mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2 0/2] sched/cpufreq: fix schedutil's boost frequency handling
@ 2026-09-08  8:30 Ananthu C V
  2026-09-08  8:30 ` [PATCH v2 1/2] arch_topology: seed capacity_freq_ref with boost-aware max freq Ananthu C V
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Ananthu C V @ 2026-09-08  8:30 UTC (permalink / raw)
  To: Vincent Guittot, Sudeep Holla, Greg Kroah-Hartman,
	Rafael J. Wysocki, Danilo Krummrich, Viresh Kumar
  Cc: linux-kernel, driver-core, linux-pm, Ananthu C V

Schedutil's ability to reach boost frequencies depends on two values
being correct: policy max, which caps the resolved target frequency,
and the per-CPU capacity frequency reference, which anchors the
utilization-to-frequency mapping.

This series fixes a few gaps in how these values are maintained across
boost transitions:

The per-CPU capacity frequency reference is set once at policy
creation and never updated when boost is enabled afterwards, leaving
schedutil unable to target boost frequencies even at full utilization.
Track the max available (boost inclusive) frequency before policy
comes online and use it to seed the capacity_freq_ref value, allowing
schedutil to utilize the boost frequency values when boost is enabled
later.

The generic boost callback only raises cpuinfo max, never lowers it.
Once boost is enabled, disabling it leaves cpuinfo max pinned at the
boost ceiling, keeping policy max stuck there too. Also track the max
available non-boost frequency and use the newly tracked max values to
control boost frequencies when a frequency table is available, allowing
the frequency to drop back to non boost values on boost disable. In
the absense of a frequency table, the handling will fall back to using
cpuinfo->max_freq, preserving the current behaviour.

Logs below for clear context:
Intermediate values from the time_in_state output and logs from bench
runs are truncated for brevity.

Before fix
----------

boost  policy0  policy12  policy6

0

4454400

4723200

4723200

355200 36958
4454400 650
4588800 0
4723200 0

After fix
---------

boost  policy0  policy12  policy6

0

4454400

4723200

4454400

0

355200 40147
4454400 79
4588800 0
4723200 0

355200 44834
4454400 93
4588800 25
4723200 569

Signed-off-by: Ananthu C V <ananthu.cv@oss.qualcomm.com>
---
Ananthu C V (2):
      arch_topology: seed capacity_freq_ref with boost-aware max freq
      cpufreq: fix schedutil not returning to non-boost freq when boost is disabled

 drivers/base/arch_topology.c |  3 ++-
 drivers/cpufreq/cpufreq.c    | 14 +++++++++++++-
 drivers/cpufreq/freq_table.c | 11 +++++++++++
 include/linux/cpufreq.h      |  2 ++
 4 files changed, 28 insertions(+), 2 deletions(-)
---
base-commit: 32b6ef9a5d0eca44f9cd91f52f4faa89f145a0de
change-id: 20260804-schedutil-boost-frequency-handling-8e6bf2387a4a

Best regards,
-- 
Ananthu C V <ananthu.cv@oss.qualcomm.com>


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v2 1/2] arch_topology: seed capacity_freq_ref with boost-aware max freq
  2026-09-08  8:30 [PATCH v2 0/2] sched/cpufreq: fix schedutil's boost frequency handling Ananthu C V
@ 2026-09-08  8:30 ` Ananthu C V
  2026-09-08  8:30 ` [PATCH v2 2/2] cpufreq: fix schedutil not returning to non-boost freq when boost is disabled Ananthu C V
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Ananthu C V @ 2026-09-08  8:30 UTC (permalink / raw)
  To: Vincent Guittot, Sudeep Holla, Greg Kroah-Hartman,
	Rafael J. Wysocki, Danilo Krummrich, Viresh Kumar
  Cc: linux-kernel, driver-core, linux-pm, Ananthu C V

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@linaro.org>
Signed-off-by: Ananthu C V <ananthu.cv@oss.qualcomm.com>
---
 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);
 		freq_inv_set_max_ratio(cpu,
 				       per_cpu(capacity_freq_ref, cpu) * HZ_PER_KHZ);
 	}
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index ea994647abc8..4984142dc08a 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -33,11 +33,15 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy)
 	struct cpufreq_frequency_table *pos, *table = policy->freq_table;
 	unsigned int min_freq = ~0;
 	unsigned int max_freq = 0;
+	unsigned int max_table_freq = 0;
 	unsigned int freq, i;
 
 	cpufreq_for_each_valid_entry_idx(pos, table, i) {
 		freq = pos->frequency;
 
+		if (freq > max_table_freq)
+			max_table_freq = freq;
+
 		if ((!cpufreq_boost_enabled() || !policy->boost_enabled)
 		    && (pos->flags & CPUFREQ_BOOST_FREQ))
 			continue;
@@ -57,6 +61,8 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy)
 	if (policy->cpuinfo.max_freq < max_freq)
 		policy->cpuinfo.max_freq = max_freq;
 
+	policy->cpuinfo.max_table_freq = max_table_freq;
+
 	if (min_freq == ~0)
 		return -EINVAL;
 	else
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 35ce665edfd8..3f3b1380251a 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -45,6 +45,7 @@ enum cpufreq_table_sorting {
 struct cpufreq_cpuinfo {
 	unsigned int		max_freq;
 	unsigned int		min_freq;
+	unsigned int		max_table_freq; /* Highest valid frequency in the table */
 
 	/* in 10^(-9) s = nanoseconds */
 	unsigned int		transition_latency;

-- 
2.43.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v2 2/2] cpufreq: fix schedutil not returning to non-boost freq when boost is disabled
  2026-09-08  8:30 [PATCH v2 0/2] sched/cpufreq: fix schedutil's boost frequency handling Ananthu C V
  2026-09-08  8:30 ` [PATCH v2 1/2] arch_topology: seed capacity_freq_ref with boost-aware max freq Ananthu C V
@ 2026-09-08  8:30 ` Ananthu C V
  2026-09-08 10:03 ` [PATCH v2 0/2] sched/cpufreq: fix schedutil's boost frequency handling Ananthu C V
  2026-09-14 16:27 ` Dietmar Eggemann
  3 siblings, 0 replies; 5+ messages in thread
From: Ananthu C V @ 2026-09-08  8:30 UTC (permalink / raw)
  To: Vincent Guittot, Sudeep Holla, Greg Kroah-Hartman,
	Rafael J. Wysocki, Danilo Krummrich, Viresh Kumar
  Cc: linux-kernel, driver-core, linux-pm, Ananthu C V

Commit 538b0188da46 ("cpufreq: ACPI: Set cpuinfo.max_freq directly if
max boost is known") introduced a guard for cpuinfo max updates to only
increase, to preserve driver-set values above the freq table maximum,
causing cpuinfo max to be stuck at boost frequency even when boost is
disabled.

Unconditionally track the highest non-boost frequency (max_base_freq)
in the freq table. When a freq table is available, use max_table_freq/
max_base_freq instead of cpuinfo->max_freq to control boost values, so
the value can decrease again when boost is disabled.

Fixes: 538b0188da46 ("cpufreq: ACPI: Set cpuinfo.max_freq directly if max boost is known")
Signed-off-by: Ananthu C V <ananthu.cv@oss.qualcomm.com>
---
 drivers/cpufreq/cpufreq.c    | 14 +++++++++++++-
 drivers/cpufreq/freq_table.c |  5 +++++
 include/linux/cpufreq.h      |  1 +
 3 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 0d0df986fa3d..a13e72711597 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -574,6 +574,7 @@ static ssize_t show_local_boost(struct cpufreq_policy *policy, char *buf)
 
 static int policy_set_boost(struct cpufreq_policy *policy, bool enable)
 {
+	unsigned int max_freq;
 	int ret;
 
 	if (policy->boost_enabled == enable)
@@ -587,7 +588,18 @@ static int policy_set_boost(struct cpufreq_policy *policy, bool enable)
 		return ret;
 	}
 
-	ret = freq_qos_update_request(&policy->boost_freq_req, policy->cpuinfo.max_freq);
+	if (policy->freq_table) {
+		max_freq = enable ? policy->cpuinfo.max_table_freq :
+				    policy->cpuinfo.max_base_freq;
+
+		if (!max_freq)
+			/* when the freq table contains only boost frequencies */
+			max_freq = policy->cpuinfo.max_table_freq;
+	} else {
+		max_freq = policy->cpuinfo.max_freq;
+	}
+
+	ret = freq_qos_update_request(&policy->boost_freq_req, max_freq);
 	if (ret < 0) {
 		policy->boost_enabled = !policy->boost_enabled;
 		cpufreq_driver->set_boost(policy, policy->boost_enabled);
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index 4984142dc08a..7e183e16162d 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -34,6 +34,7 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy)
 	unsigned int min_freq = ~0;
 	unsigned int max_freq = 0;
 	unsigned int max_table_freq = 0;
+	unsigned int max_base_freq = 0;
 	unsigned int freq, i;
 
 	cpufreq_for_each_valid_entry_idx(pos, table, i) {
@@ -42,6 +43,9 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy)
 		if (freq > max_table_freq)
 			max_table_freq = freq;
 
+		if (!(pos->flags & CPUFREQ_BOOST_FREQ) && freq > max_base_freq)
+			max_base_freq = freq;
+
 		if ((!cpufreq_boost_enabled() || !policy->boost_enabled)
 		    && (pos->flags & CPUFREQ_BOOST_FREQ))
 			continue;
@@ -62,6 +66,7 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy)
 		policy->cpuinfo.max_freq = max_freq;
 
 	policy->cpuinfo.max_table_freq = max_table_freq;
+	policy->cpuinfo.max_base_freq = max_base_freq;
 
 	if (min_freq == ~0)
 		return -EINVAL;
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 3f3b1380251a..419c71ccff7c 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -46,6 +46,7 @@ struct cpufreq_cpuinfo {
 	unsigned int		max_freq;
 	unsigned int		min_freq;
 	unsigned int		max_table_freq; /* Highest valid frequency in the table */
+	unsigned int		max_base_freq; /* Highest non-boost frequency in the table */
 
 	/* in 10^(-9) s = nanoseconds */
 	unsigned int		transition_latency;

-- 
2.43.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 0/2] sched/cpufreq: fix schedutil's boost frequency handling
  2026-09-08  8:30 [PATCH v2 0/2] sched/cpufreq: fix schedutil's boost frequency handling Ananthu C V
  2026-09-08  8:30 ` [PATCH v2 1/2] arch_topology: seed capacity_freq_ref with boost-aware max freq Ananthu C V
  2026-09-08  8:30 ` [PATCH v2 2/2] cpufreq: fix schedutil not returning to non-boost freq when boost is disabled Ananthu C V
@ 2026-09-08 10:03 ` Ananthu C V
  2026-09-14 16:27 ` Dietmar Eggemann
  3 siblings, 0 replies; 5+ messages in thread
From: Ananthu C V @ 2026-09-08 10:03 UTC (permalink / raw)
  To: Vincent Guittot, Sudeep Holla, Greg Kroah-Hartman,
	Rafael J. Wysocki, Danilo Krummrich, Viresh Kumar
  Cc: linux-kernel, driver-core, linux-pm

It seems some mangling was done and all lines starting with hashes
were considered comments and ignored, malforming the logs. Apologies
for that, this is how it's supposed to look :)

Before fix
----------
# cd /sys/devices/system/cpu/cpufreq/
# ls
boost  policy0  policy12  policy6
# cat boost
0
# cat policy6/scaling_max_freq
4454400
# echo 1 > boost
# cat policy6/scaling_max_freq
4723200
# echo 0 > boost
# cat policy6/scaling_max_freq
4723200
4723200

# echo 1 > boost
# cat policy6/stats/time_in_state
355200 36958
4454400 650
4588800 0
4723200 0

After fix
---------
# cd /sys/devices/system/cpu/cpufreq/
# ls
boost  policy0  policy12  policy6
# cat boost
0
# cat policy6/scaling_max_freq
4454400
# echo 1 > boost
# cat policy6/scaling_max_freq
4723200
# echo 0 > policy6/boost
# cat policy6/scaling_max_freq
4454400

# cat policy6/boost
0
# cat policy6/stats/time_in_state
355200 40147
4454400 79
4588800 0
4723200 0
# echo 1 > policy6/boost
# cat policy6/stats/time_in_state
355200 44834
4454400 93
4588800 25
4723200 569

Best,
Ananthu

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 0/2] sched/cpufreq: fix schedutil's boost frequency handling
  2026-09-08  8:30 [PATCH v2 0/2] sched/cpufreq: fix schedutil's boost frequency handling Ananthu C V
                   ` (2 preceding siblings ...)
  2026-09-08 10:03 ` [PATCH v2 0/2] sched/cpufreq: fix schedutil's boost frequency handling Ananthu C V
@ 2026-09-14 16:27 ` Dietmar Eggemann
  3 siblings, 0 replies; 5+ messages in thread
From: Dietmar Eggemann @ 2026-09-14 16:27 UTC (permalink / raw)
  To: Ananthu C V, Vincent Guittot, Sudeep Holla, Greg Kroah-Hartman,
	Rafael J. Wysocki, Danilo Krummrich, Viresh Kumar
  Cc: linux-kernel, driver-core, linux-pm

On 08.09.26 10:30, Ananthu C V wrote:
> Schedutil's ability to reach boost frequencies depends on two values
> being correct: policy max, which caps the resolved target frequency,
> and the per-CPU capacity frequency reference, which anchors the
> utilization-to-frequency mapping.
> 
> This series fixes a few gaps in how these values are maintained across
> boost transitions:
> 
> The per-CPU capacity frequency reference is set once at policy
> creation and never updated when boost is enabled afterwards, leaving
> schedutil unable to target boost frequencies even at full utilization.
> Track the max available (boost inclusive) frequency before policy
> comes online and use it to seed the capacity_freq_ref value, allowing
> schedutil to utilize the boost frequency values when boost is enabled
> later.
> 
> The generic boost callback only raises cpuinfo max, never lowers it.
> Once boost is enabled, disabling it leaves cpuinfo max pinned at the
> boost ceiling, keeping policy max stuck there too. Also track the max
> available non-boost frequency and use the newly tracked max values to
> control boost frequencies when a frequency table is available, allowing
> the frequency to drop back to non boost values on boost disable. In
> the absense of a frequency table, the handling will fall back to using
> cpuinfo->max_freq, preserving the current behaviour.
> 
> Logs below for clear context:
> Intermediate values from the time_in_state output and logs from bench
> runs are truncated for brevity.
> 
> Before fix
> ----------
> 
> boost  policy0  policy12  policy6
> 
> 0
> 
> 4454400
> 
> 4723200
> 
> 4723200
> 
> 355200 36958
> 4454400 650
> 4588800 0
> 4723200 0
> 
> After fix
> ---------
> 
> boost  policy0  policy12  policy6
> 
> 0
> 
> 4454400
> 
> 4723200
> 
> 4454400
> 
> 0
> 
> 355200 40147
> 4454400 79
> 4588800 0
> 4723200 0
> 
> 355200 44834
> 4454400 93
> 4588800 25
> 4723200 569
> 
> Signed-off-by: Ananthu C V <ananthu.cv@oss.qualcomm.com>
> ---
> Ananthu C V (2):
>       arch_topology: seed capacity_freq_ref with boost-aware max freq
>       cpufreq: fix schedutil not returning to non-boost freq when boost is disabled
> 
>  drivers/base/arch_topology.c |  3 ++-
>  drivers/cpufreq/cpufreq.c    | 14 +++++++++++++-
>  drivers/cpufreq/freq_table.c | 11 +++++++++++
>  include/linux/cpufreq.h      |  2 ++
>  4 files changed, 28 insertions(+), 2 deletions(-)
> ---
> base-commit: 32b6ef9a5d0eca44f9cd91f52f4faa89f145a0de
> change-id: 20260804-schedutil-boost-frequency-handling-8e6bf2387a4a
IMHO, this makes sense, also the coordination via cpufreq_pressure
(policy->max).

On ARM64 Juno R0:

# cat /sys/devices/system/cpu/cpu*/cpu_capacity
446
1024
1024
446
446
446

# cat /sys/devices/system/cpu/cpufreq/boost
0

cat
/sys/devices/system/cpu/cpu{0,1}/cpufreq/scaling_{available,boost}_frequencies
450000 575000 700000
775000 850000
450000 625000 800000
950000 1100000

# cat /sys/devices/system/cpu/cpu{0,1}/cpufreq/cpuinfo_{min,max}_freq
450000
700000
450000
800000

# dmsg | grep policy

[3.323564] cpufreq_update_pressure(): policy->related_cpus=[0,3-5]
policy->max=700000 pressure=102                                      (*)
[3.333206] cpufreq_update_pressure(): policy->related_cpus=[1-2]
policy->max=800000 pressure=280


# echo 1 > /sys/devices/system/cpu/cpufreq/boost

# dmsg | grep policy

[ 1511.188932] policy->related_cpus=[1-2] pressure=0
[ 1511.189050] policy->related_cpus=[0,3-5] pressure=0

# echo 0 > /sys/devices/system/cpu/cpufreq/boost

# dmsg | grep policy

[  204.951039] cpufreq_update_pressure(): policy->related_cpus=[1-2]
policy->max=800000 pressure=280
[  204.951223] cpufreq_update_pressure(): policy->related_cpus=[0,3-5]
policy->max=700000 pressure=79                                       (*)

(*) This is the only small issue I see. The pressure=102 is pressure
based on purely uarch differences (max_capacity(0,3-5)=578) whereas
pressure=79 later is based on uarch + max frequency differences
(max_capacity(0,3-5)=446).

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-09-14 16:27 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-08  8:30 [PATCH v2 0/2] sched/cpufreq: fix schedutil's boost frequency handling Ananthu C V
2026-09-08  8:30 ` [PATCH v2 1/2] arch_topology: seed capacity_freq_ref with boost-aware max freq Ananthu C V
2026-09-08  8:30 ` [PATCH v2 2/2] cpufreq: fix schedutil not returning to non-boost freq when boost is disabled Ananthu C V
2026-09-08 10:03 ` [PATCH v2 0/2] sched/cpufreq: fix schedutil's boost frequency handling Ananthu C V
2026-09-14 16:27 ` Dietmar Eggemann

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®