Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2b007503 authored by Talel Shenhar's avatar Talel Shenhar
Browse files

mmc: block: fix flush timeout error handling



The eMMC card can go into "reset state" due to several
reasons and without host involvement,
e.g. low voltage detection.
This kind of eMMC card reset requires eMMC host to
re-initialize the eMMC card.
In case of eMMC card reset, eMMC card firmware sets its
state to "reset state" which allows CMD0 only.
In case the eMMC host is in the middle of FLUSH request it will
get timeout which will cause the driver to requeue the flush
request and try it later on.
The problem with this is that no one is going to initialize
the eMMC card to move out of "reset state", hence, the flush
request will keep on failing over and over again.
This commit adds a device reset for the case where flush request
fails due to timeout.

Change-Id: Ic268e13cb19d0cdce0070174bf7847e6253e4513
Signed-off-by: default avatarTalel Shenhar <tatias@codeaurora.org>
parent 9754c560
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -127,6 +127,8 @@ struct mmc_blk_data {
#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
@@ -1458,6 +1460,16 @@ static int mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req)
	int ret = 0;

	ret = mmc_flush_cache(card);
	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 == -ETIMEDOUT) {
		pr_info("%s: %s: requeue flush request after timeout",
				req->rq_disk->disk_name, __func__);
+3 −1
Original line number Diff line number Diff line
@@ -3600,9 +3600,11 @@ int mmc_flush_cache(struct mmc_card *card)
			pr_err("%s: cache flush timeout\n",
					mmc_hostname(card->host));
			rc = mmc_interrupt_hpi(card);
			if (rc)
			if (rc) {
				pr_err("%s: mmc_interrupt_hpi() failed (%d)\n",
						mmc_hostname(host), rc);
				err = -ENODEV;
			}
		} else if (err) {
			pr_err("%s: cache flush error %d\n",
					mmc_hostname(card->host), err);