From: Martin Sperl <kernel@xxxxxxxxxxxxxxxx> BCM2711 shares an interrupt betweem 5 SPI interfaces (0, 3, 4, 5 & 6). Another interrupt is shared between SPI1, SPI2 and UART1, which also affects BCM2835/6/7. Acting on an interrupt intended for another interface ought to be harmless (although potentially inefficient), but it can cause this driver to crash - presumably because some critical state is not ready. Add a test to the spi-bcm2835 interrupt service routine that interrupts are enabled on this interface to avoid the crash and improve efficiency. Signed-off-by: Martin Sperl <kernel@xxxxxxxxxxxxxxxx> Link: https://github.com/raspberrypi/linux/issues/5048 Suggested-by: https://github.com/boe-pi Co-developed-by: Phil Elwell <phil@xxxxxxxxxxxxxxx> Signed-off-by: Phil Elwell <phil@xxxxxxxxxxxxxxx> Cc: Mark Brown <broonie@xxxxxxxxxx> Cc: Lukas Wunner <lukas@xxxxxxxxx> Signed-off-by: Marc Kleine-Budde <mkl@xxxxxxxxxxxxxx> --- Hello, I'm picking up the work of Martin Sperl et al. to bring the shared interrupt support for the bcm2835 driver to mainline. The original version of this patch was added in ecfbd3cf3b8b ("spi: bcm2835: Enable shared interrupt support"), but later reverted as d62069c22eda ("spi: bcm2835: Remove shared interrupt support"). Here the original version causes transfer timeouts, which lead to driver crashes. This is fixed by first checking if the interrupts are actually enabled, before serving them. The fix has been taken from the rapi downstream repo and squahed into this commit. The updated version of the patch successfully runs with concurrent SPI accesses on SPI0 and SPI3 without problems. regards, Marc Changes since v1: https://lore.kernel.org/all/20200528185805.28991-1-nsaenzjulienne@xxxxxxx - check for if interrupts are enabled before serving IRQs drivers/spi/spi-bcm2835.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 775c0bf2f923..9bdb1b85ae08 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -372,6 +372,10 @@ static irqreturn_t bcm2835_spi_interrupt(int irq, void *dev_id) struct bcm2835_spi *bs = dev_id; u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); + /* Bail out early if interrupts are not enabled */ + if (!(cs & BCM2835_SPI_CS_INTR)) + return IRQ_NONE; + /* * An interrupt is signaled either if DONE is set (TX FIFO empty) * or if RXR is set (RX FIFO >= ¾ full). @@ -1365,8 +1369,8 @@ static int bcm2835_spi_probe(struct platform_device *pdev) bcm2835_wr(bs, BCM2835_SPI_CS, BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX); - err = devm_request_irq(&pdev->dev, bs->irq, bcm2835_spi_interrupt, 0, - dev_name(&pdev->dev), bs); + err = devm_request_irq(&pdev->dev, bs->irq, bcm2835_spi_interrupt, + IRQF_SHARED, dev_name(&pdev->dev), bs); if (err) { dev_err(&pdev->dev, "could not request IRQ: %d\n", err); goto out_dma_release; base-commit: a3fd35be0eda760610a63e179ad860189b890f0b -- 2.35.1