[PATCH v2 2/2] cpufreq: fix schedutil not returning to non-boost freq when boost is disabled
From: Ananthu C V <hidden>
Date: 2026-09-08 08:31:20
Also in:
driver-core, lkml
Subsystem:
cpu frequency scaling framework, the rest · Maintainers:
"Rafael J. Wysocki", Viresh Kumar, Linus Torvalds
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 <redacted>
---
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