aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq/intel_pstate.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/cpufreq/intel_pstate.c')
-rw-r--r--drivers/cpufreq/intel_pstate.c67
1 files changed, 37 insertions, 30 deletions
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index eab8ccfe6beb..aebd4572eb6d 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -32,18 +32,16 @@
32#include <asm/msr.h> 32#include <asm/msr.h>
33#include <asm/cpu_device_id.h> 33#include <asm/cpu_device_id.h>
34 34
35#define SAMPLE_COUNT 3
36
37#define BYT_RATIOS 0x66a 35#define BYT_RATIOS 0x66a
38#define BYT_VIDS 0x66b 36#define BYT_VIDS 0x66b
39#define BYT_TURBO_RATIOS 0x66c 37#define BYT_TURBO_RATIOS 0x66c
40#define BYT_TURBO_VIDS 0x66d 38#define BYT_TURBO_VIDS 0x66d
41 39
42 40
43#define FRAC_BITS 6 41#define FRAC_BITS 8
44#define int_tofp(X) ((int64_t)(X) << FRAC_BITS) 42#define int_tofp(X) ((int64_t)(X) << FRAC_BITS)
45#define fp_toint(X) ((X) >> FRAC_BITS) 43#define fp_toint(X) ((X) >> FRAC_BITS)
46#define FP_ROUNDUP(X) ((X) += 1 << FRAC_BITS) 44
47 45
48static inline int32_t mul_fp(int32_t x, int32_t y) 46static inline int32_t mul_fp(int32_t x, int32_t y)
49{ 47{
@@ -59,8 +57,8 @@ struct sample {
59 int32_t core_pct_busy; 57 int32_t core_pct_busy;
60 u64 aperf; 58 u64 aperf;
61 u64 mperf; 59 u64 mperf;
62 unsigned long long tsc;
63 int freq; 60 int freq;
61 ktime_t time;
64}; 62};
65 63
66struct pstate_data { 64struct pstate_data {
@@ -90,17 +88,15 @@ struct _pid {
90struct cpudata { 88struct cpudata {
91 int cpu; 89 int cpu;
92 90
93 char name[64];
94
95 struct timer_list timer; 91 struct timer_list timer;
96 92
97 struct pstate_data pstate; 93 struct pstate_data pstate;
98 struct vid_data vid; 94 struct vid_data vid;
99 struct _pid pid; 95 struct _pid pid;
100 96
97 ktime_t last_sample_time;
101 u64 prev_aperf; 98 u64 prev_aperf;
102 u64 prev_mperf; 99 u64 prev_mperf;
103 unsigned long long prev_tsc;
104 struct sample sample; 100 struct sample sample;
105}; 101};
106 102
@@ -200,7 +196,10 @@ static signed int pid_calc(struct _pid *pid, int32_t busy)
200 pid->last_err = fp_error; 196 pid->last_err = fp_error;
201 197
202 result = pterm + mul_fp(pid->integral, pid->i_gain) + dterm; 198 result = pterm + mul_fp(pid->integral, pid->i_gain) + dterm;
203 199 if (result >= 0)
200 result = result + (1 << (FRAC_BITS-1));
201 else
202 result = result - (1 << (FRAC_BITS-1));
204 return (signed int)fp_toint(result); 203 return (signed int)fp_toint(result);
205} 204}
206 205
@@ -546,8 +545,6 @@ static inline void intel_pstate_pstate_decrease(struct cpudata *cpu, int steps)
546 545
547static void intel_pstate_get_cpu_pstates(struct cpudata *cpu) 546static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
548{ 547{
549 sprintf(cpu->name, "Intel 2nd generation core");
550
551 cpu->pstate.min_pstate = pstate_funcs.get_min(); 548 cpu->pstate.min_pstate = pstate_funcs.get_min();
552 cpu->pstate.max_pstate = pstate_funcs.get_max(); 549 cpu->pstate.max_pstate = pstate_funcs.get_max();
553 cpu->pstate.turbo_pstate = pstate_funcs.get_turbo(); 550 cpu->pstate.turbo_pstate = pstate_funcs.get_turbo();
@@ -557,50 +554,45 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
557 intel_pstate_set_pstate(cpu, cpu->pstate.min_pstate); 554 intel_pstate_set_pstate(cpu, cpu->pstate.min_pstate);
558} 555}
559 556
560static inline void intel_pstate_calc_busy(struct cpudata *cpu, 557static inline void intel_pstate_calc_busy(struct cpudata *cpu)
561 struct sample *sample)
562{ 558{
563 int32_t core_pct; 559 struct sample *sample = &cpu->sample;
564 int32_t c0_pct; 560 int64_t core_pct;
561 int32_t rem;
565 562
566 core_pct = div_fp(int_tofp((sample->aperf)), 563 core_pct = int_tofp(sample->aperf) * int_tofp(100);
567 int_tofp((sample->mperf))); 564 core_pct = div_u64_rem(core_pct, int_tofp(sample->mperf), &rem);
568 core_pct = mul_fp(core_pct, int_tofp(100));
569 FP_ROUNDUP(core_pct);
570 565
571 c0_pct = div_fp(int_tofp(sample->mperf), int_tofp(sample->tsc)); 566 if ((rem << 1) >= int_tofp(sample->mperf))
567 core_pct += 1;
572 568
573 sample->freq = fp_toint( 569 sample->freq = fp_toint(
574 mul_fp(int_tofp(cpu->pstate.max_pstate * 1000), core_pct)); 570 mul_fp(int_tofp(cpu->pstate.max_pstate * 1000), core_pct));
575 571
576 sample->core_pct_busy = mul_fp(core_pct, c0_pct); 572 sample->core_pct_busy = (int32_t)core_pct;
577} 573}
578 574
579static inline void intel_pstate_sample(struct cpudata *cpu) 575static inline void intel_pstate_sample(struct cpudata *cpu)
580{ 576{
581 u64 aperf, mperf; 577 u64 aperf, mperf;
582 unsigned long long tsc;
583 578
584 rdmsrl(MSR_IA32_APERF, aperf); 579 rdmsrl(MSR_IA32_APERF, aperf);
585 rdmsrl(MSR_IA32_MPERF, mperf); 580 rdmsrl(MSR_IA32_MPERF, mperf);
586 tsc = native_read_tsc();
587 581
588 aperf = aperf >> FRAC_BITS; 582 aperf = aperf >> FRAC_BITS;
589 mperf = mperf >> FRAC_BITS; 583 mperf = mperf >> FRAC_BITS;
590 tsc = tsc >> FRAC_BITS;
591 584
585 cpu->last_sample_time = cpu->sample.time;
586 cpu->sample.time = ktime_get();
592 cpu->sample.aperf = aperf; 587 cpu->sample.aperf = aperf;
593 cpu->sample.mperf = mperf; 588 cpu->sample.mperf = mperf;
594 cpu->sample.tsc = tsc;
595 cpu->sample.aperf -= cpu->prev_aperf; 589 cpu->sample.aperf -= cpu->prev_aperf;
596 cpu->sample.mperf -= cpu->prev_mperf; 590 cpu->sample.mperf -= cpu->prev_mperf;
597 cpu->sample.tsc -= cpu->prev_tsc;
598 591
599 intel_pstate_calc_busy(cpu, &cpu->sample); 592 intel_pstate_calc_busy(cpu);
600 593
601 cpu->prev_aperf = aperf; 594 cpu->prev_aperf = aperf;
602 cpu->prev_mperf = mperf; 595 cpu->prev_mperf = mperf;
603 cpu->prev_tsc = tsc;
604} 596}
605 597
606static inline void intel_pstate_set_sample_time(struct cpudata *cpu) 598static inline void intel_pstate_set_sample_time(struct cpudata *cpu)
@@ -614,13 +606,25 @@ static inline void intel_pstate_set_sample_time(struct cpudata *cpu)
614 606
615static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu) 607static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu)
616{ 608{
617 int32_t core_busy, max_pstate, current_pstate; 609 int32_t core_busy, max_pstate, current_pstate, sample_ratio;
610 u32 duration_us;
611 u32 sample_time;
618 612
619 core_busy = cpu->sample.core_pct_busy; 613 core_busy = cpu->sample.core_pct_busy;
620 max_pstate = int_tofp(cpu->pstate.max_pstate); 614 max_pstate = int_tofp(cpu->pstate.max_pstate);
621 current_pstate = int_tofp(cpu->pstate.current_pstate); 615 current_pstate = int_tofp(cpu->pstate.current_pstate);
622 core_busy = mul_fp(core_busy, div_fp(max_pstate, current_pstate)); 616 core_busy = mul_fp(core_busy, div_fp(max_pstate, current_pstate));
623 return FP_ROUNDUP(core_busy); 617
618 sample_time = (pid_params.sample_rate_ms * USEC_PER_MSEC);
619 duration_us = (u32) ktime_us_delta(cpu->sample.time,
620 cpu->last_sample_time);
621 if (duration_us > sample_time * 3) {
622 sample_ratio = div_fp(int_tofp(sample_time),
623 int_tofp(duration_us));
624 core_busy = mul_fp(core_busy, sample_ratio);
625 }
626
627 return core_busy;
624} 628}
625 629
626static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu) 630static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu)
@@ -674,10 +678,13 @@ static const struct x86_cpu_id intel_pstate_cpu_ids[] = {
674 ICPU(0x37, byt_params), 678 ICPU(0x37, byt_params),
675 ICPU(0x3a, core_params), 679 ICPU(0x3a, core_params),
676 ICPU(0x3c, core_params), 680 ICPU(0x3c, core_params),
681 ICPU(0x3d, core_params),
677 ICPU(0x3e, core_params), 682 ICPU(0x3e, core_params),
678 ICPU(0x3f, core_params), 683 ICPU(0x3f, core_params),
679 ICPU(0x45, core_params), 684 ICPU(0x45, core_params),
680 ICPU(0x46, core_params), 685 ICPU(0x46, core_params),
686 ICPU(0x4f, core_params),
687 ICPU(0x56, core_params),
681 {} 688 {}
682}; 689};
683MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids); 690MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids);