Skip to content

Commit 9861f21

Browse files
committed
pmdomain: core: Add genpd helper to correct the usage/rejected counters
In the cpuidle-psci-domain case the ->power_off() callback is usually returning zero to indicate success. This is because the actual call to the PSCI FW to enter the selected domain-idlestate, needs to be done after the ->power_off() callback has returned. When the call to the PSCI FW fails, this leads to receiving an incorrect tracking of the usage/rejected counts for the selected domain-idlestate. In other words, the presented debug-statistics for genpd may look better than what the actually are. To allow a better correctness of the data, let's add a new genpd helper function, which enables the caller adjust the usage/rejected counters for a domain-idlestate, in cases of errors during power-off. Signed-off-by: Ulf Hansson <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 9c32cda commit 9861f21

File tree

2 files changed

+31
-0
lines changed

2 files changed

+31
-0
lines changed

drivers/pmdomain/core.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,31 @@ int dev_pm_genpd_rpm_always_on(struct device *dev, bool on)
728728
}
729729
EXPORT_SYMBOL_GPL(dev_pm_genpd_rpm_always_on);
730730

731+
/**
732+
* pm_genpd_inc_rejected() - Adjust the rejected/usage counts for an idle-state.
733+
*
734+
* @genpd: The PM domain the idle-state belongs to.
735+
* @state_idx: The index of the idle-state that failed.
736+
*
737+
* In some special cases the ->power_off() callback is asynchronously powering
738+
* off the PM domain, leading to that it may return zero to indicate success,
739+
* even though the actual power-off could fail. To account for this correctly in
740+
* the rejected/usage counts for the idle-state statistics, users can call this
741+
* function to adjust the values.
742+
*
743+
* It is assumed that the users guarantee that the genpd doesn't get removed
744+
* while this routine is getting called.
745+
*/
746+
void pm_genpd_inc_rejected(struct generic_pm_domain *genpd,
747+
unsigned int state_idx)
748+
{
749+
genpd_lock(genpd);
750+
genpd->states[genpd->state_idx].rejected++;
751+
genpd->states[genpd->state_idx].usage--;
752+
genpd_unlock(genpd);
753+
}
754+
EXPORT_SYMBOL_GPL(pm_genpd_inc_rejected);
755+
731756
static int _genpd_power_on(struct generic_pm_domain *genpd, bool timed)
732757
{
733758
unsigned int state_idx = genpd->state_idx;

include/linux/pm_domain.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,8 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
285285
int pm_genpd_init(struct generic_pm_domain *genpd,
286286
struct dev_power_governor *gov, bool is_off);
287287
int pm_genpd_remove(struct generic_pm_domain *genpd);
288+
void pm_genpd_inc_rejected(struct generic_pm_domain *genpd,
289+
unsigned int state_idx);
288290
struct device *dev_to_genpd_dev(struct device *dev);
289291
int dev_pm_genpd_set_performance_state(struct device *dev, unsigned int state);
290292
int dev_pm_genpd_add_notifier(struct device *dev, struct notifier_block *nb);
@@ -336,6 +338,10 @@ static inline int pm_genpd_remove(struct generic_pm_domain *genpd)
336338
return -EOPNOTSUPP;
337339
}
338340

341+
static inline void pm_genpd_inc_rejected(struct generic_pm_domain *genpd,
342+
unsigned int state_idx)
343+
{ }
344+
339345
static inline struct device *dev_to_genpd_dev(struct device *dev)
340346
{
341347
return ERR_PTR(-EOPNOTSUPP);

0 commit comments

Comments
 (0)