diff options
author | Jin Qian <jqian@nvidia.com> | 2011-06-17 12:24:20 -0700 |
---|---|---|
committer | Niket Sirsi <nsirsi@nvidia.com> | 2011-06-22 11:44:53 -0700 |
commit | f7820484ea6558798c652c420507520de2eeeeec (patch) | |
tree | 10a25f41a96c57440ee5744906b700ec958ab436 /drivers | |
parent | 5f6c159f73520b187a58cdc1235e5e31d204ca1a (diff) |
Revert "mmc: revert deferred resume"
This reverts commit 40c8a6e8551e81ad4d7647029e0d85f7b0a7e496.
Original change broke LP1 suspend/resume
Bug 840959,841139
Change-Id: I0fd50729cb81a5e56eca397428ee2c8b04f10e23
Reviewed-on: http://git-master/r/37353
Reviewed-by: Narendra Damahe <ndamahe@nvidia.com>
Reviewed-by: Daniel Willemsen <dwillemsen@nvidia.com>
Tested-by: Jin Qian <jqian@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mmc/card/Kconfig | 9 | ||||
-rw-r--r-- | drivers/mmc/card/block.c | 23 | ||||
-rw-r--r-- | drivers/mmc/core/core.c | 47 |
3 files changed, 78 insertions, 1 deletions
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 7c136c29a11a..e6f74718e06f 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -575,8 +575,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); @@ -699,7 +712,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; } @@ -743,6 +756,9 @@ static int mmc_blk_probe(struct mmc_card *card) mmc_set_drvdata(card, md); mmc_fixup_device(card, blk_fixups); +#ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME + mmc_set_bus_resume_policy(card->host, 1); +#endif add_disk(md->disk); return 0; @@ -767,6 +783,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 @@ -785,7 +804,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 c8384a8e6819..c3225d68d9a5 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1040,6 +1040,36 @@ static inline void mmc_bus_put(struct mmc_host *host) spin_unlock_irqrestore(&host->lock, flags); } +int mmc_resume_bus(struct mmc_host *host) +{ + unsigned long flags; + + if (!mmc_bus_needs_resume(host)) + return -EINVAL; + + printk("%s: Starting deferred resume\n", mmc_hostname(host)); + spin_lock_irqsave(&host->lock, flags); + host->bus_resume_flags &= ~MMC_BUSRESUME_NEEDS_RESUME; + host->rescan_disable = 0; + spin_unlock_irqrestore(&host->lock, flags); + + mmc_bus_get(host); + if (host->bus_ops && !host->bus_dead) { + mmc_power_up(host); + BUG_ON(!host->bus_ops->resume); + host->bus_ops->resume(host); + + if (host->bus_ops->detect) + host->bus_ops->detect(host); + } + + mmc_bus_put(host); + printk("%s: Deferred resume completed\n", mmc_hostname(host)); + return 0; +} + +EXPORT_SYMBOL(mmc_resume_bus); + /* * Assign a mmc bus handler to a host. Only one bus handler may control a * host at any given time. @@ -1700,6 +1730,9 @@ int mmc_suspend_host(struct mmc_host *host) { int err = 0; + if (mmc_bus_needs_resume(host)) + return 0; + if (host->caps & MMC_CAP_DISABLE) cancel_delayed_work(&host->disable); cancel_delayed_work(&host->detect); @@ -1742,6 +1775,12 @@ int mmc_resume_host(struct mmc_host *host) int err = 0; mmc_bus_get(host); + if (mmc_bus_manual_resume(host)) { + host->bus_resume_flags |= MMC_BUSRESUME_NEEDS_RESUME; + mmc_bus_put(host); + return 0; + } + if (host->bus_ops && !host->bus_dead) { if (!(host->pm_flags & MMC_PM_KEEP_POWER)) { mmc_power_up(host); @@ -1779,6 +1818,10 @@ int mmc_pm_notify(struct notifier_block *notify_block, case PM_SUSPEND_PREPARE: spin_lock_irqsave(&host->lock, flags); + if (mmc_bus_needs_resume(host)) { + spin_unlock_irqrestore(&host->lock, flags); + break; + } host->rescan_disable = 1; spin_unlock_irqrestore(&host->lock, flags); cancel_delayed_work_sync(&host->detect); @@ -1802,6 +1845,10 @@ int mmc_pm_notify(struct notifier_block *notify_block, spin_lock_irqsave(&host->lock, flags); host->rescan_disable = 0; + if (mmc_bus_manual_resume(host)) { + spin_unlock_irqrestore(&host->lock, flags); + break; + } spin_unlock_irqrestore(&host->lock, flags); mmc_detect_change(host, 0); |