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

Commit 822d256a authored by Talel Shenhar's avatar Talel Shenhar Committed by Matt Wagantall
Browse files

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: default avatarTalel Shenhar <tatias@codeaurora.org>
parent 0e4b49de
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
@@ -127,6 +127,7 @@ 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
@@ -1457,8 +1458,21 @@ static int mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req)
	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;
	}

	blk_end_request_all(req, ret);

+11 −1
Original line number Diff line number Diff line
@@ -3110,10 +3110,20 @@ int mmc_flush_cache(struct mmc_card *card)
			(card->ext_csd.cache_ctrl & 1)) {
		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
				EXT_CSD_FLUSH_CACHE, 1, 0);
		if (err)
		if (err == -ETIMEDOUT) {
			pr_err("%s: cache flush timeout\n",
					mmc_hostname(card->host));
			err = mmc_interrupt_hpi(card);
			if (err) {
				pr_err("%s: mmc_interrupt_hpi() failed (%d)\n",
						mmc_hostname(card->host), err);
				err = -ENODEV;
			}
		} else if (err) {
			pr_err("%s: cache flush error %d\n",
					mmc_hostname(card->host), err);
		}
	}

	return err;
}