Commit 28302812 authored by Adrian Hunter's avatar Adrian Hunter Committed by Chris Ball

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: default avatarAdrian Hunter <adrian.hunter@intel.com>
Cc: <stable@vger.kernel.org>
Acked-by: default avatarJaehoon Chung <jh80.chung@samsung.com>
Acked-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarChris Ball <cjb@laptop.org>
parent 7194efb8
...@@ -873,7 +873,7 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq, ...@@ -873,7 +873,7 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
{ {
struct mmc_blk_data *md = mq->data; struct mmc_blk_data *md = mq->data;
struct mmc_card *card = md->queue.card; 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; int err = 0, type = MMC_BLK_SECDISCARD;
if (!(mmc_can_secure_erase_trim(card) || mmc_can_sanitize(card))) { 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, ...@@ -881,20 +881,26 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
goto out; goto out;
} }
from = blk_rq_pos(req);
nr = blk_rq_sectors(req);
/* The sanitize operation is supported at v4.5 only */ /* The sanitize operation is supported at v4.5 only */
if (mmc_can_sanitize(card)) { if (mmc_can_sanitize(card)) {
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, erase_arg = MMC_ERASE_ARG;
EXT_CSD_SANITIZE_START, 1, 0); trim_arg = MMC_TRIM_ARG;
goto out; } else {
erase_arg = MMC_SECURE_ERASE_ARG;
trim_arg = MMC_SECURE_TRIM1_ARG;
} }
from = blk_rq_pos(req); if (mmc_erase_group_aligned(card, from, nr))
nr = blk_rq_sectors(req); arg = erase_arg;
else if (mmc_can_trim(card))
if (mmc_can_trim(card) && !mmc_erase_group_aligned(card, from, nr)) arg = trim_arg;
arg = MMC_SECURE_TRIM1_ARG; else {
else err = -EINVAL;
arg = MMC_SECURE_ERASE_ARG; goto out;
}
retry: retry:
if (card->quirks & MMC_QUIRK_INAND_CMD38) { if (card->quirks & MMC_QUIRK_INAND_CMD38) {
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
...@@ -904,25 +910,41 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq, ...@@ -904,25 +910,41 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
INAND_CMD38_ARG_SECERASE, INAND_CMD38_ARG_SECERASE,
0); 0);
if (err) if (err)
goto out; goto out_retry;
} }
err = mmc_erase(card, from, nr, arg); 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) { if (card->quirks & MMC_QUIRK_INAND_CMD38) {
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
INAND_CMD38_ARG_EXT_CSD, INAND_CMD38_ARG_EXT_CSD,
INAND_CMD38_ARG_SECTRIM2, INAND_CMD38_ARG_SECTRIM2,
0); 0);
if (err) if (err)
goto out; goto out_retry;
} }
err = mmc_erase(card, from, nr, MMC_SECURE_TRIM2_ARG); 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; goto retry;
if (!err) if (!err)
mmc_blk_reset_success(md, type); mmc_blk_reset_success(md, type);
out:
spin_lock_irq(&md->lock); spin_lock_irq(&md->lock);
__blk_end_request(req, err, blk_rq_bytes(req)); __blk_end_request(req, err, blk_rq_bytes(req));
spin_unlock_irq(&md->lock); spin_unlock_irq(&md->lock);
......
...@@ -1702,6 +1702,8 @@ EXPORT_SYMBOL(mmc_can_discard); ...@@ -1702,6 +1702,8 @@ EXPORT_SYMBOL(mmc_can_discard);
int mmc_can_sanitize(struct mmc_card *card) 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) if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_SANITIZE)
return 1; return 1;
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment