mirror of
https://github.com/torvalds/linux.git
synced 2026-09-24 06:24:02 +02:00
mmc: mxcmmc: cancel data work and watchdog on remove
mxcmci_remove() frees the host through the devm tail, but neither it nor
mmc_remove_host() drains the driver's own asynchronous state.
host->watchdog, a 10 s timer armed on the DMA path in mxcmci_setup_data(),
is deleted only by the DMA- and IRQ-complete paths, which the remove path
does not explicitly drain; it can therefore fire after the host is freed
and dereference it in mxcmci_watchdog(). host->datawork, armed from the
IRQ handler on the PIO path, is not cancelled by the remove path either.
Free the devm-registered IRQ, then cancel datawork and delete the watchdog
in mxcmci_remove(), before dma_release_channel(). Freeing the IRQ first
keeps a trailing handler from re-arming datawork between the cancel and
the host free. Both callbacks are non-self-rearming.
This issue was found by an in-house static analysis tool.
Fixes: f6ad0a4813 ("mmc: mxcmmc: fix bug that may block a data transfer forever")
Cc: stable@vger.kernel.org
Assisted-by: Codex:gpt-5.6
Signed-off-by: Fan Wu <fanwu01@zju.edu.cn>
Signed-off-by: Ulf Hansson <ulfh@kernel.org>
This commit is contained in:
parent
2b19cf3e50
commit
d3a421c824
|
|
@ -1173,6 +1173,10 @@ static void mxcmci_remove(struct platform_device *pdev)
|
|||
|
||||
mmc_remove_host(mmc);
|
||||
|
||||
devm_free_irq(&pdev->dev, platform_get_irq(pdev, 0), host);
|
||||
cancel_work_sync(&host->datawork);
|
||||
timer_delete_sync(&host->watchdog);
|
||||
|
||||
if (host->pdata && host->pdata->exit)
|
||||
host->pdata->exit(&pdev->dev, mmc);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user