Skip to content

Commit

Permalink
mmc: core: Support zeroout using TRIM for eMMC
Browse files Browse the repository at this point in the history
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: Vincent Whitchurch <vincent.whitchurch@axis.com>
Reviewed-by: Avri Altman <Avri.Altman@wdc.com>
Link: https://lore.kernel.org/r/20220429152118.3617303-1-vincent.whitchurch@axis.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
  • Loading branch information
Vincent Whitchurch authored and Ulf Hansson committed May 10, 2022
1 parent 0c9ee5b commit f7b6fc3
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 4 deletions.
26 changes: 22 additions & 4 deletions drivers/mmc/core/block.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)) {
Expand All @@ -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;
Expand All @@ -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)
{
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions drivers/mmc/core/queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit f7b6fc3

Please sign in to comment.