PM / Domains: Don't allow an existing generic_pm_domain_data
authorUlf Hansson <ulf.hansson@linaro.org>
Tue, 27 Jan 2015 20:13:40 +0000 (21:13 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 3 Feb 2015 21:56:53 +0000 (22:56 +0100)
When adding a device to a genpd, a struct generic_pm_domain_data is
allocated per device.

Verify that there are no existing generic_pm_domain_data for the device
we are about to add, since that tells us it has already been added to a
genpd.

When genpd supported PM domain device callbacks, this was a valid
scenario. Now it isn't so let's return an error code.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
drivers/base/power/domain.c

index 351df5bbd9c92fe019b6005422d3ac25bc2f671b..76eb0c3ef2b34c4bd9cf782aa17207518e661f60 100644 (file)
@@ -1444,26 +1444,30 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
        if (ret)
                goto out;
 
-       genpd->device_count++;
-       genpd->max_off_time_changed = true;
-
        spin_lock_irq(&dev->power.lock);
 
-       dev->pm_domain = &genpd->domain;
        if (dev->power.subsys_data->domain_data) {
-               gpd_data = to_gpd_data(dev->power.subsys_data->domain_data);
-       } else {
-               gpd_data = gpd_data_new;
-               dev->power.subsys_data->domain_data = &gpd_data->base;
+               spin_unlock_irq(&dev->power.lock);
+               ret = -EINVAL;
+               goto out;
        }
+
+       gpd_data = gpd_data_new;
+       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;
+
        mutex_lock(&gpd_data->lock);
        gpd_data->base.dev = dev;
        list_add_tail(&gpd_data->base.list_node, &genpd->dev_list);