Commit f7b6fc32 authored by Vincent Whitchurch's avatar Vincent Whitchurch Committed by Ulf Hansson
Browse files

mmc: core: Support zeroout using TRIM for eMMC



If an eMMC card supports TRIM and indicates that it erases to zeros, we can
use it to support hardware offloading of REQ_OP_WRITE_ZEROES, so let's add
support for this.

Signed-off-by: default avatarVincent Whitchurch <vincent.whitchurch@axis.com>
Reviewed-by: default avatarAvri Altman <Avri.Altman@wdc.com>
Link: https://lore.kernel.org/r/20220429152118.3617303-1-vincent.whitchurch@axis.com


Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent 0c9ee5ba
Loading
Loading
Loading
Loading
+22 −4
Original line number Diff line number Diff line
@@ -126,6 +126,7 @@ struct mmc_blk_data {
#define MMC_BLK_DISCARD		BIT(2)
#define MMC_BLK_SECDISCARD	BIT(3)
#define MMC_BLK_CQE_RECOVERY	BIT(4)
#define MMC_BLK_TRIM		BIT(5)

	/*
	 * Only set in main mmc_blk_data associated
@@ -1092,12 +1093,13 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req)
	blk_mq_end_request(req, ret ? BLK_STS_IOERR : BLK_STS_OK);
}

static void mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
static void mmc_blk_issue_erase_rq(struct mmc_queue *mq, struct request *req,
				   int type, unsigned int erase_arg)
{
	struct mmc_blk_data *md = mq->blkdata;
	struct mmc_card *card = md->queue.card;
	unsigned int from, nr;
	int err = 0, type = MMC_BLK_DISCARD;
	int err = 0;
	blk_status_t status = BLK_STS_OK;

	if (!mmc_can_erase(card)) {
@@ -1113,13 +1115,13 @@ static void mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
		if (card->quirks & MMC_QUIRK_INAND_CMD38) {
			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
					 INAND_CMD38_ARG_EXT_CSD,
					 card->erase_arg == MMC_TRIM_ARG ?
					 erase_arg == MMC_TRIM_ARG ?
					 INAND_CMD38_ARG_TRIM :
					 INAND_CMD38_ARG_ERASE,
					 card->ext_csd.generic_cmd6_time);
		}
		if (!err)
			err = mmc_erase(card, from, nr, card->erase_arg);
			err = mmc_erase(card, from, nr, erase_arg);
	} while (err == -EIO && !mmc_blk_reset(md, card->host, type));
	if (err)
		status = BLK_STS_IOERR;
@@ -1129,6 +1131,19 @@ static void mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
	blk_mq_end_request(req, status);
}

static void mmc_blk_issue_trim_rq(struct mmc_queue *mq, struct request *req)
{
	mmc_blk_issue_erase_rq(mq, req, MMC_BLK_TRIM, MMC_TRIM_ARG);
}

static void mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
{
	struct mmc_blk_data *md = mq->blkdata;
	struct mmc_card *card = md->queue.card;

	mmc_blk_issue_erase_rq(mq, req, MMC_BLK_DISCARD, card->erase_arg);
}

static void mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
				       struct request *req)
{
@@ -2329,6 +2344,9 @@ enum mmc_issued mmc_blk_mq_issue_rq(struct mmc_queue *mq, struct request *req)
		case REQ_OP_SECURE_ERASE:
			mmc_blk_issue_secdiscard_rq(mq, req);
			break;
		case REQ_OP_WRITE_ZEROES:
			mmc_blk_issue_trim_rq(mq, req);
			break;
		case REQ_OP_FLUSH:
			mmc_blk_issue_flush(mq, req);
			break;
+2 −0
Original line number Diff line number Diff line
@@ -191,6 +191,8 @@ static void mmc_queue_setup_discard(struct request_queue *q,
		q->limits.discard_granularity = SECTOR_SIZE;
	if (mmc_can_secure_erase_trim(card))
		blk_queue_flag_set(QUEUE_FLAG_SECERASE, q);
	if (mmc_can_trim(card) && card->erased_byte == 0)
		blk_queue_max_write_zeroes_sectors(q, max_discard);
}

static unsigned short mmc_get_max_segments(struct mmc_host *host)