Skip to content

Commit

Permalink
mmc: fixes for eMMC v4.5 sanitize operation
Browse files Browse the repository at this point in the history
eMMC v4.5 sanitize operation erases all copies of unmapped
data.  However trim or erase operations must be used first
to unmap the required sectors.  That was not being done.

Fixes apply to linux 3.2 on.

Signed-off-by: Adrian Hunter <[email protected]>
Cc: <[email protected]>
Acked-by: Jaehoon Chung <[email protected]>
Acked-by: Linus Walleij <[email protected]>
Signed-off-by: Chris Ball <[email protected]>
  • Loading branch information
ahunter6 authored and cjb committed Apr 21, 2012
1 parent 7194efb commit 2830281
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 16 deletions.
54 changes: 38 additions & 16 deletions drivers/mmc/card/block.c
Original file line number Diff line number Diff line change
Expand Up @@ -873,28 +873,34 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
{
struct mmc_blk_data *md = mq->data;
struct mmc_card *card = md->queue.card;
unsigned int from, nr, arg;
unsigned int from, nr, arg, trim_arg, erase_arg;
int err = 0, type = MMC_BLK_SECDISCARD;

if (!(mmc_can_secure_erase_trim(card) || mmc_can_sanitize(card))) {
err = -EOPNOTSUPP;
goto out;
}

from = blk_rq_pos(req);
nr = blk_rq_sectors(req);

/* The sanitize operation is supported at v4.5 only */
if (mmc_can_sanitize(card)) {
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_SANITIZE_START, 1, 0);
goto out;
erase_arg = MMC_ERASE_ARG;
trim_arg = MMC_TRIM_ARG;
} else {
erase_arg = MMC_SECURE_ERASE_ARG;
trim_arg = MMC_SECURE_TRIM1_ARG;
}

from = blk_rq_pos(req);
nr = blk_rq_sectors(req);

if (mmc_can_trim(card) && !mmc_erase_group_aligned(card, from, nr))
arg = MMC_SECURE_TRIM1_ARG;
else
arg = MMC_SECURE_ERASE_ARG;
if (mmc_erase_group_aligned(card, from, nr))
arg = erase_arg;
else if (mmc_can_trim(card))
arg = trim_arg;
else {
err = -EINVAL;
goto out;
}
retry:
if (card->quirks & MMC_QUIRK_INAND_CMD38) {
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
Expand All @@ -904,25 +910,41 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
INAND_CMD38_ARG_SECERASE,
0);
if (err)
goto out;
goto out_retry;
}

err = mmc_erase(card, from, nr, arg);
if (!err && arg == MMC_SECURE_TRIM1_ARG) {
if (err == -EIO)
goto out_retry;
if (err)
goto out;

if (arg == MMC_SECURE_TRIM1_ARG) {
if (card->quirks & MMC_QUIRK_INAND_CMD38) {
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
INAND_CMD38_ARG_EXT_CSD,
INAND_CMD38_ARG_SECTRIM2,
0);
if (err)
goto out;
goto out_retry;
}

err = mmc_erase(card, from, nr, MMC_SECURE_TRIM2_ARG);
if (err == -EIO)
goto out_retry;
if (err)
goto out;
}
out:
if (err == -EIO && !mmc_blk_reset(md, card->host, type))

if (mmc_can_sanitize(card))
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_SANITIZE_START, 1, 0);
out_retry:
if (err && !mmc_blk_reset(md, card->host, type))
goto retry;
if (!err)
mmc_blk_reset_success(md, type);
out:
spin_lock_irq(&md->lock);
__blk_end_request(req, err, blk_rq_bytes(req));
spin_unlock_irq(&md->lock);
Expand Down
2 changes: 2 additions & 0 deletions drivers/mmc/core/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1702,6 +1702,8 @@ EXPORT_SYMBOL(mmc_can_discard);

int mmc_can_sanitize(struct mmc_card *card)
{
if (!mmc_can_trim(card) && !mmc_can_erase(card))
return 0;
if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_SANITIZE)
return 1;
return 0;
Expand Down

0 comments on commit 2830281

Please sign in to comment.