| From 1c534352f47fd83eb08075ac2474f707e74bf7f7 Mon Sep 17 00:00:00 2001 |
| From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com> |
| Date: Fri, 23 Oct 2020 17:35:19 +0200 |
| Subject: cpufreq: Introduce CPUFREQ_NEED_UPDATE_LIMITS driver flag |
| |
| From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> |
| |
| commit 1c534352f47fd83eb08075ac2474f707e74bf7f7 upstream. |
| |
| Generally, a cpufreq driver may need to update some internal upper |
| and lower frequency boundaries on policy max and min changes, |
| respectively, but currently this does not work if the target |
| frequency does not change along with the policy limit. |
| |
| Namely, if the target frequency does not change along with the |
| policy min or max, the "target_freq == policy->cur" check in |
| __cpufreq_driver_target() prevents driver callbacks from being |
| invoked and they do not even have a chance to update the |
| corresponding internal boundary. |
| |
| This particularly affects the "powersave" and "performance" |
| governors that always set the target frequency to one of the |
| policy limits and it never changes when the other limit is updated. |
| |
| To allow cpufreq the drivers needing to update internal frequency |
| boundaries on policy limits changes to avoid this issue, introduce |
| a new driver flag, CPUFREQ_NEED_UPDATE_LIMITS, that (when set) will |
| neutralize the check mentioned above. |
| |
| Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> |
| Acked-by: Viresh Kumar <viresh.kumar@linaro.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/cpufreq/cpufreq.c | 3 ++- |
| include/linux/cpufreq.h | 10 +++++++++- |
| 2 files changed, 11 insertions(+), 2 deletions(-) |
| |
| --- a/drivers/cpufreq/cpufreq.c |
| +++ b/drivers/cpufreq/cpufreq.c |
| @@ -2166,7 +2166,8 @@ int __cpufreq_driver_target(struct cpufr |
| * exactly same freq is called again and so we can save on few function |
| * calls. |
| */ |
| - if (target_freq == policy->cur) |
| + if (target_freq == policy->cur && |
| + !(cpufreq_driver->flags & CPUFREQ_NEED_UPDATE_LIMITS)) |
| return 0; |
| |
| /* Save last value to restore later on errors */ |
| --- a/include/linux/cpufreq.h |
| +++ b/include/linux/cpufreq.h |
| @@ -293,7 +293,7 @@ __ATTR(_name, 0644, show_##_name, store_ |
| |
| struct cpufreq_driver { |
| char name[CPUFREQ_NAME_LEN]; |
| - u8 flags; |
| + u16 flags; |
| void *driver_data; |
| |
| /* needed by all drivers */ |
| @@ -417,6 +417,14 @@ struct cpufreq_driver { |
| */ |
| #define CPUFREQ_IS_COOLING_DEV BIT(7) |
| |
| +/* |
| + * Set by drivers that need to update internale upper and lower boundaries along |
| + * with the target frequency and so the core and governors should also invoke |
| + * the diver if the target frequency does not change, but the policy min or max |
| + * may have changed. |
| + */ |
| +#define CPUFREQ_NEED_UPDATE_LIMITS BIT(8) |
| + |
| int cpufreq_register_driver(struct cpufreq_driver *driver_data); |
| int cpufreq_unregister_driver(struct cpufreq_driver *driver_data); |
| |