From 5ca694dfd981a371e9b18cdd4a89c002ffaccbc5 Mon Sep 17 00:00:00 2001 From: San Mehat Date: Wed, 3 Dec 2008 10:22:59 -0800 Subject: [PATCH 099/134] mmc: mmcblk: Add new feature 'CONFIG_MMC_BLOCK_PARANOID_RESUME' With this feature enabled, mmcblk will check the card-status before issuing a transaction *only* after being resumed. This protectes us from issuing transactions before the sdcard is ready (which can occur if the host driver deferrs mmc_resume_host() to reduce resume latency) Signed-off-by: San Mehat --- drivers/mmc/card/Kconfig | 7 +++++++ drivers/mmc/card/block.c | 3 +++ drivers/mmc/card/queue.c | 28 ++++++++++++++++++++++++++++ drivers/mmc/card/queue.h | 3 +++ 4 files changed, 41 insertions(+), 0 deletions(-) --- a/drivers/mmc/card/Kconfig +++ b/drivers/mmc/card/Kconfig @@ -32,6 +32,13 @@ config MMC_BLOCK_BOUNCE If unsure, say Y here. +config MMC_BLOCK_PARANOID_RESUME + bool "Check card status on resume" + depends on MMC_BLOCK + default y + help + Nohelp + config SDIO_UART tristate "SDIO UART/GPS class support" help --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -643,6 +643,9 @@ static int mmc_blk_resume(struct mmc_car if (md) { mmc_blk_set_blksize(md, card); +#ifdef CONFIG_MMC_BLOCK_PARANOID_RESUME + md->queue.check_status = 1; +#endif mmc_queue_resume(&md->queue); } return 0; --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -14,7 +14,9 @@ #include #include #include +#include +#include #include #include #include "queue.h" @@ -70,7 +72,33 @@ static int mmc_queue_thread(void *d) continue; } set_current_state(TASK_RUNNING); +#ifdef CONFIG_MMC_BLOCK_PARANOID_RESUME + if (mq->check_status) { + struct mmc_command cmd; + do { + int err; + + cmd.opcode = MMC_SEND_STATUS; + cmd.arg = mq->card->rca << 16; + cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; + + mmc_claim_host(mq->card->host); + err = mmc_wait_for_cmd(mq->card->host, &cmd, 5); + mmc_release_host(mq->card->host); + + if (err) { + printk(KERN_ERR "%s: failed to get status (%d)\n", + __func__, err); + msleep(5); + continue; + } + printk(KERN_DEBUG "%s: status 0x%.8x\n", __func__, cmd.resp[0]); + } while (!(cmd.resp[0] & R1_READY_FOR_DATA) || + (R1_CURRENT_STATE(cmd.resp[0]) == 7)); + mq->check_status = 0; + } +#endif mq->issue_fn(mq, req); } while (1); up(&mq->thread_sem); --- a/drivers/mmc/card/queue.h +++ b/drivers/mmc/card/queue.h @@ -17,6 +17,9 @@ struct mmc_queue { char *bounce_buf; struct scatterlist *bounce_sg; unsigned int bounce_sg_len; +#ifdef CONFIG_MMC_BLOCK_PARANOID_RESUME + int check_status; +#endif }; extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *);