diff mbox

[v3,3/8] Driver core: wakeup the parent device before trying probe

Message ID 1433170082-117462-4-git-send-email-andriy.shevchenko@linux.intel.com (mailing list archive)
State Superseded
Headers show

Commit Message

Andy Shevchenko June 1, 2015, 2:47 p.m. UTC
From: Heikki Krogerus <heikki.krogerus@linux.intel.com>

If the parent is still suspended when driver probe is
attempted, the result may be failure.

For example, if the parent is a PCI MFD device that has been
suspended when we try to probe our device, any register
reads will return 0xffffffff.

To fix the problem, making sure the parent is always awake
before attempting driver probe.

Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
 drivers/base/dd.c | 8 ++++++++
 1 file changed, 8 insertions(+)

Comments

Rafael J. Wysocki June 8, 2015, 11:42 p.m. UTC | #1
On Monday, June 01, 2015 05:47:57 PM Andy Shevchenko wrote:
> From: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> 
> If the parent is still suspended when driver probe is
> attempted, the result may be failure.
> 
> For example, if the parent is a PCI MFD device that has been
> suspended when we try to probe our device, any register
> reads will return 0xffffffff.
> 
> To fix the problem, making sure the parent is always awake
> before attempting driver probe.
> 
> Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> ---
>  drivers/base/dd.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/drivers/base/dd.c b/drivers/base/dd.c
> index e843fdb..cfbeff3 100644
> --- a/drivers/base/dd.c
> +++ b/drivers/base/dd.c
> @@ -399,6 +399,8 @@ EXPORT_SYMBOL_GPL(wait_for_device_probe);
>   *
>   * This function must be called with @dev lock held.  When called for a
>   * USB interface, @dev->parent lock must be held as well.
> + *
> + * If device has a parent it will be powered on during device's probe().
>   */
>  int driver_probe_device(struct device_driver *drv, struct device *dev)
>  {
> @@ -410,10 +412,16 @@ int driver_probe_device(struct device_driver *drv, struct device *dev)
>  	pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
>  		 drv->bus->name, __func__, dev_name(dev), drv->name);
>  
> +	if (dev->parent)
> +		pm_runtime_get_sync(dev->parent);
> +

For some bus types that will resume and suspend the parent for many times in
a row in device_attach() until an appropriate driver is found.  Would it be
more efficient to call it once before the bus_for_each_drv() loop in there?

>  	pm_runtime_barrier(dev);
>  	ret = really_probe(dev, drv);
>  	pm_request_idle(dev);
>  
> +	if (dev->parent)
> +		pm_runtime_put_sync(dev->parent);

Is there anything particularly wrong with calling pm_runtime_put() here
instead?

> +
>  	return ret;
>  }
>  
>
diff mbox

Patch

diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index e843fdb..cfbeff3 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -399,6 +399,8 @@  EXPORT_SYMBOL_GPL(wait_for_device_probe);
  *
  * This function must be called with @dev lock held.  When called for a
  * USB interface, @dev->parent lock must be held as well.
+ *
+ * If device has a parent it will be powered on during device's probe().
  */
 int driver_probe_device(struct device_driver *drv, struct device *dev)
 {
@@ -410,10 +412,16 @@  int driver_probe_device(struct device_driver *drv, struct device *dev)
 	pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
 		 drv->bus->name, __func__, dev_name(dev), drv->name);
 
+	if (dev->parent)
+		pm_runtime_get_sync(dev->parent);
+
 	pm_runtime_barrier(dev);
 	ret = really_probe(dev, drv);
 	pm_request_idle(dev);
 
+	if (dev->parent)
+		pm_runtime_put_sync(dev->parent);
+
 	return ret;
 }