The receive loop currently polls the status register for every 32-bit word read from the FIFO. This adds significant overhead to large data transfers.
When a complete FIFO burst remains, wait for RXFIFOBR and read eight words before polling the status register again. Retain the existing word-at-a-time path for the transfer tail. Signed-off-by: Linus Walleij <[email protected]> --- drivers/mmc/arm_pl180_mmci.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/mmc/arm_pl180_mmci.c b/drivers/mmc/arm_pl180_mmci.c index 9c18b666e4d2..5912e9d721ce 100644 --- a/drivers/mmc/arm_pl180_mmci.c +++ b/drivers/mmc/arm_pl180_mmci.c @@ -141,6 +141,7 @@ static int do_command(struct mmc *dev, struct mmc_cmd *cmd) static int read_bytes(struct mmc *dev, u32 *dest, u32 blkcount, u32 blksize) { u32 *tempbuff = dest; + int i; u64 xfercount = blkcount * blksize; struct pl180_mmc_host *host = dev->priv; u32 status, status_err; @@ -150,6 +151,19 @@ static int read_bytes(struct mmc *dev, u32 *dest, u32 blkcount, u32 blksize) status = readl(&host->base->status); status_err = status & (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT | SDI_STA_RXOVERR); + while (!status_err && + xfercount >= SDI_FIFO_BURST_SIZE * sizeof(u32)) { + if (status & SDI_STA_RXFIFOBR) { + for (i = 0; i < SDI_FIFO_BURST_SIZE; i++) + *(tempbuff + i) = readl(&host->base->fifo); + tempbuff += SDI_FIFO_BURST_SIZE; + xfercount -= SDI_FIFO_BURST_SIZE * sizeof(u32); + } + status = readl(&host->base->status); + status_err = status & (SDI_STA_DCRCFAIL | SDI_STA_DTIMEOUT | + SDI_STA_RXOVERR); + } + while ((!status_err) && (xfercount >= sizeof(u32))) { if (status & SDI_STA_RXDAVL) { *(tempbuff) = readl(&host->base->fifo); -- 2.55.0
