diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2016-04-07 17:38:46 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2016-04-08 16:41:36 -0400 |
commit | 6c9d9c81924b4b63c7a487e90fddb3b2d0f7d458 (patch) | |
tree | b21381042f1d974f0f844d1e93b6cb84767e9a3d | |
parent | 9bdcb44e391da5c41b98573bf0305a0e0b1c9569 (diff) |
cpufreq: Call cpufreq_disable_fast_switch() in sugov_exit()
Due to differences in the cpufreq core's handling of runtime CPU
offline and nonboot CPUs disabling during system suspend-to-RAM,
fast frequency switching gets disabled after a suspend-to-RAM and
resume cycle on all of the nonboot CPUs.
To prevent that from happening, move the invocation of
cpufreq_disable_fast_switch() from cpufreq_exit_governor() to
sugov_exit(), as the schedutil governor is the only user of fast
frequency switching today anyway.
That simply prevents cpufreq_disable_fast_switch() from being called
without invoking the ->governor callback for the CPUFREQ_GOV_POLICY_EXIT
event (which happens during system suspend now).
Fixes: b7898fda5bc7 (cpufreq: Support for fast frequency switching)
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
-rw-r--r-- | drivers/cpufreq/cpufreq.c | 19 | ||||
-rw-r--r-- | include/linux/cpufreq.h | 1 | ||||
-rw-r--r-- | kernel/sched/cpufreq_schedutil.c | 2 |
3 files changed, 14 insertions, 8 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index a5b7d77d4816..77d77a4e3b74 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
@@ -77,7 +77,11 @@ static inline bool has_target(void) | |||
77 | static int cpufreq_governor(struct cpufreq_policy *policy, unsigned int event); | 77 | static int cpufreq_governor(struct cpufreq_policy *policy, unsigned int event); |
78 | static unsigned int __cpufreq_get(struct cpufreq_policy *policy); | 78 | static unsigned int __cpufreq_get(struct cpufreq_policy *policy); |
79 | static int cpufreq_start_governor(struct cpufreq_policy *policy); | 79 | static int cpufreq_start_governor(struct cpufreq_policy *policy); |
80 | static int cpufreq_exit_governor(struct cpufreq_policy *policy); | 80 | |
81 | static inline int cpufreq_exit_governor(struct cpufreq_policy *policy) | ||
82 | { | ||
83 | return cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT); | ||
84 | } | ||
81 | 85 | ||
82 | /** | 86 | /** |
83 | * Two notifier lists: the "policy" list is involved in the | 87 | * Two notifier lists: the "policy" list is involved in the |
@@ -482,7 +486,11 @@ void cpufreq_enable_fast_switch(struct cpufreq_policy *policy) | |||
482 | } | 486 | } |
483 | EXPORT_SYMBOL_GPL(cpufreq_enable_fast_switch); | 487 | EXPORT_SYMBOL_GPL(cpufreq_enable_fast_switch); |
484 | 488 | ||
485 | static void cpufreq_disable_fast_switch(struct cpufreq_policy *policy) | 489 | /** |
490 | * cpufreq_disable_fast_switch - Disable fast frequency switching for policy. | ||
491 | * @policy: cpufreq policy to disable fast frequency switching for. | ||
492 | */ | ||
493 | void cpufreq_disable_fast_switch(struct cpufreq_policy *policy) | ||
486 | { | 494 | { |
487 | mutex_lock(&cpufreq_fast_switch_lock); | 495 | mutex_lock(&cpufreq_fast_switch_lock); |
488 | if (policy->fast_switch_enabled) { | 496 | if (policy->fast_switch_enabled) { |
@@ -492,6 +500,7 @@ static void cpufreq_disable_fast_switch(struct cpufreq_policy *policy) | |||
492 | } | 500 | } |
493 | mutex_unlock(&cpufreq_fast_switch_lock); | 501 | mutex_unlock(&cpufreq_fast_switch_lock); |
494 | } | 502 | } |
503 | EXPORT_SYMBOL_GPL(cpufreq_disable_fast_switch); | ||
495 | 504 | ||
496 | /********************************************************************* | 505 | /********************************************************************* |
497 | * SYSFS INTERFACE * | 506 | * SYSFS INTERFACE * |
@@ -2060,12 +2069,6 @@ static int cpufreq_start_governor(struct cpufreq_policy *policy) | |||
2060 | return ret ? ret : cpufreq_governor(policy, CPUFREQ_GOV_LIMITS); | 2069 | return ret ? ret : cpufreq_governor(policy, CPUFREQ_GOV_LIMITS); |
2061 | } | 2070 | } |
2062 | 2071 | ||
2063 | static int cpufreq_exit_governor(struct cpufreq_policy *policy) | ||
2064 | { | ||
2065 | cpufreq_disable_fast_switch(policy); | ||
2066 | return cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT); | ||
2067 | } | ||
2068 | |||
2069 | int cpufreq_register_governor(struct cpufreq_governor *governor) | 2072 | int cpufreq_register_governor(struct cpufreq_governor *governor) |
2070 | { | 2073 | { |
2071 | int err; | 2074 | int err; |
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 55e69ebb035c..4e81e08db752 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h | |||
@@ -168,6 +168,7 @@ int cpufreq_update_policy(unsigned int cpu); | |||
168 | bool have_governor_per_policy(void); | 168 | bool have_governor_per_policy(void); |
169 | struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy); | 169 | struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy); |
170 | void cpufreq_enable_fast_switch(struct cpufreq_policy *policy); | 170 | void cpufreq_enable_fast_switch(struct cpufreq_policy *policy); |
171 | void cpufreq_disable_fast_switch(struct cpufreq_policy *policy); | ||
171 | #else | 172 | #else |
172 | static inline unsigned int cpufreq_get(unsigned int cpu) | 173 | static inline unsigned int cpufreq_get(unsigned int cpu) |
173 | { | 174 | { |
diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c index d27ae064b476..154ae3a51e86 100644 --- a/kernel/sched/cpufreq_schedutil.c +++ b/kernel/sched/cpufreq_schedutil.c | |||
@@ -398,6 +398,8 @@ static int sugov_exit(struct cpufreq_policy *policy) | |||
398 | struct sugov_tunables *tunables = sg_policy->tunables; | 398 | struct sugov_tunables *tunables = sg_policy->tunables; |
399 | unsigned int count; | 399 | unsigned int count; |
400 | 400 | ||
401 | cpufreq_disable_fast_switch(policy); | ||
402 | |||
401 | mutex_lock(&global_tunables_lock); | 403 | mutex_lock(&global_tunables_lock); |
402 | 404 | ||
403 | count = gov_attr_set_put(&tunables->attr_set, &sg_policy->tunables_hook); | 405 | count = gov_attr_set_put(&tunables->attr_set, &sg_policy->tunables_hook); |