aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/dd.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-07-27 11:03:58 -0400
committerLee Jones <lee.jones@linaro.org>2015-07-28 03:50:42 -0400
commitddef08dd00f5548f943422c86e4ffe67dd040b6c (patch)
tree359d5f96695c2ecd7442df32ba4083dc4db24e5b /drivers/base/dd.c
parent712e960f0ee9337f3473ba3de2bcfc7e87b7c5a4 (diff)
Driver core: wakeup the parent device before trying probe
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: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Signed-off-by: Lee Jones <lee.jones@linaro.org>
Diffstat (limited to 'drivers/base/dd.c')
-rw-r--r--drivers/base/dd.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index a638bbb1a27a..2d6df1dd3852 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -399,6 +399,8 @@ EXPORT_SYMBOL_GPL(wait_for_device_probe);
399 * 399 *
400 * This function must be called with @dev lock held. When called for a 400 * This function must be called with @dev lock held. When called for a
401 * USB interface, @dev->parent lock must be held as well. 401 * USB interface, @dev->parent lock must be held as well.
402 *
403 * If the device has a parent, runtime-resume the parent before driver probing.
402 */ 404 */
403int driver_probe_device(struct device_driver *drv, struct device *dev) 405int driver_probe_device(struct device_driver *drv, struct device *dev)
404{ 406{
@@ -410,10 +412,16 @@ int driver_probe_device(struct device_driver *drv, struct device *dev)
410 pr_debug("bus: '%s': %s: matched device %s with driver %s\n", 412 pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
411 drv->bus->name, __func__, dev_name(dev), drv->name); 413 drv->bus->name, __func__, dev_name(dev), drv->name);
412 414
415 if (dev->parent)
416 pm_runtime_get_sync(dev->parent);
417
413 pm_runtime_barrier(dev); 418 pm_runtime_barrier(dev);
414 ret = really_probe(dev, drv); 419 ret = really_probe(dev, drv);
415 pm_request_idle(dev); 420 pm_request_idle(dev);
416 421
422 if (dev->parent)
423 pm_runtime_put(dev->parent);
424
417 return ret; 425 return ret;
418} 426}
419 427
@@ -507,11 +515,17 @@ static void __device_attach_async_helper(void *_dev, async_cookie_t cookie)
507 515
508 device_lock(dev); 516 device_lock(dev);
509 517
518 if (dev->parent)
519 pm_runtime_get_sync(dev->parent);
520
510 bus_for_each_drv(dev->bus, NULL, &data, __device_attach_driver); 521 bus_for_each_drv(dev->bus, NULL, &data, __device_attach_driver);
511 dev_dbg(dev, "async probe completed\n"); 522 dev_dbg(dev, "async probe completed\n");
512 523
513 pm_request_idle(dev); 524 pm_request_idle(dev);
514 525
526 if (dev->parent)
527 pm_runtime_put(dev->parent);
528
515 device_unlock(dev); 529 device_unlock(dev);
516 530
517 put_device(dev); 531 put_device(dev);
@@ -541,6 +555,9 @@ static int __device_attach(struct device *dev, bool allow_async)
541 .want_async = false, 555 .want_async = false,
542 }; 556 };
543 557
558 if (dev->parent)
559 pm_runtime_get_sync(dev->parent);
560
544 ret = bus_for_each_drv(dev->bus, NULL, &data, 561 ret = bus_for_each_drv(dev->bus, NULL, &data,
545 __device_attach_driver); 562 __device_attach_driver);
546 if (!ret && allow_async && data.have_async) { 563 if (!ret && allow_async && data.have_async) {
@@ -557,6 +574,9 @@ static int __device_attach(struct device *dev, bool allow_async)
557 } else { 574 } else {
558 pm_request_idle(dev); 575 pm_request_idle(dev);
559 } 576 }
577
578 if (dev->parent)
579 pm_runtime_put(dev->parent);
560 } 580 }
561out_unlock: 581out_unlock:
562 device_unlock(dev); 582 device_unlock(dev);