diff options
author | Ulf Hansson <ulf.hansson@linaro.org> | 2025-03-14 13:00:55 +0300 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@linaro.org> | 2025-04-23 11:08:33 +0300 |
commit | 9861f21ff16b6cd919144dae7ff355d5145a3474 (patch) | |
tree | d4d212eb7163bdfd95d0c742a92ca0736b25b588 | |
parent | 9c32cda43eb78f78c73aee4aa344b777714e259b (diff) | |
download | linux-9861f21ff16b6cd919144dae7ff355d5145a3474.tar.xz |
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 <ulf.hansson@linaro.org>
Link: https://lore.kernel.org/r/20250314100103.1294715-2-ulf.hansson@linaro.org
-rw-r--r-- | drivers/pmdomain/core.c | 25 | ||||
-rw-r--r-- | include/linux/pm_domain.h | 6 |
2 files changed, 31 insertions, 0 deletions
diff --git a/drivers/pmdomain/core.c b/drivers/pmdomain/core.c index 9b2f28b34bb5..c79ef6e3ab85 100644 --- a/drivers/pmdomain/core.c +++ b/drivers/pmdomain/core.c @@ -728,6 +728,31 @@ int dev_pm_genpd_rpm_always_on(struct device *dev, bool on) } EXPORT_SYMBOL_GPL(dev_pm_genpd_rpm_always_on); +/** + * pm_genpd_inc_rejected() - Adjust the rejected/usage counts for an idle-state. + * + * @genpd: The PM domain the idle-state belongs to. + * @state_idx: The index of the idle-state that failed. + * + * In some special cases the ->power_off() callback is asynchronously powering + * off the PM domain, leading to that it may return zero to indicate success, + * even though the actual power-off could fail. To account for this correctly in + * the rejected/usage counts for the idle-state statistics, users can call this + * function to adjust the values. + * + * It is assumed that the users guarantee that the genpd doesn't get removed + * while this routine is getting called. + */ +void pm_genpd_inc_rejected(struct generic_pm_domain *genpd, + unsigned int state_idx) +{ + genpd_lock(genpd); + genpd->states[genpd->state_idx].rejected++; + genpd->states[genpd->state_idx].usage--; + genpd_unlock(genpd); +} +EXPORT_SYMBOL_GPL(pm_genpd_inc_rejected); + static int _genpd_power_on(struct generic_pm_domain *genpd, bool timed) { unsigned int state_idx = genpd->state_idx; diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index d56a78af4af1..6e808aeecbcb 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -285,6 +285,8 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, int pm_genpd_init(struct generic_pm_domain *genpd, struct dev_power_governor *gov, bool is_off); int pm_genpd_remove(struct generic_pm_domain *genpd); +void pm_genpd_inc_rejected(struct generic_pm_domain *genpd, + unsigned int state_idx); struct device *dev_to_genpd_dev(struct device *dev); int dev_pm_genpd_set_performance_state(struct device *dev, unsigned int state); 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) return -EOPNOTSUPP; } +static inline void pm_genpd_inc_rejected(struct generic_pm_domain *genpd, + unsigned int state_idx) +{ } + static inline struct device *dev_to_genpd_dev(struct device *dev) { return ERR_PTR(-EOPNOTSUPP); |