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: Ohad Ben-Cohen <ohad@wizery.com> Tested-by: Luciano Coelho <luciano.coelho@nokia.com> Signed-off-by: Chris Ball <cjb@laptop.org>
This commit is contained in:
parent
87973ba27b
commit
ed2a978594
1 changed files with 29 additions and 0 deletions
|
@ -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)
|
||||
|
|
Reference in a new issue