Skip to content

Commit faecf41

Browse files
shawn1221storulf
authored andcommitted
mmc: dw_mmc: fix unmap sg twice when finding data err
DATA_OVER(the same for RI/TI of IDMAC) interrupt may come up together with data error interrupts. If so, the interrupt routine set EVENT_DATA_ERR to the pending_events and schedule the tasklet but we may still fallback to the IDMAC interrupt case as the tasklet may come up a little late, namely right after the IDMAC interrupt checking. This will casue dw_mmc unmap sg twice. We can easily see it with CONFIG_DMA_API_DEBUG enabled. WARNING: CPU: 0 PID: 0 at lib/dma-debug.c:1096 check_unmap+0x7bc/0xb38 dwmmc_exynos 12200000.mmc: DMA-API: device driver tries to free DMA memory it has not allocated [device address=0x000000006d9d2200] [size=128 bytes] Modules linked in: CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.7.0-rc4 #26 Hardware name: SAMSUNG EXYNOS (Flattened Device Tree) [<c0112b4c>] (unwind_backtrace) from [<c010d888>] (show_stack+0x20/0x24) [<c010d888>] (show_stack) from [<c03fab0c>] (dump_stack+0x80/0x94) [<c03fab0c>] (dump_stack) from [<c0123548>] (__warn+0xf8/0x110) [<c0123548>] (__warn) from [<c01235a8>] (warn_slowpath_fmt+0x48/0x50) [<c01235a8>] (warn_slowpath_fmt) from [<c042ac90>] (check_unmap+0x7bc/0xb38) [<c042ac90>] (check_unmap) from [<c042b25c>] (debug_dma_unmap_sg+0x118/0x148) [<c042b25c>] (debug_dma_unmap_sg) from [<c077512c>] (dw_mci_dma_cleanup+0x7c/0xb8) [<c077512c>] (dw_mci_dma_cleanup) from [<c0773f24>] (dw_mci_stop_dma+0x40/0x50) [<c0773f24>] (dw_mci_stop_dma) from [<c0777d04>] (dw_mci_tasklet_func+0x130/0x3b4) [<c0777d04>] (dw_mci_tasklet_func) from [<c0129760>] (tasklet_action+0xb4/0x150) ..[snip].. ---[ end trace 256f83eed365daf0 ]--- Reported-by: Seung-Woo Kim <[email protected]> Signed-off-by: Shawn Lin <[email protected]> Signed-off-by: Jaehoon Chung <[email protected]> Signed-off-by: Ulf Hansson <[email protected]>
1 parent 7e4bf1b commit faecf41

File tree

1 file changed

+4
-2
lines changed

1 file changed

+4
-2
lines changed

drivers/mmc/host/dw_mmc.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -2506,15 +2506,17 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
25062506
mci_writel(host, IDSTS64, SDMMC_IDMAC_INT_TI |
25072507
SDMMC_IDMAC_INT_RI);
25082508
mci_writel(host, IDSTS64, SDMMC_IDMAC_INT_NI);
2509-
host->dma_ops->complete((void *)host);
2509+
if (!test_bit(EVENT_DATA_ERROR, &host->pending_events))
2510+
host->dma_ops->complete((void *)host);
25102511
}
25112512
} else {
25122513
pending = mci_readl(host, IDSTS);
25132514
if (pending & (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI)) {
25142515
mci_writel(host, IDSTS, SDMMC_IDMAC_INT_TI |
25152516
SDMMC_IDMAC_INT_RI);
25162517
mci_writel(host, IDSTS, SDMMC_IDMAC_INT_NI);
2517-
host->dma_ops->complete((void *)host);
2518+
if (!test_bit(EVENT_DATA_ERROR, &host->pending_events))
2519+
host->dma_ops->complete((void *)host);
25182520
}
25192521
}
25202522

0 commit comments

Comments
 (0)