Rather than to poll in a busy-loop, let's convert into using readl_poll_timeout() and insert a small delay between each polling attempts. In particular, this avoids hogging the CPU. Additionally, to convert to readl_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@xxxxxxxxxx> Signed-off-by: Ulf Hansson <ulf.hansson@xxxxxxxxxx> --- drivers/mmc/host/sdricoh_cs.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/mmc/host/sdricoh_cs.c b/drivers/mmc/host/sdricoh_cs.c index 97ef7d71375a..7e407fb6dab8 100644 --- a/drivers/mmc/host/sdricoh_cs.c +++ b/drivers/mmc/host/sdricoh_cs.c @@ -15,6 +15,7 @@ #include <linux/module.h> #include <linux/pci.h> #include <linux/ioport.h> +#include <linux/iopoll.h> #include <linux/scatterlist.h> #include <pcmcia/cistpl.h> @@ -59,7 +60,7 @@ static unsigned int switchlocked; /* timeouts */ #define CMD_TIMEOUT 100000 -#define TRANSFER_TIMEOUT 100000 +#define SDRICOH_DATA_TIMEOUT_US 1000000 /* list of supported pcmcia devices */ static const struct pcmcia_device_id pcmcia_ids[] = { @@ -123,21 +124,23 @@ static inline unsigned int sdricoh_readb(struct sdricoh_host *host, return value; } +static bool sdricoh_status_ok(struct sdricoh_host *host, unsigned int status, + unsigned int wanted) +{ + sdricoh_writel(host, R2E4_STATUS_RESP, status); + return status & wanted; +} + static int sdricoh_query_status(struct sdricoh_host *host, unsigned int wanted) { - unsigned int loop; + int ret; unsigned int status = 0; - unsigned int timeout = TRANSFER_TIMEOUT; struct device *dev = host->dev; - for (loop = 0; loop < timeout; loop++) { - status = sdricoh_readl(host, R21C_STATUS); - sdricoh_writel(host, R2E4_STATUS_RESP, status); - if (status & wanted) - break; - } - - if (loop == timeout) { + ret = readl_poll_timeout(host->iobase + R21C_STATUS, status, + sdricoh_status_ok(host, status, wanted), + 32, SDRICOH_DATA_TIMEOUT_US); + if (ret) { dev_err(dev, "query_status: timeout waiting for %x\n", wanted); return -ETIMEDOUT; } -- 2.20.1