[PATCH] cpufreq: conservative: Ignore idle periods when a policy CPU is busy

From: hu.shengming

Date: Wed Sep 02 2026 - 03:56:28 EST


From: Shengming Hu <hu.shengming@xxxxxxxxxx>

For a shared cpufreq policy, dbs_update() derives the load from the
highest utilization among its CPUs, but it also records deferred idle
periods from any CPU whose idle time exceeds two sampling intervals.

This lets a single update report both a high load (from a busy CPU)
and several deferred idle periods (from an idle sibling). Since
conservative applies the deferred down steps before the up step
triggered by the high load, the down steps can outweigh the single
up step.

The issue reproduces on a policy shared by CPUs 2 and 3: a CPU-bound
SCHED_EXT task keeps CPU 2 at 100% utilization while CPU 3 stays
idle. On this system SCHED_EXT generates update-util callbacks less
frequently than CFS, so DBS updates are sparse, tracing shows:

load=100 idle_periods=7 interval=59 ms
load=100 idle_periods=4 interval=39 ms
load=100 idle_periods=2 interval=19 ms
load=100 idle_periods=7 interval=59 ms

With the default 5% step and a 2.6 GHz ceiling, conservative first
removes seven 130 MHz steps and then adds only one. Repeating this
sequence keeps the policy near 530 MHz despite CPU 2 being fully busy.

Only retain deferred idle periods when every CPU in the policy meets
the long-idle condition. This keeps the existing behavior for
single-CPU and fully idle shared policies, while preventing an idle
sibling from downscaling a policy that contains a busy CPU.

Cc: stable@xxxxxxxxxxxxxxx
Fixes: 00bfe05889e9 ("cpufreq: conservative: Decrease frequency faster for deferred updates")
Reviewed-by: Luo Haiyang <luo.haiyang@xxxxxxxxxx>
Reviewed-by: Run Zhang <zhang.run@xxxxxxxxxx>
Signed-off-by: Shengming Hu <hu.shengming@xxxxxxxxxx>
---
drivers/cpufreq/cpufreq_governor.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c
index 710d93ec89b5..64eb6b5f08a4 100644
--- a/drivers/cpufreq/cpufreq_governor.c
+++ b/drivers/cpufreq/cpufreq_governor.c
@@ -126,6 +126,7 @@ unsigned int dbs_update(struct cpufreq_policy *policy)
unsigned int ignore_nice = dbs_data->ignore_nice_load;
unsigned int max_load = 0, idle_periods = UINT_MAX;
unsigned int sampling_rate, io_busy, j;
+ bool all_cpus_idle = true;
u64 cur_nice;

/*
@@ -233,13 +234,15 @@ unsigned int dbs_update(struct cpufreq_policy *policy)

if (periods < idle_periods)
idle_periods = periods;
+ } else {
+ all_cpus_idle = false;
}

if (load > max_load)
max_load = load;
}

- policy_dbs->idle_periods = idle_periods;
+ policy_dbs->idle_periods = all_cpus_idle ? idle_periods : UINT_MAX;

return max_load;
}
--
2.25.1