mmc: mmcblk: Add support for deferred SD bus resume
authorSan Mehat <san@google.com>
Thu, 30 Jul 2009 15:21:19 +0000 (08:21 -0700)
committerColin Cross <ccross@android.com>
Thu, 30 Sep 2010 00:49:14 +0000 (17:49 -0700)
Signed-off-by: San Mehat <san@google.com>
mmc: card: Add MMC_BLOCK_DEFERRED_RESUME option to Kconfig

Signed-off-by: San Mehat <san@google.com>
drivers/mmc/card/Kconfig
drivers/mmc/card/block.c
drivers/mmc/core/core.c

index 3f2a912659aff9a6ad596d7271ad60df2a332752..86948f90c3ffe981139c96039d016c0e0a2fd4a6 100644 (file)
@@ -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
index d545f79f6000ebe8b5219c56a19c7bd0acbfc343..a21861b90156a6f93bc5b1422d4fe1379c8beb66 100644 (file)
@@ -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;
index 70a037099a1ae882b9ec25d7c6815bd6eb6430dc..bfde706b7236c1c078b29f53a65ed92a3460c8f1 100644 (file)
@@ -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);