[PATCH] mmc: mxcmmc: cancel data work and watchdog on remove

Fan Wu posted 1 patch 1 month, 3 weeks ago
drivers/mmc/host/mxcmmc.c | 4 ++++
1 file changed, 4 insertions(+)
[PATCH] mmc: mxcmmc: cancel data work and watchdog on remove
Posted by Fan Wu 1 month, 3 weeks ago
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: f6ad0a481342 ("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>
---
 drivers/mmc/host/mxcmmc.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c
index c405cfb8b269..097498a3f8ff 100644
--- a/drivers/mmc/host/mxcmmc.c
+++ b/drivers/mmc/host/mxcmmc.c
@@ -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);

--
2.34.1
Re: [PATCH] mmc: mxcmmc: cancel data work and watchdog on remove
Posted by Ulf Hansson 3 weeks, 4 days ago
On Fri, Aug 7, 2026 at 5:26 AM Fan Wu <fanwu01@zju.edu.cn> wrote:
>
> 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: f6ad0a481342 ("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>

Applied for fixes, thanks!

Kind regards
Uffe


> ---
>  drivers/mmc/host/mxcmmc.c | 4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c
> index c405cfb8b269..097498a3f8ff 100644
> --- a/drivers/mmc/host/mxcmmc.c
> +++ b/drivers/mmc/host/mxcmmc.c
> @@ -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);
>
> --
> 2.34.1