diff options
| author | Dirk Brandewie <dirk.j.brandewie@intel.com> | 2014-10-13 11:37:43 -0400 |
|---|---|---|
| committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-10-23 16:59:59 -0400 |
| commit | b27580b05e6f5253228debc60b8ff4a786ff573a (patch) | |
| tree | f8bbab8e5f23c465f3886863b227faecdfe1757d /drivers/cpufreq | |
| parent | c034871712730a33e0267095f48b62eae958499c (diff) | |
intel_pstate: Fix BYT frequency reporting
BYT has a different conversion from P state to frequency than the core
processors. This causes the min/max and current frequency to be
misreported on some BYT SKUs. Tested on BYT N2820, Ivybridge and
Haswell processors.
Link: https://bugzilla.yoctoproject.org/show_bug.cgi?id=6663
Cc: All applicable <stable@vger.kernel.org>
Signed-off-by: Dirk Brandewie <dirk.j.brandewie@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/cpufreq')
| -rw-r--r-- | drivers/cpufreq/intel_pstate.c | 42 |
1 files changed, 36 insertions, 6 deletions
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 97b349a6f5c7..98593e0344c5 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c | |||
| @@ -64,6 +64,7 @@ struct pstate_data { | |||
| 64 | int current_pstate; | 64 | int current_pstate; |
| 65 | int min_pstate; | 65 | int min_pstate; |
| 66 | int max_pstate; | 66 | int max_pstate; |
| 67 | int scaling; | ||
| 67 | int turbo_pstate; | 68 | int turbo_pstate; |
| 68 | }; | 69 | }; |
| 69 | 70 | ||
| @@ -113,6 +114,7 @@ struct pstate_funcs { | |||
| 113 | int (*get_max)(void); | 114 | int (*get_max)(void); |
| 114 | int (*get_min)(void); | 115 | int (*get_min)(void); |
| 115 | int (*get_turbo)(void); | 116 | int (*get_turbo)(void); |
| 117 | int (*get_scaling)(void); | ||
| 116 | void (*set)(struct cpudata*, int pstate); | 118 | void (*set)(struct cpudata*, int pstate); |
| 117 | void (*get_vid)(struct cpudata *); | 119 | void (*get_vid)(struct cpudata *); |
| 118 | }; | 120 | }; |
| @@ -433,6 +435,22 @@ static void byt_set_pstate(struct cpudata *cpudata, int pstate) | |||
| 433 | wrmsrl(MSR_IA32_PERF_CTL, val); | 435 | wrmsrl(MSR_IA32_PERF_CTL, val); |
| 434 | } | 436 | } |
| 435 | 437 | ||
| 438 | #define BYT_BCLK_FREQS 5 | ||
| 439 | static int byt_freq_table[BYT_BCLK_FREQS] = { 833, 1000, 1333, 1167, 800}; | ||
| 440 | |||
| 441 | static int byt_get_scaling(void) | ||
| 442 | { | ||
| 443 | u64 value; | ||
| 444 | int i; | ||
| 445 | |||
| 446 | rdmsrl(MSR_FSB_FREQ, value); | ||
| 447 | i = value & 0x3; | ||
| 448 | |||
| 449 | BUG_ON(i > BYT_BCLK_FREQS); | ||
| 450 | |||
| 451 | return byt_freq_table[i] * 100; | ||
| 452 | } | ||
| 453 | |||
| 436 | static void byt_get_vid(struct cpudata *cpudata) | 454 | static void byt_get_vid(struct cpudata *cpudata) |
| 437 | { | 455 | { |
| 438 | u64 value; | 456 | u64 value; |
| @@ -478,6 +496,11 @@ static int core_get_turbo_pstate(void) | |||
| 478 | return ret; | 496 | return ret; |
| 479 | } | 497 | } |
| 480 | 498 | ||
| 499 | static inline int core_get_scaling(void) | ||
| 500 | { | ||
| 501 | return 100000; | ||
| 502 | } | ||
| 503 | |||
| 481 | static void core_set_pstate(struct cpudata *cpudata, int pstate) | 504 | static void core_set_pstate(struct cpudata *cpudata, int pstate) |
| 482 | { | 505 | { |
| 483 | u64 val; | 506 | u64 val; |
| @@ -502,6 +525,7 @@ static struct cpu_defaults core_params = { | |||
| 502 | .get_max = core_get_max_pstate, | 525 | .get_max = core_get_max_pstate, |
| 503 | .get_min = core_get_min_pstate, | 526 | .get_min = core_get_min_pstate, |
| 504 | .get_turbo = core_get_turbo_pstate, | 527 | .get_turbo = core_get_turbo_pstate, |
| 528 | .get_scaling = core_get_scaling, | ||
| 505 | .set = core_set_pstate, | 529 | .set = core_set_pstate, |
| 506 | }, | 530 | }, |
| 507 | }; | 531 | }; |
| @@ -520,6 +544,7 @@ static struct cpu_defaults byt_params = { | |||
| 520 | .get_min = byt_get_min_pstate, | 544 | .get_min = byt_get_min_pstate, |
| 521 | .get_turbo = byt_get_turbo_pstate, | 545 | .get_turbo = byt_get_turbo_pstate, |
| 522 | .set = byt_set_pstate, | 546 | .set = byt_set_pstate, |
| 547 | .get_scaling = byt_get_scaling, | ||
| 523 | .get_vid = byt_get_vid, | 548 | .get_vid = byt_get_vid, |
| 524 | }, | 549 | }, |
| 525 | }; | 550 | }; |
| @@ -554,7 +579,7 @@ static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate) | |||
| 554 | if (pstate == cpu->pstate.current_pstate) | 579 | if (pstate == cpu->pstate.current_pstate) |
| 555 | return; | 580 | return; |
| 556 | 581 | ||
| 557 | trace_cpu_frequency(pstate * 100000, cpu->cpu); | 582 | trace_cpu_frequency(pstate * cpu->pstate.scaling, cpu->cpu); |
| 558 | 583 | ||
| 559 | cpu->pstate.current_pstate = pstate; | 584 | cpu->pstate.current_pstate = pstate; |
| 560 | 585 | ||
| @@ -566,6 +591,7 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu) | |||
| 566 | cpu->pstate.min_pstate = pstate_funcs.get_min(); | 591 | cpu->pstate.min_pstate = pstate_funcs.get_min(); |
| 567 | cpu->pstate.max_pstate = pstate_funcs.get_max(); | 592 | cpu->pstate.max_pstate = pstate_funcs.get_max(); |
| 568 | cpu->pstate.turbo_pstate = pstate_funcs.get_turbo(); | 593 | cpu->pstate.turbo_pstate = pstate_funcs.get_turbo(); |
| 594 | cpu->pstate.scaling = pstate_funcs.get_scaling(); | ||
| 569 | 595 | ||
| 570 | if (pstate_funcs.get_vid) | 596 | if (pstate_funcs.get_vid) |
| 571 | pstate_funcs.get_vid(cpu); | 597 | pstate_funcs.get_vid(cpu); |
| @@ -581,7 +607,9 @@ static inline void intel_pstate_calc_busy(struct cpudata *cpu) | |||
| 581 | core_pct = div64_u64(core_pct, int_tofp(sample->mperf)); | 607 | core_pct = div64_u64(core_pct, int_tofp(sample->mperf)); |
| 582 | 608 | ||
| 583 | sample->freq = fp_toint( | 609 | sample->freq = fp_toint( |
| 584 | mul_fp(int_tofp(cpu->pstate.max_pstate * 1000), core_pct)); | 610 | mul_fp(int_tofp( |
| 611 | cpu->pstate.max_pstate * cpu->pstate.scaling / 100), | ||
| 612 | core_pct)); | ||
| 585 | 613 | ||
| 586 | sample->core_pct_busy = (int32_t)core_pct; | 614 | sample->core_pct_busy = (int32_t)core_pct; |
| 587 | } | 615 | } |
| @@ -803,12 +831,13 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy) | |||
| 803 | else | 831 | else |
| 804 | policy->policy = CPUFREQ_POLICY_POWERSAVE; | 832 | policy->policy = CPUFREQ_POLICY_POWERSAVE; |
| 805 | 833 | ||
| 806 | policy->min = cpu->pstate.min_pstate * 100000; | 834 | policy->min = cpu->pstate.min_pstate * cpu->pstate.scaling; |
| 807 | policy->max = cpu->pstate.turbo_pstate * 100000; | 835 | policy->max = cpu->pstate.turbo_pstate * cpu->pstate.scaling; |
| 808 | 836 | ||
| 809 | /* cpuinfo and default policy values */ | 837 | /* cpuinfo and default policy values */ |
| 810 | policy->cpuinfo.min_freq = cpu->pstate.min_pstate * 100000; | 838 | policy->cpuinfo.min_freq = cpu->pstate.min_pstate * cpu->pstate.scaling; |
| 811 | policy->cpuinfo.max_freq = cpu->pstate.turbo_pstate * 100000; | 839 | policy->cpuinfo.max_freq = |
| 840 | cpu->pstate.turbo_pstate * cpu->pstate.scaling; | ||
| 812 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; | 841 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; |
| 813 | cpumask_set_cpu(policy->cpu, policy->cpus); | 842 | cpumask_set_cpu(policy->cpu, policy->cpus); |
| 814 | 843 | ||
| @@ -866,6 +895,7 @@ static void copy_cpu_funcs(struct pstate_funcs *funcs) | |||
| 866 | pstate_funcs.get_max = funcs->get_max; | 895 | pstate_funcs.get_max = funcs->get_max; |
| 867 | pstate_funcs.get_min = funcs->get_min; | 896 | pstate_funcs.get_min = funcs->get_min; |
| 868 | pstate_funcs.get_turbo = funcs->get_turbo; | 897 | pstate_funcs.get_turbo = funcs->get_turbo; |
| 898 | pstate_funcs.get_scaling = funcs->get_scaling; | ||
| 869 | pstate_funcs.set = funcs->set; | 899 | pstate_funcs.set = funcs->set; |
| 870 | pstate_funcs.get_vid = funcs->get_vid; | 900 | pstate_funcs.get_vid = funcs->get_vid; |
| 871 | } | 901 | } |
