summaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq/cpufreq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/cpufreq/cpufreq.c')
-rw-r--r--drivers/cpufreq/cpufreq.c100
1 files changed, 73 insertions, 27 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index e10922709d13..7ea217c88c2e 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -34,11 +34,6 @@
34 34
35static LIST_HEAD(cpufreq_policy_list); 35static LIST_HEAD(cpufreq_policy_list);
36 36
37static inline bool policy_is_inactive(struct cpufreq_policy *policy)
38{
39 return cpumask_empty(policy->cpus);
40}
41
42/* Macros to iterate over CPU policies */ 37/* Macros to iterate over CPU policies */
43#define for_each_suitable_policy(__policy, __active) \ 38#define for_each_suitable_policy(__policy, __active) \
44 list_for_each_entry(__policy, &cpufreq_policy_list, policy_list) \ 39 list_for_each_entry(__policy, &cpufreq_policy_list, policy_list) \
@@ -250,6 +245,51 @@ void cpufreq_cpu_put(struct cpufreq_policy *policy)
250} 245}
251EXPORT_SYMBOL_GPL(cpufreq_cpu_put); 246EXPORT_SYMBOL_GPL(cpufreq_cpu_put);
252 247
248/**
249 * cpufreq_cpu_release - Unlock a policy and decrement its usage counter.
250 * @policy: cpufreq policy returned by cpufreq_cpu_acquire().
251 */
252void cpufreq_cpu_release(struct cpufreq_policy *policy)
253{
254 if (WARN_ON(!policy))
255 return;
256
257 lockdep_assert_held(&policy->rwsem);
258
259 up_write(&policy->rwsem);
260
261 cpufreq_cpu_put(policy);
262}
263
264/**
265 * cpufreq_cpu_acquire - Find policy for a CPU, mark it as busy and lock it.
266 * @cpu: CPU to find the policy for.
267 *
268 * Call cpufreq_cpu_get() to get a reference on the cpufreq policy for @cpu and
269 * if the policy returned by it is not NULL, acquire its rwsem for writing.
270 * Return the policy if it is active or release it and return NULL otherwise.
271 *
272 * The policy returned by this function has to be released with the help of
273 * cpufreq_cpu_release() in order to release its rwsem and balance its usage
274 * counter properly.
275 */
276struct cpufreq_policy *cpufreq_cpu_acquire(unsigned int cpu)
277{
278 struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
279
280 if (!policy)
281 return NULL;
282
283 down_write(&policy->rwsem);
284
285 if (policy_is_inactive(policy)) {
286 cpufreq_cpu_release(policy);
287 return NULL;
288 }
289
290 return policy;
291}
292
253/********************************************************************* 293/*********************************************************************
254 * EXTERNALLY AFFECTING FREQUENCY CHANGES * 294 * EXTERNALLY AFFECTING FREQUENCY CHANGES *
255 *********************************************************************/ 295 *********************************************************************/
@@ -669,9 +709,6 @@ static ssize_t show_scaling_cur_freq(struct cpufreq_policy *policy, char *buf)
669 return ret; 709 return ret;
670} 710}
671 711
672static int cpufreq_set_policy(struct cpufreq_policy *policy,
673 struct cpufreq_policy *new_policy);
674
675/** 712/**
676 * cpufreq_per_cpu_attr_write() / store_##file_name() - sysfs write access 713 * cpufreq_per_cpu_attr_write() / store_##file_name() - sysfs write access
677 */ 714 */
@@ -857,11 +894,9 @@ static ssize_t show_bios_limit(struct cpufreq_policy *policy, char *buf)
857{ 894{
858 unsigned int limit; 895 unsigned int limit;
859 int ret; 896 int ret;
860 if (cpufreq_driver->bios_limit) { 897 ret = cpufreq_driver->bios_limit(policy->cpu, &limit);
861 ret = cpufreq_driver->bios_limit(policy->cpu, &limit); 898 if (!ret)
862 if (!ret) 899 return sprintf(buf, "%u\n", limit);
863 return sprintf(buf, "%u\n", limit);
864 }
865 return sprintf(buf, "%u\n", policy->cpuinfo.max_freq); 900 return sprintf(buf, "%u\n", policy->cpuinfo.max_freq);
866} 901}
867 902
@@ -1098,6 +1133,7 @@ static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
1098 cpufreq_global_kobject, "policy%u", cpu); 1133 cpufreq_global_kobject, "policy%u", cpu);
1099 if (ret) { 1134 if (ret) {
1100 pr_err("%s: failed to init policy->kobj: %d\n", __func__, ret); 1135 pr_err("%s: failed to init policy->kobj: %d\n", __func__, ret);
1136 kobject_put(&policy->kobj);
1101 goto err_free_real_cpus; 1137 goto err_free_real_cpus;
1102 } 1138 }
1103 1139
@@ -1550,7 +1586,7 @@ static unsigned int __cpufreq_get(struct cpufreq_policy *policy)
1550{ 1586{
1551 unsigned int ret_freq = 0; 1587 unsigned int ret_freq = 0;
1552 1588
1553 if (unlikely(policy_is_inactive(policy)) || !cpufreq_driver->get) 1589 if (unlikely(policy_is_inactive(policy)))
1554 return ret_freq; 1590 return ret_freq;
1555 1591
1556 ret_freq = cpufreq_driver->get(policy->cpu); 1592 ret_freq = cpufreq_driver->get(policy->cpu);
@@ -1588,7 +1624,8 @@ unsigned int cpufreq_get(unsigned int cpu)
1588 1624
1589 if (policy) { 1625 if (policy) {
1590 down_read(&policy->rwsem); 1626 down_read(&policy->rwsem);
1591 ret_freq = __cpufreq_get(policy); 1627 if (cpufreq_driver->get)
1628 ret_freq = __cpufreq_get(policy);
1592 up_read(&policy->rwsem); 1629 up_read(&policy->rwsem);
1593 1630
1594 cpufreq_cpu_put(policy); 1631 cpufreq_cpu_put(policy);
@@ -2229,8 +2266,8 @@ EXPORT_SYMBOL(cpufreq_get_policy);
2229 * 2266 *
2230 * The cpuinfo part of @policy is not updated by this function. 2267 * The cpuinfo part of @policy is not updated by this function.
2231 */ 2268 */
2232static int cpufreq_set_policy(struct cpufreq_policy *policy, 2269int cpufreq_set_policy(struct cpufreq_policy *policy,
2233 struct cpufreq_policy *new_policy) 2270 struct cpufreq_policy *new_policy)
2234{ 2271{
2235 struct cpufreq_governor *old_gov; 2272 struct cpufreq_governor *old_gov;
2236 int ret; 2273 int ret;
@@ -2337,17 +2374,12 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
2337 */ 2374 */
2338void cpufreq_update_policy(unsigned int cpu) 2375void cpufreq_update_policy(unsigned int cpu)
2339{ 2376{
2340 struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); 2377 struct cpufreq_policy *policy = cpufreq_cpu_acquire(cpu);
2341 struct cpufreq_policy new_policy; 2378 struct cpufreq_policy new_policy;
2342 2379
2343 if (!policy) 2380 if (!policy)
2344 return; 2381 return;
2345 2382
2346 down_write(&policy->rwsem);
2347
2348 if (policy_is_inactive(policy))
2349 goto unlock;
2350
2351 /* 2383 /*
2352 * BIOS might change freq behind our back 2384 * BIOS might change freq behind our back
2353 * -> ask driver for current freq and notify governors about a change 2385 * -> ask driver for current freq and notify governors about a change
@@ -2364,12 +2396,26 @@ void cpufreq_update_policy(unsigned int cpu)
2364 cpufreq_set_policy(policy, &new_policy); 2396 cpufreq_set_policy(policy, &new_policy);
2365 2397
2366unlock: 2398unlock:
2367 up_write(&policy->rwsem); 2399 cpufreq_cpu_release(policy);
2368
2369 cpufreq_cpu_put(policy);
2370} 2400}
2371EXPORT_SYMBOL(cpufreq_update_policy); 2401EXPORT_SYMBOL(cpufreq_update_policy);
2372 2402
2403/**
2404 * cpufreq_update_limits - Update policy limits for a given CPU.
2405 * @cpu: CPU to update the policy limits for.
2406 *
2407 * Invoke the driver's ->update_limits callback if present or call
2408 * cpufreq_update_policy() for @cpu.
2409 */
2410void cpufreq_update_limits(unsigned int cpu)
2411{
2412 if (cpufreq_driver->update_limits)
2413 cpufreq_driver->update_limits(cpu);
2414 else
2415 cpufreq_update_policy(cpu);
2416}
2417EXPORT_SYMBOL_GPL(cpufreq_update_limits);
2418
2373/********************************************************************* 2419/*********************************************************************
2374 * BOOST * 2420 * BOOST *
2375 *********************************************************************/ 2421 *********************************************************************/
@@ -2426,7 +2472,7 @@ int cpufreq_boost_trigger_state(int state)
2426 2472
2427static bool cpufreq_boost_supported(void) 2473static bool cpufreq_boost_supported(void)
2428{ 2474{
2429 return likely(cpufreq_driver) && cpufreq_driver->set_boost; 2475 return cpufreq_driver->set_boost;
2430} 2476}
2431 2477
2432static int create_boost_sysfs_file(void) 2478static int create_boost_sysfs_file(void)