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); |
