diff options
| author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-02-13 22:10:43 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-02-13 22:10:43 -0500 |
| commit | 934a3595b30c986bab52bc9c08d12c8962c88c8a (patch) | |
| tree | 1aa2acda1b45d97ce7b4027327a23a2a3c8dc81a | |
| parent | b4d9eda028e8becbb5057b554e63eea12e496a88 (diff) | |
| parent | 7d5e350fab47f1273bc8b52d5f133ed6e4baeb7f (diff) | |
Merge master.kernel.org:/pub/scm/linux/kernel/git/davej/cpufreq
| -rw-r--r-- | arch/i386/kernel/timers/timer_tsc.c | 5 | ||||
| -rw-r--r-- | drivers/cpufreq/cpufreq.c | 110 |
2 files changed, 61 insertions, 54 deletions
diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c index 7c86e3c5f1c1..a7f5a2aceba2 100644 --- a/arch/i386/kernel/timers/timer_tsc.c +++ b/arch/i386/kernel/timers/timer_tsc.c | |||
| @@ -282,6 +282,10 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, | |||
| 282 | if (val != CPUFREQ_RESUMECHANGE) | 282 | if (val != CPUFREQ_RESUMECHANGE) |
| 283 | write_seqlock_irq(&xtime_lock); | 283 | write_seqlock_irq(&xtime_lock); |
| 284 | if (!ref_freq) { | 284 | if (!ref_freq) { |
| 285 | if (!freq->old){ | ||
| 286 | ref_freq = freq->new; | ||
| 287 | goto end; | ||
| 288 | } | ||
| 285 | ref_freq = freq->old; | 289 | ref_freq = freq->old; |
| 286 | loops_per_jiffy_ref = cpu_data[freq->cpu].loops_per_jiffy; | 290 | loops_per_jiffy_ref = cpu_data[freq->cpu].loops_per_jiffy; |
| 287 | #ifndef CONFIG_SMP | 291 | #ifndef CONFIG_SMP |
| @@ -307,6 +311,7 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, | |||
| 307 | #endif | 311 | #endif |
| 308 | } | 312 | } |
| 309 | 313 | ||
| 314 | end: | ||
| 310 | if (val != CPUFREQ_RESUMECHANGE) | 315 | if (val != CPUFREQ_RESUMECHANGE) |
| 311 | write_sequnlock_irq(&xtime_lock); | 316 | write_sequnlock_irq(&xtime_lock); |
| 312 | 317 | ||
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 7a511479ae29..9582de1c9cad 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
| @@ -35,8 +35,8 @@ | |||
| 35 | * level driver of CPUFreq support, and its spinlock. This lock | 35 | * level driver of CPUFreq support, and its spinlock. This lock |
| 36 | * also protects the cpufreq_cpu_data array. | 36 | * also protects the cpufreq_cpu_data array. |
| 37 | */ | 37 | */ |
| 38 | static struct cpufreq_driver *cpufreq_driver; | 38 | static struct cpufreq_driver *cpufreq_driver; |
| 39 | static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS]; | 39 | static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS]; |
| 40 | static DEFINE_SPINLOCK(cpufreq_driver_lock); | 40 | static DEFINE_SPINLOCK(cpufreq_driver_lock); |
| 41 | 41 | ||
| 42 | /* internal prototypes */ | 42 | /* internal prototypes */ |
| @@ -50,15 +50,15 @@ static void handle_update(void *data); | |||
| 50 | * changes to devices when the CPU clock speed changes. | 50 | * changes to devices when the CPU clock speed changes. |
| 51 | * The mutex locks both lists. | 51 | * The mutex locks both lists. |
| 52 | */ | 52 | */ |
| 53 | static struct notifier_block *cpufreq_policy_notifier_list; | 53 | static struct notifier_block *cpufreq_policy_notifier_list; |
| 54 | static struct notifier_block *cpufreq_transition_notifier_list; | 54 | static struct notifier_block *cpufreq_transition_notifier_list; |
| 55 | static DECLARE_RWSEM (cpufreq_notifier_rwsem); | 55 | static DECLARE_RWSEM (cpufreq_notifier_rwsem); |
| 56 | 56 | ||
| 57 | 57 | ||
| 58 | static LIST_HEAD(cpufreq_governor_list); | 58 | static LIST_HEAD(cpufreq_governor_list); |
| 59 | static DEFINE_MUTEX (cpufreq_governor_mutex); | 59 | static DEFINE_MUTEX (cpufreq_governor_mutex); |
| 60 | 60 | ||
| 61 | struct cpufreq_policy * cpufreq_cpu_get(unsigned int cpu) | 61 | struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu) |
| 62 | { | 62 | { |
| 63 | struct cpufreq_policy *data; | 63 | struct cpufreq_policy *data; |
| 64 | unsigned long flags; | 64 | unsigned long flags; |
| @@ -85,20 +85,19 @@ struct cpufreq_policy * cpufreq_cpu_get(unsigned int cpu) | |||
| 85 | if (!kobject_get(&data->kobj)) | 85 | if (!kobject_get(&data->kobj)) |
| 86 | goto err_out_put_module; | 86 | goto err_out_put_module; |
| 87 | 87 | ||
| 88 | |||
| 89 | spin_unlock_irqrestore(&cpufreq_driver_lock, flags); | 88 | spin_unlock_irqrestore(&cpufreq_driver_lock, flags); |
| 90 | |||
| 91 | return data; | 89 | return data; |
| 92 | 90 | ||
| 93 | err_out_put_module: | 91 | err_out_put_module: |
| 94 | module_put(cpufreq_driver->owner); | 92 | module_put(cpufreq_driver->owner); |
| 95 | err_out_unlock: | 93 | err_out_unlock: |
| 96 | spin_unlock_irqrestore(&cpufreq_driver_lock, flags); | 94 | spin_unlock_irqrestore(&cpufreq_driver_lock, flags); |
| 97 | err_out: | 95 | err_out: |
| 98 | return NULL; | 96 | return NULL; |
| 99 | } | 97 | } |
| 100 | EXPORT_SYMBOL_GPL(cpufreq_cpu_get); | 98 | EXPORT_SYMBOL_GPL(cpufreq_cpu_get); |
| 101 | 99 | ||
| 100 | |||
| 102 | void cpufreq_cpu_put(struct cpufreq_policy *data) | 101 | void cpufreq_cpu_put(struct cpufreq_policy *data) |
| 103 | { | 102 | { |
| 104 | kobject_put(&data->kobj); | 103 | kobject_put(&data->kobj); |
| @@ -229,44 +228,53 @@ static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) { | |||
| 229 | 228 | ||
| 230 | 229 | ||
| 231 | /** | 230 | /** |
| 232 | * 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. | ||
| 233 | * | 233 | * |
| 234 | * 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" |
| 235 | * 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. | ||
| 236 | */ | 237 | */ |
| 237 | void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state) | 238 | void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state) |
| 238 | { | 239 | { |
| 240 | struct cpufreq_policy *policy; | ||
| 241 | |||
| 239 | BUG_ON(irqs_disabled()); | 242 | BUG_ON(irqs_disabled()); |
| 240 | 243 | ||
| 241 | freqs->flags = cpufreq_driver->flags; | 244 | freqs->flags = cpufreq_driver->flags; |
| 242 | 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); | ||
| 243 | 247 | ||
| 244 | down_read(&cpufreq_notifier_rwsem); | 248 | down_read(&cpufreq_notifier_rwsem); |
| 249 | |||
| 250 | policy = cpufreq_cpu_data[freqs->cpu]; | ||
| 245 | switch (state) { | 251 | switch (state) { |
| 252 | |||
| 246 | case CPUFREQ_PRECHANGE: | 253 | case CPUFREQ_PRECHANGE: |
| 247 | /* detect if the driver reported a value as "old frequency" which | 254 | /* detect if the driver reported a value as "old frequency" |
| 248 | * 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". | ||
| 249 | */ | 257 | */ |
| 250 | if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { | 258 | if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { |
| 251 | if ((likely(cpufreq_cpu_data[freqs->cpu])) && | 259 | if ((policy) && (policy->cpu == freqs->cpu) && |
| 252 | (likely(cpufreq_cpu_data[freqs->cpu]->cpu == freqs->cpu)) && | 260 | (policy->cur) && (policy->cur != freqs->old)) { |
| 253 | (likely(cpufreq_cpu_data[freqs->cpu]->cur)) && | 261 | dprintk(KERN_WARNING "Warning: CPU frequency is" |
| 254 | (unlikely(freqs->old != cpufreq_cpu_data[freqs->cpu]->cur))) | 262 | " %u, cpufreq assumed %u kHz.\n", |
| 255 | { | 263 | freqs->old, policy->cur); |
| 256 | dprintk(KERN_WARNING "Warning: CPU frequency is %u, " | 264 | freqs->old = policy->cur; |
| 257 | "cpufreq assumed %u kHz.\n", freqs->old, cpufreq_cpu_data[freqs->cpu]->cur); | ||
| 258 | freqs->old = cpufreq_cpu_data[freqs->cpu]->cur; | ||
| 259 | } | 265 | } |
| 260 | } | 266 | } |
| 261 | notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_PRECHANGE, freqs); | 267 | notifier_call_chain(&cpufreq_transition_notifier_list, |
| 268 | CPUFREQ_PRECHANGE, freqs); | ||
| 262 | adjust_jiffies(CPUFREQ_PRECHANGE, freqs); | 269 | adjust_jiffies(CPUFREQ_PRECHANGE, freqs); |
| 263 | break; | 270 | break; |
| 271 | |||
| 264 | case CPUFREQ_POSTCHANGE: | 272 | case CPUFREQ_POSTCHANGE: |
| 265 | adjust_jiffies(CPUFREQ_POSTCHANGE, freqs); | 273 | adjust_jiffies(CPUFREQ_POSTCHANGE, freqs); |
| 266 | notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_POSTCHANGE, freqs); | 274 | notifier_call_chain(&cpufreq_transition_notifier_list, |
| 267 | if ((likely(cpufreq_cpu_data[freqs->cpu])) && | 275 | CPUFREQ_POSTCHANGE, freqs); |
| 268 | (likely(cpufreq_cpu_data[freqs->cpu]->cpu == freqs->cpu))) | 276 | if (likely(policy) && likely(policy->cpu == freqs->cpu)) |
| 269 | cpufreq_cpu_data[freqs->cpu]->cur = freqs->new; | 277 | policy->cur = freqs->new; |
| 270 | break; | 278 | break; |
| 271 | } | 279 | } |
| 272 | up_read(&cpufreq_notifier_rwsem); | 280 | up_read(&cpufreq_notifier_rwsem); |
| @@ -308,7 +316,7 @@ static int cpufreq_parse_governor (char *str_governor, unsigned int *policy, | |||
| 308 | return 0; | 316 | return 0; |
| 309 | } | 317 | } |
| 310 | } | 318 | } |
| 311 | out: | 319 | out: |
| 312 | mutex_unlock(&cpufreq_governor_mutex); | 320 | mutex_unlock(&cpufreq_governor_mutex); |
| 313 | } | 321 | } |
| 314 | return -EINVAL; | 322 | return -EINVAL; |
| @@ -415,7 +423,6 @@ static ssize_t store_scaling_governor (struct cpufreq_policy * policy, | |||
| 415 | return -EINVAL; | 423 | return -EINVAL; |
| 416 | 424 | ||
| 417 | ret = cpufreq_set_policy(&new_policy); | 425 | ret = cpufreq_set_policy(&new_policy); |
| 418 | |||
| 419 | return ret ? ret : count; | 426 | return ret ? ret : count; |
| 420 | } | 427 | } |
| 421 | 428 | ||
| @@ -446,7 +453,7 @@ static ssize_t show_scaling_available_governors (struct cpufreq_policy * policy, | |||
| 446 | goto out; | 453 | goto out; |
| 447 | i += scnprintf(&buf[i], CPUFREQ_NAME_LEN, "%s ", t->name); | 454 | i += scnprintf(&buf[i], CPUFREQ_NAME_LEN, "%s ", t->name); |
| 448 | } | 455 | } |
| 449 | out: | 456 | out: |
| 450 | i += sprintf(&buf[i], "\n"); | 457 | i += sprintf(&buf[i], "\n"); |
| 451 | return i; | 458 | return i; |
| 452 | } | 459 | } |
| @@ -789,7 +796,6 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev) | |||
| 789 | kfree(data); | 796 | kfree(data); |
| 790 | 797 | ||
| 791 | cpufreq_debug_enable_ratelimit(); | 798 | cpufreq_debug_enable_ratelimit(); |
| 792 | |||
| 793 | return 0; | 799 | return 0; |
| 794 | } | 800 | } |
| 795 | 801 | ||
| @@ -870,8 +876,7 @@ unsigned int cpufreq_get(unsigned int cpu) | |||
| 870 | 876 | ||
| 871 | ret = cpufreq_driver->get(cpu); | 877 | ret = cpufreq_driver->get(cpu); |
| 872 | 878 | ||
| 873 | if (ret && policy->cur && !(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) | 879 | if (ret && policy->cur && !(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { |
| 874 | { | ||
| 875 | /* verify no discrepancy between actual and saved value exists */ | 880 | /* verify no discrepancy between actual and saved value exists */ |
| 876 | if (unlikely(ret != policy->cur)) { | 881 | if (unlikely(ret != policy->cur)) { |
| 877 | cpufreq_out_of_sync(cpu, policy->cur, ret); | 882 | cpufreq_out_of_sync(cpu, policy->cur, ret); |
| @@ -881,7 +886,7 @@ unsigned int cpufreq_get(unsigned int cpu) | |||
| 881 | 886 | ||
| 882 | mutex_unlock(&policy->lock); | 887 | mutex_unlock(&policy->lock); |
| 883 | 888 | ||
| 884 | out: | 889 | out: |
| 885 | cpufreq_cpu_put(policy); | 890 | cpufreq_cpu_put(policy); |
| 886 | 891 | ||
| 887 | return (ret); | 892 | return (ret); |
| @@ -962,7 +967,7 @@ static int cpufreq_suspend(struct sys_device * sysdev, pm_message_t pmsg) | |||
| 962 | cpu_policy->cur = cur_freq; | 967 | cpu_policy->cur = cur_freq; |
| 963 | } | 968 | } |
| 964 | 969 | ||
| 965 | out: | 970 | out: |
| 966 | cpufreq_cpu_put(cpu_policy); | 971 | cpufreq_cpu_put(cpu_policy); |
| 967 | return 0; | 972 | return 0; |
| 968 | } | 973 | } |
| @@ -1169,7 +1174,6 @@ int cpufreq_driver_target(struct cpufreq_policy *policy, | |||
| 1169 | mutex_unlock(&policy->lock); | 1174 | mutex_unlock(&policy->lock); |
| 1170 | 1175 | ||
| 1171 | cpufreq_cpu_put(policy); | 1176 | cpufreq_cpu_put(policy); |
| 1172 | |||
| 1173 | return ret; | 1177 | return ret; |
| 1174 | } | 1178 | } |
| 1175 | EXPORT_SYMBOL_GPL(cpufreq_driver_target); | 1179 | EXPORT_SYMBOL_GPL(cpufreq_driver_target); |
| @@ -1208,7 +1212,6 @@ int cpufreq_governor(unsigned int cpu, unsigned int event) | |||
| 1208 | mutex_unlock(&policy->lock); | 1212 | mutex_unlock(&policy->lock); |
| 1209 | 1213 | ||
| 1210 | cpufreq_cpu_put(policy); | 1214 | cpufreq_cpu_put(policy); |
| 1211 | |||
| 1212 | return ret; | 1215 | return ret; |
| 1213 | } | 1216 | } |
| 1214 | EXPORT_SYMBOL_GPL(cpufreq_governor); | 1217 | EXPORT_SYMBOL_GPL(cpufreq_governor); |
| @@ -1232,7 +1235,6 @@ int cpufreq_register_governor(struct cpufreq_governor *governor) | |||
| 1232 | list_add(&governor->governor_list, &cpufreq_governor_list); | 1235 | list_add(&governor->governor_list, &cpufreq_governor_list); |
| 1233 | 1236 | ||
| 1234 | mutex_unlock(&cpufreq_governor_mutex); | 1237 | mutex_unlock(&cpufreq_governor_mutex); |
| 1235 | |||
| 1236 | return 0; | 1238 | return 0; |
| 1237 | } | 1239 | } |
| 1238 | EXPORT_SYMBOL_GPL(cpufreq_register_governor); | 1240 | EXPORT_SYMBOL_GPL(cpufreq_register_governor); |
| @@ -1277,7 +1279,6 @@ int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu) | |||
| 1277 | mutex_unlock(&cpu_policy->lock); | 1279 | mutex_unlock(&cpu_policy->lock); |
| 1278 | 1280 | ||
| 1279 | cpufreq_cpu_put(cpu_policy); | 1281 | cpufreq_cpu_put(cpu_policy); |
| 1280 | |||
| 1281 | return 0; | 1282 | return 0; |
| 1282 | } | 1283 | } |
| 1283 | EXPORT_SYMBOL(cpufreq_get_policy); | 1284 | EXPORT_SYMBOL(cpufreq_get_policy); |
| @@ -1291,9 +1292,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli | |||
| 1291 | 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, |
| 1292 | policy->min, policy->max); | 1293 | policy->min, policy->max); |
| 1293 | 1294 | ||
| 1294 | memcpy(&policy->cpuinfo, | 1295 | memcpy(&policy->cpuinfo, &data->cpuinfo, sizeof(struct cpufreq_cpuinfo)); |
| 1295 | &data->cpuinfo, | ||
| 1296 | sizeof(struct cpufreq_cpuinfo)); | ||
| 1297 | 1296 | ||
| 1298 | /* verify the cpu speed can be set within this limit */ | 1297 | /* verify the cpu speed can be set within this limit */ |
| 1299 | ret = cpufreq_driver->verify(policy); | 1298 | ret = cpufreq_driver->verify(policy); |
| @@ -1324,8 +1323,8 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli | |||
| 1324 | 1323 | ||
| 1325 | up_read(&cpufreq_notifier_rwsem); | 1324 | up_read(&cpufreq_notifier_rwsem); |
| 1326 | 1325 | ||
| 1327 | data->min = policy->min; | 1326 | data->min = policy->min; |
| 1328 | data->max = policy->max; | 1327 | data->max = policy->max; |
| 1329 | 1328 | ||
| 1330 | 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); |
| 1331 | 1330 | ||
| @@ -1362,7 +1361,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli | |||
| 1362 | __cpufreq_governor(data, CPUFREQ_GOV_LIMITS); | 1361 | __cpufreq_governor(data, CPUFREQ_GOV_LIMITS); |
| 1363 | } | 1362 | } |
| 1364 | 1363 | ||
| 1365 | error_out: | 1364 | error_out: |
| 1366 | cpufreq_debug_enable_ratelimit(); | 1365 | cpufreq_debug_enable_ratelimit(); |
| 1367 | return ret; | 1366 | return ret; |
| 1368 | } | 1367 | } |
| @@ -1421,9 +1420,7 @@ int cpufreq_update_policy(unsigned int cpu) | |||
| 1421 | mutex_lock(&data->lock); | 1420 | mutex_lock(&data->lock); |
| 1422 | 1421 | ||
| 1423 | dprintk("updating policy for CPU %u\n", cpu); | 1422 | dprintk("updating policy for CPU %u\n", cpu); |
| 1424 | memcpy(&policy, | 1423 | memcpy(&policy, data, sizeof(struct cpufreq_policy)); |
| 1425 | data, | ||
| 1426 | sizeof(struct cpufreq_policy)); | ||
| 1427 | policy.min = data->user_policy.min; | 1424 | policy.min = data->user_policy.min; |
| 1428 | policy.max = data->user_policy.max; | 1425 | policy.max = data->user_policy.max; |
| 1429 | policy.policy = data->user_policy.policy; | 1426 | policy.policy = data->user_policy.policy; |
| @@ -1433,8 +1430,13 @@ int cpufreq_update_policy(unsigned int cpu) | |||
| 1433 | -> ask driver for current freq and notify governors about a change */ | 1430 | -> ask driver for current freq and notify governors about a change */ |
| 1434 | if (cpufreq_driver->get) { | 1431 | if (cpufreq_driver->get) { |
| 1435 | policy.cur = cpufreq_driver->get(cpu); | 1432 | policy.cur = cpufreq_driver->get(cpu); |
| 1436 | if (data->cur != policy.cur) | 1433 | if (!data->cur) { |
| 1437 | cpufreq_out_of_sync(cpu, data->cur, policy.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 | } | ||
| 1438 | } | 1440 | } |
| 1439 | 1441 | ||
| 1440 | ret = __cpufreq_set_policy(data, &policy); | 1442 | ret = __cpufreq_set_policy(data, &policy); |
