From: Martin Hicks <mort@bork.org>
Date: Mon, 28 May 2018 11:23:04 +0000 (+0200)
Subject: mmc: Throttle calls to MMC_SEND_STATUS during mmc_do_erase()
X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=833b51170feeee1718990480f792bb05cb0ca17c;p=linux.git

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>
---

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 9a769edbabe07..281826d1fcca7 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;