summaryrefslogtreecommitdiffstats
path: root/drivers/mmc/core
diff options
context:
space:
mode:
authorMartin Hicks <mort@bork.org>2018-05-28 13:23:04 +0200
committerUlf Hansson <ulf.hansson@linaro.org>2018-05-29 12:24:26 +0200
commit833b51170feeee1718990480f792bb05cb0ca17c (patch)
tree39ea333ae72b83fd6729c8f862ed2cbe8788259d /drivers/mmc/core
parenta6720c023af24220f3f26459c0aa156260a84aa0 (diff)
downloadlinux-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>
Diffstat (limited to 'drivers/mmc/core')
-rw-r--r--drivers/mmc/core/core.c11
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;