Skip to content

Commit 6a28fb8

Browse files
vireshkrafaeljw
authored andcommitted
cpufreq: conservative: Reset requested_freq on limits change
A recently reported issue highlighted that the cached requested_freq is not guaranteed to stay in sync with policy->cur. If the platform changes the actual CPU frequency after the governor sets one (e.g. due to platform-specific frequency scaling) and a re-sync occurs later, policy->cur may diverge from requested_freq. This can lead to incorrect behavior in the conservative governor. For example, the governor may assume the CPU is already running at the maximum frequency and skip further increases even though there is still headroom. Avoid this by resetting the cached requested_freq to policy->cur on detecting a change in policy limits. Reported-by: Lifeng Zheng <[email protected]> Tested-by: Lifeng Zheng <[email protected]> Link: https://lore.kernel.org/all/[email protected]/ Signed-off-by: Viresh Kumar <[email protected]> Reviewed-by: Zhongqiu Han <[email protected]> Cc: All applicable <[email protected]> Link: https://patch.msgid.link/d846a141a98ac0482f20560fcd7525c0f0ec2f30.1773999467.git.viresh.kumar@linaro.org Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 8f13c0c commit 6a28fb8

3 files changed

Lines changed: 16 additions & 0 deletions

File tree

drivers/cpufreq/cpufreq_conservative.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,17 @@ static void cs_start(struct cpufreq_policy *policy)
313313
dbs_info->requested_freq = policy->cur;
314314
}
315315

316+
static void cs_limits(struct cpufreq_policy *policy)
317+
{
318+
struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy->governor_data);
319+
320+
/*
321+
* The limits have changed, so may have the current frequency. Reset
322+
* requested_freq to avoid any unintended outcomes due to the mismatch.
323+
*/
324+
dbs_info->requested_freq = policy->cur;
325+
}
326+
316327
static struct dbs_governor cs_governor = {
317328
.gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER("conservative"),
318329
.kobj_type = { .default_groups = cs_groups },
@@ -322,6 +333,7 @@ static struct dbs_governor cs_governor = {
322333
.init = cs_init,
323334
.exit = cs_exit,
324335
.start = cs_start,
336+
.limits = cs_limits,
325337
};
326338

327339
#define CPU_FREQ_GOV_CONSERVATIVE (cs_governor.gov)

drivers/cpufreq/cpufreq_governor.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,7 @@ EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_stop);
563563

564564
void cpufreq_dbs_governor_limits(struct cpufreq_policy *policy)
565565
{
566+
struct dbs_governor *gov = dbs_governor_of(policy);
566567
struct policy_dbs_info *policy_dbs;
567568

568569
/* Protect gov->gdbs_data against cpufreq_dbs_governor_exit() */
@@ -574,6 +575,8 @@ void cpufreq_dbs_governor_limits(struct cpufreq_policy *policy)
574575
mutex_lock(&policy_dbs->update_mutex);
575576
cpufreq_policy_apply_limits(policy);
576577
gov_update_sample_delay(policy_dbs, 0);
578+
if (gov->limits)
579+
gov->limits(policy);
577580
mutex_unlock(&policy_dbs->update_mutex);
578581

579582
out:

drivers/cpufreq/cpufreq_governor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ struct dbs_governor {
138138
int (*init)(struct dbs_data *dbs_data);
139139
void (*exit)(struct dbs_data *dbs_data);
140140
void (*start)(struct cpufreq_policy *policy);
141+
void (*limits)(struct cpufreq_policy *policy);
141142
};
142143

143144
static inline struct dbs_governor *dbs_governor_of(struct cpufreq_policy *policy)

0 commit comments

Comments
 (0)