diff options
author | Steven Whitehouse <steve@men-an-tol.chygwyn.com> | 2006-02-23 04:49:43 -0500 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2006-02-23 04:49:43 -0500 |
commit | d35462b4bb847b68321c55e95c926aa485aecce2 (patch) | |
tree | b08e18bf6e672633402871ee763102fdb5e63229 /drivers/cpufreq/cpufreq.c | |
parent | 91ffd7db71e7451f89941a8f428b4daa2a7c1e38 (diff) | |
parent | 9e956c2dac9bec602ed1ba29181b45ba6d2b6448 (diff) |
Merge branch 'master'
Diffstat (limited to 'drivers/cpufreq/cpufreq.c')
-rw-r--r-- | drivers/cpufreq/cpufreq.c | 174 |
1 files changed, 94 insertions, 80 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 277a843a87a6..9582de1c9cad 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 | ||
@@ -34,8 +35,8 @@ | |||
34 | * level driver of CPUFreq support, and its spinlock. This lock | 35 | * level driver of CPUFreq support, and its spinlock. This lock |
35 | * also protects the cpufreq_cpu_data array. | 36 | * also protects the cpufreq_cpu_data array. |
36 | */ | 37 | */ |
37 | static struct cpufreq_driver *cpufreq_driver; | 38 | static struct cpufreq_driver *cpufreq_driver; |
38 | static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS]; | 39 | static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS]; |
39 | static DEFINE_SPINLOCK(cpufreq_driver_lock); | 40 | static DEFINE_SPINLOCK(cpufreq_driver_lock); |
40 | 41 | ||
41 | /* internal prototypes */ | 42 | /* internal prototypes */ |
@@ -49,15 +50,15 @@ static void handle_update(void *data); | |||
49 | * changes to devices when the CPU clock speed changes. | 50 | * changes to devices when the CPU clock speed changes. |
50 | * The mutex locks both lists. | 51 | * The mutex locks both lists. |
51 | */ | 52 | */ |
52 | static struct notifier_block *cpufreq_policy_notifier_list; | 53 | static struct notifier_block *cpufreq_policy_notifier_list; |
53 | static struct notifier_block *cpufreq_transition_notifier_list; | 54 | static struct notifier_block *cpufreq_transition_notifier_list; |
54 | static DECLARE_RWSEM (cpufreq_notifier_rwsem); | 55 | 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 | { |
62 | struct cpufreq_policy *data; | 63 | struct cpufreq_policy *data; |
63 | unsigned long flags; | 64 | unsigned long flags; |
@@ -84,20 +85,19 @@ struct cpufreq_policy * cpufreq_cpu_get(unsigned int cpu) | |||
84 | if (!kobject_get(&data->kobj)) | 85 | if (!kobject_get(&data->kobj)) |
85 | goto err_out_put_module; | 86 | goto err_out_put_module; |
86 | 87 | ||
87 | |||
88 | spin_unlock_irqrestore(&cpufreq_driver_lock, flags); | 88 | spin_unlock_irqrestore(&cpufreq_driver_lock, flags); |
89 | |||
90 | return data; | 89 | return data; |
91 | 90 | ||
92 | err_out_put_module: | 91 | err_out_put_module: |
93 | module_put(cpufreq_driver->owner); | 92 | module_put(cpufreq_driver->owner); |
94 | err_out_unlock: | 93 | err_out_unlock: |
95 | spin_unlock_irqrestore(&cpufreq_driver_lock, flags); | 94 | spin_unlock_irqrestore(&cpufreq_driver_lock, flags); |
96 | err_out: | 95 | err_out: |
97 | return NULL; | 96 | return NULL; |
98 | } | 97 | } |
99 | EXPORT_SYMBOL_GPL(cpufreq_cpu_get); | 98 | EXPORT_SYMBOL_GPL(cpufreq_cpu_get); |
100 | 99 | ||
100 | |||
101 | void cpufreq_cpu_put(struct cpufreq_policy *data) | 101 | void cpufreq_cpu_put(struct cpufreq_policy *data) |
102 | { | 102 | { |
103 | kobject_put(&data->kobj); | 103 | kobject_put(&data->kobj); |
@@ -228,44 +228,53 @@ static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) { | |||
228 | 228 | ||
229 | 229 | ||
230 | /** | 230 | /** |
231 | * cpufreq_notify_transition - call notifier chain and adjust_jiffies on frequency transition | 231 | * cpufreq_notify_transition - call notifier chain and adjust_jiffies |
232 | * on frequency transition. | ||
232 | * | 233 | * |
233 | * This function calls the transition notifiers and the "adjust_jiffies" function. It is called | 234 | * This function calls the transition notifiers and the "adjust_jiffies" |
234 | * twice on all CPU frequency changes that have external effects. | 235 | * function. It is called twice on all CPU frequency changes that have |
236 | * external effects. | ||
235 | */ | 237 | */ |
236 | void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state) | 238 | void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state) |
237 | { | 239 | { |
240 | struct cpufreq_policy *policy; | ||
241 | |||
238 | BUG_ON(irqs_disabled()); | 242 | BUG_ON(irqs_disabled()); |
239 | 243 | ||
240 | freqs->flags = cpufreq_driver->flags; | 244 | freqs->flags = cpufreq_driver->flags; |
241 | dprintk("notification %u of frequency transition to %u kHz\n", state, freqs->new); | 245 | dprintk("notification %u of frequency transition to %u kHz\n", |
246 | state, freqs->new); | ||
242 | 247 | ||
243 | down_read(&cpufreq_notifier_rwsem); | 248 | down_read(&cpufreq_notifier_rwsem); |
249 | |||
250 | policy = cpufreq_cpu_data[freqs->cpu]; | ||
244 | switch (state) { | 251 | switch (state) { |
252 | |||
245 | case CPUFREQ_PRECHANGE: | 253 | case CPUFREQ_PRECHANGE: |
246 | /* detect if the driver reported a value as "old frequency" which | 254 | /* detect if the driver reported a value as "old frequency" |
247 | * is not equal to what the cpufreq core thinks is "old frequency". | 255 | * which is not equal to what the cpufreq core thinks is |
256 | * "old frequency". | ||
248 | */ | 257 | */ |
249 | if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { | 258 | if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { |
250 | if ((likely(cpufreq_cpu_data[freqs->cpu])) && | 259 | if ((policy) && (policy->cpu == freqs->cpu) && |
251 | (likely(cpufreq_cpu_data[freqs->cpu]->cpu == freqs->cpu)) && | 260 | (policy->cur) && (policy->cur != freqs->old)) { |
252 | (likely(cpufreq_cpu_data[freqs->cpu]->cur)) && | 261 | dprintk(KERN_WARNING "Warning: CPU frequency is" |
253 | (unlikely(freqs->old != cpufreq_cpu_data[freqs->cpu]->cur))) | 262 | " %u, cpufreq assumed %u kHz.\n", |
254 | { | 263 | freqs->old, policy->cur); |
255 | dprintk(KERN_WARNING "Warning: CPU frequency is %u, " | 264 | freqs->old = policy->cur; |
256 | "cpufreq assumed %u kHz.\n", freqs->old, cpufreq_cpu_data[freqs->cpu]->cur); | ||
257 | freqs->old = cpufreq_cpu_data[freqs->cpu]->cur; | ||
258 | } | 265 | } |
259 | } | 266 | } |
260 | notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_PRECHANGE, freqs); | 267 | notifier_call_chain(&cpufreq_transition_notifier_list, |
268 | CPUFREQ_PRECHANGE, freqs); | ||
261 | adjust_jiffies(CPUFREQ_PRECHANGE, freqs); | 269 | adjust_jiffies(CPUFREQ_PRECHANGE, freqs); |
262 | break; | 270 | break; |
271 | |||
263 | case CPUFREQ_POSTCHANGE: | 272 | case CPUFREQ_POSTCHANGE: |
264 | adjust_jiffies(CPUFREQ_POSTCHANGE, freqs); | 273 | adjust_jiffies(CPUFREQ_POSTCHANGE, freqs); |
265 | notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_POSTCHANGE, freqs); | 274 | notifier_call_chain(&cpufreq_transition_notifier_list, |
266 | if ((likely(cpufreq_cpu_data[freqs->cpu])) && | 275 | CPUFREQ_POSTCHANGE, freqs); |
267 | (likely(cpufreq_cpu_data[freqs->cpu]->cpu == freqs->cpu))) | 276 | if (likely(policy) && likely(policy->cpu == freqs->cpu)) |
268 | cpufreq_cpu_data[freqs->cpu]->cur = freqs->new; | 277 | policy->cur = freqs->new; |
269 | break; | 278 | break; |
270 | } | 279 | } |
271 | up_read(&cpufreq_notifier_rwsem); | 280 | up_read(&cpufreq_notifier_rwsem); |
@@ -297,18 +306,18 @@ static int cpufreq_parse_governor (char *str_governor, unsigned int *policy, | |||
297 | return -EINVAL; | 306 | return -EINVAL; |
298 | } else { | 307 | } else { |
299 | struct cpufreq_governor *t; | 308 | struct cpufreq_governor *t; |
300 | down(&cpufreq_governor_sem); | 309 | mutex_lock(&cpufreq_governor_mutex); |
301 | if (!cpufreq_driver || !cpufreq_driver->target) | 310 | if (!cpufreq_driver || !cpufreq_driver->target) |
302 | goto out; | 311 | goto out; |
303 | list_for_each_entry(t, &cpufreq_governor_list, governor_list) { | 312 | list_for_each_entry(t, &cpufreq_governor_list, governor_list) { |
304 | if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) { | 313 | if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) { |
305 | *governor = t; | 314 | *governor = t; |
306 | up(&cpufreq_governor_sem); | 315 | mutex_unlock(&cpufreq_governor_mutex); |
307 | return 0; | 316 | return 0; |
308 | } | 317 | } |
309 | } | 318 | } |
310 | out: | 319 | out: |
311 | up(&cpufreq_governor_sem); | 320 | mutex_unlock(&cpufreq_governor_mutex); |
312 | } | 321 | } |
313 | return -EINVAL; | 322 | return -EINVAL; |
314 | } | 323 | } |
@@ -414,7 +423,6 @@ static ssize_t store_scaling_governor (struct cpufreq_policy * policy, | |||
414 | return -EINVAL; | 423 | return -EINVAL; |
415 | 424 | ||
416 | ret = cpufreq_set_policy(&new_policy); | 425 | ret = cpufreq_set_policy(&new_policy); |
417 | |||
418 | return ret ? ret : count; | 426 | return ret ? ret : count; |
419 | } | 427 | } |
420 | 428 | ||
@@ -445,7 +453,7 @@ static ssize_t show_scaling_available_governors (struct cpufreq_policy * policy, | |||
445 | goto out; | 453 | goto out; |
446 | i += scnprintf(&buf[i], CPUFREQ_NAME_LEN, "%s ", t->name); | 454 | i += scnprintf(&buf[i], CPUFREQ_NAME_LEN, "%s ", t->name); |
447 | } | 455 | } |
448 | out: | 456 | out: |
449 | i += sprintf(&buf[i], "\n"); | 457 | i += sprintf(&buf[i], "\n"); |
450 | return i; | 458 | return i; |
451 | } | 459 | } |
@@ -600,7 +608,8 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) | |||
600 | policy->cpu = cpu; | 608 | policy->cpu = cpu; |
601 | policy->cpus = cpumask_of_cpu(cpu); | 609 | policy->cpus = cpumask_of_cpu(cpu); |
602 | 610 | ||
603 | init_MUTEX_LOCKED(&policy->lock); | 611 | mutex_init(&policy->lock); |
612 | mutex_lock(&policy->lock); | ||
604 | init_completion(&policy->kobj_unregister); | 613 | init_completion(&policy->kobj_unregister); |
605 | INIT_WORK(&policy->update, handle_update, (void *)(long)cpu); | 614 | INIT_WORK(&policy->update, handle_update, (void *)(long)cpu); |
606 | 615 | ||
@@ -610,6 +619,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) | |||
610 | ret = cpufreq_driver->init(policy); | 619 | ret = cpufreq_driver->init(policy); |
611 | if (ret) { | 620 | if (ret) { |
612 | dprintk("initialization failed\n"); | 621 | dprintk("initialization failed\n"); |
622 | mutex_unlock(&policy->lock); | ||
613 | goto err_out; | 623 | goto err_out; |
614 | } | 624 | } |
615 | 625 | ||
@@ -621,9 +631,10 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) | |||
621 | strlcpy(policy->kobj.name, "cpufreq", KOBJ_NAME_LEN); | 631 | strlcpy(policy->kobj.name, "cpufreq", KOBJ_NAME_LEN); |
622 | 632 | ||
623 | ret = kobject_register(&policy->kobj); | 633 | ret = kobject_register(&policy->kobj); |
624 | if (ret) | 634 | if (ret) { |
635 | mutex_unlock(&policy->lock); | ||
625 | goto err_out_driver_exit; | 636 | goto err_out_driver_exit; |
626 | 637 | } | |
627 | /* set up files for this cpu device */ | 638 | /* set up files for this cpu device */ |
628 | drv_attr = cpufreq_driver->attr; | 639 | drv_attr = cpufreq_driver->attr; |
629 | while ((drv_attr) && (*drv_attr)) { | 640 | while ((drv_attr) && (*drv_attr)) { |
@@ -641,7 +652,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) | |||
641 | spin_unlock_irqrestore(&cpufreq_driver_lock, flags); | 652 | spin_unlock_irqrestore(&cpufreq_driver_lock, flags); |
642 | policy->governor = NULL; /* to assure that the starting sequence is | 653 | policy->governor = NULL; /* to assure that the starting sequence is |
643 | * run in cpufreq_set_policy */ | 654 | * run in cpufreq_set_policy */ |
644 | up(&policy->lock); | 655 | mutex_unlock(&policy->lock); |
645 | 656 | ||
646 | /* set default policy */ | 657 | /* set default policy */ |
647 | 658 | ||
@@ -762,10 +773,10 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev) | |||
762 | spin_unlock_irqrestore(&cpufreq_driver_lock, flags); | 773 | spin_unlock_irqrestore(&cpufreq_driver_lock, flags); |
763 | #endif | 774 | #endif |
764 | 775 | ||
765 | down(&data->lock); | 776 | mutex_lock(&data->lock); |
766 | if (cpufreq_driver->target) | 777 | if (cpufreq_driver->target) |
767 | __cpufreq_governor(data, CPUFREQ_GOV_STOP); | 778 | __cpufreq_governor(data, CPUFREQ_GOV_STOP); |
768 | up(&data->lock); | 779 | mutex_unlock(&data->lock); |
769 | 780 | ||
770 | kobject_unregister(&data->kobj); | 781 | kobject_unregister(&data->kobj); |
771 | 782 | ||
@@ -785,7 +796,6 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev) | |||
785 | kfree(data); | 796 | kfree(data); |
786 | 797 | ||
787 | cpufreq_debug_enable_ratelimit(); | 798 | cpufreq_debug_enable_ratelimit(); |
788 | |||
789 | return 0; | 799 | return 0; |
790 | } | 800 | } |
791 | 801 | ||
@@ -834,9 +844,9 @@ unsigned int cpufreq_quick_get(unsigned int cpu) | |||
834 | unsigned int ret = 0; | 844 | unsigned int ret = 0; |
835 | 845 | ||
836 | if (policy) { | 846 | if (policy) { |
837 | down(&policy->lock); | 847 | mutex_lock(&policy->lock); |
838 | ret = policy->cur; | 848 | ret = policy->cur; |
839 | up(&policy->lock); | 849 | mutex_unlock(&policy->lock); |
840 | cpufreq_cpu_put(policy); | 850 | cpufreq_cpu_put(policy); |
841 | } | 851 | } |
842 | 852 | ||
@@ -862,12 +872,11 @@ unsigned int cpufreq_get(unsigned int cpu) | |||
862 | if (!cpufreq_driver->get) | 872 | if (!cpufreq_driver->get) |
863 | goto out; | 873 | goto out; |
864 | 874 | ||
865 | down(&policy->lock); | 875 | mutex_lock(&policy->lock); |
866 | 876 | ||
867 | ret = cpufreq_driver->get(cpu); | 877 | ret = cpufreq_driver->get(cpu); |
868 | 878 | ||
869 | if (ret && policy->cur && !(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) | 879 | if (ret && policy->cur && !(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { |
870 | { | ||
871 | /* verify no discrepancy between actual and saved value exists */ | 880 | /* verify no discrepancy between actual and saved value exists */ |
872 | if (unlikely(ret != policy->cur)) { | 881 | if (unlikely(ret != policy->cur)) { |
873 | cpufreq_out_of_sync(cpu, policy->cur, ret); | 882 | cpufreq_out_of_sync(cpu, policy->cur, ret); |
@@ -875,9 +884,9 @@ unsigned int cpufreq_get(unsigned int cpu) | |||
875 | } | 884 | } |
876 | } | 885 | } |
877 | 886 | ||
878 | up(&policy->lock); | 887 | mutex_unlock(&policy->lock); |
879 | 888 | ||
880 | out: | 889 | out: |
881 | cpufreq_cpu_put(policy); | 890 | cpufreq_cpu_put(policy); |
882 | 891 | ||
883 | return (ret); | 892 | return (ret); |
@@ -958,7 +967,7 @@ static int cpufreq_suspend(struct sys_device * sysdev, pm_message_t pmsg) | |||
958 | cpu_policy->cur = cur_freq; | 967 | cpu_policy->cur = cur_freq; |
959 | } | 968 | } |
960 | 969 | ||
961 | out: | 970 | out: |
962 | cpufreq_cpu_put(cpu_policy); | 971 | cpufreq_cpu_put(cpu_policy); |
963 | return 0; | 972 | return 0; |
964 | } | 973 | } |
@@ -1158,14 +1167,13 @@ int cpufreq_driver_target(struct cpufreq_policy *policy, | |||
1158 | if (!policy) | 1167 | if (!policy) |
1159 | return -EINVAL; | 1168 | return -EINVAL; |
1160 | 1169 | ||
1161 | down(&policy->lock); | 1170 | mutex_lock(&policy->lock); |
1162 | 1171 | ||
1163 | ret = __cpufreq_driver_target(policy, target_freq, relation); | 1172 | ret = __cpufreq_driver_target(policy, target_freq, relation); |
1164 | 1173 | ||
1165 | up(&policy->lock); | 1174 | mutex_unlock(&policy->lock); |
1166 | 1175 | ||
1167 | cpufreq_cpu_put(policy); | 1176 | cpufreq_cpu_put(policy); |
1168 | |||
1169 | return ret; | 1177 | return ret; |
1170 | } | 1178 | } |
1171 | EXPORT_SYMBOL_GPL(cpufreq_driver_target); | 1179 | EXPORT_SYMBOL_GPL(cpufreq_driver_target); |
@@ -1199,12 +1207,11 @@ int cpufreq_governor(unsigned int cpu, unsigned int event) | |||
1199 | if (!policy) | 1207 | if (!policy) |
1200 | return -EINVAL; | 1208 | return -EINVAL; |
1201 | 1209 | ||
1202 | down(&policy->lock); | 1210 | mutex_lock(&policy->lock); |
1203 | ret = __cpufreq_governor(policy, event); | 1211 | ret = __cpufreq_governor(policy, event); |
1204 | up(&policy->lock); | 1212 | mutex_unlock(&policy->lock); |
1205 | 1213 | ||
1206 | cpufreq_cpu_put(policy); | 1214 | cpufreq_cpu_put(policy); |
1207 | |||
1208 | return ret; | 1215 | return ret; |
1209 | } | 1216 | } |
1210 | EXPORT_SYMBOL_GPL(cpufreq_governor); | 1217 | EXPORT_SYMBOL_GPL(cpufreq_governor); |
@@ -1217,18 +1224,17 @@ int cpufreq_register_governor(struct cpufreq_governor *governor) | |||
1217 | if (!governor) | 1224 | if (!governor) |
1218 | return -EINVAL; | 1225 | return -EINVAL; |
1219 | 1226 | ||
1220 | down(&cpufreq_governor_sem); | 1227 | mutex_lock(&cpufreq_governor_mutex); |
1221 | 1228 | ||
1222 | list_for_each_entry(t, &cpufreq_governor_list, governor_list) { | 1229 | list_for_each_entry(t, &cpufreq_governor_list, governor_list) { |
1223 | if (!strnicmp(governor->name,t->name,CPUFREQ_NAME_LEN)) { | 1230 | if (!strnicmp(governor->name,t->name,CPUFREQ_NAME_LEN)) { |
1224 | up(&cpufreq_governor_sem); | 1231 | mutex_unlock(&cpufreq_governor_mutex); |
1225 | return -EBUSY; | 1232 | return -EBUSY; |
1226 | } | 1233 | } |
1227 | } | 1234 | } |
1228 | list_add(&governor->governor_list, &cpufreq_governor_list); | 1235 | list_add(&governor->governor_list, &cpufreq_governor_list); |
1229 | 1236 | ||
1230 | up(&cpufreq_governor_sem); | 1237 | mutex_unlock(&cpufreq_governor_mutex); |
1231 | |||
1232 | return 0; | 1238 | return 0; |
1233 | } | 1239 | } |
1234 | EXPORT_SYMBOL_GPL(cpufreq_register_governor); | 1240 | EXPORT_SYMBOL_GPL(cpufreq_register_governor); |
@@ -1239,9 +1245,9 @@ void cpufreq_unregister_governor(struct cpufreq_governor *governor) | |||
1239 | if (!governor) | 1245 | if (!governor) |
1240 | return; | 1246 | return; |
1241 | 1247 | ||
1242 | down(&cpufreq_governor_sem); | 1248 | mutex_lock(&cpufreq_governor_mutex); |
1243 | list_del(&governor->governor_list); | 1249 | list_del(&governor->governor_list); |
1244 | up(&cpufreq_governor_sem); | 1250 | mutex_unlock(&cpufreq_governor_mutex); |
1245 | return; | 1251 | return; |
1246 | } | 1252 | } |
1247 | EXPORT_SYMBOL_GPL(cpufreq_unregister_governor); | 1253 | EXPORT_SYMBOL_GPL(cpufreq_unregister_governor); |
@@ -1268,12 +1274,11 @@ int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu) | |||
1268 | if (!cpu_policy) | 1274 | if (!cpu_policy) |
1269 | return -EINVAL; | 1275 | return -EINVAL; |
1270 | 1276 | ||
1271 | down(&cpu_policy->lock); | 1277 | mutex_lock(&cpu_policy->lock); |
1272 | memcpy(policy, cpu_policy, sizeof(struct cpufreq_policy)); | 1278 | memcpy(policy, cpu_policy, sizeof(struct cpufreq_policy)); |
1273 | up(&cpu_policy->lock); | 1279 | mutex_unlock(&cpu_policy->lock); |
1274 | 1280 | ||
1275 | cpufreq_cpu_put(cpu_policy); | 1281 | cpufreq_cpu_put(cpu_policy); |
1276 | |||
1277 | return 0; | 1282 | return 0; |
1278 | } | 1283 | } |
1279 | EXPORT_SYMBOL(cpufreq_get_policy); | 1284 | EXPORT_SYMBOL(cpufreq_get_policy); |
@@ -1287,9 +1292,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli | |||
1287 | dprintk("setting new policy for CPU %u: %u - %u kHz\n", policy->cpu, | 1292 | dprintk("setting new policy for CPU %u: %u - %u kHz\n", policy->cpu, |
1288 | policy->min, policy->max); | 1293 | policy->min, policy->max); |
1289 | 1294 | ||
1290 | memcpy(&policy->cpuinfo, | 1295 | memcpy(&policy->cpuinfo, &data->cpuinfo, sizeof(struct cpufreq_cpuinfo)); |
1291 | &data->cpuinfo, | ||
1292 | sizeof(struct cpufreq_cpuinfo)); | ||
1293 | 1296 | ||
1294 | /* verify the cpu speed can be set within this limit */ | 1297 | /* verify the cpu speed can be set within this limit */ |
1295 | ret = cpufreq_driver->verify(policy); | 1298 | ret = cpufreq_driver->verify(policy); |
@@ -1320,8 +1323,8 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli | |||
1320 | 1323 | ||
1321 | up_read(&cpufreq_notifier_rwsem); | 1324 | up_read(&cpufreq_notifier_rwsem); |
1322 | 1325 | ||
1323 | data->min = policy->min; | 1326 | data->min = policy->min; |
1324 | data->max = policy->max; | 1327 | data->max = policy->max; |
1325 | 1328 | ||
1326 | dprintk("new min and max freqs are %u - %u kHz\n", data->min, data->max); | 1329 | dprintk("new min and max freqs are %u - %u kHz\n", data->min, data->max); |
1327 | 1330 | ||
@@ -1358,7 +1361,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli | |||
1358 | __cpufreq_governor(data, CPUFREQ_GOV_LIMITS); | 1361 | __cpufreq_governor(data, CPUFREQ_GOV_LIMITS); |
1359 | } | 1362 | } |
1360 | 1363 | ||
1361 | error_out: | 1364 | error_out: |
1362 | cpufreq_debug_enable_ratelimit(); | 1365 | cpufreq_debug_enable_ratelimit(); |
1363 | return ret; | 1366 | return ret; |
1364 | } | 1367 | } |
@@ -1382,7 +1385,7 @@ int cpufreq_set_policy(struct cpufreq_policy *policy) | |||
1382 | return -EINVAL; | 1385 | return -EINVAL; |
1383 | 1386 | ||
1384 | /* lock this CPU */ | 1387 | /* lock this CPU */ |
1385 | down(&data->lock); | 1388 | mutex_lock(&data->lock); |
1386 | 1389 | ||
1387 | ret = __cpufreq_set_policy(data, policy); | 1390 | ret = __cpufreq_set_policy(data, policy); |
1388 | data->user_policy.min = data->min; | 1391 | data->user_policy.min = data->min; |
@@ -1390,7 +1393,7 @@ int cpufreq_set_policy(struct cpufreq_policy *policy) | |||
1390 | data->user_policy.policy = data->policy; | 1393 | data->user_policy.policy = data->policy; |
1391 | data->user_policy.governor = data->governor; | 1394 | data->user_policy.governor = data->governor; |
1392 | 1395 | ||
1393 | up(&data->lock); | 1396 | mutex_unlock(&data->lock); |
1394 | cpufreq_cpu_put(data); | 1397 | cpufreq_cpu_put(data); |
1395 | 1398 | ||
1396 | return ret; | 1399 | return ret; |
@@ -1414,20 +1417,31 @@ int cpufreq_update_policy(unsigned int cpu) | |||
1414 | if (!data) | 1417 | if (!data) |
1415 | return -ENODEV; | 1418 | return -ENODEV; |
1416 | 1419 | ||
1417 | down(&data->lock); | 1420 | mutex_lock(&data->lock); |
1418 | 1421 | ||
1419 | dprintk("updating policy for CPU %u\n", cpu); | 1422 | dprintk("updating policy for CPU %u\n", cpu); |
1420 | memcpy(&policy, | 1423 | memcpy(&policy, data, sizeof(struct cpufreq_policy)); |
1421 | data, | ||
1422 | sizeof(struct cpufreq_policy)); | ||
1423 | policy.min = data->user_policy.min; | 1424 | policy.min = data->user_policy.min; |
1424 | policy.max = data->user_policy.max; | 1425 | policy.max = data->user_policy.max; |
1425 | policy.policy = data->user_policy.policy; | 1426 | policy.policy = data->user_policy.policy; |
1426 | policy.governor = data->user_policy.governor; | 1427 | policy.governor = data->user_policy.governor; |
1427 | 1428 | ||
1429 | /* BIOS might change freq behind our back | ||
1430 | -> ask driver for current freq and notify governors about a change */ | ||
1431 | if (cpufreq_driver->get) { | ||
1432 | policy.cur = cpufreq_driver->get(cpu); | ||
1433 | if (!data->cur) { | ||
1434 | dprintk("Driver did not initialize current freq"); | ||
1435 | data->cur = policy.cur; | ||
1436 | } else { | ||
1437 | if (data->cur != policy.cur) | ||
1438 | cpufreq_out_of_sync(cpu, data->cur, policy.cur); | ||
1439 | } | ||
1440 | } | ||
1441 | |||
1428 | ret = __cpufreq_set_policy(data, &policy); | 1442 | ret = __cpufreq_set_policy(data, &policy); |
1429 | 1443 | ||
1430 | up(&data->lock); | 1444 | mutex_unlock(&data->lock); |
1431 | 1445 | ||
1432 | cpufreq_cpu_put(data); | 1446 | cpufreq_cpu_put(data); |
1433 | return ret; | 1447 | return ret; |