mmc: sdio: support suspend/resume while runtime suspended
authorOhad Ben-Cohen <ohad@wizery.com>
Sat, 2 Oct 2010 11:54:13 +0000 (13:54 +0200)
committerChris Ball <cjb@laptop.org>
Sat, 23 Oct 2010 13:11:19 +0000 (21:11 +0800)
Bring SDIO devices back to full power before their suspend
handler is invoked.

Doing so ensures that SDIO suspend/resume semantics are
maintained (drivers still get to decide whether their
card should be removed or kept during system suspend,
and at what power state), and that SDIO suspend/resume
execution paths are unchanged.

This is achieved by resuming a runtime-suspended SDIO device
in its ->prepare() PM callback (similary to the PCI subsystem).

Since the PM core always increments the run-time usage
counter before calling the ->prepare() callback and decrements
it after calling the ->complete() callback, it is guaranteed
that when the system will come out of suspend, our device's
power state will reflect its runtime PM usage counter.

Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
Tested-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Chris Ball <cjb@laptop.org>
drivers/mmc/core/sdio_bus.c

index 36374834fcff0599342fa16f454c3ba4e19017b2..2716c7ab6bbfb6fd76ae2ff3084f7d61b4dcc198 100644 (file)
@@ -189,12 +189,41 @@ out:
 
 #ifdef CONFIG_PM_RUNTIME
 
+static int sdio_bus_pm_prepare(struct device *dev)
+{
+       /*
+        * Resume an SDIO device which was suspended at run time at this
+        * point, in order to allow standard SDIO suspend/resume paths
+        * to keep working as usual.
+        *
+        * Ultimately, the SDIO driver itself will decide (in its
+        * suspend handler, or lack thereof) whether the card should be
+        * removed or kept, and if kept, at what power state.
+        *
+        * At this point, PM core have increased our use count, so it's
+        * safe to directly resume the device. After system is resumed
+        * again, PM core will drop back its runtime PM use count, and if
+        * needed device will be suspended again.
+        *
+        * The end result is guaranteed to be a power state that is
+        * coherent with the device's runtime PM use count.
+        *
+        * The return value of pm_runtime_resume is deliberately unchecked
+        * since there is little point in failing system suspend if a
+        * device can't be resumed.
+        */
+       pm_runtime_resume(dev);
+
+       return 0;
+}
+
 static const struct dev_pm_ops sdio_bus_pm_ops = {
        SET_RUNTIME_PM_OPS(
                pm_generic_runtime_suspend,
                pm_generic_runtime_resume,
                pm_generic_runtime_idle
        )
+       .prepare = sdio_bus_pm_prepare,
 };
 
 #define SDIO_PM_OPS_PTR        (&sdio_bus_pm_ops)