diff options
-rw-r--r-- | arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c | 85 |
1 files changed, 51 insertions, 34 deletions
diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c index 470c016cb254..ca2ac13b7af2 100644 --- a/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c +++ b/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c | |||
@@ -28,7 +28,8 @@ | |||
28 | #define PFX "speedstep-centrino: " | 28 | #define PFX "speedstep-centrino: " |
29 | #define MAINTAINER "cpufreq@lists.linux.org.uk" | 29 | #define MAINTAINER "cpufreq@lists.linux.org.uk" |
30 | 30 | ||
31 | #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-centrino", msg) | 31 | #define dprintk(msg...) \ |
32 | cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-centrino", msg) | ||
32 | 33 | ||
33 | #define INTEL_MSR_RANGE (0xffff) | 34 | #define INTEL_MSR_RANGE (0xffff) |
34 | 35 | ||
@@ -66,11 +67,12 @@ struct cpu_model | |||
66 | 67 | ||
67 | struct cpufreq_frequency_table *op_points; /* clock/voltage pairs */ | 68 | struct cpufreq_frequency_table *op_points; /* clock/voltage pairs */ |
68 | }; | 69 | }; |
69 | static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c, const struct cpu_id *x); | 70 | static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c, |
71 | const struct cpu_id *x); | ||
70 | 72 | ||
71 | /* Operating points for current CPU */ | 73 | /* Operating points for current CPU */ |
72 | static struct cpu_model *centrino_model[NR_CPUS]; | 74 | static DEFINE_PER_CPU(struct cpu_model *, centrino_model); |
73 | static const struct cpu_id *centrino_cpu[NR_CPUS]; | 75 | static DEFINE_PER_CPU(const struct cpu_id *, centrino_cpu); |
74 | 76 | ||
75 | static struct cpufreq_driver centrino_driver; | 77 | static struct cpufreq_driver centrino_driver; |
76 | 78 | ||
@@ -255,7 +257,7 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy) | |||
255 | return -ENOENT; | 257 | return -ENOENT; |
256 | } | 258 | } |
257 | 259 | ||
258 | centrino_model[policy->cpu] = model; | 260 | per_cpu(centrino_model, policy->cpu) = model; |
259 | 261 | ||
260 | dprintk("found \"%s\": max frequency: %dkHz\n", | 262 | dprintk("found \"%s\": max frequency: %dkHz\n", |
261 | model->model_name, model->max_freq); | 263 | model->model_name, model->max_freq); |
@@ -264,10 +266,14 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy) | |||
264 | } | 266 | } |
265 | 267 | ||
266 | #else | 268 | #else |
267 | static inline int centrino_cpu_init_table(struct cpufreq_policy *policy) { return -ENODEV; } | 269 | static inline int centrino_cpu_init_table(struct cpufreq_policy *policy) |
270 | { | ||
271 | return -ENODEV; | ||
272 | } | ||
268 | #endif /* CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE */ | 273 | #endif /* CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE */ |
269 | 274 | ||
270 | static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c, const struct cpu_id *x) | 275 | static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c, |
276 | const struct cpu_id *x) | ||
271 | { | 277 | { |
272 | if ((c->x86 == x->x86) && | 278 | if ((c->x86 == x->x86) && |
273 | (c->x86_model == x->x86_model) && | 279 | (c->x86_model == x->x86_model) && |
@@ -286,23 +292,28 @@ static unsigned extract_clock(unsigned msr, unsigned int cpu, int failsafe) | |||
286 | * for centrino, as some DSDTs are buggy. | 292 | * for centrino, as some DSDTs are buggy. |
287 | * Ideally, this can be done using the acpi_data structure. | 293 | * Ideally, this can be done using the acpi_data structure. |
288 | */ | 294 | */ |
289 | if ((centrino_cpu[cpu] == &cpu_ids[CPU_BANIAS]) || | 295 | if ((per_cpu(centrino_cpu, cpu) == &cpu_ids[CPU_BANIAS]) || |
290 | (centrino_cpu[cpu] == &cpu_ids[CPU_DOTHAN_A1]) || | 296 | (per_cpu(centrino_cpu, cpu) == &cpu_ids[CPU_DOTHAN_A1]) || |
291 | (centrino_cpu[cpu] == &cpu_ids[CPU_DOTHAN_B0])) { | 297 | (per_cpu(centrino_cpu, cpu) == &cpu_ids[CPU_DOTHAN_B0])) { |
292 | msr = (msr >> 8) & 0xff; | 298 | msr = (msr >> 8) & 0xff; |
293 | return msr * 100000; | 299 | return msr * 100000; |
294 | } | 300 | } |
295 | 301 | ||
296 | if ((!centrino_model[cpu]) || (!centrino_model[cpu]->op_points)) | 302 | if ((!per_cpu(centrino_model, cpu)) || |
303 | (!per_cpu(centrino_model, cpu)->op_points)) | ||
297 | return 0; | 304 | return 0; |
298 | 305 | ||
299 | msr &= 0xffff; | 306 | msr &= 0xffff; |
300 | for (i=0;centrino_model[cpu]->op_points[i].frequency != CPUFREQ_TABLE_END; i++) { | 307 | for (i = 0; |
301 | if (msr == centrino_model[cpu]->op_points[i].index) | 308 | per_cpu(centrino_model, cpu)->op_points[i].frequency |
302 | return centrino_model[cpu]->op_points[i].frequency; | 309 | != CPUFREQ_TABLE_END; |
310 | i++) { | ||
311 | if (msr == per_cpu(centrino_model, cpu)->op_points[i].index) | ||
312 | return per_cpu(centrino_model, cpu)-> | ||
313 | op_points[i].frequency; | ||
303 | } | 314 | } |
304 | if (failsafe) | 315 | if (failsafe) |
305 | return centrino_model[cpu]->op_points[i-1].frequency; | 316 | return per_cpu(centrino_model, cpu)->op_points[i-1].frequency; |
306 | else | 317 | else |
307 | return 0; | 318 | return 0; |
308 | } | 319 | } |
@@ -348,7 +359,8 @@ static int centrino_cpu_init(struct cpufreq_policy *policy) | |||
348 | int i; | 359 | int i; |
349 | 360 | ||
350 | /* Only Intel makes Enhanced Speedstep-capable CPUs */ | 361 | /* Only Intel makes Enhanced Speedstep-capable CPUs */ |
351 | if (cpu->x86_vendor != X86_VENDOR_INTEL || !cpu_has(cpu, X86_FEATURE_EST)) | 362 | if (cpu->x86_vendor != X86_VENDOR_INTEL || |
363 | !cpu_has(cpu, X86_FEATURE_EST)) | ||
352 | return -ENODEV; | 364 | return -ENODEV; |
353 | 365 | ||
354 | if (cpu_has(cpu, X86_FEATURE_CONSTANT_TSC)) | 366 | if (cpu_has(cpu, X86_FEATURE_CONSTANT_TSC)) |
@@ -362,9 +374,9 @@ static int centrino_cpu_init(struct cpufreq_policy *policy) | |||
362 | break; | 374 | break; |
363 | 375 | ||
364 | if (i != N_IDS) | 376 | if (i != N_IDS) |
365 | centrino_cpu[policy->cpu] = &cpu_ids[i]; | 377 | per_cpu(centrino_cpu, policy->cpu) = &cpu_ids[i]; |
366 | 378 | ||
367 | if (!centrino_cpu[policy->cpu]) { | 379 | if (!per_cpu(centrino_cpu, policy->cpu)) { |
368 | dprintk("found unsupported CPU with " | 380 | dprintk("found unsupported CPU with " |
369 | "Enhanced SpeedStep: send /proc/cpuinfo to " | 381 | "Enhanced SpeedStep: send /proc/cpuinfo to " |
370 | MAINTAINER "\n"); | 382 | MAINTAINER "\n"); |
@@ -387,23 +399,26 @@ static int centrino_cpu_init(struct cpufreq_policy *policy) | |||
387 | /* check to see if it stuck */ | 399 | /* check to see if it stuck */ |
388 | rdmsr(MSR_IA32_MISC_ENABLE, l, h); | 400 | rdmsr(MSR_IA32_MISC_ENABLE, l, h); |
389 | if (!(l & (1<<16))) { | 401 | if (!(l & (1<<16))) { |
390 | printk(KERN_INFO PFX "couldn't enable Enhanced SpeedStep\n"); | 402 | printk(KERN_INFO PFX |
403 | "couldn't enable Enhanced SpeedStep\n"); | ||
391 | return -ENODEV; | 404 | return -ENODEV; |
392 | } | 405 | } |
393 | } | 406 | } |
394 | 407 | ||
395 | freq = get_cur_freq(policy->cpu); | 408 | freq = get_cur_freq(policy->cpu); |
396 | 409 | policy->cpuinfo.transition_latency = 10000; | |
397 | policy->cpuinfo.transition_latency = 10000; /* 10uS transition latency */ | 410 | /* 10uS transition latency */ |
398 | policy->cur = freq; | 411 | policy->cur = freq; |
399 | 412 | ||
400 | dprintk("centrino_cpu_init: cur=%dkHz\n", policy->cur); | 413 | dprintk("centrino_cpu_init: cur=%dkHz\n", policy->cur); |
401 | 414 | ||
402 | ret = cpufreq_frequency_table_cpuinfo(policy, centrino_model[policy->cpu]->op_points); | 415 | ret = cpufreq_frequency_table_cpuinfo(policy, |
416 | per_cpu(centrino_model, policy->cpu)->op_points); | ||
403 | if (ret) | 417 | if (ret) |
404 | return (ret); | 418 | return (ret); |
405 | 419 | ||
406 | cpufreq_frequency_table_get_attr(centrino_model[policy->cpu]->op_points, policy->cpu); | 420 | cpufreq_frequency_table_get_attr( |
421 | per_cpu(centrino_model, policy->cpu)->op_points, policy->cpu); | ||
407 | 422 | ||
408 | return 0; | 423 | return 0; |
409 | } | 424 | } |
@@ -412,12 +427,12 @@ static int centrino_cpu_exit(struct cpufreq_policy *policy) | |||
412 | { | 427 | { |
413 | unsigned int cpu = policy->cpu; | 428 | unsigned int cpu = policy->cpu; |
414 | 429 | ||
415 | if (!centrino_model[cpu]) | 430 | if (!per_cpu(centrino_model, cpu)) |
416 | return -ENODEV; | 431 | return -ENODEV; |
417 | 432 | ||
418 | cpufreq_frequency_table_put_attr(cpu); | 433 | cpufreq_frequency_table_put_attr(cpu); |
419 | 434 | ||
420 | centrino_model[cpu] = NULL; | 435 | per_cpu(centrino_model, cpu) = NULL; |
421 | 436 | ||
422 | return 0; | 437 | return 0; |
423 | } | 438 | } |
@@ -431,14 +446,16 @@ static int centrino_cpu_exit(struct cpufreq_policy *policy) | |||
431 | */ | 446 | */ |
432 | static int centrino_verify (struct cpufreq_policy *policy) | 447 | static int centrino_verify (struct cpufreq_policy *policy) |
433 | { | 448 | { |
434 | return cpufreq_frequency_table_verify(policy, centrino_model[policy->cpu]->op_points); | 449 | return cpufreq_frequency_table_verify(policy, |
450 | per_cpu(centrino_model, policy->cpu)->op_points); | ||
435 | } | 451 | } |
436 | 452 | ||
437 | /** | 453 | /** |
438 | * centrino_setpolicy - set a new CPUFreq policy | 454 | * centrino_setpolicy - set a new CPUFreq policy |
439 | * @policy: new policy | 455 | * @policy: new policy |
440 | * @target_freq: the target frequency | 456 | * @target_freq: the target frequency |
441 | * @relation: how that frequency relates to achieved frequency (CPUFREQ_RELATION_L or CPUFREQ_RELATION_H) | 457 | * @relation: how that frequency relates to achieved frequency |
458 | * (CPUFREQ_RELATION_L or CPUFREQ_RELATION_H) | ||
442 | * | 459 | * |
443 | * Sets a new CPUFreq policy. | 460 | * Sets a new CPUFreq policy. |
444 | */ | 461 | */ |
@@ -459,21 +476,21 @@ static int centrino_target (struct cpufreq_policy *policy, | |||
459 | int retval = 0; | 476 | int retval = 0; |
460 | unsigned int j, k, first_cpu, tmp; | 477 | unsigned int j, k, first_cpu, tmp; |
461 | CPUMASK_ALLOC(allmasks); | 478 | CPUMASK_ALLOC(allmasks); |
462 | CPUMASK_VAR(online_policy_cpus, allmasks); | 479 | CPUMASK_PTR(online_policy_cpus, allmasks); |
463 | CPUMASK_VAR(saved_mask, allmasks); | 480 | CPUMASK_PTR(saved_mask, allmasks); |
464 | CPUMASK_VAR(set_mask, allmasks); | 481 | CPUMASK_PTR(set_mask, allmasks); |
465 | CPUMASK_VAR(covered_cpus, allmasks); | 482 | CPUMASK_PTR(covered_cpus, allmasks); |
466 | 483 | ||
467 | if (unlikely(allmasks == NULL)) | 484 | if (unlikely(allmasks == NULL)) |
468 | return -ENOMEM; | 485 | return -ENOMEM; |
469 | 486 | ||
470 | if (unlikely(centrino_model[cpu] == NULL)) { | 487 | if (unlikely(per_cpu(centrino_model, cpu) == NULL)) { |
471 | retval = -ENODEV; | 488 | retval = -ENODEV; |
472 | goto out; | 489 | goto out; |
473 | } | 490 | } |
474 | 491 | ||
475 | if (unlikely(cpufreq_frequency_table_target(policy, | 492 | if (unlikely(cpufreq_frequency_table_target(policy, |
476 | centrino_model[cpu]->op_points, | 493 | per_cpu(centrino_model, cpu)->op_points, |
477 | target_freq, | 494 | target_freq, |
478 | relation, | 495 | relation, |
479 | &newstate))) { | 496 | &newstate))) { |
@@ -515,7 +532,7 @@ static int centrino_target (struct cpufreq_policy *policy, | |||
515 | break; | 532 | break; |
516 | } | 533 | } |
517 | 534 | ||
518 | msr = centrino_model[cpu]->op_points[newstate].index; | 535 | msr = per_cpu(centrino_model, cpu)->op_points[newstate].index; |
519 | 536 | ||
520 | if (first_cpu) { | 537 | if (first_cpu) { |
521 | rdmsr(MSR_IA32_PERF_CTL, oldmsr, h); | 538 | rdmsr(MSR_IA32_PERF_CTL, oldmsr, h); |