Skip to content

Commit 3e23568

Browse files
storulfrafaeljw
authored andcommitted
PM / Domains: Free pm_subsys_data in error path in __pm_genpd_add_device()
The error path in __pm_genpd_add_device() didn't decrease the reference to the struct pm_subsys_data. Let's move the calls to dev_pm_get|put_subsys_data() into genpd_alloc|free_dev_data() to fix this issue and thus prevent a potential memory leakage. Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent c0356db commit 3e23568

File tree

1 file changed

+16
-9
lines changed

1 file changed

+16
-9
lines changed

drivers/base/power/domain.c

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1380,18 +1380,30 @@ EXPORT_SYMBOL_GPL(pm_genpd_syscore_poweron);
13801380
static struct generic_pm_domain_data *genpd_alloc_dev_data(struct device *dev)
13811381
{
13821382
struct generic_pm_domain_data *gpd_data;
1383+
int ret;
1384+
1385+
ret = dev_pm_get_subsys_data(dev);
1386+
if (ret)
1387+
return ERR_PTR(ret);
13831388

13841389
gpd_data = kzalloc(sizeof(*gpd_data), GFP_KERNEL);
1385-
if (!gpd_data)
1386-
return NULL;
1390+
if (!gpd_data) {
1391+
ret = -ENOMEM;
1392+
goto err_put;
1393+
}
13871394

13881395
return gpd_data;
1396+
1397+
err_put:
1398+
dev_pm_put_subsys_data(dev);
1399+
return ERR_PTR(ret);
13891400
}
13901401

13911402
static void genpd_free_dev_data(struct device *dev,
13921403
struct generic_pm_domain_data *gpd_data)
13931404
{
13941405
kfree(gpd_data);
1406+
dev_pm_put_subsys_data(dev);
13951407
}
13961408

13971409
/**
@@ -1412,8 +1424,8 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
14121424
return -EINVAL;
14131425

14141426
gpd_data = genpd_alloc_dev_data(dev);
1415-
if (!gpd_data)
1416-
return -ENOMEM;
1427+
if (IS_ERR(gpd_data))
1428+
return PTR_ERR(gpd_data);
14171429

14181430
genpd_acquire_lock(genpd);
14191431

@@ -1422,10 +1434,6 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
14221434
goto out;
14231435
}
14241436

1425-
ret = dev_pm_get_subsys_data(dev);
1426-
if (ret)
1427-
goto out;
1428-
14291437
spin_lock_irq(&dev->power.lock);
14301438

14311439
if (dev->power.subsys_data->domain_data) {
@@ -1528,7 +1536,6 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
15281536

15291537
genpd_release_lock(genpd);
15301538

1531-
dev_pm_put_subsys_data(dev);
15321539
genpd_free_dev_data(dev, gpd_data);
15331540

15341541
return 0;

0 commit comments

Comments
 (0)