aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/card
diff options
context:
space:
mode:
authorUlf Hansson <ulf.hansson@linaro.org>2013-05-02 08:02:38 -0400
committerChris Ball <cjb@laptop.org>2013-05-26 14:23:16 -0400
commite94cfef698aae6b209d8918dd319312e4b02118d (patch)
treebbf4978bf665c480608317d0544967f6600b21a3 /drivers/mmc/card
parent12d01d0b813b93e7bde1b5f468b5c85aa8b33590 (diff)
mmc: block: Enable runtime pm for mmc blkdevice
Once the mmc blkdevice is being probed, runtime pm will be enabled. By using runtime autosuspend, the power save operations can be done when request inactivity occurs for a certain time. Right now the selected timeout value is set to 3 s. Obviously this value will likely need to be configurable somehow since it needs to be trimmed depending on the power save algorithm. For SD-combo cards, we are still leaving the enablement of runtime PM to the SDIO init sequence since it depends on the capabilities of the SDIO func driver. Moreover, when the blk device is being suspended, we make sure the device will be runtime resumed. The reason for doing this is that we want the host suspend sequence to be unaware of any runtime power save operations done for the card in this phase. Thus it can just handle the suspend as the card is fully powered from a runtime perspective. Finally, this patch prepares to make it possible to move BKOPS handling into the runtime callbacks for the mmc bus_ops. Thus IDLE BKOPS can be accomplished. Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc/card')
-rw-r--r--drivers/mmc/card/block.c32
1 files changed, 26 insertions, 6 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 80b05b280241..c900d2818aa7 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -34,6 +34,7 @@
34#include <linux/delay.h> 34#include <linux/delay.h>
35#include <linux/capability.h> 35#include <linux/capability.h>
36#include <linux/compat.h> 36#include <linux/compat.h>
37#include <linux/pm_runtime.h>
37 38
38#include <linux/mmc/ioctl.h> 39#include <linux/mmc/ioctl.h>
39#include <linux/mmc/card.h> 40#include <linux/mmc/card.h>
@@ -224,7 +225,7 @@ static ssize_t power_ro_lock_store(struct device *dev,
224 md = mmc_blk_get(dev_to_disk(dev)); 225 md = mmc_blk_get(dev_to_disk(dev));
225 card = md->queue.card; 226 card = md->queue.card;
226 227
227 mmc_claim_host(card->host); 228 mmc_get_card(card);
228 229
229 ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP, 230 ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP,
230 card->ext_csd.boot_ro_lock | 231 card->ext_csd.boot_ro_lock |
@@ -235,7 +236,7 @@ static ssize_t power_ro_lock_store(struct device *dev,
235 else 236 else
236 card->ext_csd.boot_ro_lock |= EXT_CSD_BOOT_WP_B_PWR_WP_EN; 237 card->ext_csd.boot_ro_lock |= EXT_CSD_BOOT_WP_B_PWR_WP_EN;
237 238
238 mmc_release_host(card->host); 239 mmc_put_card(card);
239 240
240 if (!ret) { 241 if (!ret) {
241 pr_info("%s: Locking boot partition ro until next power on\n", 242 pr_info("%s: Locking boot partition ro until next power on\n",
@@ -522,7 +523,7 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
522 523
523 mrq.cmd = &cmd; 524 mrq.cmd = &cmd;
524 525
525 mmc_claim_host(card->host); 526 mmc_get_card(card);
526 527
527 err = mmc_blk_part_switch(card, md); 528 err = mmc_blk_part_switch(card, md);
528 if (err) 529 if (err)
@@ -599,7 +600,7 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
599 } 600 }
600 601
601cmd_rel_host: 602cmd_rel_host:
602 mmc_release_host(card->host); 603 mmc_put_card(card);
603 604
604cmd_done: 605cmd_done:
605 mmc_blk_put(md); 606 mmc_blk_put(md);
@@ -1921,7 +1922,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
1921 1922
1922 if (req && !mq->mqrq_prev->req) 1923 if (req && !mq->mqrq_prev->req)
1923 /* claim host only for the first request */ 1924 /* claim host only for the first request */
1924 mmc_claim_host(card->host); 1925 mmc_get_card(card);
1925 1926
1926 ret = mmc_blk_part_switch(card, md); 1927 ret = mmc_blk_part_switch(card, md);
1927 if (ret) { 1928 if (ret) {
@@ -1965,7 +1966,7 @@ out:
1965 * In case sepecial request, there is no reentry to 1966 * In case sepecial request, there is no reentry to
1966 * the 'mmc_blk_issue_rq' with 'mqrq_prev->req'. 1967 * the 'mmc_blk_issue_rq' with 'mqrq_prev->req'.
1967 */ 1968 */
1968 mmc_release_host(card->host); 1969 mmc_put_card(card);
1969 return ret; 1970 return ret;
1970} 1971}
1971 1972
@@ -2362,6 +2363,19 @@ static int mmc_blk_probe(struct mmc_card *card)
2362 if (mmc_add_disk(part_md)) 2363 if (mmc_add_disk(part_md))
2363 goto out; 2364 goto out;
2364 } 2365 }
2366
2367 pm_runtime_set_autosuspend_delay(&card->dev, 3000);
2368 pm_runtime_use_autosuspend(&card->dev);
2369
2370 /*
2371 * Don't enable runtime PM for SD-combo cards here. Leave that
2372 * decision to be taken during the SDIO init sequence instead.
2373 */
2374 if (card->type != MMC_TYPE_SD_COMBO) {
2375 pm_runtime_set_active(&card->dev);
2376 pm_runtime_enable(&card->dev);
2377 }
2378
2365 return 0; 2379 return 0;
2366 2380
2367 out: 2381 out:
@@ -2375,9 +2389,13 @@ static void mmc_blk_remove(struct mmc_card *card)
2375 struct mmc_blk_data *md = mmc_get_drvdata(card); 2389 struct mmc_blk_data *md = mmc_get_drvdata(card);
2376 2390
2377 mmc_blk_remove_parts(card, md); 2391 mmc_blk_remove_parts(card, md);
2392 pm_runtime_get_sync(&card->dev);
2378 mmc_claim_host(card->host); 2393 mmc_claim_host(card->host);
2379 mmc_blk_part_switch(card, md); 2394 mmc_blk_part_switch(card, md);
2380 mmc_release_host(card->host); 2395 mmc_release_host(card->host);
2396 if (card->type != MMC_TYPE_SD_COMBO)
2397 pm_runtime_disable(&card->dev);
2398 pm_runtime_put_noidle(&card->dev);
2381 mmc_blk_remove_req(md); 2399 mmc_blk_remove_req(md);
2382 mmc_set_drvdata(card, NULL); 2400 mmc_set_drvdata(card, NULL);
2383} 2401}
@@ -2389,6 +2407,7 @@ static int mmc_blk_suspend(struct mmc_card *card)
2389 struct mmc_blk_data *md = mmc_get_drvdata(card); 2407 struct mmc_blk_data *md = mmc_get_drvdata(card);
2390 2408
2391 if (md) { 2409 if (md) {
2410 pm_runtime_get_sync(&card->dev);
2392 mmc_queue_suspend(&md->queue); 2411 mmc_queue_suspend(&md->queue);
2393 list_for_each_entry(part_md, &md->part, part) { 2412 list_for_each_entry(part_md, &md->part, part) {
2394 mmc_queue_suspend(&part_md->queue); 2413 mmc_queue_suspend(&part_md->queue);
@@ -2412,6 +2431,7 @@ static int mmc_blk_resume(struct mmc_card *card)
2412 list_for_each_entry(part_md, &md->part, part) { 2431 list_for_each_entry(part_md, &md->part, part) {
2413 mmc_queue_resume(&part_md->queue); 2432 mmc_queue_resume(&part_md->queue);
2414 } 2433 }
2434 pm_runtime_put(&card->dev);
2415 } 2435 }
2416 return 0; 2436 return 0;
2417} 2437}