2
2
/*
3
3
* Timer events oriented CPU idle governor
4
4
*
5
- * TEO governor:
6
5
* Copyright (C) 2018 - 2021 Intel Corporation
7
6
* Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
8
- *
9
- * Util-awareness mechanism:
10
- * Copyright (C) 2022 Arm Ltd.
11
- * Author: Kajetan Puchalski <kajetan.puchalski@arm.com>
12
7
*/
13
8
14
9
/**
104
99
* select the given idle state instead of the candidate one.
105
100
*
106
101
* 3. By default, select the candidate state.
107
- *
108
- * Util-awareness mechanism:
109
- *
110
- * The idea behind the util-awareness extension is that there are two distinct
111
- * scenarios for the CPU which should result in two different approaches to idle
112
- * state selection - utilized and not utilized.
113
- *
114
- * In this case, 'utilized' means that the average runqueue util of the CPU is
115
- * above a certain threshold.
116
- *
117
- * When the CPU is utilized while going into idle, more likely than not it will
118
- * be woken up to do more work soon and so a shallower idle state should be
119
- * selected to minimise latency and maximise performance. When the CPU is not
120
- * being utilized, the usual metrics-based approach to selecting the deepest
121
- * available idle state should be preferred to take advantage of the power
122
- * saving.
123
- *
124
- * In order to achieve this, the governor uses a utilization threshold.
125
- * The threshold is computed per-CPU as a percentage of the CPU's capacity
126
- * by bit shifting the capacity value. Based on testing, the shift of 6 (~1.56%)
127
- * seems to be getting the best results.
128
- *
129
- * Before selecting the next idle state, the governor compares the current CPU
130
- * util to the precomputed util threshold. If it's below, it defaults to the
131
- * TEO metrics mechanism. If it's above, the closest shallower idle state will
132
- * be selected instead, as long as is not a polling state.
133
102
*/
134
103
135
104
#include <linux/cpuidle.h>
136
105
#include <linux/jiffies.h>
137
106
#include <linux/kernel.h>
138
- #include <linux/sched.h>
139
107
#include <linux/sched/clock.h>
140
- #include <linux/sched/topology.h>
141
108
#include <linux/tick.h>
142
109
143
110
#include "gov.h"
144
111
145
- /*
146
- * The number of bits to shift the CPU's capacity by in order to determine
147
- * the utilized threshold.
148
- *
149
- * 6 was chosen based on testing as the number that achieved the best balance
150
- * of power and performance on average.
151
- *
152
- * The resulting threshold is high enough to not be triggered by background
153
- * noise and low enough to react quickly when activity starts to ramp up.
154
- */
155
- #define UTIL_THRESHOLD_SHIFT 6
156
-
157
112
/*
158
113
* The PULSE value is added to metrics when they grow and the DECAY_SHIFT value
159
114
* is used for decreasing metrics on a regular basis.
@@ -188,7 +143,6 @@ struct teo_bin {
188
143
* @next_recent_idx: Index of the next @recent_idx entry to update.
189
144
* @recent_idx: Indices of bins corresponding to recent "intercepts".
190
145
* @tick_hits: Number of "hits" after TICK_NSEC.
191
- * @util_threshold: Threshold above which the CPU is considered utilized
192
146
*/
193
147
struct teo_cpu {
194
148
s64 time_span_ns ;
@@ -198,28 +152,10 @@ struct teo_cpu {
198
152
int next_recent_idx ;
199
153
int recent_idx [NR_RECENT ];
200
154
unsigned int tick_hits ;
201
- unsigned long util_threshold ;
202
155
};
203
156
204
157
static DEFINE_PER_CPU (struct teo_cpu , teo_cpus ) ;
205
158
206
- /**
207
- * teo_cpu_is_utilized - Check if the CPU's util is above the threshold
208
- * @cpu: Target CPU
209
- * @cpu_data: Governor CPU data for the target CPU
210
- */
211
- #ifdef CONFIG_SMP
212
- static bool teo_cpu_is_utilized (int cpu , struct teo_cpu * cpu_data )
213
- {
214
- return sched_cpu_util (cpu ) > cpu_data -> util_threshold ;
215
- }
216
- #else
217
- static bool teo_cpu_is_utilized (int cpu , struct teo_cpu * cpu_data )
218
- {
219
- return false;
220
- }
221
- #endif
222
-
223
159
/**
224
160
* teo_update - Update CPU metrics after wakeup.
225
161
* @drv: cpuidle driver containing state data.
@@ -386,7 +322,6 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
386
322
int constraint_idx = 0 ;
387
323
int idx0 = 0 , idx = -1 ;
388
324
bool alt_intercepts , alt_recent ;
389
- bool cpu_utilized ;
390
325
s64 duration_ns ;
391
326
int i ;
392
327
@@ -411,32 +346,6 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
411
346
if (!dev -> states_usage [0 ].disable )
412
347
idx = 0 ;
413
348
414
- cpu_utilized = teo_cpu_is_utilized (dev -> cpu , cpu_data );
415
- /*
416
- * If the CPU is being utilized over the threshold and there are only 2
417
- * states to choose from, the metrics need not be considered, so choose
418
- * the shallowest non-polling state and exit.
419
- */
420
- if (drv -> state_count < 3 && cpu_utilized ) {
421
- /*
422
- * If state 0 is enabled and it is not a polling one, select it
423
- * right away unless the scheduler tick has been stopped, in
424
- * which case care needs to be taken to leave the CPU in a deep
425
- * enough state in case it is not woken up any time soon after
426
- * all. If state 1 is disabled, though, state 0 must be used
427
- * anyway.
428
- */
429
- if ((!idx && !(drv -> states [0 ].flags & CPUIDLE_FLAG_POLLING ) &&
430
- teo_state_ok (0 , drv )) || dev -> states_usage [1 ].disable ) {
431
- idx = 0 ;
432
- goto out_tick ;
433
- }
434
- /* Assume that state 1 is not a polling one and use it. */
435
- idx = 1 ;
436
- duration_ns = drv -> states [1 ].target_residency_ns ;
437
- goto end ;
438
- }
439
-
440
349
/* Compute the sums of metrics for early wakeup pattern detection. */
441
350
for (i = 1 ; i < drv -> state_count ; i ++ ) {
442
351
struct teo_bin * prev_bin = & cpu_data -> state_bins [i - 1 ];
@@ -560,18 +469,6 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
560
469
if (idx > constraint_idx )
561
470
idx = constraint_idx ;
562
471
563
- /*
564
- * If the CPU is being utilized over the threshold, choose a shallower
565
- * non-polling state to improve latency, unless the scheduler tick has
566
- * been stopped already and the shallower state's target residency is
567
- * not sufficiently large.
568
- */
569
- if (cpu_utilized ) {
570
- i = teo_find_shallower_state (drv , dev , idx , KTIME_MAX , true);
571
- if (teo_state_ok (i , drv ))
572
- idx = i ;
573
- }
574
-
575
472
/*
576
473
* Skip the timers check if state 0 is the current candidate one,
577
474
* because an immediate non-timer wakeup is expected in that case.
@@ -667,11 +564,9 @@ static int teo_enable_device(struct cpuidle_driver *drv,
667
564
struct cpuidle_device * dev )
668
565
{
669
566
struct teo_cpu * cpu_data = per_cpu_ptr (& teo_cpus , dev -> cpu );
670
- unsigned long max_capacity = arch_scale_cpu_capacity (dev -> cpu );
671
567
int i ;
672
568
673
569
memset (cpu_data , 0 , sizeof (* cpu_data ));
674
- cpu_data -> util_threshold = max_capacity >> UTIL_THRESHOLD_SHIFT ;
675
570
676
571
for (i = 0 ; i < NR_RECENT ; i ++ )
677
572
cpu_data -> recent_idx [i ] = -1 ;
0 commit comments