From cfc51f6f0f342e1b30c00a170f2ff70d7f9bf658 Mon Sep 17 00:00:00 2001 From: San Mehat Date: Thu, 30 Jul 2009 08:21:19 -0700 Subject: [PATCH] mmc: mmcblk: Add support for deferred SD bus resume Signed-off-by: San Mehat mmc: card: Add MMC_BLOCK_DEFERRED_RESUME option to Kconfig Signed-off-by: San Mehat --- drivers/mmc/card/Kconfig | 9 +++++++++ drivers/mmc/card/block.c | 23 ++++++++++++++++++++++- drivers/mmc/core/core.c | 6 ++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/card/Kconfig b/drivers/mmc/card/Kconfig index 3f2a912659af..86948f90c3ff 100644 --- a/drivers/mmc/card/Kconfig +++ b/drivers/mmc/card/Kconfig @@ -32,6 +32,15 @@ config MMC_BLOCK_BOUNCE If unsure, say Y here. +config MMC_BLOCK_DEFERRED_RESUME + bool "Deferr MMC layer resume until I/O is requested" + depends on MMC_BLOCK + default n + help + Say Y here to enable deferred MMC resume until I/O + is requested. This will reduce overall resume latency and + save power when theres an SD card inserted but not being used. + config SDIO_UART tristate "SDIO UART/GPS class support" help diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index d545f79f6000..a21861b90156 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -544,8 +544,21 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req) return 0; } +static int +mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card); + static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) { +#ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME + struct mmc_blk_data *md = mq->data; + struct mmc_card *card = md->queue.card; + + if (mmc_bus_needs_resume(card->host)) { + mmc_resume_bus(card->host); + mmc_blk_set_blksize(md, card); + } +#endif + if (req->cmd_flags & REQ_DISCARD) { if (req->cmd_flags & REQ_SECURE) return mmc_blk_issue_secdiscard_rq(mq, req); @@ -667,7 +680,7 @@ mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card) if (err) { printk(KERN_ERR "%s: unable to set block size to %d: %d\n", - md->disk->disk_name, cmd.arg, err); + md->disk->disk_name, cmd.arg, err); return -EINVAL; } @@ -702,6 +715,9 @@ static int mmc_blk_probe(struct mmc_card *card) cap_str, md->read_only ? "(ro)" : ""); mmc_set_drvdata(card, md); +#ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME + mmc_set_bus_resume_policy(card->host, 1); +#endif add_disk(md->disk); return 0; @@ -726,6 +742,9 @@ static void mmc_blk_remove(struct mmc_card *card) mmc_blk_put(md); } mmc_set_drvdata(card, NULL); +#ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME + mmc_set_bus_resume_policy(card->host, 0); +#endif } #ifdef CONFIG_PM @@ -744,7 +763,9 @@ static int mmc_blk_resume(struct mmc_card *card) struct mmc_blk_data *md = mmc_get_drvdata(card); if (md) { +#ifndef CONFIG_MMC_BLOCK_DEFERRED_RESUME mmc_blk_set_blksize(md, card); +#endif mmc_queue_resume(&md->queue); } return 0; diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 70a037099a1a..bfde706b7236 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1449,6 +1449,12 @@ void mmc_rescan(struct work_struct *work) if ((host->bus_ops != NULL) && host->bus_ops->detect && !host->bus_dead) host->bus_ops->detect(host); + /* If the card was removed the bus will be marked + * as dead - extend the wakelock so userspace + * can respond */ + if (host->bus_dead) + extend_wakelock = 1; + mmc_bus_put(host); -- 2.34.1