mmc: core: Re-work the code for eMMC sanitize
The error path for sanitize operations that completes with -ETIMEDOUT, is tightly coupled with the internal request handling code of the core. More precisely, mmc_wait_for_req_done() checks for specific sanitize errors. This is not only inefficient as it affects all types of requests, but also hackish. Therefore, let's improve the behaviour by moving the error path out of the mmc core. To do that, retuning needs to be held while running the sanitize operation. Moreover, to avoid exporting unnecessary symbols to the mmc block module, let's move the code into the mmc_ops.c file. While updating the actual code, let's also take the opportunity to clean up some of the mess around it. Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Link: https://lore.kernel.org/r/20200316152152.15122-1-ulf.hansson@linaro.org
This commit is contained in:
parent
fa0910107a
commit
55c2b8b9a3
|
@ -70,7 +70,6 @@ MODULE_ALIAS("mmc:block");
|
||||||
* ample.
|
* ample.
|
||||||
*/
|
*/
|
||||||
#define MMC_BLK_TIMEOUT_MS (10 * 1000)
|
#define MMC_BLK_TIMEOUT_MS (10 * 1000)
|
||||||
#define MMC_SANITIZE_REQ_TIMEOUT 240000
|
|
||||||
#define MMC_EXTRACT_INDEX_FROM_ARG(x) ((x & 0x00FF0000) >> 16)
|
#define MMC_EXTRACT_INDEX_FROM_ARG(x) ((x & 0x00FF0000) >> 16)
|
||||||
#define MMC_EXTRACT_VALUE_FROM_ARG(x) ((x & 0x0000FF00) >> 8)
|
#define MMC_EXTRACT_VALUE_FROM_ARG(x) ((x & 0x0000FF00) >> 8)
|
||||||
|
|
||||||
|
@ -413,34 +412,6 @@ static int mmc_blk_ioctl_copy_to_user(struct mmc_ioc_cmd __user *ic_ptr,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ioctl_do_sanitize(struct mmc_card *card)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
|
|
||||||
if (!mmc_can_sanitize(card)) {
|
|
||||||
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 card_busy_detect(struct mmc_card *card, unsigned int timeout_ms,
|
static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms,
|
||||||
u32 *resp_errs)
|
u32 *resp_errs)
|
||||||
{
|
{
|
||||||
|
@ -569,15 +540,8 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_SANITIZE_START) &&
|
if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_SANITIZE_START) &&
|
||||||
(cmd.opcode == MMC_SWITCH)) {
|
(cmd.opcode == MMC_SWITCH))
|
||||||
err = ioctl_do_sanitize(card);
|
return mmc_sanitize(card);
|
||||||
|
|
||||||
if (err)
|
|
||||||
pr_err("%s: ioctl_do_sanitize() failed. err = %d",
|
|
||||||
__func__, err);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
mmc_wait_for_req(card->host, &mrq);
|
mmc_wait_for_req(card->host, &mrq);
|
||||||
|
|
||||||
|
|
|
@ -403,23 +403,6 @@ void mmc_wait_for_req_done(struct mmc_host *host, struct mmc_request *mrq)
|
||||||
|
|
||||||
cmd = mrq->cmd;
|
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_warn("%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 ||
|
if (!cmd->error || !cmd->retries ||
|
||||||
mmc_card_removed(host->card))
|
mmc_card_removed(host->card))
|
||||||
break;
|
break;
|
||||||
|
@ -1925,7 +1908,6 @@ int mmc_can_sanitize(struct mmc_card *card)
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(mmc_can_sanitize);
|
|
||||||
|
|
||||||
int mmc_can_secure_erase_trim(struct mmc_card *card)
|
int mmc_can_secure_erase_trim(struct mmc_card *card)
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#define MMC_BKOPS_TIMEOUT_MS (120 * 1000) /* 120s */
|
#define MMC_BKOPS_TIMEOUT_MS (120 * 1000) /* 120s */
|
||||||
#define MMC_CACHE_FLUSH_TIMEOUT_MS (30 * 1000) /* 30s */
|
#define MMC_CACHE_FLUSH_TIMEOUT_MS (30 * 1000) /* 30s */
|
||||||
|
#define MMC_SANITIZE_TIMEOUT_MS (240 * 1000) /* 240s */
|
||||||
|
|
||||||
static const u8 tuning_blk_pattern_4bit[] = {
|
static const u8 tuning_blk_pattern_4bit[] = {
|
||||||
0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc,
|
0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc,
|
||||||
|
@ -597,9 +598,6 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
|
||||||
cmd.flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1;
|
cmd.flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index == EXT_CSD_SANITIZE_START)
|
|
||||||
cmd.sanitize_busy = true;
|
|
||||||
|
|
||||||
err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
|
err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -1032,3 +1030,37 @@ int mmc_cmdq_disable(struct mmc_card *card)
|
||||||
return mmc_cmdq_switch(card, false);
|
return mmc_cmdq_switch(card, false);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(mmc_cmdq_disable);
|
EXPORT_SYMBOL_GPL(mmc_cmdq_disable);
|
||||||
|
|
||||||
|
int mmc_sanitize(struct mmc_card *card)
|
||||||
|
{
|
||||||
|
struct mmc_host *host = card->host;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (!mmc_can_sanitize(card)) {
|
||||||
|
pr_warn("%s: Sanitize not supported\n", mmc_hostname(host));
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_debug("%s: Sanitize in progress...\n", mmc_hostname(host));
|
||||||
|
|
||||||
|
mmc_retune_hold(host);
|
||||||
|
|
||||||
|
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_SANITIZE_START,
|
||||||
|
1, MMC_SANITIZE_TIMEOUT_MS);
|
||||||
|
if (err)
|
||||||
|
pr_err("%s: Sanitize failed err=%d\n", mmc_hostname(host), err);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the sanitize operation timed out, the card is probably still busy
|
||||||
|
* in the R1_STATE_PRG. Rather than continue to wait, let's try to abort
|
||||||
|
* it with a HPI command to get back into R1_STATE_TRAN.
|
||||||
|
*/
|
||||||
|
if (err == -ETIMEDOUT && !mmc_interrupt_hpi(card))
|
||||||
|
pr_warn("%s: Sanitize aborted\n", mmc_hostname(host));
|
||||||
|
|
||||||
|
mmc_retune_release(host);
|
||||||
|
|
||||||
|
pr_debug("%s: Sanitize completed\n", mmc_hostname(host));
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(mmc_sanitize);
|
||||||
|
|
|
@ -32,7 +32,6 @@ int mmc_send_cid(struct mmc_host *host, u32 *cid);
|
||||||
int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp);
|
int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp);
|
||||||
int mmc_spi_set_crc(struct mmc_host *host, int use_crc);
|
int mmc_spi_set_crc(struct mmc_host *host, int use_crc);
|
||||||
int mmc_bus_test(struct mmc_card *card, u8 bus_width);
|
int mmc_bus_test(struct mmc_card *card, u8 bus_width);
|
||||||
int mmc_interrupt_hpi(struct mmc_card *card);
|
|
||||||
int mmc_can_ext_csd(struct mmc_card *card);
|
int mmc_can_ext_csd(struct mmc_card *card);
|
||||||
int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd);
|
int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd);
|
||||||
int mmc_switch_status(struct mmc_card *card, bool crc_err_fatal);
|
int mmc_switch_status(struct mmc_card *card, bool crc_err_fatal);
|
||||||
|
@ -47,6 +46,7 @@ void mmc_run_bkops(struct mmc_card *card);
|
||||||
int mmc_flush_cache(struct mmc_card *card);
|
int mmc_flush_cache(struct mmc_card *card);
|
||||||
int mmc_cmdq_enable(struct mmc_card *card);
|
int mmc_cmdq_enable(struct mmc_card *card);
|
||||||
int mmc_cmdq_disable(struct mmc_card *card);
|
int mmc_cmdq_disable(struct mmc_card *card);
|
||||||
|
int mmc_sanitize(struct mmc_card *card);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -107,9 +107,6 @@ struct mmc_command {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
unsigned int busy_timeout; /* busy detect timeout in ms */
|
unsigned int busy_timeout; /* busy detect timeout in ms */
|
||||||
/* Set this flag only for blocking sanitize request */
|
|
||||||
bool sanitize_busy;
|
|
||||||
|
|
||||||
struct mmc_data *data; /* data segment associated with cmd */
|
struct mmc_data *data; /* data segment associated with cmd */
|
||||||
struct mmc_request *mrq; /* associated request */
|
struct mmc_request *mrq; /* associated request */
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue