Re: [PATCH] cpufreq: fail to start a governor if limits weren't updated correctly

From: Viresh Kumar
Date: Mon May 20 2024 - 03:12:15 EST


On 30-04-24, 14:39, Fares Mehanna wrote:
> Current cpufreq governors are using `__cpufreq_driver_target()` in their
> `.limits()` functions to update the frequency. `__cpufreq_driver_target()`
> will eventually call `.target()` or `.target_index()` in the cpufreq driver
> to update the frequency.
>
> `.target()`, `.target_index()` and `__cpufreq_driver_target()` may fail and
> all do return an error code, this error code is dropped by the governor and
> not propagated to the core.
>
> This have the downside of accepting a new CPU governor even if it fails to
> set the wanted limits. This is misleading to the sysfs user, as setting the
> governor will be accepted but the governor itself is not functioning as
> expected. Especially with `performance` and `powersave` where they only
> target specific frequency during starting of the governor and stays the
> same during their lifetime.
>
> This change will cause a failure to start the new governor if `.limits()`
> failed, propagating back to userspace if the change is driven by sysfs.
>
> Signed-off-by: Fares Mehanna <faresx@xxxxxxxxx>
> ---
> drivers/cpufreq/cpufreq.c | 7 +++++--
> drivers/cpufreq/cpufreq_governor.c | 6 ++++--
> drivers/cpufreq/cpufreq_governor.h | 2 +-
> drivers/cpufreq/cpufreq_performance.c | 4 ++--
> drivers/cpufreq/cpufreq_powersave.c | 4 ++--
> drivers/cpufreq/cpufreq_userspace.c | 16 +++++++++-------
> include/linux/cpufreq.h | 13 +++++++------
> kernel/sched/cpufreq_schedutil.c | 6 ++++--
> 8 files changed, 34 insertions(+), 24 deletions(-)
>
> diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
> index 66e10a19d76a..5ac44a44d319 100644
> --- a/drivers/cpufreq/cpufreq.c
> +++ b/drivers/cpufreq/cpufreq.c
> @@ -2474,8 +2474,11 @@ int cpufreq_start_governor(struct cpufreq_policy *policy)
> return ret;
> }
>
> - if (policy->governor->limits)
> - policy->governor->limits(policy);
> + if (policy->governor->limits) {
> + ret = policy->governor->limits(policy);
> + if (ret)
> + return ret;

You need to stop the governor here on failure as this function started it
successfully.

--
viresh