Merge branch 'pm-domains'

* pm-domains:
  PM / domains: Improve wording of dev_pm_domain_attach() comment
  PM / Domains: Don't return -EEXIST at attach when PM domain exists
  spi: Respect all error codes from dev_pm_domain_attach()
  soundwire: Respect all error codes from dev_pm_domain_attach()
  mmc: sdio: Respect all error codes from dev_pm_domain_attach()
  i2c: Respect all error codes from dev_pm_domain_attach()
  driver core: Respect all error codes from dev_pm_domain_attach()
  amba: Respect all error codes from dev_pm_domain_attach()
  PM / Domains: Allow a better error handling of dev_pm_domain_attach()
  PM / Domains: Check for existing PM domain in dev_pm_domain_attach()
  PM / Domains: Drop redundant code in genpd while attaching devices
  PM / Domains: Drop comment in genpd about legacy Samsung DT binding
  PM / Domains: Fix error path during attach in genpd
This commit is contained in:
Rafael J. Wysocki 2018-06-04 10:40:33 +02:00
commit 5b550c92d7
11 changed files with 53 additions and 68 deletions

View file

@ -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 */

View file

@ -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;
}

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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;
/*

View file

@ -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.

View file

@ -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);

View file

@ -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;
}

View file

@ -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

View file

@ -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,