提交 9e08cf42 编写于 作者: R Rafael J. Wysocki

PM / Domains: Make pm_genpd_poweron() always survive parent removal

If pm_genpd_remove_subdomain() is called to remove a PM domain's
subdomain and pm_genpd_poweron() is called for that subdomain at
the same time, and the pm_genpd_poweron() called by it recursively
for the parent returns an error, the first pm_genpd_poweron()'s
error code path will attempt to decrement the subdomain counter of
a PM domain that it's not a subdomain of any more.

Rearrange the code in pm_genpd_poweron() to prevent this from
happening.
Signed-off-by: NRafael J. Wysocki <rjw@sisk.pl>
上级 3c07cbc4
...@@ -89,12 +89,14 @@ static void genpd_set_active(struct generic_pm_domain *genpd) ...@@ -89,12 +89,14 @@ static void genpd_set_active(struct generic_pm_domain *genpd)
*/ */
int pm_genpd_poweron(struct generic_pm_domain *genpd) int pm_genpd_poweron(struct generic_pm_domain *genpd)
{ {
struct generic_pm_domain *parent = genpd->parent; struct generic_pm_domain *parent;
int ret = 0; int ret = 0;
start:
mutex_lock(&genpd->lock); mutex_lock(&genpd->lock);
parent = genpd->parent;
start:
if (genpd->status == GPD_STATE_ACTIVE if (genpd->status == GPD_STATE_ACTIVE
|| (genpd->prepared_count > 0 && genpd->suspend_power_off)) || (genpd->prepared_count > 0 && genpd->suspend_power_off))
goto out; goto out;
...@@ -110,29 +112,34 @@ int pm_genpd_poweron(struct generic_pm_domain *genpd) ...@@ -110,29 +112,34 @@ int pm_genpd_poweron(struct generic_pm_domain *genpd)
mutex_unlock(&genpd->lock); mutex_unlock(&genpd->lock);
ret = pm_genpd_poweron(parent); ret = pm_genpd_poweron(parent);
if (ret) {
genpd_sd_counter_dec(parent); mutex_lock(&genpd->lock);
return ret;
} if (ret)
goto err;
parent = NULL; parent = NULL;
goto start; goto start;
} }
if (genpd->power_on) if (genpd->power_on) {
ret = genpd->power_on(genpd); ret = genpd->power_on(genpd);
if (ret)
if (ret) { goto err;
if (genpd->parent)
genpd_sd_counter_dec(genpd->parent);
} else {
genpd_set_active(genpd);
} }
genpd_set_active(genpd);
out: out:
mutex_unlock(&genpd->lock); mutex_unlock(&genpd->lock);
return ret; return ret;
err:
if (genpd->parent)
genpd_sd_counter_dec(genpd->parent);
goto out;
} }
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册