diff options
author | Shawn Lin <shawn.lin@rock-chips.com> | 2016-06-24 15:39:52 +0800 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@linaro.org> | 2016-07-25 10:34:30 +0200 |
commit | faecf41106123ac62c06475ef3a61bc1dabfcad2 (patch) | |
tree | e6b26ed5d1e1f18121e6a1188e122bf11938552f /drivers/mmc | |
parent | 7e4bf1bc9543a1760cd93f0e23325e7b0365b30a (diff) | |
download | linux-faecf41106123ac62c06475ef3a61bc1dabfcad2.tar.bz2 |
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 <sw0312.kim@samsung.com>
Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/host/dw_mmc.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index e857beb43144..2dfdc58bae13 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -2506,7 +2506,8 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) mci_writel(host, IDSTS64, SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI); mci_writel(host, IDSTS64, SDMMC_IDMAC_INT_NI); - host->dma_ops->complete((void *)host); + if (!test_bit(EVENT_DATA_ERROR, &host->pending_events)) + host->dma_ops->complete((void *)host); } } else { pending = mci_readl(host, IDSTS); @@ -2514,7 +2515,8 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) mci_writel(host, IDSTS, SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI); mci_writel(host, IDSTS, SDMMC_IDMAC_INT_NI); - host->dma_ops->complete((void *)host); + if (!test_bit(EVENT_DATA_ERROR, &host->pending_events)) + host->dma_ops->complete((void *)host); } } |