summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSerge Semin <Sergey.Semin@baikalelectronics.ru>2023-01-13 21:59:42 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2023-02-15 17:22:25 +0100
commit4863f46ddaf9ceca8acd0cb9d2f02a2c8e9c55ad (patch)
tree85ceb26de5fcb7b1a9de2b2e0ffe87e916cd3ca5
parent6e2a0521e4e84a2698f2da3950fb5c5496a4d208 (diff)
downloadlinux-4863f46ddaf9ceca8acd0cb9d2f02a2c8e9c55ad.tar.gz
linux-4863f46ddaf9ceca8acd0cb9d2f02a2c8e9c55ad.tar.bz2
linux-4863f46ddaf9ceca8acd0cb9d2f02a2c8e9c55ad.zip
spi: dw: Fix wrong FIFO level setting for long xfers
[ Upstream commit c63b8fd14a7db719f8252038a790638728c4eb66 ] Due to using the u16 type in the min_t() macros the SPI transfer length will be cast to word before participating in the conditional statement implied by the macro. Thus if the transfer length is greater than 64KB the Tx/Rx FIFO threshold level value will be determined by the leftover of the truncated after the type-case length. In the worst case it will cause the dramatical performance drop due to the "Tx FIFO Empty" or "Rx FIFO Full" interrupts triggered on each xfer word sent/received to/from the bus. The problem can be easily fixed by specifying the unsigned int type in the min_t() macros thus preventing the possible data loss. Fixes: ea11370fffdf ("spi: dw: get TX level without an additional variable") Reported-by: Sergey Nazarov <Sergey.Nazarov@baikalelectronics.ru> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Link: https://lore.kernel.org/r/20230113185942.2516-1-Sergey.Semin@baikalelectronics.ru Signed-off-by: Mark Brown <broonie@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--drivers/spi/spi-dw-core.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
index c33866f747db..aa116cee1fd8 100644
--- a/drivers/spi/spi-dw-core.c
+++ b/drivers/spi/spi-dw-core.c
@@ -353,7 +353,7 @@ static void dw_spi_irq_setup(struct dw_spi *dws)
* will be adjusted at the final stage of the IRQ-based SPI transfer
* execution so not to lose the leftover of the incoming data.
*/
- level = min_t(u16, dws->fifo_len / 2, dws->tx_len);
+ level = min_t(unsigned int, dws->fifo_len / 2, dws->tx_len);
dw_writel(dws, DW_SPI_TXFTLR, level);
dw_writel(dws, DW_SPI_RXFTLR, level - 1);