aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2016-09-13 20:28:13 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2016-09-13 20:28:13 -0400
commit09c448d3c61f31322c097cb4c1484778d50da399 (patch)
tree7e33715f303d6796388fbe0d344736f067be485a /drivers/cpufreq
parent21ca6d2c52f8ca8638129c1dfc489d0b0ae68532 (diff)
cpufreq: intel_pstate: Use IOWAIT flag in Atom algorithm
Modify the P-state selection algorithm for Atom processors to use the new SCHED_CPUFREQ_IOWAIT flag instead of the questionable get_cpu_iowait_time_us() function. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/cpufreq')
-rw-r--r--drivers/cpufreq/intel_pstate.c58
1 files changed, 31 insertions, 27 deletions
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index bdbe9369146b..7c457ccf9153 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -181,6 +181,8 @@ struct _pid {
181 * @cpu: CPU number for this instance data 181 * @cpu: CPU number for this instance data
182 * @update_util: CPUFreq utility callback information 182 * @update_util: CPUFreq utility callback information
183 * @update_util_set: CPUFreq utility callback is set 183 * @update_util_set: CPUFreq utility callback is set
184 * @iowait_boost: iowait-related boost fraction
185 * @last_update: Time of the last update.
184 * @pstate: Stores P state limits for this CPU 186 * @pstate: Stores P state limits for this CPU
185 * @vid: Stores VID limits for this CPU 187 * @vid: Stores VID limits for this CPU
186 * @pid: Stores PID parameters for this CPU 188 * @pid: Stores PID parameters for this CPU
@@ -206,6 +208,7 @@ struct cpudata {
206 struct vid_data vid; 208 struct vid_data vid;
207 struct _pid pid; 209 struct _pid pid;
208 210
211 u64 last_update;
209 u64 last_sample_time; 212 u64 last_sample_time;
210 u64 prev_aperf; 213 u64 prev_aperf;
211 u64 prev_mperf; 214 u64 prev_mperf;
@@ -216,6 +219,7 @@ struct cpudata {
216 struct acpi_processor_performance acpi_perf_data; 219 struct acpi_processor_performance acpi_perf_data;
217 bool valid_pss_table; 220 bool valid_pss_table;
218#endif 221#endif
222 unsigned int iowait_boost;
219}; 223};
220 224
221static struct cpudata **all_cpu_data; 225static struct cpudata **all_cpu_data;
@@ -229,6 +233,7 @@ static struct cpudata **all_cpu_data;
229 * @p_gain_pct: PID proportional gain 233 * @p_gain_pct: PID proportional gain
230 * @i_gain_pct: PID integral gain 234 * @i_gain_pct: PID integral gain
231 * @d_gain_pct: PID derivative gain 235 * @d_gain_pct: PID derivative gain
236 * @boost_iowait: Whether or not to use iowait boosting.
232 * 237 *
233 * Stores per CPU model static PID configuration data. 238 * Stores per CPU model static PID configuration data.
234 */ 239 */
@@ -240,6 +245,7 @@ struct pstate_adjust_policy {
240 int p_gain_pct; 245 int p_gain_pct;
241 int d_gain_pct; 246 int d_gain_pct;
242 int i_gain_pct; 247 int i_gain_pct;
248 bool boost_iowait;
243}; 249};
244 250
245/** 251/**
@@ -1037,6 +1043,7 @@ static struct cpu_defaults silvermont_params = {
1037 .p_gain_pct = 14, 1043 .p_gain_pct = 14,
1038 .d_gain_pct = 0, 1044 .d_gain_pct = 0,
1039 .i_gain_pct = 4, 1045 .i_gain_pct = 4,
1046 .boost_iowait = true,
1040 }, 1047 },
1041 .funcs = { 1048 .funcs = {
1042 .get_max = atom_get_max_pstate, 1049 .get_max = atom_get_max_pstate,
@@ -1058,6 +1065,7 @@ static struct cpu_defaults airmont_params = {
1058 .p_gain_pct = 14, 1065 .p_gain_pct = 14,
1059 .d_gain_pct = 0, 1066 .d_gain_pct = 0,
1060 .i_gain_pct = 4, 1067 .i_gain_pct = 4,
1068 .boost_iowait = true,
1061 }, 1069 },
1062 .funcs = { 1070 .funcs = {
1063 .get_max = atom_get_max_pstate, 1071 .get_max = atom_get_max_pstate,
@@ -1099,6 +1107,7 @@ static struct cpu_defaults bxt_params = {
1099 .p_gain_pct = 14, 1107 .p_gain_pct = 14,
1100 .d_gain_pct = 0, 1108 .d_gain_pct = 0,
1101 .i_gain_pct = 4, 1109 .i_gain_pct = 4,
1110 .boost_iowait = true,
1102 }, 1111 },
1103 .funcs = { 1112 .funcs = {
1104 .get_max = core_get_max_pstate, 1113 .get_max = core_get_max_pstate,
@@ -1222,36 +1231,18 @@ static inline int32_t get_avg_pstate(struct cpudata *cpu)
1222static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu) 1231static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu)
1223{ 1232{
1224 struct sample *sample = &cpu->sample; 1233 struct sample *sample = &cpu->sample;
1225 u64 cummulative_iowait, delta_iowait_us; 1234 int32_t busy_frac, boost;
1226 u64 delta_iowait_mperf;
1227 u64 mperf, now;
1228 int32_t cpu_load;
1229 1235
1230 cummulative_iowait = get_cpu_iowait_time_us(cpu->cpu, &now); 1236 busy_frac = div_fp(sample->mperf, sample->tsc);
1231 1237
1232 /* 1238 boost = cpu->iowait_boost;
1233 * Convert iowait time into number of IO cycles spent at max_freq. 1239 cpu->iowait_boost >>= 1;
1234 * IO is considered as busy only for the cpu_load algorithm. For
1235 * performance this is not needed since we always try to reach the
1236 * maximum P-State, so we are already boosting the IOs.
1237 */
1238 delta_iowait_us = cummulative_iowait - cpu->prev_cummulative_iowait;
1239 delta_iowait_mperf = div64_u64(delta_iowait_us * cpu->pstate.scaling *
1240 cpu->pstate.max_pstate, MSEC_PER_SEC);
1241 1240
1242 mperf = cpu->sample.mperf + delta_iowait_mperf; 1241 if (busy_frac < boost)
1243 cpu->prev_cummulative_iowait = cummulative_iowait; 1242 busy_frac = boost;
1244 1243
1245 /* 1244 sample->busy_scaled = busy_frac * 100;
1246 * The load can be estimated as the ratio of the mperf counter 1245 return get_avg_pstate(cpu) - pid_calc(&cpu->pid, sample->busy_scaled);
1247 * running at a constant frequency during active periods
1248 * (C0) and the time stamp counter running at the same frequency
1249 * also during C-states.
1250 */
1251 cpu_load = div64_u64(int_tofp(100) * mperf, sample->tsc);
1252 cpu->sample.busy_scaled = cpu_load;
1253
1254 return get_avg_pstate(cpu) - pid_calc(&cpu->pid, cpu_load);
1255} 1246}
1256 1247
1257static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu) 1248static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu)
@@ -1332,8 +1323,21 @@ static void intel_pstate_update_util(struct update_util_data *data, u64 time,
1332 unsigned int flags) 1323 unsigned int flags)
1333{ 1324{
1334 struct cpudata *cpu = container_of(data, struct cpudata, update_util); 1325 struct cpudata *cpu = container_of(data, struct cpudata, update_util);
1335 u64 delta_ns = time - cpu->sample.time; 1326 u64 delta_ns;
1327
1328 if (pid_params.boost_iowait) {
1329 if (flags & SCHED_CPUFREQ_IOWAIT) {
1330 cpu->iowait_boost = int_tofp(1);
1331 } else if (cpu->iowait_boost) {
1332 /* Clear iowait_boost if the CPU may have been idle. */
1333 delta_ns = time - cpu->last_update;
1334 if (delta_ns > TICK_NSEC)
1335 cpu->iowait_boost = 0;
1336 }
1337 cpu->last_update = time;
1338 }
1336 1339
1340 delta_ns = time - cpu->sample.time;
1337 if ((s64)delta_ns >= pid_params.sample_rate_ns) { 1341 if ((s64)delta_ns >= pid_params.sample_rate_ns) {
1338 bool sample_taken = intel_pstate_sample(cpu, time); 1342 bool sample_taken = intel_pstate_sample(cpu, time);
1339 1343