diff options
author | Ulf Hansson <ulf.hansson@linaro.org> | 2020-02-04 09:54:45 +0100 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@linaro.org> | 2020-03-24 14:35:40 +0100 |
commit | 0d84c3e6a5b2cd4ddd68b7ef7cf7c2dafd5146ef (patch) | |
tree | e723e0502b0f8407c9ff46338bb72dbd3127d2db /drivers/mmc/core/mmc_ops.c | |
parent | 2a1c7cda52b7b9db50086a40654dc5c03fca866f (diff) |
mmc: core: Convert to mmc_poll_for_busy() for erase/trim/discard
Rather than open coding the polling loop in mmc_do_erase(), let's convert
to use mmc_poll_for_busy().
To allow a slightly different error parsing during polling, compared to the
__mmc_switch() case, a new in-parameter to mmc_poll_for_busy() is needed,
but other than that the conversion is straight forward.
Besides addressing the open coding issue, moving to mmc_poll_for_busy() for
erase/trim/discard improves the behaviour according to below.
- Adds support for polling via the optional ->card_busy() host ops.
- Returns zero to indicate success when the final polling attempt finds the
card non-busy, even if the timeout expired.
- Exits the polling loop when state moves to R1_STATE_TRAN, rather than
when leaving R1_STATE_PRG.
- Decreases the starting range for throttling to 32-64us.
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Tested-by: Baolin Wang <baolin.wang7@gmail.com>
Tested-by: Ludovic Barre <ludovic.barre@st.com>
Reviewed-by: Ludovic Barre <ludovic.barre@st.com>
Link: https://lore.kernel.org/r/20200204085449.32585-9-ulf.hansson@linaro.org
Diffstat (limited to 'drivers/mmc/core/mmc_ops.c')
-rw-r--r-- | drivers/mmc/core/mmc_ops.c | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 4566f43305d5..3f510348b916 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -445,7 +445,7 @@ int mmc_switch_status(struct mmc_card *card, bool crc_err_fatal) } static int mmc_busy_status(struct mmc_card *card, bool retry_crc_err, - bool *busy) + enum mmc_busy_cmd busy_cmd, bool *busy) { struct mmc_host *host = card->host; u32 status = 0; @@ -464,7 +464,17 @@ static int mmc_busy_status(struct mmc_card *card, bool retry_crc_err, if (err) return err; - err = mmc_switch_status_error(card->host, status); + switch (busy_cmd) { + case MMC_BUSY_CMD6: + err = mmc_switch_status_error(card->host, status); + break; + case MMC_BUSY_ERASE: + err = R1_STATUS(status) ? -EIO : 0; + break; + default: + err = -EINVAL; + } + if (err) return err; @@ -472,8 +482,9 @@ static int mmc_busy_status(struct mmc_card *card, bool retry_crc_err, return 0; } -static int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, - bool send_status, bool retry_crc_err) +static int __mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, + bool send_status, bool retry_crc_err, + enum mmc_busy_cmd busy_cmd) { struct mmc_host *host = card->host; int err; @@ -500,7 +511,7 @@ static int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, */ expired = time_after(jiffies, timeout); - err = mmc_busy_status(card, retry_crc_err, &busy); + err = mmc_busy_status(card, retry_crc_err, busy_cmd, &busy); if (err) return err; @@ -522,6 +533,12 @@ static int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, return 0; } +int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, + enum mmc_busy_cmd busy_cmd) +{ + return __mmc_poll_for_busy(card, timeout_ms, true, false, busy_cmd); +} + /** * __mmc_switch - modify EXT_CSD register * @card: the MMC card associated with the data transfer @@ -591,7 +608,8 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, goto out_tim; /* Let's try to poll to find out when the command is completed. */ - err = mmc_poll_for_busy(card, timeout_ms, send_status, retry_crc_err); + err = __mmc_poll_for_busy(card, timeout_ms, send_status, retry_crc_err, + MMC_BUSY_CMD6); if (err) goto out; |