diff options
author | Martin Hicks <mort@bork.org> | 2018-05-28 13:23:04 +0200 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@linaro.org> | 2018-05-29 12:24:26 +0200 |
commit | 833b51170feeee1718990480f792bb05cb0ca17c (patch) | |
tree | 39ea333ae72b83fd6729c8f862ed2cbe8788259d | |
parent | a6720c023af24220f3f26459c0aa156260a84aa0 (diff) | |
download | linux-stable-833b51170feeee1718990480f792bb05cb0ca17c.tar.gz linux-stable-833b51170feeee1718990480f792bb05cb0ca17c.tar.bz2 linux-stable-833b51170feeee1718990480f792bb05cb0ca17c.zip |
mmc: Throttle calls to MMC_SEND_STATUS during mmc_do_erase()
This drastically reduces the rate at which the MMC_SEND_STATUS cmd polls
for completion of the MMC Erase operation. The patch does this by adding
a backoff sleep that starts by sleeping for short intervals (128-256us),
and ramps up to sleeping for 32-64ms.
Even on very quickly completing erase operations, the loop iterates a few
times, so not too much extra latency is added to these commands.
For long running discard operarations, like a full-device secure discard,
this change drops the interrupt rates on my single-core NXP I.MX6UL from
45000/s to about 20/s, and greatly improves system responsiveness.
Signed-off-by: Martin Hicks <mort@bork.org>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r-- | drivers/mmc/core/core.c | 11 |
1 files changed, 9 insertions, 2 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 9a769edbabe0..281826d1fcca 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1969,6 +1969,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from, unsigned int qty = 0, busy_timeout = 0; bool use_r1b_resp = false; unsigned long timeout; + int loop_udelay=64, udelay_max=32768; int err; mmc_retune_hold(card->host); @@ -2093,9 +2094,15 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from, err = -EIO; goto out; } + if ((cmd.resp[0] & R1_READY_FOR_DATA) && + R1_CURRENT_STATE(cmd.resp[0]) != R1_STATE_PRG) + break; + + usleep_range(loop_udelay, loop_udelay*2); + if (loop_udelay < udelay_max) + loop_udelay *= 2; + } while (1); - } while (!(cmd.resp[0] & R1_READY_FOR_DATA) || - (R1_CURRENT_STATE(cmd.resp[0]) == R1_STATE_PRG)); out: mmc_retune_release(card->host); return err; |