Skip to content

Commit 71f4dd3

Browse files
committed
Merge back earlier cpuidle updates for v5.13.
2 parents 31c6ae4 + 22141d5 commit 71f4dd3

6 files changed

Lines changed: 55 additions & 35 deletions

File tree

drivers/cpuidle/driver.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,9 +181,13 @@ static void __cpuidle_driver_init(struct cpuidle_driver *drv)
181181
*/
182182
if (s->target_residency > 0)
183183
s->target_residency_ns = s->target_residency * NSEC_PER_USEC;
184+
else if (s->target_residency_ns < 0)
185+
s->target_residency_ns = 0;
184186

185187
if (s->exit_latency > 0)
186188
s->exit_latency_ns = s->exit_latency * NSEC_PER_USEC;
189+
else if (s->exit_latency_ns < 0)
190+
s->exit_latency_ns = 0;
187191
}
188192
}
189193

drivers/cpuidle/governors/menu.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
271271
u64 predicted_ns;
272272
u64 interactivity_req;
273273
unsigned long nr_iowaiters;
274-
ktime_t delta_next;
274+
ktime_t delta, delta_tick;
275275
int i, idx;
276276

277277
if (data->needs_update) {
@@ -280,7 +280,12 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
280280
}
281281

282282
/* determine the expected residency time, round up */
283-
data->next_timer_ns = tick_nohz_get_sleep_length(&delta_next);
283+
delta = tick_nohz_get_sleep_length(&delta_tick);
284+
if (unlikely(delta < 0)) {
285+
delta = 0;
286+
delta_tick = 0;
287+
}
288+
data->next_timer_ns = delta;
284289

285290
nr_iowaiters = nr_iowait_cpu(dev->cpu);
286291
data->bucket = which_bucket(data->next_timer_ns, nr_iowaiters);
@@ -318,7 +323,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
318323
* state selection.
319324
*/
320325
if (predicted_ns < TICK_NSEC)
321-
predicted_ns = delta_next;
326+
predicted_ns = data->next_timer_ns;
322327
} else {
323328
/*
324329
* Use the performance multiplier and the user-configurable
@@ -377,7 +382,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
377382
* stuck in the shallow one for too long.
378383
*/
379384
if (drv->states[idx].target_residency_ns < TICK_NSEC &&
380-
s->target_residency_ns <= delta_next)
385+
s->target_residency_ns <= delta_tick)
381386
idx = i;
382387

