diff options
Diffstat (limited to 'drivers/cpufreq/cpufreq.c')
-rw-r--r-- | drivers/cpufreq/cpufreq.c | 70 |
1 files changed, 41 insertions, 29 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 277a843a87a6..7a511479ae29 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/cpu.h> | 27 | #include <linux/cpu.h> |
28 | #include <linux/completion.h> | 28 | #include <linux/completion.h> |
29 | #include <linux/mutex.h> | ||
29 | 30 | ||
30 | #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, "cpufreq-core", msg) | 31 | #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, "cpufreq-core", msg) |
31 | 32 | ||
@@ -55,7 +56,7 @@ static DECLARE_RWSEM (cpufreq_notifier_rwsem); | |||
55 | 56 | ||
56 | 57 | ||
57 | static LIST_HEAD(cpufreq_governor_list); | 58 | static LIST_HEAD(cpufreq_governor_list); |
58 | static DECLARE_MUTEX (cpufreq_governor_sem); | 59 | static DEFINE_MUTEX (cpufreq_governor_mutex); |
59 | 60 | ||
60 | struct cpufreq_policy * cpufreq_cpu_get(unsigned int cpu) | 61 | struct cpufreq_policy * cpufreq_cpu_get(unsigned int cpu) |
61 | { | 62 | { |
@@ -297,18 +298,18 @@ static int cpufreq_parse_governor (char *str_governor, unsigned int *policy, | |||
297 | return -EINVAL; | 298 | return -EINVAL; |
298 | } else { | 299 | } else { |
299 | struct cpufreq_governor *t; | 300 | struct cpufreq_governor *t; |
300 | down(&cpufreq_governor_sem); | 301 | mutex_lock(&cpufreq_governor_mutex); |
301 | if (!cpufreq_driver || !cpufreq_driver->target) | 302 | if (!cpufreq_driver || !cpufreq_driver->target) |
302 | goto out; | 303 | goto out; |
303 | list_for_each_entry(t, &cpufreq_governor_list, governor_list) { | 304 | list_for_each_entry(t, &cpufreq_governor_list, governor_list) { |
304 | if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) { | 305 | if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) { |
305 | *governor = t; | 306 | *governor = t; |
306 | up(&cpufreq_governor_sem); | 307 | mutex_unlock(&cpufreq_governor_mutex); |
307 | return 0; | 308 | return 0; |
308 | } | 309 | } |
309 | } | 310 | } |
310 | out: | 311 | out: |
311 | up(&cpufreq_governor_sem); | 312 | mutex_unlock(&cpufreq_governor_mutex); |
312 | } | 313 | } |
313 | return -EINVAL; | 314 | return -EINVAL; |
314 | } | 315 | } |
@@ -600,7 +601,8 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) | |||
600 | policy->cpu = cpu; | 601 | policy->cpu = cpu; |
601 | policy->cpus = cpumask_of_cpu(cpu); | 602 | policy->cpus = cpumask_of_cpu(cpu); |
602 | 603 | ||
603 | init_MUTEX_LOCKED(&policy->lock); | 604 | mutex_init(&policy->lock); |
605 | mutex_lock(&policy->lock); | ||
604 | init_completion(&policy->kobj_unregister); | 606 | init_completion(&policy->kobj_unregister); |
605 | INIT_WORK(&policy->update, handle_update, (void *)(long)cpu); | 607 | INIT_WORK(&policy->update, handle_update, (void *)(long)cpu); |
606 | 608 | ||
@@ -610,6 +612,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) | |||
610 | ret = cpufreq_driver->init(policy); | 612 | ret = cpufreq_driver->init(policy); |
611 | if (ret) { | 613 | if (ret) { |
612 | dprintk("initialization failed\n"); | 614 | dprintk("initialization failed\n"); |
615 | mutex_unlock(&policy->lock); | ||
613 | goto err_out; | 616 | goto err_out; |
614 | } | 617 | } |
615 | 618 | ||
@@ -621,9 +624,10 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) | |||
621 | strlcpy(policy->kobj.name, "cpufreq", KOBJ_NAME_LEN); | 624 | strlcpy(policy->kobj.name, "cpufreq", KOBJ_NAME_LEN); |
622 | 625 | ||
623 | ret = kobject_register(&policy->kobj); | 626 | ret = kobject_register(&policy->kobj); |
624 | if (ret) | 627 | if (ret) { |
628 | mutex_unlock(&policy->lock); | ||
625 | goto err_out_driver_exit; | 629 | goto err_out_driver_exit; |
626 | 630 | } | |
627 | /* set up files for this cpu device */ | 631 | /* set up files for this cpu device */ |
628 | drv_attr = cpufreq_driver->attr; | 632 | drv_attr = cpufreq_driver->attr; |
629 | while ((drv_attr) && (*drv_attr)) { | 633 | while ((drv_attr) && (*drv_attr)) { |
@@ -641,7 +645,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) | |||
641 | spin_unlock_irqrestore(&cpufreq_driver_lock, flags); | 645 | spin_unlock_irqrestore(&cpufreq_driver_lock, flags); |
642 | policy->governor = NULL; /* to assure that the starting sequence is | 646 | policy->governor = NULL; /* to assure that the starting sequence is |
643 | * run in cpufreq_set_policy */ | 647 | * run in cpufreq_set_policy */ |
644 | up(&policy->lock); | 648 | mutex_unlock(&policy->lock); |
645 | 649 | ||
646 | /* set default policy */ | 650 | /* set default policy */ |
647 | 651 | ||
@@ -762,10 +766,10 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev) | |||
762 | spin_unlock_irqrestore(&cpufreq_driver_lock, flags); | 766 | spin_unlock_irqrestore(&cpufreq_driver_lock, flags); |
763 | #endif | 767 | #endif |
764 | 768 | ||
765 | down(&data->lock); | 769 | mutex_lock(&data->lock); |
766 | if (cpufreq_driver->target) | 770 | if (cpufreq_driver->target) |
767 | __cpufreq_governor(data, CPUFREQ_GOV_STOP); | 771 | __cpufreq_governor(data, CPUFREQ_GOV_STOP); |
768 | up(&data->lock); | 772 | mutex_unlock(&data->lock); |
769 | 773 | ||
770 | kobject_unregister(&data->kobj); | 774 | kobject_unregister(&data->kobj); |
771 | 775 | ||
@@ -834,9 +838,9 @@ unsigned int cpufreq_quick_get(unsigned int cpu) | |||
834 | unsigned int ret = 0; | 838 | unsigned int ret = 0; |
835 | 839 | ||
836 | if (policy) { | 840 | if (policy) { |
837 | down(&policy->lock); | 841 | mutex_lock(&policy->lock); |
838 | ret = policy->cur; | 842 | ret = policy->cur; |
839 | up(&policy->lock); | 843 | mutex_unlock(&policy->lock); |
840 | cpufreq_cpu_put(policy); | 844 | cpufreq_cpu_put(policy); |
841 | } | 845 | } |
842 | 846 | ||
@@ -862,7 +866,7 @@ unsigned int cpufreq_get(unsigned int cpu) | |||
862 | if (!cpufreq_driver->get) | 866 | if (!cpufreq_driver->get) |
863 | goto out; | 867 | goto out; |
864 | 868 | ||
865 | down(&policy->lock); | 869 | mutex_lock(&policy->lock); |
866 | 870 | ||
867 | ret = cpufreq_driver->get(cpu); | 871 | ret = cpufreq_driver->get(cpu); |
868 | 872 | ||
@@ -875,7 +879,7 @@ unsigned int cpufreq_get(unsigned int cpu) | |||
875 | } | 879 | } |
876 | } | 880 | } |
877 | 881 | ||
878 | up(&policy->lock); | 882 | mutex_unlock(&policy->lock); |
879 | 883 | ||
880 | out: | 884 | out: |
881 | cpufreq_cpu_put(policy); | 885 | cpufreq_cpu_put(policy); |
@@ -1158,11 +1162,11 @@ int cpufreq_driver_target(struct cpufreq_policy *policy, | |||
1158 | if (!policy) | 1162 | if (!policy) |
1159 | return -EINVAL; | 1163 | return -EINVAL; |
1160 | 1164 | ||
1161 | down(&policy->lock); | 1165 | mutex_lock(&policy->lock); |
1162 | 1166 | ||
1163 | ret = __cpufreq_driver_target(policy, target_freq, relation); | 1167 | ret = __cpufreq_driver_target(policy, target_freq, relation); |
1164 | 1168 | ||
1165 | up(&policy->lock); | 1169 | mutex_unlock(&policy->lock); |
1166 | 1170 | ||
1167 | cpufreq_cpu_put(policy); | 1171 | cpufreq_cpu_put(policy); |
1168 | 1172 | ||
@@ -1199,9 +1203,9 @@ int cpufreq_governor(unsigned int cpu, unsigned int event) | |||
1199 | if (!policy) | 1203 | if (!policy) |
1200 | return -EINVAL; | 1204 | return -EINVAL; |
1201 | 1205 | ||
1202 | down(&policy->lock); | 1206 | mutex_lock(&policy->lock); |
1203 | ret = __cpufreq_governor(policy, event); | 1207 | ret = __cpufreq_governor(policy, event); |
1204 | up(&policy->lock); | 1208 | mutex_unlock(&policy->lock); |
1205 | 1209 | ||
1206 | cpufreq_cpu_put(policy); | 1210 | cpufreq_cpu_put(policy); |
1207 | 1211 | ||
@@ -1217,17 +1221,17 @@ int cpufreq_register_governor(struct cpufreq_governor *governor) | |||
1217 | if (!governor) | 1221 | if (!governor) |
1218 | return -EINVAL; | 1222 | return -EINVAL; |
1219 | 1223 | ||
1220 | down(&cpufreq_governor_sem); | 1224 | mutex_lock(&cpufreq_governor_mutex); |
1221 | 1225 | ||
1222 | list_for_each_entry(t, &cpufreq_governor_list, governor_list) { | 1226 | list_for_each_entry(t, &cpufreq_governor_list, governor_list) { |
1223 | if (!strnicmp(governor->name,t->name,CPUFREQ_NAME_LEN)) { | 1227 | if (!strnicmp(governor->name,t->name,CPUFREQ_NAME_LEN)) { |
1224 | up(&cpufreq_governor_sem); | 1228 | mutex_unlock(&cpufreq_governor_mutex); |
1225 | return -EBUSY; | 1229 | return -EBUSY; |
1226 | } | 1230 | } |
1227 | } | 1231 | } |
1228 | list_add(&governor->governor_list, &cpufreq_governor_list); | 1232 | list_add(&governor->governor_list, &cpufreq_governor_list); |
1229 | 1233 | ||
1230 | up(&cpufreq_governor_sem); | 1234 | mutex_unlock(&cpufreq_governor_mutex); |
1231 | 1235 | ||
1232 | return 0; | 1236 | return 0; |
1233 | } | 1237 | } |
@@ -1239,9 +1243,9 @@ void cpufreq_unregister_governor(struct cpufreq_governor *governor) | |||
1239 | if (!governor) | 1243 | if (!governor) |
1240 | return; | 1244 | return; |
1241 | 1245 | ||
1242 | down(&cpufreq_governor_sem); | 1246 | mutex_lock(&cpufreq_governor_mutex); |
1243 | list_del(&governor->governor_list); | 1247 | list_del(&governor->governor_list); |
1244 | up(&cpufreq_governor_sem); | 1248 | mutex_unlock(&cpufreq_governor_mutex); |
1245 | return; | 1249 | return; |
1246 | } | 1250 | } |
1247 | EXPORT_SYMBOL_GPL(cpufreq_unregister_governor); | 1251 | EXPORT_SYMBOL_GPL(cpufreq_unregister_governor); |
@@ -1268,9 +1272,9 @@ int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu) | |||
1268 | if (!cpu_policy) | 1272 | if (!cpu_policy) |
1269 | return -EINVAL; | 1273 | return -EINVAL; |
1270 | 1274 | ||
1271 | down(&cpu_policy->lock); | 1275 | mutex_lock(&cpu_policy->lock); |
1272 | memcpy(policy, cpu_policy, sizeof(struct cpufreq_policy)); | 1276 | memcpy(policy, cpu_policy, sizeof(struct cpufreq_policy)); |
1273 | up(&cpu_policy->lock); | 1277 | mutex_unlock(&cpu_policy->lock); |
1274 | 1278 | ||
1275 | cpufreq_cpu_put(cpu_policy); | 1279 | cpufreq_cpu_put(cpu_policy); |
1276 | 1280 | ||
@@ -1382,7 +1386,7 @@ int cpufreq_set_policy(struct cpufreq_policy *policy) | |||
1382 | return -EINVAL; | 1386 | return -EINVAL; |
1383 | 1387 | ||
1384 | /* lock this CPU */ | 1388 | /* lock this CPU */ |
1385 | down(&data->lock); | 1389 | mutex_lock(&data->lock); |
1386 | 1390 | ||
1387 | ret = __cpufreq_set_policy(data, policy); | 1391 | ret = __cpufreq_set_policy(data, policy); |
1388 | data->user_policy.min = data->min; | 1392 | data->user_policy.min = data->min; |
@@ -1390,7 +1394,7 @@ int cpufreq_set_policy(struct cpufreq_policy *policy) | |||
1390 | data->user_policy.policy = data->policy; | 1394 | data->user_policy.policy = data->policy; |
1391 | data->user_policy.governor = data->governor; | 1395 | data->user_policy.governor = data->governor; |
1392 | 1396 | ||
1393 | up(&data->lock); | 1397 | mutex_unlock(&data->lock); |
1394 | cpufreq_cpu_put(data); | 1398 | cpufreq_cpu_put(data); |
1395 | 1399 | ||
1396 | return ret; | 1400 | return ret; |
@@ -1414,7 +1418,7 @@ int cpufreq_update_policy(unsigned int cpu) | |||
1414 | if (!data) | 1418 | if (!data) |
1415 | return -ENODEV; | 1419 | return -ENODEV; |
1416 | 1420 | ||
1417 | down(&data->lock); | 1421 | mutex_lock(&data->lock); |
1418 | 1422 | ||
1419 | dprintk("updating policy for CPU %u\n", cpu); | 1423 | dprintk("updating policy for CPU %u\n", cpu); |
1420 | memcpy(&policy, | 1424 | memcpy(&policy, |
@@ -1425,9 +1429,17 @@ int cpufreq_update_policy(unsigned int cpu) | |||
1425 | policy.policy = data->user_policy.policy; | 1429 | policy.policy = data->user_policy.policy; |
1426 | policy.governor = data->user_policy.governor; | 1430 | policy.governor = data->user_policy.governor; |
1427 | 1431 | ||
1432 | /* BIOS might change freq behind our back | ||
1433 | -> ask driver for current freq and notify governors about a change */ | ||
1434 | if (cpufreq_driver->get) { | ||
1435 | policy.cur = cpufreq_driver->get(cpu); | ||
1436 | if (data->cur != policy.cur) | ||
1437 | cpufreq_out_of_sync(cpu, data->cur, policy.cur); | ||
1438 | } | ||
1439 | |||
1428 | ret = __cpufreq_set_policy(data, &policy); | 1440 | ret = __cpufreq_set_policy(data, &policy); |
1429 | 1441 | ||
1430 | up(&data->lock); | 1442 | mutex_unlock(&data->lock); |
1431 | 1443 | ||
1432 | cpufreq_cpu_put(data); | 1444 | cpufreq_cpu_put(data); |
1433 | return ret; | 1445 | return ret; |