diff options
author | Ulf Hansson <ulf.hansson@linaro.org> | 2020-05-08 12:52:18 +0300 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@linaro.org> | 2020-05-28 12:22:14 +0300 |
commit | 3eea697c1da58f169b3abfebaa6d07cff7cb1c8d (patch) | |
tree | ca6513309184aa1e60ec10964b774dceb8eed344 | |
parent | eadb7897652d5bf9fbab393b3774598a04846aff (diff) | |
download | linux-3eea697c1da58f169b3abfebaa6d07cff7cb1c8d.tar.xz |
mmc: sdricoh_cs: Throttle polling rate for commands
Rather than to poll in a busy-loop, let's convert into using
read_poll_timeout() and insert a small delay between each polling attempts.
In particular, this avoids hogging the CPU.
Additionally, to convert to read_poll_timeout() we also need to switch from
using a specific number of polling attempts, into a specific timeout in us
instead. The previous 100000 attempts, is translated into a total timeout
of total 1s, as that seemed like reasonable value to pick.
Cc: Sascha Sommer <saschasommer@freenet.de>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Link: https://lore.kernel.org/r/20200508095218.14177-1-ulf.hansson@linaro.org
-rw-r--r-- | drivers/mmc/host/sdricoh_cs.c | 33 |
1 files changed, 16 insertions, 17 deletions
diff --git a/drivers/mmc/host/sdricoh_cs.c b/drivers/mmc/host/sdricoh_cs.c index 8392158e2e9f..0594b5ffe151 100644 --- a/drivers/mmc/host/sdricoh_cs.c +++ b/drivers/mmc/host/sdricoh_cs.c @@ -59,7 +59,7 @@ static unsigned int switchlocked; #define STATUS_BUSY 0x40000000 /* timeouts */ -#define CMD_TIMEOUT 100000 +#define SDRICOH_CMD_TIMEOUT_US 1000000 #define SDRICOH_DATA_TIMEOUT_US 1000000 /* list of supported pcmcia devices */ @@ -158,8 +158,7 @@ static int sdricoh_query_status(struct sdricoh_host *host, unsigned int wanted) static int sdricoh_mmc_cmd(struct sdricoh_host *host, struct mmc_command *cmd) { unsigned int status; - int result = 0; - unsigned int loop = 0; + int ret; unsigned char opcode = cmd->opcode; /* reset status reg? */ @@ -175,24 +174,24 @@ static int sdricoh_mmc_cmd(struct sdricoh_host *host, struct mmc_command *cmd) /* fill parameters */ sdricoh_writel(host, R204_CMD_ARG, cmd->arg); sdricoh_writel(host, R200_CMD, (0x10000 << 8) | opcode); + /* wait for command completion */ - if (opcode) { - for (loop = 0; loop < CMD_TIMEOUT; loop++) { - status = sdricoh_readl(host, R21C_STATUS); - sdricoh_writel(host, R2E4_STATUS_RESP, status); - if (status & STATUS_CMD_FINISHED) - break; - } - /* don't check for timeout in the loop it is not always - reset correctly - */ - if (loop == CMD_TIMEOUT || status & STATUS_CMD_TIMEOUT) - result = -ETIMEDOUT; + if (!opcode) + return 0; - } + ret = read_poll_timeout(sdricoh_readl, status, + sdricoh_status_ok(host, status, STATUS_CMD_FINISHED), + 32, SDRICOH_CMD_TIMEOUT_US, false, + host, R21C_STATUS); - return result; + /* + * Don't check for timeout status in the loop, as it's not always reset + * correctly. + */ + if (ret || status & STATUS_CMD_TIMEOUT) + return -ETIMEDOUT; + return 0; } static int sdricoh_reset(struct sdricoh_host *host) |