diff options
Diffstat (limited to 'drivers/cpufreq/intel_pstate.c')
-rw-r--r-- | drivers/cpufreq/intel_pstate.c | 67 |
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 | ||
48 | static inline int32_t mul_fp(int32_t x, int32_t y) | 46 | static 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 | ||
66 | struct pstate_data { | 64 | struct pstate_data { |
@@ -90,17 +88,15 @@ struct _pid { | |||
90 | struct cpudata { | 88 | struct 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 | ||
547 | static void intel_pstate_get_cpu_pstates(struct cpudata *cpu) | 546 | static 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 | ||
560 | static inline void intel_pstate_calc_busy(struct cpudata *cpu, | 557 | static 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 | ||
579 | static inline void intel_pstate_sample(struct cpudata *cpu) | 575 | static 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 | ||
606 | static inline void intel_pstate_set_sample_time(struct cpudata *cpu) | 598 | static 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 | ||
615 | static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu) | 607 | static 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 | ||
626 | static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu) | 630 | static 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 | }; |
683 | MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids); | 690 | MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids); |