diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2014-03-14 05:26:45 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2014-03-14 05:26:45 -0400 |
commit | 9e294427f6e427dbaf46140303acded06365f53c (patch) | |
tree | 0669100cbd79fe8612463900171c98873d8dc454 /drivers/cpufreq/intel_pstate.c | |
parent | 23600969ff137cf4c3bc9098f77e381de334e3f7 (diff) | |
parent | fa389e220254c69ffae0d403eac4146171062d08 (diff) |
Merge tag 'v3.14-rc6' into devel
Linux 3.14-rc6
Diffstat (limited to 'drivers/cpufreq/intel_pstate.c')
-rw-r--r-- | drivers/cpufreq/intel_pstate.c | 61 |
1 files changed, 41 insertions, 20 deletions
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 7e257b233602..2cd36b9297f3 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c | |||
@@ -34,12 +34,15 @@ | |||
34 | 34 | ||
35 | #define SAMPLE_COUNT 3 | 35 | #define SAMPLE_COUNT 3 |
36 | 36 | ||
37 | #define BYT_RATIOS 0x66a | 37 | #define BYT_RATIOS 0x66a |
38 | #define BYT_VIDS 0x66b | 38 | #define BYT_VIDS 0x66b |
39 | #define BYT_TURBO_RATIOS 0x66c | ||
39 | 40 | ||
40 | #define FRAC_BITS 8 | 41 | |
42 | #define FRAC_BITS 6 | ||
41 | #define int_tofp(X) ((int64_t)(X) << FRAC_BITS) | 43 | #define int_tofp(X) ((int64_t)(X) << FRAC_BITS) |
42 | #define fp_toint(X) ((X) >> FRAC_BITS) | 44 | #define fp_toint(X) ((X) >> FRAC_BITS) |
45 | #define FP_ROUNDUP(X) ((X) += 1 << FRAC_BITS) | ||
43 | 46 | ||
44 | static inline int32_t mul_fp(int32_t x, int32_t y) | 47 | static inline int32_t mul_fp(int32_t x, int32_t y) |
45 | { | 48 | { |
@@ -51,12 +54,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); | 54 | return div_s64((int64_t)x << FRAC_BITS, (int64_t)y); |
52 | } | 55 | } |
53 | 56 | ||
54 | static u64 energy_divisor; | ||
55 | |||
56 | struct sample { | 57 | struct sample { |
57 | int32_t core_pct_busy; | 58 | int32_t core_pct_busy; |
58 | u64 aperf; | 59 | u64 aperf; |
59 | u64 mperf; | 60 | u64 mperf; |
61 | unsigned long long tsc; | ||
60 | int freq; | 62 | int freq; |
61 | }; | 63 | }; |
62 | 64 | ||
@@ -96,6 +98,7 @@ struct cpudata { | |||
96 | 98 | ||
97 | u64 prev_aperf; | 99 | u64 prev_aperf; |
98 | u64 prev_mperf; | 100 | u64 prev_mperf; |
101 | unsigned long long prev_tsc; | ||
99 | int sample_ptr; | 102 | int sample_ptr; |
100 | struct sample samples[SAMPLE_COUNT]; | 103 | struct sample samples[SAMPLE_COUNT]; |
101 | }; | 104 | }; |
@@ -357,7 +360,7 @@ static int byt_get_min_pstate(void) | |||
357 | { | 360 | { |
358 | u64 value; | 361 | u64 value; |
359 | rdmsrl(BYT_RATIOS, value); | 362 | rdmsrl(BYT_RATIOS, value); |
360 | return value & 0xFF; | 363 | return (value >> 8) & 0xFF; |
361 | } | 364 | } |
362 | 365 | ||
363 | static int byt_get_max_pstate(void) | 366 | static int byt_get_max_pstate(void) |
@@ -367,6 +370,13 @@ static int byt_get_max_pstate(void) | |||
367 | return (value >> 16) & 0xFF; | 370 | return (value >> 16) & 0xFF; |
368 | } | 371 | } |
369 | 372 | ||
373 | static int byt_get_turbo_pstate(void) | ||
374 | { | ||
375 | u64 value; | ||
376 | rdmsrl(BYT_TURBO_RATIOS, value); | ||
377 | return value & 0x3F; | ||
378 | } | ||
379 | |||
370 | static void byt_set_pstate(struct cpudata *cpudata, int pstate) | 380 | static void byt_set_pstate(struct cpudata *cpudata, int pstate) |
371 | { | 381 | { |
372 | u64 val; | 382 | u64 val; |
@@ -469,7 +479,7 @@ static struct cpu_defaults byt_params = { | |||
469 | .funcs = { | 479 | .funcs = { |
470 | .get_max = byt_get_max_pstate, | 480 | .get_max = byt_get_max_pstate, |
471 | .get_min = byt_get_min_pstate, | 481 | .get_min = byt_get_min_pstate, |
472 | .get_turbo = byt_get_max_pstate, | 482 | .get_turbo = byt_get_turbo_pstate, |
473 | .set = byt_set_pstate, | 483 | .set = byt_set_pstate, |
474 | .get_vid = byt_get_vid, | 484 | .get_vid = byt_get_vid, |
475 | }, | 485 | }, |
@@ -547,31 +557,48 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu) | |||
547 | static inline void intel_pstate_calc_busy(struct cpudata *cpu, | 557 | static inline void intel_pstate_calc_busy(struct cpudata *cpu, |
548 | struct sample *sample) | 558 | struct sample *sample) |
549 | { | 559 | { |
550 | u64 core_pct; | 560 | int32_t core_pct; |
551 | core_pct = div64_u64(int_tofp(sample->aperf * 100), | 561 | int32_t c0_pct; |
552 | sample->mperf); | 562 | |
553 | sample->freq = fp_toint(cpu->pstate.max_pstate * core_pct * 1000); | 563 | core_pct = div_fp(int_tofp((sample->aperf)), |
564 | int_tofp((sample->mperf))); | ||
565 | core_pct = mul_fp(core_pct, int_tofp(100)); | ||
566 | FP_ROUNDUP(core_pct); | ||
567 | |||
568 | c0_pct = div_fp(int_tofp(sample->mperf), int_tofp(sample->tsc)); | ||
554 | 569 | ||
555 | sample->core_pct_busy = core_pct; | 570 | sample->freq = fp_toint( |
571 | mul_fp(int_tofp(cpu->pstate.max_pstate * 1000), core_pct)); | ||
572 | |||
573 | sample->core_pct_busy = mul_fp(core_pct, c0_pct); | ||
556 | } | 574 | } |
557 | 575 | ||
558 | static inline void intel_pstate_sample(struct cpudata *cpu) | 576 | static inline void intel_pstate_sample(struct cpudata *cpu) |
559 | { | 577 | { |
560 | u64 aperf, mperf; | 578 | u64 aperf, mperf; |
579 | unsigned long long tsc; | ||
561 | 580 | ||
562 | rdmsrl(MSR_IA32_APERF, aperf); | 581 | rdmsrl(MSR_IA32_APERF, aperf); |
563 | rdmsrl(MSR_IA32_MPERF, mperf); | 582 | rdmsrl(MSR_IA32_MPERF, mperf); |
583 | tsc = native_read_tsc(); | ||
584 | |||
585 | aperf = aperf >> FRAC_BITS; | ||
586 | mperf = mperf >> FRAC_BITS; | ||
587 | tsc = tsc >> FRAC_BITS; | ||
564 | 588 | ||
565 | cpu->sample_ptr = (cpu->sample_ptr + 1) % SAMPLE_COUNT; | 589 | cpu->sample_ptr = (cpu->sample_ptr + 1) % SAMPLE_COUNT; |
566 | cpu->samples[cpu->sample_ptr].aperf = aperf; | 590 | cpu->samples[cpu->sample_ptr].aperf = aperf; |
567 | cpu->samples[cpu->sample_ptr].mperf = mperf; | 591 | cpu->samples[cpu->sample_ptr].mperf = mperf; |
592 | cpu->samples[cpu->sample_ptr].tsc = tsc; | ||
568 | cpu->samples[cpu->sample_ptr].aperf -= cpu->prev_aperf; | 593 | cpu->samples[cpu->sample_ptr].aperf -= cpu->prev_aperf; |
569 | cpu->samples[cpu->sample_ptr].mperf -= cpu->prev_mperf; | 594 | cpu->samples[cpu->sample_ptr].mperf -= cpu->prev_mperf; |
595 | cpu->samples[cpu->sample_ptr].tsc -= cpu->prev_tsc; | ||
570 | 596 | ||
571 | intel_pstate_calc_busy(cpu, &cpu->samples[cpu->sample_ptr]); | 597 | intel_pstate_calc_busy(cpu, &cpu->samples[cpu->sample_ptr]); |
572 | 598 | ||
573 | cpu->prev_aperf = aperf; | 599 | cpu->prev_aperf = aperf; |
574 | cpu->prev_mperf = mperf; | 600 | cpu->prev_mperf = mperf; |
601 | cpu->prev_tsc = tsc; | ||
575 | } | 602 | } |
576 | 603 | ||
577 | static inline void intel_pstate_set_sample_time(struct cpudata *cpu) | 604 | static inline void intel_pstate_set_sample_time(struct cpudata *cpu) |
@@ -590,7 +617,8 @@ static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu) | |||
590 | core_busy = cpu->samples[cpu->sample_ptr].core_pct_busy; | 617 | core_busy = cpu->samples[cpu->sample_ptr].core_pct_busy; |
591 | max_pstate = int_tofp(cpu->pstate.max_pstate); | 618 | max_pstate = int_tofp(cpu->pstate.max_pstate); |
592 | current_pstate = int_tofp(cpu->pstate.current_pstate); | 619 | current_pstate = int_tofp(cpu->pstate.current_pstate); |
593 | return mul_fp(core_busy, div_fp(max_pstate, current_pstate)); | 620 | core_busy = mul_fp(core_busy, div_fp(max_pstate, current_pstate)); |
621 | return FP_ROUNDUP(core_busy); | ||
594 | } | 622 | } |
595 | 623 | ||
596 | static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu) | 624 | static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu) |
@@ -617,12 +645,10 @@ static void intel_pstate_timer_func(unsigned long __data) | |||
617 | { | 645 | { |
618 | struct cpudata *cpu = (struct cpudata *) __data; | 646 | struct cpudata *cpu = (struct cpudata *) __data; |
619 | struct sample *sample; | 647 | struct sample *sample; |
620 | u64 energy; | ||
621 | 648 | ||
622 | intel_pstate_sample(cpu); | 649 | intel_pstate_sample(cpu); |
623 | 650 | ||
624 | sample = &cpu->samples[cpu->sample_ptr]; | 651 | sample = &cpu->samples[cpu->sample_ptr]; |
625 | rdmsrl(MSR_PKG_ENERGY_STATUS, energy); | ||
626 | 652 | ||
627 | intel_pstate_adjust_busy_pstate(cpu); | 653 | intel_pstate_adjust_busy_pstate(cpu); |
628 | 654 | ||
@@ -631,7 +657,6 @@ static void intel_pstate_timer_func(unsigned long __data) | |||
631 | cpu->pstate.current_pstate, | 657 | cpu->pstate.current_pstate, |
632 | sample->mperf, | 658 | sample->mperf, |
633 | sample->aperf, | 659 | sample->aperf, |
634 | div64_u64(energy, energy_divisor), | ||
635 | sample->freq); | 660 | sample->freq); |
636 | 661 | ||
637 | intel_pstate_set_sample_time(cpu); | 662 | intel_pstate_set_sample_time(cpu); |
@@ -913,7 +938,6 @@ static int __init intel_pstate_init(void) | |||
913 | int cpu, rc = 0; | 938 | int cpu, rc = 0; |
914 | const struct x86_cpu_id *id; | 939 | const struct x86_cpu_id *id; |
915 | struct cpu_defaults *cpu_info; | 940 | struct cpu_defaults *cpu_info; |
916 | u64 units; | ||
917 | 941 | ||
918 | if (no_load) | 942 | if (no_load) |
919 | return -ENODEV; | 943 | return -ENODEV; |
@@ -947,9 +971,6 @@ static int __init intel_pstate_init(void) | |||
947 | if (rc) | 971 | if (rc) |
948 | goto out; | 972 | goto out; |
949 | 973 | ||
950 | rdmsrl(MSR_RAPL_POWER_UNIT, units); | ||
951 | energy_divisor = 1 << ((units >> 8) & 0x1f); /* bits{12:8} */ | ||
952 | |||
953 | intel_pstate_debug_expose_params(); | 974 | intel_pstate_debug_expose_params(); |
954 | intel_pstate_sysfs_expose_params(); | 975 | intel_pstate_sysfs_expose_params(); |
955 | 976 | ||