mmc: block: handle flush request timeout
In case of a flush request timeout, an error is returned
to the block layer.
The problem with this is that the eMMC card is left in
programming state and while the device is in the
programming state it cannot serve any request.
This commit moves the card out of the programming state,
in case of timeout, by issuing HPI, thereby allowing the
device to continue serving requests.
Some filesystems, such as EXT4, remount the partition as
read-only after receiving an error from the block layer, thus
this change will allow the remounted partition to work as the
card can serve read request thanks to the HPI.
In case where the card doesn't even respond to HPI it
cannot serve any request, thereby, this commit reset the
card in such catastrophic cases.
Change-Id: Idbca6ff3a420a954c61cf4fb79c9094542888d89
Signed-off-by: Talel Shenhar <tatias@codeaurora.org>
[xiaonian@codeaurora.org: fixed trivial merge conflicts]
Signed-off-by: Xiaonian Wang <xiaonian@codeaurora.org>
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 69a81e0..1b3ce5d 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -127,6 +127,7 @@
#define MMC_BLK_WRITE BIT(1)
#define MMC_BLK_DISCARD BIT(2)
#define MMC_BLK_SECDISCARD BIT(3)
+#define MMC_BLK_FLUSH BIT(4)
/*
* Only set in main mmc_blk_data associated
@@ -1837,8 +1838,21 @@
int ret = 0;
ret = mmc_flush_cache(card);
- if (ret)
+ if (ret == -ENODEV) {
+ pr_err("%s: %s: restart mmc card",
+ req->rq_disk->disk_name, __func__);
+ if (mmc_blk_reset(md, card->host, MMC_BLK_FLUSH))
+ pr_err("%s: %s: fail to restart mmc",
+ req->rq_disk->disk_name, __func__);
+ else
+ mmc_blk_reset_success(md, MMC_BLK_FLUSH);
+ }
+
+ if (ret) {
+ pr_err("%s: %s: notify flush error to upper layers",
+ req->rq_disk->disk_name, __func__);
ret = -EIO;
+ }
#ifdef CONFIG_MMC_SIMULATE_MAX_SPEED
else if (atomic_read(&mq->cache_size)) {