From: Ulf Hansson Date: Fri, 14 Mar 2025 10:00:58 +0000 (+0100) Subject: pmdomain: core: Add residency reflection for domain-idlestates to debugfs X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=0a8a888167ddaaec7a292e5045782b8a240e6f3e;p=users%2Fjedix%2Flinux-maple.git pmdomain: core: Add residency reflection for domain-idlestates to debugfs For regular cpuidle states we are reflecting over the selected/entered state to see if the sleep-duration meets the residency for the state. The output from the reflection is an "above" value to indicate the number of times the state was too deep and a "below" value for the number of times it was too shallow. Let's implement the similar thing for genpd's domain-idlestates along with genpd's governor and put the information in the genpd's debugfs. Signed-off-by: Ulf Hansson Link: https://lore.kernel.org/r/20250314100103.1294715-5-ulf.hansson@linaro.org --- diff --git a/drivers/pmdomain/core.c b/drivers/pmdomain/core.c index c79ef6e3ab85..3327de2f9ed2 100644 --- a/drivers/pmdomain/core.c +++ b/drivers/pmdomain/core.c @@ -304,10 +304,40 @@ static void genpd_update_accounting(struct generic_pm_domain *genpd) genpd->accounting_time = now; } + +static void genpd_reflect_residency(struct generic_pm_domain *genpd) +{ + struct genpd_governor_data *gd = genpd->gd; + struct genpd_power_state *state, *next_state; + unsigned int state_idx; + s64 sleep_ns, target_ns; + + if (!gd || !gd->reflect_residency) + return; + + sleep_ns = ktime_to_ns(ktime_sub(ktime_get(), gd->last_enter)); + state_idx = genpd->state_idx; + state = &genpd->states[state_idx]; + target_ns = state->power_off_latency_ns + state->residency_ns; + + if (sleep_ns < target_ns) { + state->above++; + } else if (state_idx < (genpd->state_count -1)) { + next_state = &genpd->states[state_idx + 1]; + target_ns = next_state->power_off_latency_ns + + next_state->residency_ns; + + if (sleep_ns >= target_ns) + state->below++; + } + + gd->reflect_residency = false; +} #else static inline void genpd_debug_add(struct generic_pm_domain *genpd) {} static inline void genpd_debug_remove(struct generic_pm_domain *genpd) {} static inline void genpd_update_accounting(struct generic_pm_domain *genpd) {} +static inline void genpd_reflect_residency(struct generic_pm_domain *genpd) {} #endif static int _genpd_reeval_performance_state(struct generic_pm_domain *genpd, @@ -982,6 +1012,9 @@ static int genpd_power_on(struct generic_pm_domain *genpd, unsigned int depth) if (genpd_status_on(genpd)) return 0; + /* Reflect over the entered idle-states residency for debugfs. */ + genpd_reflect_residency(genpd); + /* * The list is guaranteed not to change while the loop below is being * executed, unless one of the parents' .power_on() callbacks fiddles @@ -3517,7 +3550,7 @@ static int idle_states_show(struct seq_file *s, void *data) if (ret) return -ERESTARTSYS; - seq_puts(s, "State Time Spent(ms) Usage Rejected\n"); + seq_puts(s, "State Time Spent(ms) Usage Rejected Above Below\n"); for (i = 0; i < genpd->state_count; i++) { struct genpd_power_state *state = &genpd->states[i]; @@ -3537,9 +3570,10 @@ static int idle_states_show(struct seq_file *s, void *data) snprintf(state_name, ARRAY_SIZE(state_name), "S%-13d", i); do_div(idle_time, NSEC_PER_MSEC); - seq_printf(s, "%-14s %-14llu %-14llu %llu\n", + seq_printf(s, "%-14s %-14llu %-10llu %-10llu %-10llu %llu\n", state->name ?: state_name, idle_time, - state->usage, state->rejected); + state->usage, state->rejected, state->above, + state->below); } genpd_unlock(genpd); diff --git a/drivers/pmdomain/governor.c b/drivers/pmdomain/governor.c index d1a10eeebd16..c1e148657c87 100644 --- a/drivers/pmdomain/governor.c +++ b/drivers/pmdomain/governor.c @@ -392,6 +392,8 @@ static bool cpu_power_down_ok(struct dev_pm_domain *pd) if (idle_duration_ns >= (genpd->states[i].residency_ns + genpd->states[i].power_off_latency_ns)) { genpd->state_idx = i; + genpd->gd->last_enter = now; + genpd->gd->reflect_residency = true; return true; } } while (--i >= 0); diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 6e808aeecbcb..0b18160901a2 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -142,6 +142,8 @@ struct genpd_governor_data { bool max_off_time_changed; ktime_t next_wakeup; ktime_t next_hrtimer; + ktime_t last_enter; + bool reflect_residency; bool cached_power_down_ok; bool cached_power_down_state_idx; }; @@ -153,6 +155,8 @@ struct genpd_power_state { s64 residency_ns; u64 usage; u64 rejected; + u64 above; + u64 below; struct fwnode_handle *fwnode; u64 idle_time; void *data;