diff options
author | Dirk Brandewie <dirk.j.brandewie@intel.com> | 2014-05-29 09:32:24 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-06-11 11:54:13 -0700 |
commit | fb145ac9f30cf84d18a26b63e18c94849be54313 (patch) | |
tree | bc54381269e6d3bb2d522a7e94bf80616d422a59 | |
parent | 85db8604350ab6eb012a08fb6b81eb840201eb29 (diff) |
intel_pstate: add sample time scaling
commit c4ee841f602e5eef8eab673295c49c5b49d7732b upstream.
The PID assumes that samples are of equal time, which for a deferable
timers this is not true when the system goes idle. This causes the
PID to take a long time to converge to the min P state and depending
on the pattern of the idle load can make the P state appear stuck.
The hold-off value of three sample times before using the scaling is
to give a grace period for applications that have high performance
requirements and spend a lot of time idle, The poster child for this
behavior is the ffmpeg benchmark in the Phoronix test suite.
Signed-off-by: Dirk Brandewie <dirk.j.brandewie@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/cpufreq/intel_pstate.c | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 595b0f9dc22..b92051031ac 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -60,6 +60,7 @@ struct sample { u64 aperf; u64 mperf; int freq; + ktime_t time; }; struct pstate_data { @@ -97,6 +98,7 @@ struct cpudata { struct vid_data vid; struct _pid pid; + ktime_t last_sample_time; u64 prev_aperf; u64 prev_mperf; struct sample sample; @@ -583,6 +585,8 @@ static inline void intel_pstate_sample(struct cpudata *cpu) aperf = aperf >> FRAC_BITS; mperf = mperf >> FRAC_BITS; + cpu->last_sample_time = cpu->sample.time; + cpu->sample.time = ktime_get(); cpu->sample.aperf = aperf; cpu->sample.mperf = mperf; cpu->sample.aperf -= cpu->prev_aperf; @@ -605,12 +609,24 @@ 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)); + + 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; } |