aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorUlf Hansson <ulf.hansson@linaro.org>2015-01-27 21:13:44 +0100
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-02-03 22:56:54 +0100
commitf104e1e5ef5788f02de2053bfbd0f02d629b6036 (patch)
treef336adc77a74f738525b3693dcf5bb6fbd08423e /drivers
parentPM / Domains: Free pm_subsys_data in error path in __pm_genpd_add_device() (diff)
downloadlinux-dev-f104e1e5ef5788f02de2053bfbd0f02d629b6036.tar.xz
linux-dev-f104e1e5ef5788f02de2053bfbd0f02d629b6036.zip
PM / Domains: Re-order initialization of generic_pm_domain_data
Move the initialization of the struct generic_pm_domain_data into genpd_alloc_dev_data(), including the assignment of the device's ->pm_domain() callback. Make corresponding changes to genpd_free_dev_data(). These changes will make the related code more readable. It will also decrease the critical regions for where genpd's mutex is being held and for where the device's power related spinlock is being held. Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/base/power/domain.c67
1 files changed, 35 insertions, 32 deletions
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 3bd342f22519..0fd5ee127c30 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -1377,7 +1377,9 @@ EXPORT_SYMBOL_GPL(pm_genpd_syscore_poweron);
#endif /* CONFIG_PM_SLEEP */
-static struct generic_pm_domain_data *genpd_alloc_dev_data(struct device *dev)
+static struct generic_pm_domain_data *genpd_alloc_dev_data(struct device *dev,
+ struct generic_pm_domain *genpd,
+ struct gpd_timing_data *td)
{
struct generic_pm_domain_data *gpd_data;
int ret;
@@ -1392,8 +1394,32 @@ static struct generic_pm_domain_data *genpd_alloc_dev_data(struct device *dev)
goto err_put;
}
+ if (td)
+ gpd_data->td = *td;
+
+ gpd_data->base.dev = dev;
+ gpd_data->need_restore = -1;
+ gpd_data->td.constraint_changed = true;
+ gpd_data->td.effective_constraint_ns = -1;
+ gpd_data->nb.notifier_call = genpd_dev_pm_qos_notifier;
+
+ spin_lock_irq(&dev->power.lock);
+
+ if (dev->power.subsys_data->domain_data) {
+ ret = -EINVAL;
+ goto err_free;
+ }
+
+ dev->power.subsys_data->domain_data = &gpd_data->base;
+ dev->pm_domain = &genpd->domain;
+
+ spin_unlock_irq(&dev->power.lock);
+
return gpd_data;
+ err_free:
+ spin_unlock_irq(&dev->power.lock);
+ kfree(gpd_data);
err_put:
dev_pm_put_subsys_data(dev);
return ERR_PTR(ret);
@@ -1402,6 +1428,13 @@ static struct generic_pm_domain_data *genpd_alloc_dev_data(struct device *dev)
static void genpd_free_dev_data(struct device *dev,
struct generic_pm_domain_data *gpd_data)
{
+ spin_lock_irq(&dev->power.lock);
+
+ dev->pm_domain = NULL;
+ dev->power.subsys_data->domain_data = NULL;
+
+ spin_unlock_irq(&dev->power.lock);
+
kfree(gpd_data);
dev_pm_put_subsys_data(dev);
}
@@ -1423,7 +1456,7 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(dev))
return -EINVAL;
- gpd_data = genpd_alloc_dev_data(dev);
+ gpd_data = genpd_alloc_dev_data(dev, genpd, td);
if (IS_ERR(gpd_data))
return PTR_ERR(gpd_data);
@@ -1434,35 +1467,13 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
goto out;
}
- spin_lock_irq(&dev->power.lock);
-
- if (dev->power.subsys_data->domain_data) {
- spin_unlock_irq(&dev->power.lock);
- ret = -EINVAL;
- goto out;
- }
-
- dev->power.subsys_data->domain_data = &gpd_data->base;
-
- if (td)
- gpd_data->td = *td;
-
- dev->pm_domain = &genpd->domain;
-
- spin_unlock_irq(&dev->power.lock);
-
if (genpd->attach_dev)
genpd->attach_dev(genpd, dev);
genpd->device_count++;
genpd->max_off_time_changed = true;
- gpd_data->base.dev = dev;
list_add_tail(&gpd_data->base.list_node, &genpd->dev_list);
- gpd_data->need_restore = -1;
- gpd_data->td.constraint_changed = true;
- gpd_data->td.effective_constraint_ns = -1;
- gpd_data->nb.notifier_call = genpd_dev_pm_qos_notifier;
out:
genpd_release_lock(genpd);
@@ -1524,15 +1535,7 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
if (genpd->detach_dev)
genpd->detach_dev(genpd, dev);
- spin_lock_irq(&dev->power.lock);
-
- dev->pm_domain = NULL;
list_del_init(&pdd->list_node);
- dev->power.subsys_data->domain_data = NULL;
-
- spin_unlock_irq(&dev->power.lock);
-
- pdd->dev = NULL;
genpd_release_lock(genpd);