mmc: card: Adding support for sanitize in eMMC 4.5
Subsystems (2)
PATCH v2 1/1 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.
--- drivers/mmc/card/block.c | 68 +++++++++++++++++++++++++++++++-------------- drivers/mmc/card/queue.c | 2 +- drivers/mmc/core/core.c | 21 ++++++++++++++ include/linux/mmc/core.h | 2 + include/linux/mmc/host.h | 1 + 5 files changed, 72 insertions(+), 22 deletions(-)
drivers/mmc/card/block.c +47 -21
@@ -58,6 +58,8 @@ MODULE_ALIAS("mmc:block");#define INAND_CMD38_ARG_SECTRIM1 0x81#define INAND_CMD38_ARG_SECTRIM2 0x88#define MMC_BLK_TIMEOUT_MS (10 * 60 * 1000)/* 10 minute timeout */ +#define MMC_SANITIZE_REQ_TIMEOUT 240000 +#define MMC_EXTRACT_INDEX_FROM_ARG (x) ((x & 0x00FF0000) >> 16)#define mmc_req_rel_wr (req) (((req->cmd_flags & REQ_FUA) || \ (req->cmd_flags & REQ_META)) && \
@@ -409,6 +411,35 @@ static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status,return err; } +static int ioctl_do_sanitize (struct mmc_card *card) +{ +int err; + +if (!(mmc_can_sanitize (card) && + (card->host->caps2 &MMC_CAP2_SANITIZE ))) { +pr_warn ("%s: %s - SANITIZE is not supported\n" , +mmc_hostname (card->host), __func__); + err = -EOPNOTSUPP ; + goto out; + } + +pr_debug ("%s: %s - SANITIZE IN PROGRESS...\n" , +mmc_hostname (card->host), __func__); + + err =mmc_switch (card,EXT_CSD_CMD_SET_NORMAL , +EXT_CSD_SANITIZE_START ,1 , +MMC_SANITIZE_REQ_TIMEOUT ); + +if (err) +pr_err ("%s: %s - EXT_CSD_SANITIZE_START failed. err=%d\n" , +mmc_hostname (card->host), __func__, err); + +pr_debug ("%s: %s - SANITIZE COMPLETED\n" ,mmc_hostname (card->host), + __func__); +out: +return err; +} +static int mmc_blk_ioctl_cmd (struct block_device *bdev,struct mmc_ioc_cmd __user *ic_ptr) {
@@ -511,6 +542,16 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, goto cmd_rel_host; } +if (MMC_EXTRACT_INDEX_FROM_ARG (cmd.arg) ==EXT_CSD_SANITIZE_START ) { + err =ioctl_do_sanitize (card); + +if (err) +pr_err ("%s: ioctl_do_sanitize() failed. err = %d" , + __func__, err); + + goto cmd_rel_host; + } +mmc_wait_for_req (card->host, &mrq);if (cmd.error) {
@@ -940,10 +981,10 @@ 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, trim_arg, erase_arg; +unsigned int from, nr, arg;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))) { err = -EOPNOTSUPP ; goto out; }
@@ -951,23 +992,11 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq, from =blk_rq_pos (req); nr =blk_rq_sectors (req); -/* 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_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,
@@ -1003,9 +1032,6 @@ retry: goto out; } -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;
drivers/mmc/card/queue.c +1 -1
@@ -173,7 +173,7 @@ static void mmc_queue_setup_discard(struct request_queue *q,/* granularity must not be greater than max. discard */ if (card->pref_erase > max_discard) q->limits.discard_granularity =0 ; -if (mmc_can_secure_erase_trim (card) ||mmc_can_sanitize (card)) +if (mmc_can_secure_erase_trim (card))queue_flag_set_unlocked (QUEUE_FLAG_SECDISCARD , q); }
drivers/mmc/core/core.c +21 -0
@@ -402,6 +402,27 @@ static int mmc_wait_for_data_req_done(struct mmc_host *host, context_info->is_done_rcv = false; context_info->is_new_req = false; cmd = mrq->cmd; + +/* +* If host has timed out waiting for the sanitize +* to complete, card might be still in programming state +* so let's try to bring the card out of programming +* state. +*/ +if (cmd->sanitize_busy && cmd->error == -ETIMEDOUT ) { +if (!mmc_interrupt_hpi (host->card)) { +pr_warning ("%s: %s: Interrupted " +"sanitize\n" , +mmc_hostname (host), + __func__); + cmd->error =0 ; +break ; + }else { +pr_err ("%s: %s: Failed to interrupt " +"sanitize\n" , +mmc_hostname (host), __func__); + } + }if (!cmd->error || !cmd->retries ||mmc_card_removed (host->card)) { err = host->areq->err_check(host->card,
include/linux/mmc/core.h +2 -0
@@ -96,6 +96,8 @@ struct mmc_command {*/ unsigned int cmd_timeout_ms;/* in milliseconds */ +/* Set this flag only for blocking sanitize request */ +bool sanitize_busy;struct mmc_data *data;/* data segment associated with cmd */ struct mmc_request *mrq;/* associated request */
include/linux/mmc/host.h +1 -0
@@ -281,6 +281,7 @@ struct mmc_host {#define MMC_CAP2_PACKED_CMD (MMC_CAP2_PACKED_RD | \ MMC_CAP2_PACKED_WR)#define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14)/* Don't power up before scan */ +#define MMC_CAP2_SANITIZE (1 << 15)/* Support Sanitize */ mmc_pm_flag_t pm_caps;/* supported pm features */
Signature · 4 lines
1.7.3.3 -- QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
Quoted 200 lines · Maya Erez
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 theEXT_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 <[email protected]>Signed-off-by Maya Erez <[email protected]>--- drivers/mmc/card/block.c | 68 +++++++++++++++++++++++++++++++-------------- drivers/mmc/card/queue.c | 2 +- drivers/mmc/core/core.c | 21 ++++++++++++++ include/linux/mmc/core.h | 2 + include/linux/mmc/host.h | 1 + 5 files changed, 72 insertions(+), 22 deletions(-)drivers/mmc/card/block.c +47
-21@@ -58,6 +58,8 @@ MODULE_ALIAS("mmc:block");#define INAND_CMD38_ARG_SECTRIM1 0x81#define INAND_CMD38_ARG_SECTRIM2 0x88#define MMC_BLK_TIMEOUT_MS (10 * 60 * 1000)/* 10 minute timeout */ +#define MMC_SANITIZE_REQ_TIMEOUT 240000 +#define MMC_EXTRACT_INDEX_FROM_ARG (x) ((x & 0x00FF0000) >> 16)#define mmc_req_rel_wr (req) (((req->cmd_flags & REQ_FUA) || \ (req->cmd_flags & REQ_META)) && \@@ -409,6 +411,35 @@ static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status,return err; } +static int ioctl_do_sanitize (struct mmc_card *card) +{ +int err; + +if (!(mmc_can_sanitize (card) && + (card->host->caps2 &MMC_CAP2_SANITIZE ))) { +pr_warn ("%s: %s - SANITIZE is not supported\n" , +mmc_hostname (card->host), __func__); + err = -EOPNOTSUPP ; + goto out; + } + +pr_debug ("%s: %s - SANITIZE IN PROGRESS...\n" , +mmc_hostname (card->host), __func__); + + err =mmc_switch (card,EXT_CSD_CMD_SET_NORMAL , +EXT_CSD_SANITIZE_START ,1 , +MMC_SANITIZE_REQ_TIMEOUT ); + +if (err) +pr_err ("%s: %s - EXT_CSD_SANITIZE_START failed. err=%d\n" , +mmc_hostname (card->host), __func__, err); + +pr_debug ("%s: %s - SANITIZE COMPLETED\n" ,mmc_hostname (card->host), + __func__); +out: +return err; +} +static int mmc_blk_ioctl_cmd (struct block_device *bdev,struct mmc_ioc_cmd __user *ic_ptr) {@@ -511,6 +542,16 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, goto cmd_rel_host; } +if (MMC_EXTRACT_INDEX_FROM_ARG (cmd.arg) ==EXT_CSD_SANITIZE_START ) { + err =ioctl_do_sanitize (card); + +if (err) +pr_err ("%s: ioctl_do_sanitize() failed. err = %d" , + __func__, err); + + goto cmd_rel_host; + } +mmc_wait_for_req (card->host, &mrq);if (cmd.error) {@@ -940,10 +981,10 @@ 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, trim_arg, erase_arg; +unsigned int from, nr, arg;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))) { err = -EOPNOTSUPP ; goto out; }@@ -951,23 +992,11 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq, from =blk_rq_pos (req); nr =blk_rq_sectors (req); -/* 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_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,@@ -1003,9 +1032,6 @@ retry: goto out; } -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;drivers/mmc/card/queue.c +1
-1@@ -173,7 +173,7 @@ static void mmc_queue_setup_discard(struct request_queue *q,/* granularity must not be greater than max. discard */ if (card->pref_erase > max_discard) q->limits.discard_granularity =0 ; -if (mmc_can_secure_erase_trim (card) ||mmc_can_sanitize (card)) +if (mmc_can_secure_erase_trim (card))queue_flag_set_unlocked (QUEUE_FLAG_SECDISCARD , q); }drivers/mmc/core/core.c +21
-0@@ -402,6 +402,27 @@ static int mmc_wait_for_data_req_done(struct mmc_host *host, context_info->is_done_rcv = false; context_info->is_new_req = false; cmd = mrq->cmd; + +/* +* If host has timed out waiting for the sanitize +* to complete, card might be still in programming state +* so let's try to bring the card out of programming +* state. +*/ +if (cmd->sanitize_busy && cmd->error == -ETIMEDOUT ) { +if (!mmc_interrupt_hpi (host->card)) { +pr_warning ("%s: %s: Interrupted " +"sanitize\n" , +mmc_hostname (host), + __func__); + cmd->error =0 ; +break ; + }else { +pr_err ("%s: %s: Failed to interrupt " +"sanitize\n" , +mmc_hostname (host), __func__); + } + }if (!cmd->error || !cmd->retries ||mmc_card_removed (host->card)) { err = host->areq->err_check(host->card,include/linux/mmc/core.h +2
-0@@ -96,6 +96,8 @@ struct mmc_command {*/ unsigned int cmd_timeout_ms;/* in milliseconds */ +/* Set this flag only for blocking sanitize request */ +bool sanitize_busy;struct mmc_data *data;/* data segment associated with cmd */ struct mmc_request *mrq;/* associated request */ include/linux/mmc/host.h +0
-0
include/linux/mmc/host.h struct mmc_host { · line 284
Quoted 4 lines
include/linux/mmc/host.h +1
-0@@ -281,6 +281,7 @@ struct mmc_host {#define MMC_CAP2_PACKED_CMD (MMC_CAP2_PACKED_RD | \ MMC_CAP2_PACKED_WR)#define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14)/* Don't power up before scan */ +#define MMC_CAP2_SANITIZE (1 << 15)/* Support Sanitize */
Is there a specific reason to why a cap is needed? Would it be okay to use this feature just if the card supports it?
Quoted 9 lines
include/linux/mmc/host.h +0
-1mmc_pm_flag_t pm_caps;/* supported pm features */ --1.7.3.3
--
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
Quoted 5 lines
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Kind regards
Ulf Hansson
Hi Ulf,
You are right, the caps2 flag for Sanitize can be removed. I will send a fix for that.
Thanks,
Maya
Quoted 258 lines · Maya Erez
Quoted 225 lines
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 theEXT_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 <[email protected]>Signed-off-by Maya Erez <[email protected]>--- drivers/mmc/card/block.c | 68 +++++++++++++++++++++++++++++++-------------- drivers/mmc/card/queue.c | 2 +- drivers/mmc/core/core.c | 21 ++++++++++++++ include/linux/mmc/core.h | 2 + include/linux/mmc/host.h | 1 + 5 files changed, 72 insertions(+), 22 deletions(-)drivers/mmc/card/block.c +0
-0@@ -58,6 +58,8 @@ MODULE_ALIAS("mmc:block");#define INAND_CMD38_ARG_SECTRIM1 0x81#define INAND_CMD38_ARG_SECTRIM2 0x88#define MMC_BLK_TIMEOUT_MS (10 * 60 * 1000)/* 10 minute timeout */
drivers/mmc/card/block.c +31
-0+#define MMC_SANITIZE_REQ_TIMEOUT 240000 +#define MMC_EXTRACT_INDEX_FROM_ARG (x) ((x & 0x00FF0000) >> 16)#define mmc_req_rel_wr (req) (((req->cmd_flags & REQ_FUA) || \ (req->cmd_flags & REQ_META)) && \@@ -409,6 +411,35 @@ static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status, return err; } +static int ioctl_do_sanitize (struct mmc_card *card) +{ +int err; + +if (!(mmc_can_sanitize (card) && + (card->host->caps2 &MMC_CAP2_SANITIZE ))) { +pr_warn ("%s: %s - SANITIZE is not supported\n" , +mmc_hostname (card->host), __func__); + err = -EOPNOTSUPP ; + goto out; + } + +pr_debug ("%s: %s - SANITIZE IN PROGRESS...\n" , +mmc_hostname (card->host), __func__); + + err =mmc_switch (card,EXT_CSD_CMD_SET_NORMAL , +EXT_CSD_SANITIZE_START ,1 , +MMC_SANITIZE_REQ_TIMEOUT ); + +if (err) +pr_err ("%s: %s - EXT_CSD_SANITIZE_START failed. err=%d\n", +mmc_hostname (card->host), __func__, err); + +pr_debug ("%s: %s - SANITIZE COMPLETED\n" ,mmc_hostname (card->host), + __func__); +out: +return err; +} +static int mmc_blk_ioctl_cmd(struct
block_device*bdev,
structmmc_ioc_cmd__user*ic_ptr)
{drivers/mmc/card/block.c +10
-0@@ -511,6 +542,16 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, goto cmd_rel_host; } +if (MMC_EXTRACT_INDEX_FROM_ARG (cmd.arg) ==EXT_CSD_SANITIZE_START ) { + err =ioctl_do_sanitize (card); + +if (err) + pr_err("%s: ioctl_do_sanitize() failed. err = %d", + __func__, err); + + goto cmd_rel_host; + } +mmc_wait_for_req(card->host, &mrq); if (cmd.error) {drivers/mmc/card/block.c +2
-2@@ -940,10 +981,10 @@ 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, trim_arg, erase_arg; +unsigned int from, nr, arg;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))) { err = -EOPNOTSUPP ;goto out; }drivers/mmc/card/block.c +4
-16@@ -951,23 +992,11 @@ static int mmc_blk_issue_secdiscard_rq(structmmc_queue *mq, from =blk_rq_pos (req); nr =blk_rq_sectors (req); -/* 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_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,drivers/mmc/card/block.c +0
-3@@ -1003,9 +1032,6 @@ retry: goto out; } -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;drivers/mmc/card/queue.c +1
-1@@ -173,7 +173,7 @@ static void mmc_queue_setup_discard(struct request_queue *q,/* granularity must not be greater than max. discard */ if (card->pref_erase > max_discard) q->limits.discard_granularity = 0; -if (mmc_can_secure_erase_trim (card) ||mmc_can_sanitize (card)) +if (mmc_can_secure_erase_trim (card))queue_flag_set_unlocked (QUEUE_FLAG_SECDISCARD , q); }drivers/mmc/core/core.c +3
-0@@ -402,6 +402,27 @@ static int mmc_wait_for_data_req_done(struct mmc_host *host, context_info->is_done_rcv = false; context_info->is_new_req = false; cmd = mrq->cmd; + +/* +* If host has timed out waiting for the sanitize
+ * to complete, card might be still in
programming state
+ * so let's try to bring the card out of
programmingdrivers/mmc/core/core.c +5
-1+* state. +*/ +if (cmd->sanitize_busy && cmd->error == -ETIMEDOUT) { + if (!mmc_interrupt_hpi(host->card)) { + pr_warning("%s: %s: Interrupted"
drivers/mmc/core/core.c +7
-0+"sanitize\n" , +mmc_hostname (host), + __func__); + cmd->error =0 ; +break ; + }else { + pr_err("%s: %s: Failed tointerrupt "
drivers/mmc/core/core.c +2
-0+"sanitize\n" , + mmc_hostname(host),
__func__);drivers/mmc/core/core.c +2
-0+ } + }if (!cmd->error || !cmd->retries ||mmc_card_removed (host->card)) { err = host->areq->err_check(host->card,include/linux/mmc/core.h +2
-0@@ -96,6 +96,8 @@ struct mmc_command {*/ unsigned int cmd_timeout_ms;/* in milliseconds */ +/* Set this flag only for blocking sanitize request */ +bool sanitize_busy;struct mmc_data *data;/* data segment associated with cmd */
structmmc_request*mrq; /* associated request */include/linux/mmc/host.h +0
-0@@ -281,6 +281,7 @@ struct mmc_host {#define MMC_CAP2_PACKED_CMD (MMC_CAP2_PACKED_RD | \ MMC_CAP2_PACKED_WR)#define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14)/* Don't power up before Quoted 3 lines
scan */
+#defineMMC_CAP2_SANITIZE(1 << 15) /* Support
Sanitize */Is there a specific reason to why a cap is needed? Would it be okay to use this feature just if the card supports it?
Quoted 11 lines
mmc_pm_flag_tpm_caps; /* supported pm features
*/--
1.7.3.3
--
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux FoundationQuoted 6 lines
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/Kind regards
Ulf Hansson
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 3 lines
Maya Erez QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
Hi Maya,
Quoted 58 lines
-----Original Message-----
From: [email protected] [mailto:linux-mmc- [email protected]] On Behalf Of Maya Erez
Sent: Wednesday, April 17, 2013 1:39 PM
To: [email protected]
Cc: [email protected]; Maya Erez; Yaniv Gardi; open list
Subject: [PATCH v2] mmc: card: Adding support for sanitize in eMMC 4.5The 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 theEXT_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 <[email protected]>Signed-off-by Maya Erez <[email protected]>--- drivers/mmc/card/block.c | 68 +++++++++++++++++++++++++++++++----------- --- drivers/mmc/card/queue.c | 2 +- drivers/mmc/core/core.c | 21 ++++++++++++++ include/linux/mmc/core.h | 2 + include/linux/mmc/host.h | 1 + 5 files changed, 72 insertions(+), 22 deletions(-)drivers/mmc/card/block.c +2
-0@@ -58,6 +58,8 @@ MODULE_ALIAS("mmc:block");#define INAND_CMD38_ARG_SECTRIM1 0x81#define INAND_CMD38_ARG_SECTRIM2 0x88#define MMC_BLK_TIMEOUT_MS (10 * 60 * 1000)/* 10 minute timeout */ +#define MMC_SANITIZE_REQ_TIMEOUT 240000 +#define MMC_EXTRACT_INDEX_FROM_ARG (x) ((x & 0x00FF0000) >> 16)#define mmc_req_rel_wr (req) (((req->cmd_flags & REQ_FUA) || \drivers/mmc/card/block.c +10
-0(req->cmd_flags & REQ_META)) && \@@ -409,6 +411,35 @@ static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status, return err; } +static int ioctl_do_sanitize (struct mmc_card *card) +{ +int err; + +if (!(mmc_can_sanitize (card) && + (card->host->caps2 &MMC_CAP2_SANITIZE ))) { +pr_warn ("%s: %s - SANITIZE is not supported\n" , +mmc_hostname (card->host), __func__); + err = -EOPNOTSUPP ; + goto out;
drivers/mmc/card/block.c static int ioctl_rpmb_card_status_poll(struct mmc_card · line 434
Quoted 10 lines
drivers/mmc/card/block.c +10
-0+ } + +pr_debug ("%s: %s - SANITIZE IN PROGRESS...\n" , +mmc_hostname (card->host), __func__); + + err =mmc_switch (card,EXT_CSD_CMD_SET_NORMAL , +EXT_CSD_SANITIZE_START ,1 , +MMC_SANITIZE_REQ_TIMEOUT ); + +if (err)
Shouldn't you set the sanitize_busy flag here in case of timeout error? Otherwise the patch looks good to me.
Thanks,
Luca
Quoted 167 lines
drivers/mmc/card/block.c +9
-0+pr_err ("%s: %s - EXT_CSD_SANITIZE_START failed. err=%d\n" , +mmc_hostname (card->host), __func__, err); + +pr_debug ("%s: %s - SANITIZE COMPLETED\n" ,mmc_hostname (card->host), + __func__); +out: +return err; +} +static int mmc_blk_ioctl_cmd (struct block_device *bdev,struct mmc_ioc_cmd __user *ic_ptr){
drivers/mmc/card/block.c +10
-0@@ -511,6 +542,16 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, goto cmd_rel_host; } +if (MMC_EXTRACT_INDEX_FROM_ARG (cmd.arg) ==EXT_CSD_SANITIZE_START ) { + err =ioctl_do_sanitize (card); + +if (err) +pr_err ("%s: ioctl_do_sanitize() failed. err = %d" , + __func__, err); + + goto cmd_rel_host; + } +mmc_wait_for_req (card->host, &mrq);drivers/mmc/card/block.c +2
-2if (cmd.error) {@@ -940,10 +981,10 @@ 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, trim_arg, erase_arg; +unsigned int from, nr, arg;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))) { err = -EOPNOTSUPP ; goto out;drivers/mmc/card/block.c +4
-16}@@ -951,23 +992,11 @@ static int mmc_blk_issue_secdiscard_rq(structmmc_queue *mq, from =blk_rq_pos (req); nr =blk_rq_sectors (req); -/* 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_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 ) {drivers/mmc/card/block.c +0
-3err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,@@ -1003,9 +1032,6 @@ retry: goto out; } -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;drivers/mmc/card/queue.c +1
-1@@ -173,7 +173,7 @@ static void mmc_queue_setup_discard(struct request_queue *q,/* granularity must not be greater than max. discard */ if (card->pref_erase > max_discard) q->limits.discard_granularity = 0; -if (mmc_can_secure_erase_trim (card) ||mmc_can_sanitize (card)) +if (mmc_can_secure_erase_trim (card))queue_flag_set_unlocked (QUEUE_FLAG_SECDISCARD , q); }drivers/mmc/core/core.c +21
-0@@ -402,6 +402,27 @@ static int mmc_wait_for_data_req_done(struct mmc_host *host, context_info->is_done_rcv = false; context_info->is_new_req = false; cmd = mrq->cmd; + +/* +* If host has timed out waiting for the sanitize +* to complete, card might be still in programming state +* so let's try to bring the card out of programming +* state. +*/ +if (cmd->sanitize_busy && cmd->error == -ETIMEDOUT ) { +if (!mmc_interrupt_hpi (host->card)) { +pr_warning ("%s: %s: Interrupted " +"sanitize\n" , +mmc_hostname (host), + __func__); + cmd->error =0 ; +break ; + }else { +pr_err ("%s: %s: Failed to interrupt " +"sanitize\n" , +mmc_hostname (host), __func__); + } + }if (!cmd->error || !cmd->retries ||mmc_card_removed (host->card)) {drivers/mmc/core/core.c +0
-0err = host->areq->err_check(host->card,include/linux/mmc/core.h +2
-0@@ -96,6 +96,8 @@ struct mmc_command {*/ unsigned int cmd_timeout_ms;/* in milliseconds */ +/* Set this flag only for blocking sanitize request */ +bool sanitize_busy;struct mmc_data *data;/* data segment associated with cmd */
include/linux/mmc/core.h +0
-0struct mmc_request *mrq;/* associated request */ include/linux/mmc/host.h +0
-0@@ -281,6 +281,7 @@ struct mmc_host {#define MMC_CAP2_PACKED_CMD (MMC_CAP2_PACKED_RD | \ MMC_CAP2_PACKED_WR)#define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14)/* Don't power up before scan */
include/linux/mmc/host.h +1
-1+#define MMC_CAP2_SANITIZE (1 << 15)/* Support Sanitize */ mmc_pm_flag_t pm_caps;/* supported pm features */ --1.7.3.3
--
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi Luca,
See below (2 comments).
Thanks,
Maya
Quoted 77 lines
Hi Maya,
Quoted 61 lines
-----Original Message-----
From: [email protected] [mailto:linux-mmc- [email protected]] On Behalf Of Maya Erez
Sent: Wednesday, April 17, 2013 1:39 PM
To: [email protected]
Cc: [email protected]; Maya Erez; Yaniv Gardi; open list
Subject: [PATCH v2] mmc: card: Adding support for sanitize in eMMC 4.5The 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 theEXT_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 <[email protected]>Signed-off-by Maya Erez <[email protected]>--- drivers/mmc/card/block.c | 68 +++++++++++++++++++++++++++++++----------- --- drivers/mmc/card/queue.c | 2 +- drivers/mmc/core/core.c | 21 ++++++++++++++ include/linux/mmc/core.h | 2 + include/linux/mmc/host.h | 1 + 5 files changed, 72 insertions(+), 22 deletions(-)drivers/mmc/card/block.c +0
-0@@ -58,6 +58,8 @@ MODULE_ALIAS("mmc:block");#define INAND_CMD38_ARG_SECTRIM1 0x81#define INAND_CMD38_ARG_SECTRIM2 0x88#define MMC_BLK_TIMEOUT_MS (10 * 60 * 1000)/* 10 minute timeout
*/drivers/mmc/card/block.c +2
-0+#define MMC_SANITIZE_REQ_TIMEOUT 240000 +#define MMC_EXTRACT_INDEX_FROM_ARG (x) ((x & 0x00FF0000) >> 16)#define mmc_req_rel_wr (req) (((req->cmd_flags & REQ_FUA) || \ (req->cmd_flags & REQ_META)) && \@@ -409,6 +411,35 @@ static int ioctl_rpmb_card_status_poll(struct
mmc_card
*card, u32 *status,drivers/mmc/card/block.c +10
-0return err; } +static int ioctl_do_sanitize (struct mmc_card *card) +{ +int err; + +if (!(mmc_can_sanitize (card) && + (card->host->caps2 &MMC_CAP2_SANITIZE ))) { +pr_warn ("%s: %s - SANITIZE is not supported\n" , +mmc_hostname (card->host), __func__); + err = -EOPNOTSUPP ; + goto out;drivers/mmc/card/block.c static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status, · line 433
Quoted 10 lines
drivers/mmc/card/block.c +10
-0+ } + +pr_debug ("%s: %s - SANITIZE IN PROGRESS...\n" , +mmc_hostname (card->host), __func__); + + err =mmc_switch (card,EXT_CSD_CMD_SET_NORMAL , +EXT_CSD_SANITIZE_START ,1 , +MMC_SANITIZE_REQ_TIMEOUT ); + +if (err)Shouldn't you set the
sanitize_busyflag here in case of timeout error? Otherwise the patch looks good to me
Quoted 2 lines
Thanks,
Luca
This is done in __mmc_switch.
I sent an uncomplete patch by mistake. Good catch!
Quoted 121 lines
Quoted 121 lines
drivers/mmc/card/block.c +19
-0+pr_err ("%s: %s - EXT_CSD_SANITIZE_START failed. err=%d\n" , +mmc_hostname (card->host), __func__, err); + +pr_debug ("%s: %s - SANITIZE COMPLETED\n" ,mmc_hostname (card->host), + __func__); +out: +return err; +} +static int mmc_blk_ioctl_cmd (struct block_device *bdev,struct mmc_ioc_cmd __user *ic_ptr) {@@ -511,6 +542,16 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, goto cmd_rel_host; } +if (MMC_EXTRACT_INDEX_FROM_ARG (cmd.arg) ==EXT_CSD_SANITIZE_START ) { + err =ioctl_do_sanitize (card); + +if (err) +pr_err ("%s: ioctl_do_sanitize() failed. err = %d" , + __func__, err); + + goto cmd_rel_host; + } +mmc_wait_for_req (card->host, &mrq);drivers/mmc/card/block.c +2
-2if (cmd.error) {@@ -940,10 +981,10 @@ 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, trim_arg, erase_arg; +unsigned int from, nr, arg;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))) { err = -EOPNOTSUPP ; goto out;drivers/mmc/card/block.c +4
-16}@@ -951,23 +992,11 @@ static int mmc_blk_issue_secdiscard_rq(structmmc_queue *mq, from =blk_rq_pos (req); nr =blk_rq_sectors (req); -/* 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_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 ) {drivers/mmc/card/block.c +0
-3err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,@@ -1003,9 +1032,6 @@ retry: goto out; } -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;drivers/mmc/card/queue.c +1
-1@@ -173,7 +173,7 @@ static void mmc_queue_setup_discard(struct request_queue *q,/* granularity must not be greater than max. discard */ if (card->pref_erase > max_discard) q->limits.discard_granularity = 0; -if (mmc_can_secure_erase_trim (card) ||mmc_can_sanitize (card)) +if (mmc_can_secure_erase_trim (card))queue_flag_set_unlocked (QUEUE_FLAG_SECDISCARD , q); }drivers/mmc/core/core.c +0
-0@@ -402,6 +402,27 @@ static int mmc_wait_for_data_req_done(struct
mmc_host
*host,drivers/mmc/core/core.c +13
-0context_info->is_done_rcv = false; context_info->is_new_req = false; cmd = mrq->cmd; + +/* +* If host has timed out waiting for the sanitize +* to complete, card might be still in programming state +* so let's try to bring the card out of programming +* state. +*/ +if (cmd->sanitize_busy && cmd->error == -ETIMEDOUT ) { +if (!mmc_interrupt_hpi (host->card)) { +pr_warning ("%s: %s: Interrupted " +"sanitize\n" , +mmc_hostname (host), + __func__);
Quoted 8 lines
drivers/mmc/core/core.c static int mmc_wait_for_data_req_done(struct mmc_host *host, · line 425
Quoted 8 lines
drivers/mmc/core/core.c +8
-0+ cmd->error =0 ; +break ; + }else { +pr_err ("%s: %s: Failed to interrupt " +"sanitize\n" , +mmc_hostname (host), __func__); + } + }
This should be moved to mmc_wait_for_req_done. Sorry for the mistake. Will send a new patch with the fix.
Quoted 46 lines
Quoted 37 lines
drivers/mmc/core/core.c +0
-0if (!cmd->error || !cmd->retries ||mmc_card_removed (host->card)) { err = host->areq->err_check(host->card,include/linux/mmc/core.h +2
-0@@ -96,6 +96,8 @@ struct mmc_command {*/ unsigned int cmd_timeout_ms;/* in milliseconds */ +/* Set this flag only for blocking sanitize request */ +bool sanitize_busy;struct mmc_data *data;/* data segment associated with cmd */
include/linux/mmc/core.h +0
-0struct mmc_request *mrq;/* associated request */ include/linux/mmc/host.h +0
-0@@ -281,6 +281,7 @@ struct mmc_host {#define MMC_CAP2_PACKED_CMD (MMC_CAP2_PACKED_RD | \ MMC_CAP2_PACKED_WR)#define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14)/* Don't power up before scan */
include/linux/mmc/host.h +1
-1+#define MMC_CAP2_SANITIZE (1 << 15)/* Support Sanitize */ mmc_pm_flag_t pm_caps;/* supported pm features */ --1.7.3.3
--
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux FoundationQuoted 4 lines
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 3 lines
Maya Erez QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation