]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
clk: qcom: gdsc: Capture pm_genpd_add_subdomain result code
authorBryan O'Donoghue <bryan.odonoghue@linaro.org>
Fri, 17 Jan 2025 13:54:08 +0000 (13:54 +0000)
committerBjorn Andersson <andersson@kernel.org>
Sat, 8 Feb 2025 05:20:55 +0000 (23:20 -0600)
Adding a new clause to this if/else I noticed the existing usage of
pm_genpd_add_subdomain() wasn't capturing and returning the result code.

pm_genpd_add_subdomain() returns an int and can fail. Capture that result
code and throw it up the call stack if something goes wrong.

Fixes: 1b771839de05 ("clk: qcom: gdsc: enable optional power domain support")
Cc: stable@vger.kernel.org
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Link: https://lore.kernel.org/r/20250117-b4-linux-next-24-11-18-clock-multiple-power-domains-v10-2-13f2bb656dad@linaro.org
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
drivers/clk/qcom/gdsc.c

index bc1b1e37bf4222017c172b77603f8dedba961ed5..fdedf6dfe7b90c074b200353fc0c2b897863c79f 100644 (file)
@@ -506,6 +506,23 @@ err_disable_supply:
        return ret;
 }
 
+static void gdsc_pm_subdomain_remove(struct gdsc_desc *desc, size_t num)
+{
+       struct device *dev = desc->dev;
+       struct gdsc **scs = desc->scs;
+       int i;
+
+       /* Remove subdomains */
+       for (i = num - 1; i >= 0; i--) {
+               if (!scs[i])
+                       continue;
+               if (scs[i]->parent)
+                       pm_genpd_remove_subdomain(scs[i]->parent, &scs[i]->pd);
+               else if (!IS_ERR_OR_NULL(dev->pm_domain))
+                       pm_genpd_remove_subdomain(pd_to_genpd(dev->pm_domain), &scs[i]->pd);
+       }
+}
+
 int gdsc_register(struct gdsc_desc *desc,
                  struct reset_controller_dev *rcdev, struct regmap *regmap)
 {
@@ -555,30 +572,27 @@ int gdsc_register(struct gdsc_desc *desc,
                if (!scs[i])
                        continue;
                if (scs[i]->parent)
-                       pm_genpd_add_subdomain(scs[i]->parent, &scs[i]->pd);
+                       ret = pm_genpd_add_subdomain(scs[i]->parent, &scs[i]->pd);
                else if (!IS_ERR_OR_NULL(dev->pm_domain))
-                       pm_genpd_add_subdomain(pd_to_genpd(dev->pm_domain), &scs[i]->pd);
+                       ret = pm_genpd_add_subdomain(pd_to_genpd(dev->pm_domain), &scs[i]->pd);
+               if (ret)
+                       goto err_pm_subdomain_remove;
        }
 
        return of_genpd_add_provider_onecell(dev->of_node, data);
+
+err_pm_subdomain_remove:
+       gdsc_pm_subdomain_remove(desc, i);
+
+       return ret;
 }
 
 void gdsc_unregister(struct gdsc_desc *desc)
 {
-       int i;
        struct device *dev = desc->dev;
-       struct gdsc **scs = desc->scs;
        size_t num = desc->num;
 
-       /* Remove subdomains */
-       for (i = num - 1; i >= 0; i--) {
-               if (!scs[i])
-                       continue;
-               if (scs[i]->parent)
-                       pm_genpd_remove_subdomain(scs[i]->parent, &scs[i]->pd);
-               else if (!IS_ERR_OR_NULL(dev->pm_domain))
-                       pm_genpd_remove_subdomain(pd_to_genpd(dev->pm_domain), &scs[i]->pd);
-       }
+       gdsc_pm_subdomain_remove(desc, num);
        of_genpd_del_provider(dev->of_node);
 }