From 56375fd420f851944960bd53dbb08d674f4d9406 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 12 Jul 2011 00:40:03 +0200 Subject: PM / Domains: Queue up power off work only if it is not pending In theory it is possible that pm_genpd_poweroff() for two different subdomains of the same parent domain will attempt to queue up the execution of pm_genpd_poweroff() for the parent twice in a row. This would lead to unpleasant consequences, so prevent it from happening by checking if genpd->power_off_work is pending before attempting to queue it up. Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'drivers/base') diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index b6e29ffbb70d..c3e4e2934e16 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -212,6 +212,19 @@ static bool genpd_abort_poweroff(struct generic_pm_domain *genpd) return genpd->status == GPD_STATE_ACTIVE || genpd->resume_count > 0; } +/** + * genpd_queue_power_off_work - Queue up the execution of pm_genpd_poweroff(). + * @genpd: PM domait to power off. + * + * Queue up the execution of pm_genpd_poweroff() unless it's already been done + * before. + */ +static void genpd_queue_power_off_work(struct generic_pm_domain *genpd) +{ + if (!work_pending(&genpd->power_off_work)) + queue_work(pm_wq, &genpd->power_off_work); +} + /** * pm_genpd_poweroff - Remove power from a given PM domain. * @genpd: PM domain to power down. @@ -304,7 +317,7 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd) if (parent) { genpd_sd_counter_dec(parent); if (parent->sd_count == 0) - queue_work(pm_wq, &parent->power_off_work); + genpd_queue_power_off_work(parent); genpd_release_lock(parent); } -- cgit v1.2.3