diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 3d96e4da2d98..a7c2673ffd36 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -1257,10 +1257,7 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on) struct acpi_device *adev = ACPI_COMPANION(dev); if (!adev) - return -ENODEV; - - if (dev->pm_domain) - return -EEXIST; + return 0; /* * Only attach the power domain to the first device if the @@ -1268,7 +1265,7 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on) * management twice. */ if (!acpi_device_is_first_physical_node(adev, dev)) - return -EBUSY; + return 0; acpi_add_pm_notifier(adev, dev, acpi_pm_notify_work_func); dev_pm_domain_set(dev, &acpi_general_pm_domain); @@ -1278,7 +1275,7 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on) } dev->pm_domain->detach = acpi_dev_pm_detach; - return 0; + return 1; } EXPORT_SYMBOL_GPL(acpi_dev_pm_attach); #endif /* CONFIG_PM */ diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index 4a3ac31c07d0..b0160b5c5608 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -248,7 +248,7 @@ static int amba_probe(struct device *dev) break; ret = dev_pm_domain_attach(dev, true); - if (ret == -EPROBE_DEFER) + if (ret) break; ret = amba_get_enable_pclk(pcdev); @@ -375,7 +375,7 @@ static int amba_device_try_add(struct amba_device *dev, struct resource *parent) } ret = dev_pm_domain_attach(&dev->dev, true); - if (ret == -EPROBE_DEFER) { + if (ret) { iounmap(tmp); goto err_release; } diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 8075ddc70a17..9460139d9b02 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -572,17 +572,16 @@ static int platform_drv_probe(struct device *_dev) return ret; ret = dev_pm_domain_attach(_dev, true); - if (ret != -EPROBE_DEFER) { - if (drv->probe) { - ret = drv->probe(dev); - if (ret) - dev_pm_domain_detach(_dev, true); - } else { - /* don't fail if just dev_pm_domain_attach failed */ - ret = 0; - } + if (ret) + goto out; + + if (drv->probe) { + ret = drv->probe(dev); + if (ret) + dev_pm_domain_detach(_dev, true); } +out: if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER) { dev_warn(_dev, "probe deferral not supported\n"); ret = -ENXIO; diff --git a/drivers/base/power/common.c b/drivers/base/power/common.c index f6a9ad52cbbf..7ae62b6355b8 100644 --- a/drivers/base/power/common.c +++ b/drivers/base/power/common.c @@ -98,17 +98,21 @@ EXPORT_SYMBOL_GPL(dev_pm_put_subsys_data); * Callers must ensure proper synchronization of this function with power * management callbacks. * - * Returns 0 on successfully attached PM domain or negative error code. + * Returns 0 on successfully attached PM domain, or when it is found that the + * device doesn't need a PM domain, else a negative error code. */ int dev_pm_domain_attach(struct device *dev, bool power_on) { int ret; + if (dev->pm_domain) + return 0; + ret = acpi_dev_pm_attach(dev, power_on); - if (ret) + if (!ret) ret = genpd_dev_pm_attach(dev); - return ret; + return ret < 0 ? ret : 0; } EXPORT_SYMBOL_GPL(dev_pm_domain_attach); diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 1ea0e2502e8e..455ecea6c812 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -1377,7 +1377,7 @@ static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev, struct gpd_timing_data *td) { struct generic_pm_domain_data *gpd_data; - int ret = 0; + int ret; dev_dbg(dev, "%s()\n", __func__); @@ -1390,11 +1390,6 @@ static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev, genpd_lock(genpd); - if (genpd->prepared_count > 0) { - ret = -EAGAIN; - goto out; - } - ret = genpd->attach_dev ? genpd->attach_dev(genpd, dev) : 0; if (ret) goto out; @@ -2185,31 +2180,25 @@ static void genpd_dev_pm_sync(struct device *dev) * Parse device's OF node to find a PM domain specifier. If such is found, * attaches the device to retrieved pm_domain ops. * - * Both generic and legacy Samsung-specific DT bindings are supported to keep - * backwards compatibility with existing DTBs. - * - * Returns 0 on successfully attached PM domain or negative error code. Note - * that if a power-domain exists for the device, but it cannot be found or - * turned on, then return -EPROBE_DEFER to ensure that the device is not - * probed and to re-try again later. + * Returns 1 on successfully attached PM domain, 0 when the device don't need a + * PM domain or a negative error code in case of failures. Note that if a + * power-domain exists for the device, but it cannot be found or turned on, + * then return -EPROBE_DEFER to ensure that the device is not probed and to + * re-try again later. */ int genpd_dev_pm_attach(struct device *dev) { struct of_phandle_args pd_args; struct generic_pm_domain *pd; - unsigned int i; int ret; if (!dev->of_node) - return -ENODEV; - - if (dev->pm_domain) - return -EEXIST; + return 0; ret = of_parse_phandle_with_args(dev->of_node, "power-domains", "#power-domain-cells", 0, &pd_args); if (ret < 0) - return ret; + return 0; mutex_lock(&gpd_list_lock); pd = genpd_get_from_provider(&pd_args); @@ -2223,21 +2212,14 @@ int genpd_dev_pm_attach(struct device *dev) dev_dbg(dev, "adding to PM domain %s\n", pd->name); - for (i = 1; i < GENPD_RETRY_MAX_MS; i <<= 1) { - ret = genpd_add_device(pd, dev, NULL); - if (ret != -EAGAIN) - break; - - mdelay(i); - cond_resched(); - } + ret = genpd_add_device(pd, dev, NULL); mutex_unlock(&gpd_list_lock); if (ret < 0) { if (ret != -EPROBE_DEFER) dev_err(dev, "failed to add to PM domain %s: %d", pd->name, ret); - goto out; + return ret; } dev->pm_domain->detach = genpd_dev_pm_detach; @@ -2246,8 +2228,11 @@ int genpd_dev_pm_attach(struct device *dev) genpd_lock(pd); ret = genpd_power_on(pd, 0); genpd_unlock(pd); -out: - return ret ? -EPROBE_DEFER : 0; + + if (ret) + genpd_remove_device(pd, dev); + + return ret ? -EPROBE_DEFER : 1; } EXPORT_SYMBOL_GPL(genpd_dev_pm_attach); diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 1ba40bb2b966..a17f46a95f73 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -363,7 +363,7 @@ static int i2c_device_probe(struct device *dev) goto err_clear_wakeup_irq; status = dev_pm_domain_attach(&client->dev, true); - if (status == -EPROBE_DEFER) + if (status) goto err_clear_wakeup_irq; /* diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c index 2b32b88949ba..b6d8203e46eb 100644 --- a/drivers/mmc/core/sdio_bus.c +++ b/drivers/mmc/core/sdio_bus.c @@ -139,7 +139,7 @@ static int sdio_bus_probe(struct device *dev) return -ENODEV; ret = dev_pm_domain_attach(dev, false); - if (ret == -EPROBE_DEFER) + if (ret) return ret; /* Unbound SDIO functions are always suspended. diff --git a/drivers/soundwire/bus_type.c b/drivers/soundwire/bus_type.c index d5f3a70c06b0..283b2832728e 100644 --- a/drivers/soundwire/bus_type.c +++ b/drivers/soundwire/bus_type.c @@ -83,17 +83,16 @@ static int sdw_drv_probe(struct device *dev) * attach to power domain but don't turn on (last arg) */ ret = dev_pm_domain_attach(dev, false); - if (ret != -EPROBE_DEFER) { - ret = drv->probe(slave, id); - if (ret) { - dev_err(dev, "Probe of %s failed: %d\n", drv->name, ret); - dev_pm_domain_detach(dev, false); - } - } - if (ret) return ret; + ret = drv->probe(slave, id); + if (ret) { + dev_err(dev, "Probe of %s failed: %d\n", drv->name, ret); + dev_pm_domain_detach(dev, false); + return ret; + } + /* device is probed so let's read the properties now */ if (slave->ops && slave->ops->read_prop) slave->ops->read_prop(slave); diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 7b213faa0a2b..eeab67f50580 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -356,11 +356,12 @@ static int spi_drv_probe(struct device *dev) } ret = dev_pm_domain_attach(dev, true); - if (ret != -EPROBE_DEFER) { - ret = sdrv->probe(spi); - if (ret) - dev_pm_domain_detach(dev, true); - } + if (ret) + return ret; + + ret = sdrv->probe(spi); + if (ret) + dev_pm_domain_detach(dev, true); return ret; } diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 15bfb15c2fa5..c01675b3d93f 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -899,7 +899,7 @@ static inline int acpi_subsys_runtime_suspend(struct device *dev) { return 0; } static inline int acpi_subsys_runtime_resume(struct device *dev) { return 0; } static inline int acpi_dev_pm_attach(struct device *dev, bool power_on) { - return -ENODEV; + return 0; } #endif diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 04dbef9847d3..ab1854863a8c 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -280,7 +280,7 @@ static inline int of_genpd_parse_idle_states(struct device_node *dn, static inline int genpd_dev_pm_attach(struct device *dev) { - return -ENODEV; + return 0; } static inline @@ -297,7 +297,7 @@ extern void dev_pm_domain_set(struct device *dev, struct dev_pm_domain *pd); #else static inline int dev_pm_domain_attach(struct device *dev, bool power_on) { - return -ENODEV; + return 0; } static inline void dev_pm_domain_detach(struct device *dev, bool power_off) {} static inline void dev_pm_domain_set(struct device *dev,