cpufreq: intel_pstate: Account for IO wait time
authorPhilippe Longepe <philippe.longepe@intel.com>
Fri, 4 Dec 2015 16:40:35 +0000 (17:40 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Thu, 10 Dec 2015 00:17:40 +0000 (01:17 +0100)
In cases where we have many IOs, the global load becomes low and the
load algorithm will decrease the requested P-State. Because of that,
the IOs overheads will increase and impact the IO performances.

To improve IO bound work, we can count the io-wait time as busy time
in calculating CPU busy.

This change uses get_cpu_iowait_time_us() to obtain the IO wait time value
and converts time into number of cycles spent waiting on IO at the TSC
rate. At the moment, this trick is only used for Atom.

Signed-off-by: Philippe Longepe <philippe.longepe@intel.com>
Signed-off-by: Stephane Gasparini <stephane.gasparini@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
drivers/cpufreq/intel_pstate.c

index 8bfebaeda2dd12b1b741afd4a12471fc1d2b3d58..efc581392bd14724da3d81e30f8eb19cdf253d12 100644 (file)
@@ -113,6 +113,7 @@ struct cpudata {
        u64     prev_aperf;
        u64     prev_mperf;
        u64     prev_tsc;
+       u64     prev_cummulative_iowait;
        struct sample sample;
 };
 
@@ -933,22 +934,39 @@ static inline void intel_pstate_set_sample_time(struct cpudata *cpu)
 static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu)
 {
        struct sample *sample = &cpu->sample;
+       u64 cummulative_iowait, delta_iowait_us;
+       u64 delta_iowait_mperf;
+       u64 mperf, now;
        int32_t cpu_load;
 
+       cummulative_iowait = get_cpu_iowait_time_us(cpu->cpu, &now);
+
+       /*
+        * Convert iowait time into number of IO cycles spent at max_freq.
+        * IO is considered as busy only for the cpu_load algorithm. For
+        * performance this is not needed since we always try to reach the
+        * maximum P-State, so we are already boosting the IOs.
+        */
+       delta_iowait_us = cummulative_iowait - cpu->prev_cummulative_iowait;
+       delta_iowait_mperf = div64_u64(delta_iowait_us * cpu->pstate.scaling *
+               cpu->pstate.max_pstate, MSEC_PER_SEC);
+
+       mperf = cpu->sample.mperf + delta_iowait_mperf;
+       cpu->prev_cummulative_iowait = cummulative_iowait;
+
+
        /*
         * The load can be estimated as the ratio of the mperf counter
         * running at a constant frequency during active periods
         * (C0) and the time stamp counter running at the same frequency
         * also during C-states.
         */
-       cpu_load = div64_u64(int_tofp(100) * sample->mperf, sample->tsc);
-
+       cpu_load = div64_u64(int_tofp(100) * mperf, sample->tsc);
        cpu->sample.busy_scaled = cpu_load;
 
        return cpu->pstate.current_pstate - pid_calc(&cpu->pid, cpu_load);
 }
 
-
 static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu)
 {
        int32_t core_busy, max_pstate, current_pstate, sample_ratio;