383388
return idx;
@@ -399,7 +404,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
399404
predicted_ns < TICK_NSEC) && !tick_nohz_tick_stopped()) {
400405
*stop_tick = false;
401406

402-
if (idx > 0 && drv->states[idx].target_residency_ns > delta_next) {
407+
if (idx > 0 && drv->states[idx].target_residency_ns > delta_tick) {
403408
/*
404409
* The tick is not going to be stopped and the target
405410
* residency of the state to be returned is not within
@@ -411,7 +416,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
411416
continue;
412417

413418
idx = i;
414-
if (drv->states[i].target_residency_ns <= delta_next)
419+
if (drv->states[i].target_residency_ns <= delta_tick)
415420
break;
416421
}
417422
}

drivers/cpuidle/governors/teo.c

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,8 @@ struct teo_idle_state {
100100
* @intervals: Saved idle duration values.
101101
*/
102102
struct teo_cpu {
103-
u64 time_span_ns;
104-
u64 sleep_length_ns;
103+
s64 time_span_ns;
104+
s64 sleep_length_ns;
105105
struct teo_idle_state states[CPUIDLE_STATE_MAX];
106106
int interval_idx;
107107
u64 intervals[INTERVALS];
@@ -117,7 +117,8 @@ static DEFINE_PER_CPU(struct teo_cpu, teo_cpus);
117117
static void teo_update(struct cpuidle_driver *drv, struct cpuidle_device *dev)
118118
{
119119
struct teo_cpu *cpu_data = per_cpu_ptr(&teo_cpus, dev->cpu);
120-
int i, idx_hit = -1, idx_timer = -1;
120+
int i, idx_hit = 0, idx_timer = 0;
121+
unsigned int hits, misses;
121122
u64 measured_ns;
122123

123124
if (cpu_data->time_span_ns >= cpu_data->sleep_length_ns) {
@@ -174,25 +175,22 @@ static void teo_update(struct cpuidle_driver *drv, struct cpuidle_device *dev)
174175
* also increase the "early hits" metric for the state that actually
175176
* matches the measured idle duration.
176177
*/
177-
if (idx_timer >= 0) {
178-
unsigned int hits = cpu_data->states[idx_timer].hits;
179-
unsigned int misses = cpu_data->states[idx_timer].misses;
180-
181-
hits -= hits >> DECAY_SHIFT;
182-
misses -= misses >> DECAY_SHIFT;
183-
184-
if (idx_timer > idx_hit) {
185-
misses += PULSE;
186-
if (idx_hit >= 0)
187-
cpu_data->states[idx_hit].early_hits += PULSE;
188-
} else {
189-
hits += PULSE;
190-
}
178+
hits = cpu_data->states[idx_timer].hits;
179+
hits -= hits >> DECAY_SHIFT;
180+
181+
misses = cpu_data->states[idx_timer].misses;
182+
misses -= misses >> DECAY_SHIFT;
191183

192-
cpu_data->states[idx_timer].misses = misses;
193-
cpu_data->states[idx_timer].hits = hits;
184+
if (idx_timer == idx_hit) {
185+
hits += PULSE;
186+
} else {
187+
misses += PULSE;
188+
cpu_data->states[idx_hit].early_hits += PULSE;
194189
}
195190

191+
cpu_data->states[idx_timer].misses = misses;
192+
cpu_data->states[idx_timer].hits = hits;
193+
196194
/*
197195
* Save idle duration values corresponding to non-timer wakeups for
198196
* pattern detection.
@@ -216,7 +214,7 @@ static bool teo_time_ok(u64 interval_ns)
216214
*/
217215
static int teo_find_shallower_state(struct cpuidle_driver *drv,
218216
struct cpuidle_device *dev, int state_idx,
219-
u64 duration_ns)
217+
s64 duration_ns)
220218
{
221219
int i;
222220

@@ -242,10 +240,10 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
242240
{
243241
struct teo_cpu *cpu_data = per_cpu_ptr(&teo_cpus, dev->cpu);
244242
s64 latency_req = cpuidle_governor_latency_req(dev->cpu);
245-
u64 duration_ns;
243+
int max_early_idx, prev_max_early_idx, constraint_idx, idx0, idx, i;
246244
unsigned int hits, misses, early_hits;
247-
int max_early_idx, prev_max_early_idx, constraint_idx, idx, i;
248245
ktime_t delta_tick;
246+
s64 duration_ns;
249247

250248
if (dev->last_state_idx >= 0) {
251249
teo_update(drv, dev);
@@ -264,6 +262,7 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
264262
prev_max_early_idx = -1;
265263
constraint_idx = drv->state_count;
266264
idx = -1;
265+
idx0 = idx;
267266

268267
for (i = 0; i < drv->state_count; i++) {
269268
struct cpuidle_state *s = &drv->states[i];
@@ -324,6 +323,7 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
324323
idx = i; /* first enabled state */
325324
hits = cpu_data->states[i].hits;
326325
misses = cpu_data->states[i].misses;
326+
idx0 = i;
327327
}
328328

329329
if (s->target_residency_ns > duration_ns)
@@ -376,11 +376,16 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
376376

377377
if (idx < 0) {
378378
idx = 0; /* No states enabled. Must use 0. */
379-
} else if (idx > 0) {
379+
} else if (idx > idx0) {
380380
unsigned int count = 0;
381381
u64 sum = 0;
382382

383383
/*
384+
* The target residencies of at least two different enabled idle
385+
* states are less than or equal to the current expected idle
386+
* duration. Try to refine the selection using the most recent
387+
* measured idle duration values.
388+
*
384389
* Count and sum the most recent idle duration values less than
385390
* the current expected idle duration value.
386391
*/
@@ -428,7 +433,8 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
428433
* till the closest timer including the tick, try to correct
429434
* that.
430435
*/
431-
if (idx > 0 && drv->states[idx].target_residency_ns > delta_tick)
436+
if (idx > idx0 &&
437+
drv->states[idx].target_residency_ns > delta_tick)
432438
idx = teo_find_shallower_state(drv, dev, idx, delta_tick);
433439
}
434440

drivers/idle/intel_idle.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -744,8 +744,8 @@ static struct cpuidle_state icx_cstates[] __initdata = {
744744
.name = "C6",
745745
.desc = "MWAIT 0x20",
746746
.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
747-
.exit_latency = 128,
748-
.target_residency = 384,
747+
.exit_latency = 170,
748+
.target_residency = 600,
749749
.enter = &intel_idle,
750750
.enter_s2idle = intel_idle_s2idle, },
751751
{
@@ -1156,6 +1156,7 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = {
11561156
X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE, &idle_cpu_skl),
11571157
X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_X, &idle_cpu_skx),
11581158
X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_X, &idle_cpu_icx),
1159+
X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_D, &idle_cpu_icx),
11591160
X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNL, &idle_cpu_knl),
11601161
X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNM, &idle_cpu_knl),
11611162
X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT, &idle_cpu_bxt),

include/linux/cpuidle.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ struct cpuidle_state {
4949
char name[CPUIDLE_NAME_LEN];
5050
char desc[CPUIDLE_DESC_LEN];
5151

52-
u64 exit_latency_ns;
53-
u64 target_residency_ns;
52+
s64 exit_latency_ns;
53+
s64 target_residency_ns;
5454
unsigned int flags;
5555
unsigned int exit_latency; /* in US */
5656
int power_usage; /* in mW */

kernel/time/tick-sched.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1124,7 +1124,11 @@ ktime_t tick_nohz_get_next_hrtimer(void)
11241124
* tick_nohz_get_sleep_length - return the expected length of the current sleep
11251125
* @delta_next: duration until the next event if the tick cannot be stopped
11261126
*
1127-
* Called from power state control code with interrupts disabled
1127+
* Called from power state control code with interrupts disabled.
1128+
*
1129+
* The return value of this function and/or the value returned by it through the
1130+
* @delta_next pointer can be negative which must be taken into account by its
1131+
* callers.
11281132
*/
11291133
ktime_t tick_nohz_get_sleep_length(ktime_t *delta_next)
11301134
{

0 commit comments

Comments
 (0)