Skip to content

Commit 1504fb5

Browse files
nagasureshmchpgregkh
authored andcommitted
spi: microchip-core: fix the issues in the isr
[ Upstream commit 502a582 ] It is possible for the TXDONE interrupt be raised if the tx FIFO becomes temporarily empty while transmitting, resulting in recursive calls to mchp_corespi_write_fifo() and therefore a garbage message might be transmitted depending on when the interrupt is triggered. Moving all of the tx FIFO writes out of the TXDONE portion of the interrupt handler avoids this problem. Most of rest of the TXDONE portion of the handler is problematic too. Only reading the rx FIFO (and finalising the transfer) when the TXDONE interrupt is raised can cause the transfer to stall, if the final bytes of rx data are not available in the rx FIFO when the final TXDONE interrupt is raised. The transfer should be finalised regardless of which interrupt is raised, provided that all tx data has been set and all rx data received. The first issue was encountered "in the wild", the second is theoretical. Fixes: 9ac8d17 ("spi: add support for microchip fpga spi controllers") Signed-off-by: Naga Sureshkumar Relli <nagasuresh.relli@microchip.com> Signed-off-by: Conor Dooley <conor.dooley@microchip.com> Link: https://patch.msgid.link/20240715-candied-deforest-585685ef3c8a@wendy Signed-off-by: Mark Brown <broonie@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent aa650d0 commit 1504fb5

1 file changed

Lines changed: 8 additions & 10 deletions

File tree

drivers/spi/spi-microchip-core.c

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -380,21 +380,18 @@ static irqreturn_t mchp_corespi_interrupt(int irq, void *dev_id)
380380
if (intfield == 0)
381381
return IRQ_NONE;
382382

383-
if (intfield & INT_TXDONE) {
383+
if (intfield & INT_TXDONE)
384384
mchp_corespi_write(spi, REG_INT_CLEAR, INT_TXDONE);
385385

386+
if (intfield & INT_RXRDY) {
387+
mchp_corespi_write(spi, REG_INT_CLEAR, INT_RXRDY);
388+
386389
if (spi->rx_len)
387390
mchp_corespi_read_fifo(spi);
388-
389-
if (spi->tx_len)
390-
mchp_corespi_write_fifo(spi);
391-
392-
if (!spi->rx_len)
393-
finalise = true;
394391
}
395392

396-
if (intfield & INT_RXRDY)
397-
mchp_corespi_write(spi, REG_INT_CLEAR, INT_RXRDY);
393+
if (!spi->rx_len && !spi->tx_len)
394+
finalise = true;
398395

399396
if (intfield & INT_RX_CHANNEL_OVERFLOW) {
400397
mchp_corespi_write(spi, REG_INT_CLEAR, INT_RX_CHANNEL_OVERFLOW);
@@ -479,8 +476,9 @@ static int mchp_corespi_transfer_one(struct spi_controller *host,
479476
mchp_corespi_set_xfer_size(spi, (spi->tx_len > FIFO_DEPTH)
480477
? FIFO_DEPTH : spi->tx_len);
481478

482-
if (spi->tx_len)
479+
while (spi->tx_len)
483480
mchp_corespi_write_fifo(spi);
481+
484482
return 1;
485483
}
486484

0 commit comments

Comments
 (0)