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 | } |