aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq/intel_pstate.c
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2014-03-14 05:26:45 -0400
committerLinus Walleij <linus.walleij@linaro.org>2014-03-14 05:26:45 -0400
commit9e294427f6e427dbaf46140303acded06365f53c (patch)
tree0669100cbd79fe8612463900171c98873d8dc454 /drivers/cpufreq/intel_pstate.c
parent23600969ff137cf4c3bc9098f77e381de334e3f7 (diff)
parentfa389e220254c69ffae0d403eac4146171062d08 (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.c61
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
44static inline int32_t mul_fp(int32_t x, int32_t y) 47static 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
54static u64 energy_divisor;
55
56struct sample { 57struct 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
363static int byt_get_max_pstate(void) 366static 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
373static int byt_get_turbo_pstate(void)
374{
375 u64 value;
376 rdmsrl(BYT_TURBO_RATIOS, value);
377 return value & 0x3F;
378}
379
370static void byt_set_pstate(struct cpudata *cpudata, int pstate) 380static 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)
547static inline void intel_pstate_calc_busy(struct cpudata *cpu, 557static 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
558static inline void intel_pstate_sample(struct cpudata *cpu) 576static 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
577static inline void intel_pstate_set_sample_time(struct cpudata *cpu) 604static 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
596static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu) 624static 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