diff options
author | Viresh Kumar <viresh.kumar@linaro.org> | 2013-06-19 10:16:55 +0530 |
---|---|---|
committer | Chanho Park <chanho61.park@samsung.com> | 2014-11-18 11:47:23 +0900 |
commit | 6a7e6f0f6546aa4990cdd1b1101daab20aec9b65 (patch) | |
tree | cabb284de11667f5cf7efba13b2ab5af0b382e28 /drivers | |
parent | 2247da9c0bb0427f1d81a71a8339edf5c1e434b2 (diff) | |
download | linux-3.10-6a7e6f0f6546aa4990cdd1b1101daab20aec9b65.tar.gz linux-3.10-6a7e6f0f6546aa4990cdd1b1101daab20aec9b65.tar.bz2 linux-3.10-6a7e6f0f6546aa4990cdd1b1101daab20aec9b65.zip |
cpufreq: make sure frequency transitions are serialized
Whenever we are changing frequency of a cpu, we are calling PRECHANGE and
POSTCHANGE notifiers. They must be serialized. i.e. PRECHANGE or POSTCHANGE
shouldn't be called twice contiguously.
This can happen due to bugs in users of __cpufreq_driver_target() or actual
cpufreq drivers who are sending these notifiers.
This patch adds some protection against this. Now, we keep track of the last
transaction and see if something went wrong.
Change-Id: I0f5465bd515c431ae2d3711d065f70aacec7e978
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/cpufreq/cpufreq.c | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index df519221ccd..0426ce8f0b0 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -266,6 +266,12 @@ void __cpufreq_notify_transition(struct cpufreq_policy *policy, switch (state) { case CPUFREQ_PRECHANGE: + if (WARN(policy->transition_ongoing, + "In middle of another frequency transition\n")) + return; + + policy->transition_ongoing = true; + /* detect if the driver reported a value as "old frequency" * which is not equal to what the cpufreq core thinks is * "old frequency". @@ -285,6 +291,12 @@ void __cpufreq_notify_transition(struct cpufreq_policy *policy, break; case CPUFREQ_POSTCHANGE: + if (WARN(!policy->transition_ongoing, + "No frequency transition in progress\n")) + return; + + policy->transition_ongoing = false; + adjust_jiffies(CPUFREQ_POSTCHANGE, freqs); pr_debug("FREQ: %lu - CPU: %lu", (unsigned long)freqs->new, (unsigned long)freqs->cpu); @@ -1529,6 +1541,8 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, if (cpufreq_disabled()) return -ENODEV; + if (policy->transition_ongoing) + return -EBUSY; /* Make sure that target_freq is within supported range */ if (target_freq > policy->max) |