pm: policy: default: Optimize power state selection

Update power state selection. Previously, it was iterating over states
starting from the last one so the most common short sleep periods were
taking the longest time to select. Order is now swapped so that short
sleeps will get power state as quick as possible.

Signed-off-by: Krzysztof Chruściński <krzysztof.chruscinski@nordicsemi.no>
This commit is contained in:
Krzysztof Chruściński 2025-04-02 15:32:55 +02:00 committed by Benjamin Cabé
commit bb4fb12ca4

View file

@ -9,13 +9,12 @@
#include <zephyr/sys_clock.h>
#include <zephyr/pm/device.h>
extern int32_t max_latency_cyc;
const struct pm_state_info *pm_policy_next_state(uint8_t cpu, int32_t ticks)
{
int64_t cyc = -1;
uint8_t num_cpu_states;
const struct pm_state_info *cpu_states;
const struct pm_state_info *out_state = NULL;
#ifdef CONFIG_PM_NEED_ALL_DEVICES_IDLE
if (pm_device_is_any_busy()) {
@ -29,29 +28,25 @@ const struct pm_state_info *pm_policy_next_state(uint8_t cpu, int32_t ticks)
num_cpu_states = pm_state_cpu_get_all(cpu, &cpu_states);
for (int16_t i = (int16_t)num_cpu_states - 1; i >= 0; i--) {
for (uint32_t i = 0; i < num_cpu_states; i++) {
const struct pm_state_info *state = &cpu_states[i];
uint32_t min_residency_cyc, exit_latency_cyc;
uint32_t min_residency_ticks;
/* check if there is a lock on state + substate */
if (pm_policy_state_lock_is_active(state->state, state->substate_id)) {
min_residency_ticks =
k_us_to_ticks_ceil32(state->min_residency_us + state->exit_latency_us);
if (ticks < min_residency_ticks) {
/* If current state has higher residency then use the previous state; */
break;
}
/* check if state is available. */
if (!pm_policy_state_is_available(state->state, state->substate_id)) {
continue;
}
min_residency_cyc = k_us_to_cyc_ceil32(state->min_residency_us);
exit_latency_cyc = k_us_to_cyc_ceil32(state->exit_latency_us);
/* skip state if it brings too much latency */
if ((max_latency_cyc >= 0) &&
(exit_latency_cyc >= max_latency_cyc)) {
continue;
}
if ((cyc < 0) ||
(cyc >= (min_residency_cyc + exit_latency_cyc))) {
return state;
}
out_state = state;
}
return NULL;
return out_state;
}