Commit ed2a9785 authored by Ohad Ben-Cohen's avatar Ohad Ben-Cohen Committed by Chris Ball
Browse files

mmc: sdio: support suspend/resume while runtime suspended



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: default avatarOhad Ben-Cohen <ohad@wizery.com>
Tested-by: default avatarLuciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: default avatarChris Ball <cjb@laptop.org>
parent 87973ba2
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -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)