[PATCH v2] spi: bcm2835: enable shared interrupt support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [Linux Kernel]     [Linux ARM (vger)]     [Linux ARM MSM]     [Linux Omap]     [Linux Arm]     [Linux Tegra]     [Fedora ARM]     [Linux for Samsung SOC]     [eCos]     [Linux Fastboot]     [Gcc Help]     [Git]     [DCCP]     [IETF Announce]     [Security]     [Linux MIPS]     [Yosemite Campsites]

  Powered by Linux