spi: spi-mt65xx: Use threaded interrupt for non-SPIMEM transfer

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@collabora.com>
Link: https://patch.msgid.link/20240726114721.142196-1-angelogioacchino.delregno@collabora.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
AngeloGioacchino Del Regno 2024-07-26 13:47:21 +02:00 committed by Mark Brown
parent dc58d15ae7
commit 5972eb05ca
No known key found for this signature in database
GPG key ID: 24D68B725D5487D0

View file

@ -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");