aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOhad Ben-Cohen <ohad@wizery.com>2010-11-28 00:21:30 -0500
committerChris Ball <cjb@laptop.org>2011-01-08 22:48:13 -0500
commite594573d790bd7e269f05955d316b88f7be0c14a (patch)
treecccb8d144f418c059db4f64cea5ec8442287b588
parent30201e7f3ac639fe98fcd25d40346b65dde9ecba (diff)
mmc: sdio: don't power up cards on system suspend
Initial SDIO runtime PM implementation took a conservative approach of powering up cards (and fully reinitializing them) on system suspend, just before the suspend handlers of the relevant drivers were executed. To avoid redundant power and reinitialization cycles, this patch removes this behavior: if a card is already powered off when system suspend kicks in, it is left at that state. If a card is active when a system sleep starts, everything is straightforward and works exactly like before. But if the card was already suspended before the sleep began, then when the MMC core powers it back up on resume, its run-time PM status has to be updated to reflect the actual post-system sleep status. The technique to do that is borrowed from the I2C runtime PM implementation (for more info see Documentation/power/runtime_pm.txt). Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com> Reviewed-by: Chris Ball <cjb@laptop.org> Signed-off-by: Chris Ball <cjb@laptop.org>
-rw-r--r--drivers/mmc/core/core.c13
-rw-r--r--drivers/mmc/core/sdio_bus.c32
2 files changed, 13 insertions, 32 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 9683d4d3fced..241ffb28351c 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -22,6 +22,7 @@
22#include <linux/scatterlist.h> 22#include <linux/scatterlist.h>
23#include <linux/log2.h> 23#include <linux/log2.h>
24#include <linux/regulator/consumer.h> 24#include <linux/regulator/consumer.h>
25#include <linux/pm_runtime.h>
25 26
26#include <linux/mmc/card.h> 27#include <linux/mmc/card.h>
27#include <linux/mmc/host.h> 28#include <linux/mmc/host.h>
@@ -1785,6 +1786,18 @@ int mmc_resume_host(struct mmc_host *host)
1785 if (!(host->pm_flags & MMC_PM_KEEP_POWER)) { 1786 if (!(host->pm_flags & MMC_PM_KEEP_POWER)) {
1786 mmc_power_up(host); 1787 mmc_power_up(host);
1787 mmc_select_voltage(host, host->ocr); 1788 mmc_select_voltage(host, host->ocr);
1789 /*
1790 * Tell runtime PM core we just powered up the card,
1791 * since it still believes the card is powered off.
1792 * Note that currently runtime PM is only enabled
1793 * for SDIO cards that are MMC_CAP_POWER_OFF_CARD
1794 */
1795 if (mmc_card_sdio(host->card) &&
1796 (host->caps & MMC_CAP_POWER_OFF_CARD)) {
1797 pm_runtime_disable(&host->card->dev);
1798 pm_runtime_set_active(&host->card->dev);
1799 pm_runtime_enable(&host->card->dev);
1800 }
1788 } 1801 }
1789 BUG_ON(!host->bus_ops->resume); 1802 BUG_ON(!host->bus_ops->resume);
1790 err = host->bus_ops->resume(host); 1803 err = host->bus_ops->resume(host);
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
index 203da443e339..d29b9c36919a 100644
--- a/drivers/mmc/core/sdio_bus.c
+++ b/drivers/mmc/core/sdio_bus.c
@@ -197,44 +197,12 @@ out:
197 197
198#ifdef CONFIG_PM_RUNTIME 198#ifdef CONFIG_PM_RUNTIME
199 199
200static int sdio_bus_pm_prepare(struct device *dev)
201{
202 struct sdio_func *func = dev_to_sdio_func(dev);
203
204 /*
205 * Resume an SDIO device which was suspended at run time at this
206 * point, in order to allow standard SDIO suspend/resume paths
207 * to keep working as usual.
208 *
209 * Ultimately, the SDIO driver itself will decide (in its
210 * suspend handler, or lack thereof) whether the card should be
211 * removed or kept, and if kept, at what power state.
212 *
213 * At this point, PM core have increased our use count, so it's
214 * safe to directly resume the device. After system is resumed
215 * again, PM core will drop back its runtime PM use count, and if
216 * needed device will be suspended again.
217 *
218 * The end result is guaranteed to be a power state that is
219 * coherent with the device's runtime PM use count.
220 *
221 * The return value of pm_runtime_resume is deliberately unchecked
222 * since there is little point in failing system suspend if a
223 * device can't be resumed.
224 */
225 if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
226 pm_runtime_resume(dev);
227
228 return 0;
229}
230
231static const struct dev_pm_ops sdio_bus_pm_ops = { 200static const struct dev_pm_ops sdio_bus_pm_ops = {
232 SET_RUNTIME_PM_OPS( 201 SET_RUNTIME_PM_OPS(
233 pm_generic_runtime_suspend, 202 pm_generic_runtime_suspend,
234 pm_generic_runtime_resume, 203 pm_generic_runtime_resume,
235 pm_generic_runtime_idle 204 pm_generic_runtime_idle
236 ) 205 )
237 .prepare = sdio_bus_pm_prepare,
238}; 206};
239 207
240#define SDIO_PM_OPS_PTR (&sdio_bus_pm_ops) 208#define SDIO_PM_OPS_PTR (&sdio_bus_pm_ops)