summaryrefslogtreecommitdiff
path: root/drivers/mmc/core/mmc_ops.c
diff options
context:
space:
mode:
authorUlf Hansson <ulf.hansson@linaro.org>2020-02-04 09:54:45 +0100
committerUlf Hansson <ulf.hansson@linaro.org>2020-03-24 14:35:40 +0100
commit0d84c3e6a5b2cd4ddd68b7ef7cf7c2dafd5146ef (patch)
treee723e0502b0f8407c9ff46338bb72dbd3127d2db /drivers/mmc/core/mmc_ops.c
parent2a1c7cda52b7b9db50086a40654dc5c03fca866f (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.c30
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;