dect
/
linux-2.6
Archived
13
0
Fork 0

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:
Adrian Hunter 2012-04-05 14:45:48 +03:00 committed by Chris Ball
parent 7194efb8f0
commit 283028122d
2 changed files with 41 additions and 17 deletions

View File

@ -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;
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);

View File

@ -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;