mmc: fixes for eMMC v4.5 sanitize operation
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 <adrian.hunter@intel.com> Cc: <stable@vger.kernel.org> Acked-by: Jaehoon Chung <jh80.chung@samsung.com> Acked-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Chris Ball <cjb@laptop.org>
This commit is contained in:
parent
7194efb8f0
commit
283028122d
|
@ -873,7 +873,7 @@ 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))) {
|
||||
|
@ -881,20 +881,26 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
|
|||
goto out;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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;
|
||||
/* The sanitize operation is supported at v4.5 only */
|
||||
if (mmc_can_sanitize(card)) {
|
||||
erase_arg = MMC_ERASE_ARG;
|
||||
trim_arg = MMC_TRIM_ARG;
|
||||
} else {
|
||||
erase_arg = MMC_SECURE_ERASE_ARG;
|
||||
trim_arg = MMC_SECURE_TRIM1_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,
|
||||
|
@ -904,25 +910,41 @@ retry:
|
|||
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_retry;
|
||||
}
|
||||
|
||||
err = mmc_erase(card, from, nr, MMC_SECURE_TRIM2_ARG);
|
||||
if (err == -EIO)
|
||||
goto out_retry;
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
err = mmc_erase(card, from, nr, MMC_SECURE_TRIM2_ARG);
|
||||
}
|
||||
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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue