Message ID | 3010358.e9J7NaK4W3@rjwysocki.net (mailing list archive) |
---|---|
State | In Next |
Delegated to: | Rafael Wysocki |
Headers | show |
Series | cpufreq/sched: Improve synchronization of policy limits updates with schedutil | expand |
On 4/15/25 10:58, Rafael J. Wysocki wrote: > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > > Commit 8e461a1cb43d ("cpufreq: schedutil: Fix superfluous updates caused > by need_freq_update") modified sugov_should_update_freq() to set the > need_freq_update flag only for drivers with CPUFREQ_NEED_UPDATE_LIMITS > set, but that flag generally needs to be set when the policy limits > change because the driver callback may need to be invoked for the new > limits to take effect. > > However, if the return value of cpufreq_driver_resolve_freq() after > applying the new limits is still equal to the previously selected > frequency, the driver callback needs to be invoked only in the case > when CPUFREQ_NEED_UPDATE_LIMITS is set (which means that the driver > specifically wants its callback to be invoked every time the policy > limits change). > > Update the code accordingly to avoid missing policy limits changes for > drivers without CPUFREQ_NEED_UPDATE_LIMITS. > > Fixes: 8e461a1cb43d ("cpufreq: schedutil: Fix superfluous updates caused by need_freq_update") > Closes: https://lore.kernel.org/lkml/Z_Tlc6Qs-tYpxWYb@linaro.org/ > Reported-by: Stephan Gerhold <stephan.gerhold@linaro.org> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Reviewed-by: Christian Loehle <christian.loehle@arm.com> > --- > > v1 -> v2: > * Always set need_freq_update when limits_changed is set. > * Take CPUFREQ_NEED_UPDATE_LIMITS into account in sugov_update_next_freq(). > > --- > kernel/sched/cpufreq_schedutil.c | 18 +++++++++++++++--- > 1 file changed, 15 insertions(+), 3 deletions(-) > > --- a/kernel/sched/cpufreq_schedutil.c > +++ b/kernel/sched/cpufreq_schedutil.c > @@ -83,7 +83,7 @@ > > if (unlikely(sg_policy->limits_changed)) { > sg_policy->limits_changed = false; > - sg_policy->need_freq_update = cpufreq_driver_test_flags(CPUFREQ_NEED_UPDATE_LIMITS); > + sg_policy->need_freq_update = true; > return true; > } > > @@ -95,10 +95,22 @@ > static bool sugov_update_next_freq(struct sugov_policy *sg_policy, u64 time, > unsigned int next_freq) > { > - if (sg_policy->need_freq_update) > + if (sg_policy->need_freq_update) { > sg_policy->need_freq_update = false; > - else if (sg_policy->next_freq == next_freq) > + /* > + * The policy limits have changed, but if the return value of > + * cpufreq_driver_resolve_freq() after applying the new limits > + * is still equal to the previously selected frequency, the > + * driver callback need not be invoked unless the driver > + * specifically wants that to happen on every update of the > + * policy limits. > + */ > + if (sg_policy->next_freq == next_freq && > + !cpufreq_driver_test_flags(CPUFREQ_NEED_UPDATE_LIMITS)) > + return false; > + } else if (sg_policy->next_freq == next_freq) { > return false; > + } > > sg_policy->next_freq = next_freq; > sg_policy->last_freq_update_time = time; > > >
--- a/kernel/sched/cpufreq_schedutil.c +++ b/kernel/sched/cpufreq_schedutil.c @@ -83,7 +83,7 @@ if (unlikely(sg_policy->limits_changed)) { sg_policy->limits_changed = false; - sg_policy->need_freq_update = cpufreq_driver_test_flags(CPUFREQ_NEED_UPDATE_LIMITS); + sg_policy->need_freq_update = true; return true; } @@ -95,10 +95,22 @@ static bool sugov_update_next_freq(struct sugov_policy *sg_policy, u64 time, unsigned int next_freq) { - if (sg_policy->need_freq_update) + if (sg_policy->need_freq_update) { sg_policy->need_freq_update = false; - else if (sg_policy->next_freq == next_freq) + /* + * The policy limits have changed, but if the return value of + * cpufreq_driver_resolve_freq() after applying the new limits + * is still equal to the previously selected frequency, the + * driver callback need not be invoked unless the driver + * specifically wants that to happen on every update of the + * policy limits. + */ + if (sg_policy->next_freq == next_freq && + !cpufreq_driver_test_flags(CPUFREQ_NEED_UPDATE_LIMITS)) + return false; + } else if (sg_policy->next_freq == next_freq) { return false; + } sg_policy->next_freq = next_freq; sg_policy->last_freq_update_time = time;