aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host
diff options
context:
space:
mode:
authorTeppei Kamijou <teppei.kamijou.yb@renesas.com>2012-12-12 09:38:12 -0500
committerChris Ball <cjb@laptop.org>2013-02-11 13:28:21 -0500
commiteae309836509496c981ceaebdef57041de86ecd4 (patch)
tree1c9422ea98f6f831d85665abd79226b4af257f29 /drivers/mmc/host
parent5df460b15e10ffcf2c9a05d0c55b309568d330ea (diff)
mmc: sh_mmcif: Terminate DMA transactions when detecting timeout or error
If a DMA transaction fails, terminate all outstanding DMA transfers and unmap buffers. Signed-off-by: Teppei Kamijou <teppei.kamijou.yb@renesas.com> Signed-off-by: Shinya Kuribayashi <shinya.kuribayashi.px@renesas.com> [g.liakhovetski@gmx.de: forward-port, add dma_unmap_sg() in error cases] Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc/host')
-rw-r--r--drivers/mmc/host/sh_mmcif.c31
1 files changed, 17 insertions, 14 deletions
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index f4b10c8f6384..8aa7b0e6dec2 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -263,15 +263,6 @@ static void mmcif_dma_complete(void *arg)
263 dev_name(&host->pd->dev))) 263 dev_name(&host->pd->dev)))
264 return; 264 return;
265 265
266 if (data->flags & MMC_DATA_READ)
267 dma_unmap_sg(host->chan_rx->device->dev,
268 data->sg, data->sg_len,
269 DMA_FROM_DEVICE);
270 else
271 dma_unmap_sg(host->chan_tx->device->dev,
272 data->sg, data->sg_len,
273 DMA_TO_DEVICE);
274
275 complete(&host->dma_complete); 266 complete(&host->dma_complete);
276} 267}
277 268
@@ -1088,14 +1079,20 @@ static bool sh_mmcif_end_cmd(struct sh_mmcif_host *host)
1088 /* Running in the IRQ thread, can sleep */ 1079 /* Running in the IRQ thread, can sleep */
1089 time = wait_for_completion_interruptible_timeout(&host->dma_complete, 1080 time = wait_for_completion_interruptible_timeout(&host->dma_complete,
1090 host->timeout); 1081 host->timeout);
1082
1083 if (data->flags & MMC_DATA_READ)
1084 dma_unmap_sg(host->chan_rx->device->dev,
1085 data->sg, data->sg_len,
1086 DMA_FROM_DEVICE);
1087 else
1088 dma_unmap_sg(host->chan_tx->device->dev,
1089 data->sg, data->sg_len,
1090 DMA_TO_DEVICE);
1091
1091 if (host->sd_error) { 1092 if (host->sd_error) {
1092 dev_err(host->mmc->parent, 1093 dev_err(host->mmc->parent,
1093 "Error IRQ while waiting for DMA completion!\n"); 1094 "Error IRQ while waiting for DMA completion!\n");
1094 /* Woken up by an error IRQ: abort DMA */ 1095 /* Woken up by an error IRQ: abort DMA */
1095 if (data->flags & MMC_DATA_READ)
1096 dmaengine_terminate_all(host->chan_rx);
1097 else
1098 dmaengine_terminate_all(host->chan_tx);
1099 data->error = sh_mmcif_error_manage(host); 1096 data->error = sh_mmcif_error_manage(host);
1100 } else if (!time) { 1097 } else if (!time) {
1101 data->error = -ETIMEDOUT; 1098 data->error = -ETIMEDOUT;
@@ -1106,8 +1103,14 @@ static bool sh_mmcif_end_cmd(struct sh_mmcif_host *host)
1106 BUF_ACC_DMAREN | BUF_ACC_DMAWEN); 1103 BUF_ACC_DMAREN | BUF_ACC_DMAWEN);
1107 host->dma_active = false; 1104 host->dma_active = false;
1108 1105
1109 if (data->error) 1106 if (data->error) {
1110 data->bytes_xfered = 0; 1107 data->bytes_xfered = 0;
1108 /* Abort DMA */
1109 if (data->flags & MMC_DATA_READ)
1110 dmaengine_terminate_all(host->chan_rx);
1111 else
1112 dmaengine_terminate_all(host->chan_tx);
1113 }
1111 1114
1112 return false; 1115 return false;
1113} 1116}