Skip to content

Commit 0a8a888

Browse files
committed
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 <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent d0252ba commit 0a8a888

File tree

3 files changed

+43
-3
lines changed

3 files changed

+43
-3
lines changed

drivers/pmdomain/core.c

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -304,10 +304,40 @@ static void genpd_update_accounting(struct generic_pm_domain *genpd)
304304

305305
genpd->accounting_time = now;
306306
}
307+
308+
static void genpd_reflect_residency(struct generic_pm_domain *genpd)
309+
{
310+
struct genpd_governor_data *gd = genpd->gd;
311+
struct genpd_power_state *state, *next_state;
312+
unsigned int state_idx;
313+
s64 sleep_ns, target_ns;
314+
315+
if (!gd || !gd->reflect_residency)
316+
return;
317+
318+
sleep_ns = ktime_to_ns(ktime_sub(ktime_get(), gd->last_enter));
319+
state_idx = genpd->state_idx;
320+
state = &genpd->states[state_idx];
321+
target_ns = state->power_off_latency_ns + state->residency_ns;
322+
323+
if (sleep_ns < target_ns) {
324+
state->above++;
325+
} else if (state_idx < (genpd->state_count -1)) {
326+
next_state = &genpd->states[state_idx + 1];
327+
target_ns = next_state->power_off_latency_ns +
328+
next_state->residency_ns;
329+
330+
if (sleep_ns >= target_ns)
331+
state->below++;
332+
}
333+
334+
gd->reflect_residency = false;
335+
}
307336
#else
308337
static inline void genpd_debug_add(struct generic_pm_domain *genpd) {}
309338
static inline void genpd_debug_remove(struct generic_pm_domain *genpd) {}
310339
static inline void genpd_update_accounting(struct generic_pm_domain *genpd) {}
340+
static inline void genpd_reflect_residency(struct generic_pm_domain *genpd) {}
311341
#endif
312342

313343
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)
9821012
if (genpd_status_on(genpd))
9831013
return 0;
9841014

1015+
/* Reflect over the entered idle-states residency for debugfs. */
1016+
genpd_reflect_residency(genpd);
1017+
9851018
/*
9861019
* The list is guaranteed not to change while the loop below is being
9871020
* 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)
35173550
if (ret)
35183551
return -ERESTARTSYS;
35193552

3520-
seq_puts(s, "State Time Spent(ms) Usage Rejected\n");
3553+
seq_puts(s, "State Time Spent(ms) Usage Rejected Above Below\n");
35213554

35223555
for (i = 0; i < genpd->state_count; i++) {
35233556
struct genpd_power_state *state = &genpd->states[i];
@@ -3537,9 +3570,10 @@ static int idle_states_show(struct seq_file *s, void *data)
35373570
snprintf(state_name, ARRAY_SIZE(state_name), "S%-13d", i);
35383571

35393572
do_div(idle_time, NSEC_PER_MSEC);
3540-
seq_printf(s, "%-14s %-14llu %-14llu %llu\n",
3573+
seq_printf(s, "%-14s %-14llu %-10llu %-10llu %-10llu %llu\n",
35413574
state->name ?: state_name, idle_time,
3542-
state->usage, state->rejected);
3575+
state->usage, state->rejected, state->above,
3576+
state->below);
35433577
}
35443578

35453579
genpd_unlock(genpd);

drivers/pmdomain/governor.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,8 @@ static bool cpu_power_down_ok(struct dev_pm_domain *pd)
392392
if (idle_duration_ns >= (genpd->states[i].residency_ns +
393393
genpd->states[i].power_off_latency_ns)) {
394394
genpd->state_idx = i;
395+
genpd->gd->last_enter = now;
396+
genpd->gd->reflect_residency = true;
395397
return true;
396398
}
397399
} while (--i >= 0);

include/linux/pm_domain.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ struct genpd_governor_data {
142142
bool max_off_time_changed;
143143
ktime_t next_wakeup;
144144
ktime_t next_hrtimer;
145+
ktime_t last_enter;
146+
bool reflect_residency;
145147
bool cached_power_down_ok;
146148
bool cached_power_down_state_idx;
147149
};
@@ -153,6 +155,8 @@ struct genpd_power_state {
153155
s64 residency_ns;
154156
u64 usage;
155157
u64 rejected;
158+
u64 above;
159+
u64 below;
156160
struct fwnode_handle *fwnode;
157161
u64 idle_time;
158162
void *data;

0 commit comments

Comments
 (0)