aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/power
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2012-05-01 15:33:53 -0400
committerRafael J. Wysocki <rjw@sisk.pl>2012-05-05 15:51:50 -0400
commitefa6902501ffc87d69bfb10b8a09b7d6ee222d77 (patch)
tree1fc2840dea09457e84c8b593e2ad7ff9f77ce501 /drivers/base/power
parent23e0fc5ae64925e0ff1b6221b83dff1b217545df (diff)
PM / Domains: Make device removal more straightforward
The removal of a device from a PM domain doesn't have to browse the domain's device list, because it can check directly if the device belongs to the given domain. Moreover, it should clear the domain_data pointer in dev->power.subsys_data, because dev_pm_put_subsys_data(dev) may not remove dev->power.subsys_data and the stale domain data pointer may cause problems to happen. Rework pm_genpd_remove_device() taking the above observations into account. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Diffstat (limited to 'drivers/base/power')
-rw-r--r--drivers/base/power/domain.c27
1 files changed, 11 insertions, 16 deletions
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 45c2b7f0fe3b..6ae5672c35ab 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -1279,11 +1279,13 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
1279 struct device *dev) 1279 struct device *dev)
1280{ 1280{
1281 struct pm_domain_data *pdd; 1281 struct pm_domain_data *pdd;
1282 int ret = -EINVAL; 1282 int ret = 0;
1283 1283
1284 dev_dbg(dev, "%s()\n", __func__); 1284 dev_dbg(dev, "%s()\n", __func__);
1285 1285
1286 if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(dev)) 1286 if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(dev)
1287 || IS_ERR_OR_NULL(dev->pm_domain)
1288 || pd_to_genpd(dev->pm_domain) != genpd)
1287 return -EINVAL; 1289 return -EINVAL;
1288 1290
1289 genpd_acquire_lock(genpd); 1291 genpd_acquire_lock(genpd);
@@ -1293,21 +1295,14 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
1293 goto out; 1295 goto out;
1294 } 1296 }
1295 1297
1296 list_for_each_entry(pdd, &genpd->dev_list, list_node) { 1298 dev->pm_domain = NULL;
1297 if (pdd->dev != dev) 1299 pdd = dev->power.subsys_data->domain_data;
1298 continue; 1300 list_del_init(&pdd->list_node);
1299 1301 dev->power.subsys_data->domain_data = NULL;
1300 list_del_init(&pdd->list_node); 1302 dev_pm_put_subsys_data(dev);
1301 pdd->dev = NULL; 1303 kfree(to_gpd_data(pdd));
1302 dev_pm_put_subsys_data(dev);
1303 dev->pm_domain = NULL;
1304 kfree(to_gpd_data(pdd));
1305
1306 genpd->device_count--;
1307 1304
1308 ret = 0; 1305 genpd->device_count--;
1309 break;
1310 }
1311 1306
1312 out: 1307 out:
1313 genpd_release_lock(genpd); 1308 genpd_release_lock(genpd);