diff options
Diffstat (limited to 'drivers/cpufreq/intel_pstate.c')
-rw-r--r-- | drivers/cpufreq/intel_pstate.c | 30 |
1 files changed, 17 insertions, 13 deletions
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 7e257b233602..c788abf1c457 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c | |||
@@ -51,12 +51,11 @@ static inline int32_t div_fp(int32_t x, int32_t y) | |||
51 | return div_s64((int64_t)x << FRAC_BITS, (int64_t)y); | 51 | return div_s64((int64_t)x << FRAC_BITS, (int64_t)y); |
52 | } | 52 | } |
53 | 53 | ||
54 | static u64 energy_divisor; | ||
55 | |||
56 | struct sample { | 54 | struct sample { |
57 | int32_t core_pct_busy; | 55 | int32_t core_pct_busy; |
58 | u64 aperf; | 56 | u64 aperf; |
59 | u64 mperf; | 57 | u64 mperf; |
58 | unsigned long long tsc; | ||
60 | int freq; | 59 | int freq; |
61 | }; | 60 | }; |
62 | 61 | ||
@@ -96,6 +95,7 @@ struct cpudata { | |||
96 | 95 | ||
97 | u64 prev_aperf; | 96 | u64 prev_aperf; |
98 | u64 prev_mperf; | 97 | u64 prev_mperf; |
98 | unsigned long long prev_tsc; | ||
99 | int sample_ptr; | 99 | int sample_ptr; |
100 | struct sample samples[SAMPLE_COUNT]; | 100 | struct sample samples[SAMPLE_COUNT]; |
101 | }; | 101 | }; |
@@ -548,30 +548,41 @@ static inline void intel_pstate_calc_busy(struct cpudata *cpu, | |||
548 | struct sample *sample) | 548 | struct sample *sample) |
549 | { | 549 | { |
550 | u64 core_pct; | 550 | u64 core_pct; |
551 | core_pct = div64_u64(int_tofp(sample->aperf * 100), | 551 | u64 c0_pct; |
552 | sample->mperf); | 552 | |
553 | sample->freq = fp_toint(cpu->pstate.max_pstate * core_pct * 1000); | 553 | core_pct = div64_u64(sample->aperf * 100, sample->mperf); |
554 | 554 | ||
555 | sample->core_pct_busy = core_pct; | 555 | c0_pct = div64_u64(sample->mperf * 100, sample->tsc); |
556 | sample->freq = fp_toint( | ||
557 | mul_fp(int_tofp(cpu->pstate.max_pstate), | ||
558 | int_tofp(core_pct * 1000))); | ||
559 | |||
560 | sample->core_pct_busy = mul_fp(int_tofp(core_pct), | ||
561 | div_fp(int_tofp(c0_pct + 1), int_tofp(100))); | ||
556 | } | 562 | } |
557 | 563 | ||
558 | static inline void intel_pstate_sample(struct cpudata *cpu) | 564 | static inline void intel_pstate_sample(struct cpudata *cpu) |
559 | { | 565 | { |
560 | u64 aperf, mperf; | 566 | u64 aperf, mperf; |
567 | unsigned long long tsc; | ||
561 | 568 | ||
562 | rdmsrl(MSR_IA32_APERF, aperf); | 569 | rdmsrl(MSR_IA32_APERF, aperf); |
563 | rdmsrl(MSR_IA32_MPERF, mperf); | 570 | rdmsrl(MSR_IA32_MPERF, mperf); |
571 | tsc = native_read_tsc(); | ||
564 | 572 | ||
565 | cpu->sample_ptr = (cpu->sample_ptr + 1) % SAMPLE_COUNT; | 573 | cpu->sample_ptr = (cpu->sample_ptr + 1) % SAMPLE_COUNT; |
566 | cpu->samples[cpu->sample_ptr].aperf = aperf; | 574 | cpu->samples[cpu->sample_ptr].aperf = aperf; |
567 | cpu->samples[cpu->sample_ptr].mperf = mperf; | 575 | cpu->samples[cpu->sample_ptr].mperf = mperf; |
576 | cpu->samples[cpu->sample_ptr].tsc = tsc; | ||
568 | cpu->samples[cpu->sample_ptr].aperf -= cpu->prev_aperf; | 577 | cpu->samples[cpu->sample_ptr].aperf -= cpu->prev_aperf; |
569 | cpu->samples[cpu->sample_ptr].mperf -= cpu->prev_mperf; | 578 | cpu->samples[cpu->sample_ptr].mperf -= cpu->prev_mperf; |
579 | cpu->samples[cpu->sample_ptr].tsc -= cpu->prev_tsc; | ||
570 | 580 | ||
571 | intel_pstate_calc_busy(cpu, &cpu->samples[cpu->sample_ptr]); | 581 | intel_pstate_calc_busy(cpu, &cpu->samples[cpu->sample_ptr]); |
572 | 582 | ||
573 | cpu->prev_aperf = aperf; | 583 | cpu->prev_aperf = aperf; |
574 | cpu->prev_mperf = mperf; | 584 | cpu->prev_mperf = mperf; |
585 | cpu->prev_tsc = tsc; | ||
575 | } | 586 | } |
576 | 587 | ||
577 | static inline void intel_pstate_set_sample_time(struct cpudata *cpu) | 588 | static inline void intel_pstate_set_sample_time(struct cpudata *cpu) |
@@ -617,12 +628,10 @@ static void intel_pstate_timer_func(unsigned long __data) | |||
617 | { | 628 | { |
618 | struct cpudata *cpu = (struct cpudata *) __data; | 629 | struct cpudata *cpu = (struct cpudata *) __data; |
619 | struct sample *sample; | 630 | struct sample *sample; |
620 | u64 energy; | ||
621 | 631 | ||
622 | intel_pstate_sample(cpu); | 632 | intel_pstate_sample(cpu); |
623 | 633 | ||
624 | sample = &cpu->samples[cpu->sample_ptr]; | 634 | sample = &cpu->samples[cpu->sample_ptr]; |
625 | rdmsrl(MSR_PKG_ENERGY_STATUS, energy); | ||
626 | 635 | ||
627 | intel_pstate_adjust_busy_pstate(cpu); | 636 | intel_pstate_adjust_busy_pstate(cpu); |
628 | 637 | ||
@@ -631,7 +640,6 @@ static void intel_pstate_timer_func(unsigned long __data) | |||
631 | cpu->pstate.current_pstate, | 640 | cpu->pstate.current_pstate, |
632 | sample->mperf, | 641 | sample->mperf, |
633 | sample->aperf, | 642 | sample->aperf, |
634 | div64_u64(energy, energy_divisor), | ||
635 | sample->freq); | 643 | sample->freq); |
636 | 644 | ||
637 | intel_pstate_set_sample_time(cpu); | 645 | intel_pstate_set_sample_time(cpu); |
@@ -913,7 +921,6 @@ static int __init intel_pstate_init(void) | |||
913 | int cpu, rc = 0; | 921 | int cpu, rc = 0; |
914 | const struct x86_cpu_id *id; | 922 | const struct x86_cpu_id *id; |
915 | struct cpu_defaults *cpu_info; | 923 | struct cpu_defaults *cpu_info; |
916 | u64 units; | ||
917 | 924 | ||
918 | if (no_load) | 925 | if (no_load) |
919 | return -ENODEV; | 926 | return -ENODEV; |
@@ -947,9 +954,6 @@ static int __init intel_pstate_init(void) | |||
947 | if (rc) | 954 | if (rc) |
948 | goto out; | 955 | goto out; |
949 | 956 | ||
950 | rdmsrl(MSR_RAPL_POWER_UNIT, units); | ||
951 | energy_divisor = 1 << ((units >> 8) & 0x1f); /* bits{12:8} */ | ||
952 | |||
953 | intel_pstate_debug_expose_params(); | 957 | intel_pstate_debug_expose_params(); |
954 | intel_pstate_sysfs_expose_params(); | 958 | intel_pstate_sysfs_expose_params(); |
955 | 959 | ||