@@ -100,8 +100,8 @@ struct teo_idle_state {
100100 * @intervals: Saved idle duration values.
101101 */
102102struct 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);
117117static 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 */
217215static 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
0 commit comments