]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
spi: geni-qcom: Check DMA interrupts early in ISR
authorPraveen Talari <praveen.talari@oss.qualcomm.com>
Fri, 13 Mar 2026 16:19:01 +0000 (21:49 +0530)
committerMark Brown <broonie@kernel.org>
Tue, 17 Mar 2026 17:07:47 +0000 (17:07 +0000)
The current interrupt handler only checks the GENI main IRQ status
(m_irq) before deciding to return IRQ_NONE. This can lead to spurious
IRQ_NONE returns when DMA interrupts are pending but m_irq is zero.

Move the DMA TX/RX status register reads to the beginning of the ISR,
right after reading m_irq. Update the early return condition to check
all three status registers (m_irq, dma_tx_status, dma_rx_status) before
returning IRQ_NONE.

Signed-off-by: Praveen Talari <praveen.talari@oss.qualcomm.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Link: https://patch.msgid.link/20260313-spi-geni-qcom-fix-dma-irq-handling-v1-1-0bd122589e02@oss.qualcomm.com
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/spi/spi-geni-qcom.c

index 772b7148ba5f0d20ee42d3532412954d111c64c2..d5fb0edc8e0c8b24f24f21ffa9afcdaee2350af0 100644 (file)
@@ -906,10 +906,13 @@ static irqreturn_t geni_spi_isr(int irq, void *data)
        struct spi_controller *spi = data;
        struct spi_geni_master *mas = spi_controller_get_devdata(spi);
        struct geni_se *se = &mas->se;
-       u32 m_irq;
+       u32 m_irq, dma_tx_status, dma_rx_status;
 
        m_irq = readl(se->base + SE_GENI_M_IRQ_STATUS);
-       if (!m_irq)
+       dma_tx_status = readl_relaxed(se->base + SE_DMA_TX_IRQ_STAT);
+       dma_rx_status = readl_relaxed(se->base + SE_DMA_RX_IRQ_STAT);
+
+       if (!m_irq && !dma_tx_status && !dma_rx_status)
                return IRQ_NONE;
 
        if (m_irq & (M_CMD_OVERRUN_EN | M_ILLEGAL_CMD_EN | M_CMD_FAILURE_EN |
@@ -957,8 +960,6 @@ static irqreturn_t geni_spi_isr(int irq, void *data)
                }
        } else if (mas->cur_xfer_mode == GENI_SE_DMA) {
                const struct spi_transfer *xfer = mas->cur_xfer;
-               u32 dma_tx_status = readl_relaxed(se->base + SE_DMA_TX_IRQ_STAT);
-               u32 dma_rx_status = readl_relaxed(se->base + SE_DMA_RX_IRQ_STAT);
 
                if (dma_tx_status)
                        writel(dma_tx_status, se->base + SE_DMA_TX_IRQ_CLR);