Commit b27580b05e6f5253228debc60b8ff4a786ff573a
Committed by
Rafael J. Wysocki
1 parent
c034871712
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
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>
Showing 1 changed file with 36 additions and 6 deletions Side-by-side Diff
drivers/cpufreq/intel_pstate.c
... | ... | @@ -64,6 +64,7 @@ |
64 | 64 | int current_pstate; |
65 | 65 | int min_pstate; |
66 | 66 | int max_pstate; |
67 | + int scaling; | |
67 | 68 | int turbo_pstate; |
68 | 69 | }; |
69 | 70 | |
... | ... | @@ -113,6 +114,7 @@ |
113 | 114 | int (*get_max)(void); |
114 | 115 | int (*get_min)(void); |
115 | 116 | int (*get_turbo)(void); |
117 | + int (*get_scaling)(void); | |
116 | 118 | void (*set)(struct cpudata*, int pstate); |
117 | 119 | void (*get_vid)(struct cpudata *); |
118 | 120 | }; |
... | ... | @@ -433,6 +435,22 @@ |
433 | 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 | 454 | static void byt_get_vid(struct cpudata *cpudata) |
437 | 455 | { |
438 | 456 | u64 value; |
... | ... | @@ -478,6 +496,11 @@ |
478 | 496 | return ret; |
479 | 497 | } |
480 | 498 | |
499 | +static inline int core_get_scaling(void) | |
500 | +{ | |
501 | + return 100000; | |
502 | +} | |
503 | + | |
481 | 504 | static void core_set_pstate(struct cpudata *cpudata, int pstate) |
482 | 505 | { |
483 | 506 | u64 val; |
... | ... | @@ -502,6 +525,7 @@ |
502 | 525 | .get_max = core_get_max_pstate, |
503 | 526 | .get_min = core_get_min_pstate, |
504 | 527 | .get_turbo = core_get_turbo_pstate, |
528 | + .get_scaling = core_get_scaling, | |
505 | 529 | .set = core_set_pstate, |
506 | 530 | }, |
507 | 531 | }; |
... | ... | @@ -520,6 +544,7 @@ |
520 | 544 | .get_min = byt_get_min_pstate, |
521 | 545 | .get_turbo = byt_get_turbo_pstate, |
522 | 546 | .set = byt_set_pstate, |
547 | + .get_scaling = byt_get_scaling, | |
523 | 548 | .get_vid = byt_get_vid, |
524 | 549 | }, |
525 | 550 | }; |
... | ... | @@ -554,7 +579,7 @@ |
554 | 579 | if (pstate == cpu->pstate.current_pstate) |
555 | 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 | 584 | cpu->pstate.current_pstate = pstate; |
560 | 585 | |
... | ... | @@ -566,6 +591,7 @@ |
566 | 591 | cpu->pstate.min_pstate = pstate_funcs.get_min(); |
567 | 592 | cpu->pstate.max_pstate = pstate_funcs.get_max(); |
568 | 593 | cpu->pstate.turbo_pstate = pstate_funcs.get_turbo(); |
594 | + cpu->pstate.scaling = pstate_funcs.get_scaling(); | |
569 | 595 | |
570 | 596 | if (pstate_funcs.get_vid) |
571 | 597 | pstate_funcs.get_vid(cpu); |
... | ... | @@ -581,7 +607,9 @@ |
581 | 607 | core_pct = div64_u64(core_pct, int_tofp(sample->mperf)); |
582 | 608 | |
583 | 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 | 614 | sample->core_pct_busy = (int32_t)core_pct; |
587 | 615 | } |
588 | 616 | |
... | ... | @@ -803,12 +831,13 @@ |
803 | 831 | else |
804 | 832 | policy->policy = CPUFREQ_POLICY_POWERSAVE; |
805 | 833 | |
806 | - policy->min = cpu->pstate.min_pstate * 100000; | |
807 | - policy->max = cpu->pstate.turbo_pstate * 100000; | |
834 | + policy->min = cpu->pstate.min_pstate * cpu->pstate.scaling; | |
835 | + policy->max = cpu->pstate.turbo_pstate * cpu->pstate.scaling; | |
808 | 836 | |
809 | 837 | /* cpuinfo and default policy values */ |
810 | - policy->cpuinfo.min_freq = cpu->pstate.min_pstate * 100000; | |
811 | - policy->cpuinfo.max_freq = cpu->pstate.turbo_pstate * 100000; | |
838 | + policy->cpuinfo.min_freq = cpu->pstate.min_pstate * cpu->pstate.scaling; | |
839 | + policy->cpuinfo.max_freq = | |
840 | + cpu->pstate.turbo_pstate * cpu->pstate.scaling; | |
812 | 841 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; |
813 | 842 | cpumask_set_cpu(policy->cpu, policy->cpus); |
814 | 843 | |
... | ... | @@ -866,6 +895,7 @@ |
866 | 895 | pstate_funcs.get_max = funcs->get_max; |
867 | 896 | pstate_funcs.get_min = funcs->get_min; |
868 | 897 | pstate_funcs.get_turbo = funcs->get_turbo; |
898 | + pstate_funcs.get_scaling = funcs->get_scaling; | |
869 | 899 | pstate_funcs.set = funcs->set; |
870 | 900 | pstate_funcs.get_vid = funcs->get_vid; |
871 | 901 | } |