Skip to content

Commit 2c2a83d

Browse files
committed
Merge back earlier cpuidle material for v5.5.
2 parents 31d8514 + 159e485 commit 2c2a83d

File tree

1 file changed

+59
-19
lines changed
  • drivers/cpuidle/governors

1 file changed

+59
-19
lines changed

drivers/cpuidle/governors/teo.c

Lines changed: 59 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
233233
{
234234
struct teo_cpu *cpu_data = per_cpu_ptr(&teo_cpus, dev->cpu);
235235
int latency_req = cpuidle_governor_latency_req(dev->cpu);
236-
unsigned int duration_us, count;
236+
unsigned int duration_us, hits, misses, early_hits;
237237
int max_early_idx, constraint_idx, idx, i;
238238
ktime_t delta_tick;
239239

@@ -247,7 +247,9 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
247247
cpu_data->sleep_length_ns = tick_nohz_get_sleep_length(&delta_tick);
248248
duration_us = ktime_to_us(cpu_data->sleep_length_ns);
249249

250-
count = 0;
250+
hits = 0;
251+
misses = 0;
252+
early_hits = 0;
251253
max_early_idx = -1;
252254
constraint_idx = drv->state_count;
253255
idx = -1;
@@ -258,23 +260,61 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
258260

259261
if (s->disabled || su->disable) {
260262
/*
261-
* If the "early hits" metric of a disabled state is
262-
* greater than the current maximum, it should be taken
263-
* into account, because it would be a mistake to select
264-
* a deeper state with lower "early hits" metric. The
265-
* index cannot be changed to point to it, however, so
266-
* just increase the max count alone and let the index
267-
* still point to a shallower idle state.
263+
* Ignore disabled states with target residencies beyond
264+
* the anticipated idle duration.
268265
*/
269-
if (max_early_idx >= 0 &&
270-
count < cpu_data->states[i].early_hits)
271-
count = cpu_data->states[i].early_hits;
266+
if (s->target_residency > duration_us)
267+
continue;
268+
269+
/*
270+
* This state is disabled, so the range of idle duration
271+
* values corresponding to it is covered by the current
272+
* candidate state, but still the "hits" and "misses"
273+
* metrics of the disabled state need to be used to
274+
* decide whether or not the state covering the range in
275+
* question is good enough.
276+
*/
277+
hits = cpu_data->states[i].hits;
278+
misses = cpu_data->states[i].misses;
279+
280+
if (early_hits >= cpu_data->states[i].early_hits ||
281+
idx < 0)
282+
continue;
283+
284+
/*
285+
* If the current candidate state has been the one with
286+
* the maximum "early hits" metric so far, the "early
287+
* hits" metric of the disabled state replaces the
288+
* current "early hits" count to avoid selecting a
289+
* deeper state with lower "early hits" metric.
290+
*/
291+
if (max_early_idx == idx) {
292+
early_hits = cpu_data->states[i].early_hits;
293+
continue;
294+
}
295+
296+
/*
297+
* The current candidate state is closer to the disabled
298+
* one than the current maximum "early hits" state, so
299+
* replace the latter with it, but in case the maximum
300+
* "early hits" state index has not been set so far,
301+
* check if the current candidate state is not too
302+
* shallow for that role.
303+
*/
304+
if (!(tick_nohz_tick_stopped() &&
305+
drv->states[idx].target_residency < TICK_USEC)) {
306+
early_hits = cpu_data->states[i].early_hits;
307+
max_early_idx = idx;
308+
}
272309

273310
continue;
274311
}
275312

276-
if (idx < 0)
313+
if (idx < 0) {
277314
idx = i; /* first enabled state */
315+
hits = cpu_data->states[i].hits;
316+
misses = cpu_data->states[i].misses;
317+
}
278318

279319
if (s->target_residency > duration_us)
280320
break;
@@ -283,11 +323,13 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
283323
constraint_idx = i;
284324

285325
idx = i;
326+
hits = cpu_data->states[i].hits;
327+
misses = cpu_data->states[i].misses;
286328

287-
if (count < cpu_data->states[i].early_hits &&
329+
if (early_hits < cpu_data->states[i].early_hits &&
288330
!(tick_nohz_tick_stopped() &&
289331
drv->states[i].target_residency < TICK_USEC)) {
290-
count = cpu_data->states[i].early_hits;
332+
early_hits = cpu_data->states[i].early_hits;
291333
max_early_idx = i;
292334
}
293335
}
@@ -300,8 +342,7 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
300342
* "early hits" metric, but if that cannot be determined, just use the
301343
* state selected so far.
302344
*/
303-
if (cpu_data->states[idx].hits <= cpu_data->states[idx].misses &&
304-
max_early_idx >= 0) {
345+
if (hits <= misses && max_early_idx >= 0) {
305346
idx = max_early_idx;
306347
duration_us = drv->states[idx].target_residency;
307348
}
@@ -316,10 +357,9 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
316357
if (idx < 0) {
317358
idx = 0; /* No states enabled. Must use 0. */
318359
} else if (idx > 0) {
360+
unsigned int count = 0;
319361
u64 sum = 0;
320362

321-
count = 0;
322-
323363
/*
324364
* Count and sum the most recent idle duration values less than
325365
* the current expected idle duration value.

0 commit comments

Comments
 (0)