Properly handle and cleanup errors in gdsc_register() instead of just returning an error and leaving some of resources registered/hanging in the system. Fixes: c2c7f0a47493 ("clk: qcom: gdsc: Add support for hierarchical power domains") Fixes: 45dd0e55317c ("clk: qcom: Add support for GDSCs") Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@xxxxxxxxxx> --- drivers/clk/qcom/gdsc.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/drivers/clk/qcom/gdsc.c b/drivers/clk/qcom/gdsc.c index 51ed640e527b..241186d9d08c 100644 --- a/drivers/clk/qcom/gdsc.c +++ b/drivers/clk/qcom/gdsc.c @@ -429,7 +429,7 @@ int gdsc_register(struct gdsc_desc *desc, scs[i]->rcdev = rcdev; ret = gdsc_init(scs[i]); if (ret) - return ret; + goto err_init; data->domains[i] = &scs[i]->pd; } @@ -437,11 +437,35 @@ int gdsc_register(struct gdsc_desc *desc, for (i = 0; i < num; i++) { if (!scs[i]) continue; - if (scs[i]->parent) - pm_genpd_add_subdomain(scs[i]->parent, &scs[i]->pd); + if (scs[i]->parent) { + ret = pm_genpd_add_subdomain(scs[i]->parent, &scs[i]->pd); + if (ret) + goto err_subdomain; + } } - return of_genpd_add_provider_onecell(dev->of_node, data); + ret = of_genpd_add_provider_onecell(dev->of_node, data); + if (!ret) + return 0; + +err_subdomain: + i--; + for (; i >= 0; i--) { + if (!scs[i] || !scs[i]->parent) + continue; + pm_genpd_remove_subdomain(scs[i]->parent, &scs[i]->pd); + } + i = num; + +err_init: + i--; + for (; i >= 0; i--) { + if (!scs[i]) + continue; + pm_genpd_remove(&scs[i]->pd); + } + + return ret; } void gdsc_unregister(struct gdsc_desc *desc) -- 2.30.2