Thread (23 messages) 23 messages, 8 authors, 2015-06-02
STALE4052d
Revisions (6)
  1. v1 [diff vs current]
  2. v2 current
  3. v3 [diff vs current]
  4. v4 [diff vs current]
  5. v5 [diff vs current]
  6. v6 [diff vs current]

[PATCH v2 3/8] core: platform: wakeup the parent before trying any driver operations

From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Date: 2015-05-25 16:11:37
Also in: linux-acpi, lkml
Subsystem: driver core, kobjects, debugfs and sysfs, the rest · Maintainers: Greg Kroah-Hartman, "Rafael J. Wysocki", Danilo Krummrich, Linus Torvalds

From: Heikki Krogerus <heikki.krogerus@linux.intel.com>

If the parent is still suspended when a driver probe,
remove or shutdown is attempted, the result may be a
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 using driver probe, remove or shutdown.

Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
 drivers/base/platform.c | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index ebf034b..59fcda5 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -518,9 +518,15 @@ static int platform_drv_probe(struct device *_dev)
 
 	ret = dev_pm_domain_attach(_dev, true);
 	if (ret != -EPROBE_DEFER) {
+		if (_dev->parent != &platform_bus)
+			pm_runtime_get_sync(_dev->parent);
+
 		ret = drv->probe(dev);
 		if (ret)
 			dev_pm_domain_detach(_dev, true);
+
+		if (_dev->parent != &platform_bus)
+			pm_runtime_put(_dev->parent);
 	}
 
 	if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER) {
@@ -542,9 +548,15 @@ static int platform_drv_remove(struct device *_dev)
 	struct platform_device *dev = to_platform_device(_dev);
 	int ret;
 
+	if (_dev->parent != &platform_bus)
+		pm_runtime_get_sync(_dev->parent);
+
 	ret = drv->remove(dev);
-	dev_pm_domain_detach(_dev, true);
 
+	if (_dev->parent != &platform_bus)
+		pm_runtime_put(_dev->parent);
+
+	dev_pm_domain_detach(_dev, true);
 	return ret;
 }
 
@@ -553,7 +565,14 @@ static void platform_drv_shutdown(struct device *_dev)
 	struct platform_driver *drv = to_platform_driver(_dev->driver);
 	struct platform_device *dev = to_platform_device(_dev);
 
+	if (_dev->parent != &platform_bus)
+		pm_runtime_get_sync(_dev->parent);
+
 	drv->shutdown(dev);
+
+	if (_dev->parent != &platform_bus)
+		pm_runtime_put(_dev->parent);
+
 	dev_pm_domain_detach(_dev, true);
 }
 
-- 
2.1.4
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help