aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/card
diff options
context:
space:
mode:
authorMaya Erez <merez@codeaurora.org>2013-04-18 08:41:55 -0400
committerChris Ball <cjb@laptop.org>2013-05-26 14:23:13 -0400
commit775a9362b5d7e006ff6bbec5cb9c9c9d5a751696 (patch)
tree78d66b7a04b5e339c2e0faa24290f72eb8f8bae4 /drivers/mmc/card
parentb689167984bc14ed06c8bcff52ef5eb1fd9cf83b (diff)
mmc: card: Adding support for sanitize in eMMC 4.5
The sanitize support is added as a user-app ioctl call, and was removed from the block-device request, since its purpose is to be invoked not via File-System but by a user. This feature deletes the unmap memory region of the eMMC card, by writing to a specific register in the EXT_CSD. unmap region is the memory region that was previously deleted (by erase, trim or discard operation). In order to avoid timeout when sanitizing large-scale cards, the timeout for sanitize operation is 240 seconds. Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org> Signed-off-by: Maya Erez <merez@codeaurora.org> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc/card')
-rw-r--r--drivers/mmc/card/block.c68
-rw-r--r--drivers/mmc/card/queue.c2
2 files changed, 48 insertions, 22 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index dd27b0783d52..80b05b280241 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -58,6 +58,8 @@ MODULE_ALIAS("mmc:block");
58#define INAND_CMD38_ARG_SECTRIM1 0x81 58#define INAND_CMD38_ARG_SECTRIM1 0x81
59#define INAND_CMD38_ARG_SECTRIM2 0x88 59#define INAND_CMD38_ARG_SECTRIM2 0x88
60#define MMC_BLK_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */ 60#define MMC_BLK_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */
61#define MMC_SANITIZE_REQ_TIMEOUT 240000
62#define MMC_EXTRACT_INDEX_FROM_ARG(x) ((x & 0x00FF0000) >> 16)
61 63
62#define mmc_req_rel_wr(req) (((req->cmd_flags & REQ_FUA) || \ 64#define mmc_req_rel_wr(req) (((req->cmd_flags & REQ_FUA) || \
63 (req->cmd_flags & REQ_META)) && \ 65 (req->cmd_flags & REQ_META)) && \
@@ -408,6 +410,35 @@ static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status,
408 return err; 410 return err;
409} 411}
410 412
413static int ioctl_do_sanitize(struct mmc_card *card)
414{
415 int err;
416
417 if (!(mmc_can_sanitize(card) &&
418 (card->host->caps2 & MMC_CAP2_SANITIZE))) {
419 pr_warn("%s: %s - SANITIZE is not supported\n",
420 mmc_hostname(card->host), __func__);
421 err = -EOPNOTSUPP;
422 goto out;
423 }
424
425 pr_debug("%s: %s - SANITIZE IN PROGRESS...\n",
426 mmc_hostname(card->host), __func__);
427
428 err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
429 EXT_CSD_SANITIZE_START, 1,
430 MMC_SANITIZE_REQ_TIMEOUT);
431
432 if (err)
433 pr_err("%s: %s - EXT_CSD_SANITIZE_START failed. err=%d\n",
434 mmc_hostname(card->host), __func__, err);
435
436 pr_debug("%s: %s - SANITIZE COMPLETED\n", mmc_hostname(card->host),
437 __func__);
438out:
439 return err;
440}
441
411static int mmc_blk_ioctl_cmd(struct block_device *bdev, 442static int mmc_blk_ioctl_cmd(struct block_device *bdev,
412 struct mmc_ioc_cmd __user *ic_ptr) 443 struct mmc_ioc_cmd __user *ic_ptr)
413{ 444{
@@ -510,6 +541,16 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
510 goto cmd_rel_host; 541 goto cmd_rel_host;
511 } 542 }
512 543
544 if (MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_SANITIZE_START) {
545 err = ioctl_do_sanitize(card);
546
547 if (err)
548 pr_err("%s: ioctl_do_sanitize() failed. err = %d",
549 __func__, err);
550
551 goto cmd_rel_host;
552 }
553
513 mmc_wait_for_req(card->host, &mrq); 554 mmc_wait_for_req(card->host, &mrq);
514 555
515 if (cmd.error) { 556 if (cmd.error) {
@@ -939,10 +980,10 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
939{ 980{
940 struct mmc_blk_data *md = mq->data; 981 struct mmc_blk_data *md = mq->data;
941 struct mmc_card *card = md->queue.card; 982 struct mmc_card *card = md->queue.card;
942 unsigned int from, nr, arg, trim_arg, erase_arg; 983 unsigned int from, nr, arg;
943 int err = 0, type = MMC_BLK_SECDISCARD; 984 int err = 0, type = MMC_BLK_SECDISCARD;
944 985
945 if (!(mmc_can_secure_erase_trim(card) || mmc_can_sanitize(card))) { 986 if (!(mmc_can_secure_erase_trim(card))) {
946 err = -EOPNOTSUPP; 987 err = -EOPNOTSUPP;
947 goto out; 988 goto out;
948 } 989 }
@@ -950,23 +991,11 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
950 from = blk_rq_pos(req); 991 from = blk_rq_pos(req);
951 nr = blk_rq_sectors(req); 992 nr = blk_rq_sectors(req);
952 993
953 /* The sanitize operation is supported at v4.5 only */ 994 if (mmc_can_trim(card) && !mmc_erase_group_aligned(card, from, nr))
954 if (mmc_can_sanitize(card)) { 995 arg = MMC_SECURE_TRIM1_ARG;
955 erase_arg = MMC_ERASE_ARG; 996 else
956 trim_arg = MMC_TRIM_ARG; 997 arg = MMC_SECURE_ERASE_ARG;
957 } else {
958 erase_arg = MMC_SECURE_ERASE_ARG;
959 trim_arg = MMC_SECURE_TRIM1_ARG;
960 }
961 998
962 if (mmc_erase_group_aligned(card, from, nr))
963 arg = erase_arg;
964 else if (mmc_can_trim(card))
965 arg = trim_arg;
966 else {
967 err = -EINVAL;
968 goto out;
969 }
970retry: 999retry:
971 if (card->quirks & MMC_QUIRK_INAND_CMD38) { 1000 if (card->quirks & MMC_QUIRK_INAND_CMD38) {
972 err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, 1001 err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
@@ -1002,9 +1031,6 @@ retry:
1002 goto out; 1031 goto out;
1003 } 1032 }
1004 1033
1005 if (mmc_can_sanitize(card))
1006 err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
1007 EXT_CSD_SANITIZE_START, 1, 0);
1008out_retry: 1034out_retry:
1009 if (err && !mmc_blk_reset(md, card->host, type)) 1035 if (err && !mmc_blk_reset(md, card->host, type))
1010 goto retry; 1036 goto retry;
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index 9447a0e970d1..fa9632eb63f1 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -173,7 +173,7 @@ static void mmc_queue_setup_discard(struct request_queue *q,
173 /* granularity must not be greater than max. discard */ 173 /* granularity must not be greater than max. discard */
174 if (card->pref_erase > max_discard) 174 if (card->pref_erase > max_discard)
175 q->limits.discard_granularity = 0; 175 q->limits.discard_granularity = 0;
176 if (mmc_can_secure_erase_trim(card) || mmc_can_sanitize(card)) 176 if (mmc_can_secure_erase_trim(card))
177 queue_flag_set_unlocked(QUEUE_FLAG_SECDISCARD, q); 177 queue_flag_set_unlocked(QUEUE_FLAG_SECDISCARD, q);
178} 178}
179 179