aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/cpufreq/cpufreq.c56
1 files changed, 47 insertions, 9 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index bb63347f6af1..d8fc395af773 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -250,6 +250,51 @@ void cpufreq_cpu_put(struct cpufreq_policy *policy)
250} 250}
251EXPORT_SYMBOL_GPL(cpufreq_cpu_put); 251EXPORT_SYMBOL_GPL(cpufreq_cpu_put);
252 252
253/**
254 * cpufreq_cpu_release - Unlock a policy and decrement its usage counter.
255 * @policy: cpufreq policy returned by cpufreq_cpu_acquire().
256 */
257static void cpufreq_cpu_release(struct cpufreq_policy *policy)
258{
259 if (WARN_ON(!policy))
260 return;
261
262 lockdep_assert_held(&policy->rwsem);
263
264 up_write(&policy->rwsem);
265
266 cpufreq_cpu_put(policy);
267}
268
269/**
270 * cpufreq_cpu_acquire - Find policy for a CPU, mark it as busy and lock it.
271 * @cpu: CPU to find the policy for.
272 *
273 * Call cpufreq_cpu_get() to get a reference on the cpufreq policy for @cpu and
274 * if the policy returned by it is not NULL, acquire its rwsem for writing.
275 * Return the policy if it is active or release it and return NULL otherwise.
276 *
277 * The policy returned by this function has to be released with the help of
278 * cpufreq_cpu_release() in order to release its rwsem and balance its usage
279 * counter properly.
280 */
281static struct cpufreq_policy *cpufreq_cpu_acquire(unsigned int cpu)
282{
283 struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
284
285 if (!policy)
286 return NULL;
287
288 down_write(&policy->rwsem);
289
290 if (policy_is_inactive(policy)) {
291 cpufreq_cpu_release(policy);
292 return NULL;
293 }
294
295 return policy;
296}
297
253/********************************************************************* 298/*********************************************************************
254 * EXTERNALLY AFFECTING FREQUENCY CHANGES * 299 * EXTERNALLY AFFECTING FREQUENCY CHANGES *
255 *********************************************************************/ 300 *********************************************************************/
@@ -2337,17 +2382,12 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
2337 */ 2382 */
2338void cpufreq_update_policy(unsigned int cpu) 2383void cpufreq_update_policy(unsigned int cpu)
2339{ 2384{
2340 struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); 2385 struct cpufreq_policy *policy = cpufreq_cpu_acquire(cpu);
2341 struct cpufreq_policy new_policy; 2386 struct cpufreq_policy new_policy;
2342 2387
2343 if (!policy) 2388 if (!policy)
2344 return; 2389 return;
2345 2390
2346 down_write(&policy->rwsem);
2347
2348 if (policy_is_inactive(policy))
2349 goto unlock;
2350
2351 /* 2391 /*
2352 * BIOS might change freq behind our back 2392 * BIOS might change freq behind our back
2353 * -> ask driver for current freq and notify governors about a change 2393 * -> ask driver for current freq and notify governors about a change
@@ -2364,9 +2404,7 @@ void cpufreq_update_policy(unsigned int cpu)
2364 cpufreq_set_policy(policy, &new_policy); 2404 cpufreq_set_policy(policy, &new_policy);
2365 2405
2366unlock: 2406unlock:
2367 up_write(&policy->rwsem); 2407 cpufreq_cpu_release(policy);
2368
2369 cpufreq_cpu_put(policy);
2370} 2408}
2371EXPORT_SYMBOL(cpufreq_update_policy); 2409EXPORT_SYMBOL(cpufreq_update_policy);
2372 2410