diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2016-09-13 20:28:13 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2016-09-13 20:28:13 -0400 |
commit | 09c448d3c61f31322c097cb4c1484778d50da399 (patch) | |
tree | 7e33715f303d6796388fbe0d344736f067be485a /drivers/cpufreq | |
parent | 21ca6d2c52f8ca8638129c1dfc489d0b0ae68532 (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.c | 58 |
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 | ||
221 | static struct cpudata **all_cpu_data; | 225 | static 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) | |||
1222 | static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu) | 1231 | static 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 | ||
1257 | static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu) | 1248 | static 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 | ||