From a7e049b7651a6ee03b048e78442a513b0a26868e Mon Sep 17 00:00:00 2001 From: Doug Smythies Date: Sat, 14 Jun 2014 22:30:52 -0700 Subject: [PATCH 2/4] intel_pstate: Include C0 for light loads only. --- drivers/cpufreq/intel_pstate.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index c1178ba..5f38783 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -59,6 +59,10 @@ struct sample { int32_t core_pct_busy; u64 aperf; u64 mperf; + u64 tsc; + u64 c0_1; + u64 c0_2; + u64 c0_3; int freq; }; @@ -99,6 +103,7 @@ struct cpudata { u64 prev_aperf; u64 prev_mperf; + u64 prev_tsc; struct sample sample; }; @@ -561,40 +566,61 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu) static inline void intel_pstate_calc_busy(struct cpudata *cpu, struct sample *sample) { + +#define C0_THRESHOLD 4 << FRAC_BITS +#define C0_SCALE (100 << (FRAC_BITS)) / (C0_THRESHOLD) + int64_t core_pct; - int32_t rem; + int64_t c0_pct, c0_scaled; core_pct = int_tofp(sample->aperf) * int_tofp(100); - core_pct = div_u64_rem(core_pct, int_tofp(sample->mperf), &rem); + core_pct = div_u64(core_pct, int_tofp(sample->mperf)); - if ((rem << 1) >= int_tofp(sample->mperf)) - core_pct += 1; + c0_pct = int_tofp(sample->mperf) * int_tofp(100); + c0_pct = div_u64(c0_pct, int_tofp(sample->tsc)); sample->freq = fp_toint( mul_fp(int_tofp(cpu->pstate.max_pstate * 1000), core_pct)); + if(c0_pct < C0_THRESHOLD && sample->c0_1 < C0_THRESHOLD && sample->c0_2 < C0_THRESHOLD && sample->c0_3 < C0_THRESHOLD) + { + c0_scaled = c0_pct * C0_SCALE; + core_pct = core_pct - int_tofp(limits.min_perf_pct); + core_pct = core_pct * c0_scaled; + core_pct = div_u64(core_pct, int_tofp(100)); + core_pct = core_pct + int_tofp(limits.min_perf_pct); + } sample->core_pct_busy = (int32_t)core_pct; + sample->c0_3 = sample->c0_2; + sample->c0_2 = sample->c0_1; + sample->c0_1 = c0_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->sample.aperf = aperf; cpu->sample.mperf = mperf; + cpu->sample.tsc = (u64) 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); cpu->prev_aperf = aperf; cpu->prev_mperf = mperf; + cpu->prev_tsc = (u64) tsc; } static inline void intel_pstate_set_sample_time(struct cpudata *cpu) -- 1.9.1