diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 3dc44f216067..179bb269a58f 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -276,12 +276,15 @@ static void genpd_queue_power_off_work(struct generic_pm_domain *genpd) /** * genpd_power_off - Remove power from a given PM domain. * @genpd: PM domain to power down. - * @is_async: PM domain is powered down from a scheduled work + * @one_dev_on: If invoked from genpd's ->runtime_suspend|resume() callback, the + * RPM status of the releated device is in an intermediate state, not yet turned + * into RPM_SUSPENDED. This means genpd_power_off() must allow one device to not + * be RPM_SUSPENDED, while it tries to power off the PM domain. * * If all of the @genpd's devices have been suspended and all of its subdomains * have been powered down, remove power from @genpd. */ -static int genpd_power_off(struct generic_pm_domain *genpd, bool is_async) +static int genpd_power_off(struct generic_pm_domain *genpd, bool one_dev_on) { struct pm_domain_data *pdd; struct gpd_link *link; @@ -317,7 +320,7 @@ static int genpd_power_off(struct generic_pm_domain *genpd, bool is_async) not_suspended++; } - if (not_suspended > 1 || (not_suspended == 1 && is_async)) + if (not_suspended > 1 || (not_suspended == 1 && !one_dev_on)) return -EBUSY; if (genpd->gov && genpd->gov->power_down_ok) { @@ -459,7 +462,7 @@ static void genpd_power_off_work_fn(struct work_struct *work) genpd = container_of(work, struct generic_pm_domain, power_off_work); genpd_lock(genpd); - genpd_power_off(genpd, true); + genpd_power_off(genpd, false); genpd_unlock(genpd); } @@ -578,7 +581,7 @@ static int genpd_runtime_suspend(struct device *dev) return 0; genpd_lock(genpd); - genpd_power_off(genpd, false); + genpd_power_off(genpd, true); genpd_unlock(genpd); return 0; @@ -658,7 +661,7 @@ err_poweroff: if (!pm_runtime_is_irq_safe(dev) || (pm_runtime_is_irq_safe(dev) && genpd_is_irq_safe(genpd))) { genpd_lock(genpd); - genpd_power_off(genpd, 0); + genpd_power_off(genpd, true); genpd_unlock(genpd); }