diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index d41067cd1f1b..4e78f4caab3a 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -2368,9 +2368,13 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, * exactly same freq is called again and so we can save on few function * calls. */ - if (target_freq == policy->cur && - !(cpufreq_driver->flags & CPUFREQ_NEED_UPDATE_LIMITS)) - return 0; + if (target_freq == policy->cur) { + if (!(cpufreq_driver->flags & CPUFREQ_NEED_UPDATE_LIMITS) || + !policy->update_limits) + return 0; + + policy->update_limits = false; + } if (cpufreq_driver->target) { /* @@ -2622,6 +2626,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy, { struct cpufreq_policy_data new_data; struct cpufreq_governor *old_gov; + unsigned int freq; int ret; memcpy(&new_data.cpuinfo, &policy->cpuinfo, sizeof(policy->cpuinfo)); @@ -2654,12 +2659,20 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy, * compiler optimizations around them because they may be accessed * concurrently by cpufreq_driver_resolve_freq() during the update. */ - WRITE_ONCE(policy->max, __resolve_freq(policy, new_data.max, - new_data.min, new_data.max, - CPUFREQ_RELATION_H)); - new_data.min = __resolve_freq(policy, new_data.min, new_data.min, - new_data.max, CPUFREQ_RELATION_L); - WRITE_ONCE(policy->min, new_data.min > policy->max ? policy->max : new_data.min); + freq = __resolve_freq(policy, new_data.max, new_data.min, new_data.max, + CPUFREQ_RELATION_H); + if (freq != policy->max) { + WRITE_ONCE(policy->max, freq); + policy->update_limits = true; + } + + freq = __resolve_freq(policy, new_data.min, new_data.min, new_data.max, + CPUFREQ_RELATION_L); + freq = min(freq, policy->max); + if (freq != policy->min) { + WRITE_ONCE(policy->min, freq); + policy->update_limits = true; + } trace_cpu_frequency_limits(policy); diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 4d4b4ed24b30..ae9d1ce4f49c 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -146,6 +146,9 @@ struct cpufreq_policy { /* Per policy boost supported flag. */ bool boost_supported; + /* Pending policy->min/max update for the driver */ + bool update_limits; + /* Cached frequency lookup from cpufreq_driver_resolve_freq. */ unsigned int cached_target_freq; unsigned int cached_resolved_idx;