Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

cpuidle: governors: teo: Simplify intercepts-based state lookup

Simplify the loop looking up a candidate idle state in the case when an
intercept is likely to occur by adding a search for the state index limit
if the tick is stopped before it.

First, call tick_nohz_tick_stopped() just once and if it returns true,
look for the shallowest state index below the current candidate one with
target residency at least equal to the tick period length.

Next, simply look for a state that is not shallower than the one found
in the previous step and satisfies the intercepts majority condition (if
there are no such states, the shallowest state that is not shallower
than the one found in the previous step becomes the new candidate).

Since teo_state_ok() has no callers any more after the above changes,
drop it.

No intentional functional impact.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Reviewed-by: Christian Loehle <christian.loehle@arm.com>
[ rjw: Changelog clarification and code comment edit ]
Link: https://patch.msgid.link/2418792.ElGaqSPkdT@rafael.j.wysocki
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

+16 -46
+16 -46
drivers/cpuidle/governors/teo.c
··· 256 256 } 257 257 } 258 258 259 - static bool teo_state_ok(int i, struct cpuidle_driver *drv) 260 - { 261 - return !tick_nohz_tick_stopped() || 262 - drv->states[i].target_residency_ns >= TICK_NSEC; 263 - } 264 - 265 259 /** 266 260 * teo_find_shallower_state - Find shallower idle state matching given duration. 267 261 * @drv: cpuidle driver containing state data. ··· 377 383 * better choice. 378 384 */ 379 385 if (2 * idx_intercept_sum > cpu_data->total - idx_hit_sum) { 380 - int first_suitable_idx = idx; 386 + int min_idx = idx0; 387 + 388 + if (tick_nohz_tick_stopped()) { 389 + /* 390 + * Look for the shallowest idle state below the current 391 + * candidate one whose target residency is at least 392 + * equal to the tick period length. 393 + */ 394 + while (min_idx < idx && 395 + drv->states[min_idx].target_residency_ns < TICK_NSEC) 396 + min_idx++; 397 + } 381 398 382 399 /* 383 400 * Look for the deepest idle state whose target residency had ··· 398 393 * Take the possible duration limitation present if the tick 399 394 * has been stopped already into account. 400 395 */ 401 - intercept_sum = 0; 402 - 403 - for (i = idx - 1; i >= 0; i--) { 404 - struct teo_bin *bin = &cpu_data->state_bins[i]; 405 - 406 - intercept_sum += bin->intercepts; 407 - 408 - if (2 * intercept_sum > idx_intercept_sum) { 409 - /* 410 - * Use the current state unless it is too 411 - * shallow or disabled, in which case take the 412 - * first enabled state that is deep enough. 413 - */ 414 - if (teo_state_ok(i, drv) && 415 - !dev->states_usage[i].disable) { 416 - idx = i; 417 - break; 418 - } 419 - idx = first_suitable_idx; 420 - break; 421 - } 396 + for (i = idx - 1, intercept_sum = 0; i >= min_idx; i--) { 397 + intercept_sum += cpu_data->state_bins[i].intercepts; 422 398 423 399 if (dev->states_usage[i].disable) 424 400 continue; 425 401 426 - if (teo_state_ok(i, drv)) { 427 - /* 428 - * The current state is deep enough, but still 429 - * there may be a better one. 430 - */ 431 - first_suitable_idx = i; 432 - continue; 433 - } 434 - 435 - /* 436 - * The current state is too shallow, so if no suitable 437 - * states other than the initial candidate have been 438 - * found, give up (the remaining states to check are 439 - * shallower still), but otherwise the first suitable 440 - * state other than the initial candidate may turn out 441 - * to be preferable. 442 - */ 443 - if (first_suitable_idx == idx) 402 + idx = i; 403 + if (2 * intercept_sum > idx_intercept_sum) 444 404 break; 445 405 } 446 406 }