[RFC PATCH] mmc: dw_mmc: disable bh_work and stop timers on remove

From: BeaCox

Date: Sun Nov 01 2026 - 01:37:58 EST


dw_mci_remove() does not drain bh_work before the driver core releases
the devm-managed host. The interrupt handler, watchdog, fault-injection
timer and DMA completion path can queue that work, whose callback
accesses the host and MMC request state.

After removing the MMC host and masking controller interrupts, drain
the interrupt handler and disable bh_work synchronously. Disabling the
work also rejects later queue attempts, unlike cancellation alone.
Stop both timers after the work callback has finished so that it cannot
rearm a timer after teardown has cancelled it.

The analysis, patch and validation were assisted by OpenAI Codex.

Fixes: 921c87ba3893 ("mmc: Convert from tasklet to BH workqueue")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: BeaCox <0xbeac@xxxxxxxxx>
---
Testing: x86_64 object build with gcc 13.3 and W=1, with
CONFIG_FAULT_INJECTION enabled and disabled. A userspace model of the
extracted remove function checks pending work and modeled late IRQ/timer
queue attempts. It is an ordering check, not a kernel reproducer.

No matching hardware, kernel crash trace or demonstrated unprivileged
trigger is available. Please review the MMC shutdown assumptions and
external DMA callback lifetime. This is an RFC for a teardown fix; no
privilege-escalation or CVE eligibility claim is made.

drivers/mmc/host/dw_mmc.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index ff0b25d287..cc5e163ee7 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -3406,6 +3406,12 @@ void dw_mci_remove(struct dw_mci *host)
mci_writel(host, RINTSTS, 0xFFFFFFFF);
mci_writel(host, INTMASK, 0); /* disable all mmc interrupt first */

+ synchronize_irq(host->irq);
+ /* Stop the work before cancelling timers that it can rearm. */
+ disable_work_sync(&host->bh_work);
+ dw_mci_stop_fault_timer(host);
+ hrtimer_cancel(&host->wd_timer);
+
/* disable clock to CIU */
mci_writel(host, CLKENA, 0);
mci_writel(host, CLKSRC, 0);

base-commit: cbbddb6b08cc9900a87cccaa9b22bbe06aa4f50a
--
2.43.0