diff options
author | Rafael J. Wysocki <rjw@sisk.pl> | 2012-05-01 15:33:53 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rjw@sisk.pl> | 2012-05-05 15:51:50 -0400 |
commit | efa6902501ffc87d69bfb10b8a09b7d6ee222d77 (patch) | |
tree | 1fc2840dea09457e84c8b593e2ad7ff9f77ce501 /drivers/base | |
parent | 23e0fc5ae64925e0ff1b6221b83dff1b217545df (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')
-rw-r--r-- | drivers/base/power/domain.c | 27 |
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); |