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 @@ #include <asm/msr.h> #include <asm/cpu_device_id.h> -#define SAMPLE_COUNT 3 - #define BYT_RATIOS 0x66a #define BYT_VIDS 0x66b #define BYT_TURBO_RATIOS 0x66c #define BYT_TURBO_VIDS 0x66d -#define FRAC_BITS 6 +#define FRAC_BITS 8 #define int_tofp(X) ((int64_t)(X) << FRAC_BITS) #define fp_toint(X) ((X) >> FRAC_BITS) -#define FP_ROUNDUP(X) ((X) += 1 << FRAC_BITS) + static inline int32_t mul_fp(int32_t x, int32_t y) { @@ -59,8 +57,8 @@ struct sample { int32_t core_pct_busy; u64 aperf; u64 mperf; - unsigned long long tsc; int freq; + ktime_t time; }; struct pstate_data { @@ -90,17 +88,15 @@ struct _pid { struct cpudata { int cpu; - char name[64]; - struct timer_list timer; struct pstate_data pstate; struct vid_data vid; struct _pid pid; + ktime_t last_sample_time; u64 prev_aperf; u64 prev_mperf; - unsigned long long prev_tsc; struct sample sample; }; @@ -200,7 +196,10 @@ static signed int pid_calc(struct _pid *pid, int32_t busy) pid->last_err = fp_error; result = pterm + mul_fp(pid->integral, pid->i_gain) + dterm; - + if (result >= 0) + result = result + (1 << (FRAC_BITS-1)); + else + result = result - (1 << (FRAC_BITS-1)); return (signed int)fp_toint(result); } @@ -546,8 +545,6 @@ static inline void intel_pstate_pstate_decrease(struct cpudata *cpu, int steps) static void intel_pstate_get_cpu_pstates(struct cpudata *cpu) { - sprintf(cpu->name, "Intel 2nd generation core"); - cpu->pstate.min_pstate = pstate_funcs.get_min(); cpu->pstate.max_pstate = pstate_funcs.get_max(); cpu->pstate.turbo_pstate = pstate_funcs.get_turbo(); @@ -557,50 +554,45 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu) intel_pstate_set_pstate(cpu, cpu->pstate.min_pstate); } -static inline void intel_pstate_calc_busy(struct cpudata *cpu, - struct sample *sample) +static inline void intel_pstate_calc_busy(struct cpudata *cpu) { - int32_t core_pct; - int32_t c0_pct; + struct sample *sample = &cpu->sample; + int64_t core_pct; + int32_t rem; - core_pct = div_fp(int_tofp((sample->aperf)), - int_tofp((sample->mperf))); - core_pct = mul_fp(core_pct, int_tofp(100)); - FP_ROUNDUP(core_pct); + core_pct = int_tofp(sample->aperf) * int_tofp(100); + core_pct = div_u64_rem(core_pct, int_tofp(sample->mperf), &rem); - c0_pct = div_fp(int_tofp(sample->mperf), int_tofp(sample->tsc)); + if ((rem << 1) >= int_tofp(sample->mperf)) + core_pct += 1; sample->freq = fp_toint( mul_fp(int_tofp(cpu->pstate.max_pstate * 1000), core_pct)); - sample->core_pct_busy = mul_fp(core_pct, c0_pct); + sample->core_pct_busy = (int32_t)core_pct; } static inline void intel_pstate_sample(struct cpudata *cpu) { u64 aperf, mperf; - unsigned long long tsc; rdmsrl(MSR_IA32_APERF, aperf); rdmsrl(MSR_IA32_MPERF, mperf); - tsc = native_read_tsc(); aperf = aperf >> FRAC_BITS; mperf = mperf >> FRAC_BITS; - tsc = tsc >> FRAC_BITS; + cpu->last_sample_time = cpu->sample.time; + cpu->sample.time = ktime_get(); cpu->sample.aperf = aperf; cpu->sample.mperf = mperf; - cpu->sample.tsc = tsc; cpu->sample.aperf -= cpu->prev_aperf; cpu->sample.mperf -= cpu->prev_mperf; - cpu->sample.tsc -= cpu->prev_tsc; - intel_pstate_calc_busy(cpu, &cpu->sample); + intel_pstate_calc_busy(cpu); cpu->prev_aperf = aperf; cpu->prev_mperf = mperf; - cpu->prev_tsc = tsc; } 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) static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu) { - int32_t core_busy, max_pstate, current_pstate; + int32_t core_busy, max_pstate, current_pstate, sample_ratio; + u32 duration_us; + u32 sample_time; core_busy = cpu->sample.core_pct_busy; max_pstate = int_tofp(cpu->pstate.max_pstate); current_pstate = int_tofp(cpu->pstate.current_pstate); core_busy = mul_fp(core_busy, div_fp(max_pstate, current_pstate)); - return FP_ROUNDUP(core_busy); + + sample_time = (pid_params.sample_rate_ms * USEC_PER_MSEC); + duration_us = (u32) ktime_us_delta(cpu->sample.time, + cpu->last_sample_time); + if (duration_us > sample_time * 3) { + sample_ratio = div_fp(int_tofp(sample_time), + int_tofp(duration_us)); + core_busy = mul_fp(core_busy, sample_ratio); + } + + return core_busy; } 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[] = { ICPU(0x37, byt_params), ICPU(0x3a, core_params), ICPU(0x3c, core_params), + ICPU(0x3d, core_params), ICPU(0x3e, core_params), ICPU(0x3f, core_params), ICPU(0x45, core_params), ICPU(0x46, core_params), + ICPU(0x4f, core_params), + ICPU(0x56, core_params), {} }; MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids); |