In order to avoid blocking for an excessive amount of time, eventually impacting on system responsiveness, interrupt handlers should finish executing in as little time as possible. Use threaded interrupt and move the SPI transfer handling (both CPU and DMA) for the non-spimem case to an interrupt thread instead. For SPI-MEM (IPM) controllers, handling is kept in the blocking interrupt as it simply consists in signalling completion. Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@xxxxxxxxxxxxx> --- drivers/spi/spi-mt65xx.c | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c index 36c2f52cd6b8..dfee244fc317 100644 --- a/drivers/spi/spi-mt65xx.c +++ b/drivers/spi/spi-mt65xx.c @@ -743,25 +743,13 @@ static int mtk_spi_setup(struct spi_device *spi) return 0; } -static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id) +static irqreturn_t mtk_spi_interrupt_thread(int irq, void *dev_id) { u32 cmd, reg_val, cnt, remainder, len; struct spi_controller *host = dev_id; struct mtk_spi *mdata = spi_controller_get_devdata(host); struct spi_transfer *xfer = mdata->cur_transfer; - reg_val = readl(mdata->base + SPI_STATUS0_REG); - if (reg_val & MTK_SPI_PAUSE_INT_STATUS) - mdata->state = MTK_SPI_PAUSED; - else - mdata->state = MTK_SPI_IDLE; - - /* SPI-MEM ops */ - if (mdata->use_spimem) { - complete(&mdata->spimem_done); - return IRQ_HANDLED; - } - if (!host->can_dma(host, NULL, xfer)) { if (xfer->rx_buf) { cnt = mdata->xfer_len / 4; @@ -845,6 +833,27 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } +static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id) +{ + struct spi_controller *host = dev_id; + struct mtk_spi *mdata = spi_controller_get_devdata(host); + u32 reg_val; + + reg_val = readl(mdata->base + SPI_STATUS0_REG); + if (reg_val & MTK_SPI_PAUSE_INT_STATUS) + mdata->state = MTK_SPI_PAUSED; + else + mdata->state = MTK_SPI_IDLE; + + /* SPI-MEM ops */ + if (mdata->use_spimem) { + complete(&mdata->spimem_done); + return IRQ_HANDLED; + } + + return IRQ_WAKE_THREAD; +} + static int mtk_spi_mem_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) { @@ -1255,8 +1264,9 @@ static int mtk_spi_probe(struct platform_device *pdev) dev_notice(dev, "SPI dma_set_mask(%d) failed, ret:%d\n", addr_bits, ret); - ret = devm_request_irq(dev, irq, mtk_spi_interrupt, - IRQF_TRIGGER_NONE, dev_name(dev), host); + ret = devm_request_threaded_irq(dev, irq, mtk_spi_interrupt, + mtk_spi_interrupt_thread, + IRQF_TRIGGER_NONE, dev_name(dev), host); if (ret) return dev_err_probe(dev, ret, "failed to register irq\n"); -- 2.45.2