mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-09-18 23:09:29 +02:00
spi: davinci: switch to managed controller allocation
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: 5b3bb5963f ("spi: davinci: Use devm_*() functions")
Assisted-by: Codex:gpt-5.6
Signed-off-by: Fan Wu <fanwu01@zju.edu.cn>
Link: https://patch.msgid.link/20260719010014.3163356-2-fanwu01@zju.edu.cn
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
@@ -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 @@ free_dma:
|
||||
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 = {
|
||||
|
||||
Reference in New Issue
Block a user