]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
pmdomain: core: Fix error path in pm_genpd_init() when ida alloc fails
authorUlf Hansson <ulf.hansson@linaro.org>
Fri, 22 Nov 2024 13:42:03 +0000 (14:42 +0100)
committerUlf Hansson <ulf.hansson@linaro.org>
Mon, 2 Dec 2024 16:06:09 +0000 (17:06 +0100)
When the ida allocation fails we need to free up the previously allocated
memory before returning the error code. Let's fix this and while at it,
let's also move the ida allocation to genpd_alloc_data() and the freeing to
genpd_free_data(), as it better belongs there.

Fixes: 899f44531fe6 ("pmdomain: core: Add GENPD_FLAG_DEV_NAME_FW flag")
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Message-ID: <20241122134207.157283-3-ulf.hansson@linaro.org>

drivers/pmdomain/core.c

index 4d8b0d18bb4a4dce1873cf3bed32aec70e1274d5..bb11f467dc78c7dd0a695f0b26c425f54b2fea26 100644 (file)
@@ -2172,8 +2172,24 @@ static int genpd_alloc_data(struct generic_pm_domain *genpd)
        }
 
        genpd->gd = gd;
-       return 0;
+       device_initialize(&genpd->dev);
+
+       if (!genpd_is_dev_name_fw(genpd)) {
+               dev_set_name(&genpd->dev, "%s", genpd->name);
+       } else {
+               ret = ida_alloc(&genpd_ida, GFP_KERNEL);
+               if (ret < 0)
+                       goto put;
 
+               genpd->device_id = ret;
+               dev_set_name(&genpd->dev, "%s_%u", genpd->name, genpd->device_id);
+       }
+
+       return 0;
+put:
+       put_device(&genpd->dev);
+       if (genpd->free_states == genpd_free_default_power_state)
+               kfree(genpd->states);
 free:
        if (genpd_is_cpu_domain(genpd))
                free_cpumask_var(genpd->cpus);
@@ -2184,6 +2200,8 @@ free:
 static void genpd_free_data(struct generic_pm_domain *genpd)
 {
        put_device(&genpd->dev);
+       if (genpd->device_id != -ENXIO)
+               ida_free(&genpd_ida, genpd->device_id);
        if (genpd_is_cpu_domain(genpd))
                free_cpumask_var(genpd->cpus);
        if (genpd->free_states)
@@ -2272,20 +2290,6 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
        if (ret)
                return ret;
 
-       device_initialize(&genpd->dev);
-
-       if (!genpd_is_dev_name_fw(genpd)) {
-               dev_set_name(&genpd->dev, "%s", genpd->name);
-       } else {
-               ret = ida_alloc(&genpd_ida, GFP_KERNEL);
-               if (ret < 0) {
-                       put_device(&genpd->dev);
-                       return ret;
-               }
-               genpd->device_id = ret;
-               dev_set_name(&genpd->dev, "%s_%u", genpd->name, genpd->device_id);
-       }
-
        mutex_lock(&gpd_list_lock);
        list_add(&genpd->gpd_list_node, &gpd_list);
        mutex_unlock(&gpd_list_lock);
@@ -2326,8 +2330,6 @@ static int genpd_remove(struct generic_pm_domain *genpd)
        genpd_unlock(genpd);
        genpd_debug_remove(genpd);
        cancel_work_sync(&genpd->power_off_work);
-       if (genpd->device_id != -ENXIO)
-               ida_free(&genpd_ida, genpd->device_id);
        genpd_free_data(genpd);
 
        pr_debug("%s: removed %s\n", __func__, dev_name(&genpd->dev));