drivers/spi/spi-davinci.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
The controller is allocated with the non-managed spi_alloc_host() while
the interrupt is registered with devm_request_threaded_irq(). During
removal, spi_bitbang_stop() only unregisters the controller; the
subsequent spi_controller_put() then frees the controller together with
its embedded davinci_spi devdata, which is the IRQ handler's dev_id.
The devm_request_threaded_irq() release action (free_irq()), which
drains the handler, does not run until after .remove() returns. A late
or latched interrupt can therefore reach davinci_spi_irq() and
dereference already-freed memory.
Switch to devm_spi_alloc_host() so that the devres LIFO order releases
the controller only after free_irq() has drained the handler, and drop
the now-redundant spi_controller_put() from .remove(). The probe error
path is simplified to direct returns.
The clock is acquired with devm_clk_get_enabled(), which is registered
after the IRQ and thus released before it by the devres LIFO order.
Drain the interrupt explicitly with devm_free_irq() before disabling the
controller so that a late interrupt cannot access the registers of a
clock-gated controller.
This issue was found by an in-house static analysis tool.
Fixes: 5b3bb5963ff2 ("spi: davinci: Use devm_*() functions")
Assisted-by: Codex:gpt-5.6
Signed-off-by: Fan Wu <fanwu01@zju.edu.cn>
---
drivers/spi/spi-davinci.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c
index da7f2ae3a570..087735ed9c80 100644
--- a/drivers/spi/spi-davinci.c
+++ b/drivers/spi/spi-davinci.c
@@ -928,7 +928,7 @@ static int davinci_spi_probe(struct platform_device *pdev)
int ret = 0;
u32 spipc0;
- host = spi_alloc_host(&pdev->dev, sizeof(struct davinci_spi));
+ host = devm_spi_alloc_host(&pdev->dev, sizeof(struct davinci_spi));
if (host == NULL) {
ret = -ENOMEM;
goto err;
@@ -1057,7 +1057,6 @@ static int davinci_spi_probe(struct platform_device *pdev)
dma_release_channel(dspi->dma_tx);
}
free_host:
- spi_controller_put(host);
err:
return ret;
}
@@ -1081,6 +1080,8 @@ static void davinci_spi_remove(struct platform_device *pdev)
spi_bitbang_stop(&dspi->bitbang);
+ devm_free_irq(&pdev->dev, dspi->irq, dspi);
+
/* This bit needs to be cleared to disable dpsi->clk */
clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK);
@@ -1088,8 +1089,6 @@ static void davinci_spi_remove(struct platform_device *pdev)
dma_release_channel(dspi->dma_rx);
dma_release_channel(dspi->dma_tx);
}
-
- spi_controller_put(host);
}
static struct platform_driver davinci_spi_driver = {
--
2.34.1
© 2016 - 2026 Red Hat, Inc.