diff options
Diffstat (limited to 'drivers/cpufreq/intel_pstate.c')
-rw-r--r-- | drivers/cpufreq/intel_pstate.c | 130 |
1 files changed, 107 insertions, 23 deletions
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index d51f17ed691e..2cd36b9297f3 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c | |||
@@ -34,11 +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 | ||
39 | #define BYT_TURBO_RATIOS 0x66c | ||
38 | 40 | ||
39 | #define FRAC_BITS 8 | 41 | |
42 | #define FRAC_BITS 6 | ||
40 | #define int_tofp(X) ((int64_t)(X) << FRAC_BITS) | 43 | #define int_tofp(X) ((int64_t)(X) << FRAC_BITS) |
41 | #define fp_toint(X) ((X) >> FRAC_BITS) | 44 | #define fp_toint(X) ((X) >> FRAC_BITS) |
45 | #define FP_ROUNDUP(X) ((X) += 1 << FRAC_BITS) | ||
42 | 46 | ||
43 | 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) |
44 | { | 48 | { |
@@ -54,6 +58,7 @@ struct sample { | |||
54 | int32_t core_pct_busy; | 58 | int32_t core_pct_busy; |
55 | u64 aperf; | 59 | u64 aperf; |
56 | u64 mperf; | 60 | u64 mperf; |
61 | unsigned long long tsc; | ||
57 | int freq; | 62 | int freq; |
58 | }; | 63 | }; |
59 | 64 | ||
@@ -64,6 +69,12 @@ struct pstate_data { | |||
64 | int turbo_pstate; | 69 | int turbo_pstate; |
65 | }; | 70 | }; |
66 | 71 | ||
72 | struct vid_data { | ||
73 | int32_t min; | ||
74 | int32_t max; | ||
75 | int32_t ratio; | ||
76 | }; | ||
77 | |||
67 | struct _pid { | 78 | struct _pid { |
68 | int setpoint; | 79 | int setpoint; |
69 | int32_t integral; | 80 | int32_t integral; |
@@ -82,12 +93,12 @@ struct cpudata { | |||
82 | struct timer_list timer; | 93 | struct timer_list timer; |
83 | 94 | ||
84 | struct pstate_data pstate; | 95 | struct pstate_data pstate; |
96 | struct vid_data vid; | ||
85 | struct _pid pid; | 97 | struct _pid pid; |
86 | 98 | ||
87 | int min_pstate_count; | ||
88 | |||
89 | u64 prev_aperf; | 99 | u64 prev_aperf; |
90 | u64 prev_mperf; | 100 | u64 prev_mperf; |
101 | unsigned long long prev_tsc; | ||
91 | int sample_ptr; | 102 | int sample_ptr; |
92 | struct sample samples[SAMPLE_COUNT]; | 103 | struct sample samples[SAMPLE_COUNT]; |
93 | }; | 104 | }; |
@@ -106,7 +117,8 @@ struct pstate_funcs { | |||
106 | int (*get_max)(void); | 117 | int (*get_max)(void); |
107 | int (*get_min)(void); | 118 | int (*get_min)(void); |
108 | int (*get_turbo)(void); | 119 | int (*get_turbo)(void); |
109 | void (*set)(int pstate); | 120 | void (*set)(struct cpudata*, int pstate); |
121 | void (*get_vid)(struct cpudata *); | ||
110 | }; | 122 | }; |
111 | 123 | ||
112 | struct cpu_defaults { | 124 | struct cpu_defaults { |
@@ -348,7 +360,7 @@ static int byt_get_min_pstate(void) | |||
348 | { | 360 | { |
349 | u64 value; | 361 | u64 value; |
350 | rdmsrl(BYT_RATIOS, value); | 362 | rdmsrl(BYT_RATIOS, value); |
351 | return value & 0xFF; | 363 | return (value >> 8) & 0xFF; |
352 | } | 364 | } |
353 | 365 | ||
354 | static int byt_get_max_pstate(void) | 366 | static int byt_get_max_pstate(void) |
@@ -358,6 +370,49 @@ static int byt_get_max_pstate(void) | |||
358 | return (value >> 16) & 0xFF; | 370 | return (value >> 16) & 0xFF; |
359 | } | 371 | } |
360 | 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 | |||
380 | static void byt_set_pstate(struct cpudata *cpudata, int pstate) | ||
381 | { | ||
382 | u64 val; | ||
383 | int32_t vid_fp; | ||
384 | u32 vid; | ||
385 | |||
386 | val = pstate << 8; | ||
387 | if (limits.no_turbo) | ||
388 | val |= (u64)1 << 32; | ||
389 | |||
390 | vid_fp = cpudata->vid.min + mul_fp( | ||
391 | int_tofp(pstate - cpudata->pstate.min_pstate), | ||
392 | cpudata->vid.ratio); | ||
393 | |||
394 | vid_fp = clamp_t(int32_t, vid_fp, cpudata->vid.min, cpudata->vid.max); | ||
395 | vid = fp_toint(vid_fp); | ||
396 | |||
397 | val |= vid; | ||
398 | |||
399 | wrmsrl(MSR_IA32_PERF_CTL, val); | ||
400 | } | ||
401 | |||
402 | static void byt_get_vid(struct cpudata *cpudata) | ||
403 | { | ||
404 | u64 value; | ||
405 | |||
406 | rdmsrl(BYT_VIDS, value); | ||
407 | cpudata->vid.min = int_tofp((value >> 8) & 0x7f); | ||
408 | cpudata->vid.max = int_tofp((value >> 16) & 0x7f); | ||
409 | cpudata->vid.ratio = div_fp( | ||
410 | cpudata->vid.max - cpudata->vid.min, | ||
411 | int_tofp(cpudata->pstate.max_pstate - | ||
412 | cpudata->pstate.min_pstate)); | ||
413 | } | ||
414 | |||
415 | |||
361 | static int core_get_min_pstate(void) | 416 | static int core_get_min_pstate(void) |
362 | { | 417 | { |
363 | u64 value; | 418 | u64 value; |
@@ -384,7 +439,7 @@ static int core_get_turbo_pstate(void) | |||
384 | return ret; | 439 | return ret; |
385 | } | 440 | } |
386 | 441 | ||
387 | static void core_set_pstate(int pstate) | 442 | static void core_set_pstate(struct cpudata *cpudata, int pstate) |
388 | { | 443 | { |
389 | u64 val; | 444 | u64 val; |
390 | 445 | ||
@@ -424,8 +479,9 @@ static struct cpu_defaults byt_params = { | |||
424 | .funcs = { | 479 | .funcs = { |
425 | .get_max = byt_get_max_pstate, | 480 | .get_max = byt_get_max_pstate, |
426 | .get_min = byt_get_min_pstate, | 481 | .get_min = byt_get_min_pstate, |
427 | .get_turbo = byt_get_max_pstate, | 482 | .get_turbo = byt_get_turbo_pstate, |
428 | .set = core_set_pstate, | 483 | .set = byt_set_pstate, |
484 | .get_vid = byt_get_vid, | ||
429 | }, | 485 | }, |
430 | }; | 486 | }; |
431 | 487 | ||
@@ -462,7 +518,7 @@ static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate) | |||
462 | 518 | ||
463 | cpu->pstate.current_pstate = pstate; | 519 | cpu->pstate.current_pstate = pstate; |
464 | 520 | ||
465 | pstate_funcs.set(pstate); | 521 | pstate_funcs.set(cpu, pstate); |
466 | } | 522 | } |
467 | 523 | ||
468 | static inline void intel_pstate_pstate_increase(struct cpudata *cpu, int steps) | 524 | static inline void intel_pstate_pstate_increase(struct cpudata *cpu, int steps) |
@@ -488,6 +544,9 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu) | |||
488 | cpu->pstate.max_pstate = pstate_funcs.get_max(); | 544 | cpu->pstate.max_pstate = pstate_funcs.get_max(); |
489 | cpu->pstate.turbo_pstate = pstate_funcs.get_turbo(); | 545 | cpu->pstate.turbo_pstate = pstate_funcs.get_turbo(); |
490 | 546 | ||
547 | if (pstate_funcs.get_vid) | ||
548 | pstate_funcs.get_vid(cpu); | ||
549 | |||
491 | /* | 550 | /* |
492 | * goto max pstate so we don't slow up boot if we are built-in if we are | 551 | * goto max pstate so we don't slow up boot if we are built-in if we are |
493 | * a module we will take care of it during normal operation | 552 | * a module we will take care of it during normal operation |
@@ -498,30 +557,48 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu) | |||
498 | static inline void intel_pstate_calc_busy(struct cpudata *cpu, | 557 | static inline void intel_pstate_calc_busy(struct cpudata *cpu, |
499 | struct sample *sample) | 558 | struct sample *sample) |
500 | { | 559 | { |
501 | u64 core_pct; | 560 | int32_t core_pct; |
502 | core_pct = div64_u64(int_tofp(sample->aperf * 100), | 561 | int32_t c0_pct; |
503 | sample->mperf); | 562 | |
504 | 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)); | ||
505 | 569 | ||
506 | 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); | ||
507 | } | 574 | } |
508 | 575 | ||
509 | static inline void intel_pstate_sample(struct cpudata *cpu) | 576 | static inline void intel_pstate_sample(struct cpudata *cpu) |
510 | { | 577 | { |
511 | u64 aperf, mperf; | 578 | u64 aperf, mperf; |
579 | unsigned long long tsc; | ||
512 | 580 | ||
513 | rdmsrl(MSR_IA32_APERF, aperf); | 581 | rdmsrl(MSR_IA32_APERF, aperf); |
514 | 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; | ||
588 | |||
515 | cpu->sample_ptr = (cpu->sample_ptr + 1) % SAMPLE_COUNT; | 589 | cpu->sample_ptr = (cpu->sample_ptr + 1) % SAMPLE_COUNT; |
516 | cpu->samples[cpu->sample_ptr].aperf = aperf; | 590 | cpu->samples[cpu->sample_ptr].aperf = aperf; |
517 | cpu->samples[cpu->sample_ptr].mperf = mperf; | 591 | cpu->samples[cpu->sample_ptr].mperf = mperf; |
592 | cpu->samples[cpu->sample_ptr].tsc = tsc; | ||
518 | cpu->samples[cpu->sample_ptr].aperf -= cpu->prev_aperf; | 593 | cpu->samples[cpu->sample_ptr].aperf -= cpu->prev_aperf; |
519 | 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; | ||
520 | 596 | ||
521 | intel_pstate_calc_busy(cpu, &cpu->samples[cpu->sample_ptr]); | 597 | intel_pstate_calc_busy(cpu, &cpu->samples[cpu->sample_ptr]); |
522 | 598 | ||
523 | cpu->prev_aperf = aperf; | 599 | cpu->prev_aperf = aperf; |
524 | cpu->prev_mperf = mperf; | 600 | cpu->prev_mperf = mperf; |
601 | cpu->prev_tsc = tsc; | ||
525 | } | 602 | } |
526 | 603 | ||
527 | static inline void intel_pstate_set_sample_time(struct cpudata *cpu) | 604 | static inline void intel_pstate_set_sample_time(struct cpudata *cpu) |
@@ -540,7 +617,8 @@ static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu) | |||
540 | core_busy = cpu->samples[cpu->sample_ptr].core_pct_busy; | 617 | core_busy = cpu->samples[cpu->sample_ptr].core_pct_busy; |
541 | max_pstate = int_tofp(cpu->pstate.max_pstate); | 618 | max_pstate = int_tofp(cpu->pstate.max_pstate); |
542 | current_pstate = int_tofp(cpu->pstate.current_pstate); | 619 | current_pstate = int_tofp(cpu->pstate.current_pstate); |
543 | 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); | ||
544 | } | 622 | } |
545 | 623 | ||
546 | static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu) | 624 | static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu) |
@@ -556,6 +634,7 @@ static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu) | |||
556 | ctl = pid_calc(pid, busy_scaled); | 634 | ctl = pid_calc(pid, busy_scaled); |
557 | 635 | ||
558 | steps = abs(ctl); | 636 | steps = abs(ctl); |
637 | |||
559 | if (ctl < 0) | 638 | if (ctl < 0) |
560 | intel_pstate_pstate_increase(cpu, steps); | 639 | intel_pstate_pstate_increase(cpu, steps); |
561 | else | 640 | else |
@@ -565,17 +644,20 @@ static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu) | |||
565 | static void intel_pstate_timer_func(unsigned long __data) | 644 | static void intel_pstate_timer_func(unsigned long __data) |
566 | { | 645 | { |
567 | struct cpudata *cpu = (struct cpudata *) __data; | 646 | struct cpudata *cpu = (struct cpudata *) __data; |
647 | struct sample *sample; | ||
568 | 648 | ||
569 | intel_pstate_sample(cpu); | 649 | intel_pstate_sample(cpu); |
650 | |||
651 | sample = &cpu->samples[cpu->sample_ptr]; | ||
652 | |||
570 | intel_pstate_adjust_busy_pstate(cpu); | 653 | intel_pstate_adjust_busy_pstate(cpu); |
571 | 654 | ||
572 | if (cpu->pstate.current_pstate == cpu->pstate.min_pstate) { | 655 | trace_pstate_sample(fp_toint(sample->core_pct_busy), |
573 | cpu->min_pstate_count++; | 656 | fp_toint(intel_pstate_get_scaled_busy(cpu)), |
574 | if (!(cpu->min_pstate_count % 5)) { | 657 | cpu->pstate.current_pstate, |
575 | intel_pstate_set_pstate(cpu, cpu->pstate.max_pstate); | 658 | sample->mperf, |
576 | } | 659 | sample->aperf, |
577 | } else | 660 | sample->freq); |
578 | cpu->min_pstate_count = 0; | ||
579 | 661 | ||
580 | intel_pstate_set_sample_time(cpu); | 662 | intel_pstate_set_sample_time(cpu); |
581 | } | 663 | } |
@@ -782,6 +864,7 @@ static void copy_cpu_funcs(struct pstate_funcs *funcs) | |||
782 | pstate_funcs.get_min = funcs->get_min; | 864 | pstate_funcs.get_min = funcs->get_min; |
783 | pstate_funcs.get_turbo = funcs->get_turbo; | 865 | pstate_funcs.get_turbo = funcs->get_turbo; |
784 | pstate_funcs.set = funcs->set; | 866 | pstate_funcs.set = funcs->set; |
867 | pstate_funcs.get_vid = funcs->get_vid; | ||
785 | } | 868 | } |
786 | 869 | ||
787 | #if IS_ENABLED(CONFIG_ACPI) | 870 | #if IS_ENABLED(CONFIG_ACPI) |
@@ -890,6 +973,7 @@ static int __init intel_pstate_init(void) | |||
890 | 973 | ||
891 | intel_pstate_debug_expose_params(); | 974 | intel_pstate_debug_expose_params(); |
892 | intel_pstate_sysfs_expose_params(); | 975 | intel_pstate_sysfs_expose_params(); |
976 | |||
893 | return rc; | 977 | return rc; |
894 | out: | 978 | out: |
895 | get_online_cpus(); | 979 | get_online_cpus(); |