| From c2c298b49e428909d9f7fd6f2ba724458c486475 Mon Sep 17 00:00:00 2001 |
| From: Trent Piepho <tpiepho@impinj.com> |
| Date: Mon, 4 Mar 2019 20:18:49 +0000 |
| Subject: spi: imx: stop buffer overflow in RX FIFO flush |
| |
| [ Upstream commit c842749ea1d32513f9e603c074d60d7aa07cb2ef ] |
| |
| Commit 71abd29057cb ("spi: imx: Add support for SPI Slave mode") added |
| an RX FIFO flush before start of a transfer. In slave mode, the master |
| may have sent more data than expected and this data will still be in the |
| RX FIFO at the start of the next transfer, and so needs to be flushed. |
| |
| However, the code to do the flush was accidentally saving this data into |
| the previous transfer's RX buffer, clobbering the contents of whatever |
| followed that buffer. |
| |
| Change it to empty the FIFO and throw away the data. Every one of the |
| RX functions for the different eCSPI versions and modes reads the RX |
| FIFO data using the same readl() call, so just use that, rather than |
| using the spi_imx->rx function pointer and making sure all the different |
| rx functions have a working "throw away" mode. |
| |
| There is another issue, which affects master mode when switching from |
| DMA to PIO. There can be extra data in the RX FIFO which triggers this |
| flush code, causing memory corruption in the same manner. I don't know |
| why this data is unexpectedly in the FIFO. It's likely there is a |
| different bug or erratum responsible for that. But regardless of that, |
| I think this is proper fix the for bug at hand here. |
| |
| Fixes: 71abd29057cb ("spi: imx: Add support for SPI Slave mode") |
| Cc: Jiada Wang <jiada_wang@mentor.com> |
| Cc: Fabio Estevam <festevam@gmail.com> |
| Cc: Stefan Agner <stefan@agner.ch> |
| Cc: Shawn Guo <shawnguo@kernel.org> |
| Signed-off-by: Trent Piepho <tpiepho@impinj.com> |
| Signed-off-by: Mark Brown <broonie@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/spi/spi-imx.c | 2 +- |
| 1 file changed, 1 insertion(+), 1 deletion(-) |
| |
| diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c |
| index 6ec647bbba772..a81ae29aa68a9 100644 |
| --- a/drivers/spi/spi-imx.c |
| +++ b/drivers/spi/spi-imx.c |
| @@ -1494,7 +1494,7 @@ static int spi_imx_transfer(struct spi_device *spi, |
| |
| /* flush rxfifo before transfer */ |
| while (spi_imx->devtype_data->rx_available(spi_imx)) |
| - spi_imx->rx(spi_imx); |
| + readl(spi_imx->base + MXC_CSPIRXDATA); |
| |
| if (spi_imx->slave_mode) |
| return spi_imx_pio_transfer_slave(spi, transfer); |
| -- |
| 2.20.1 |
| |