diff mbox

[3/3] mmc: mxcmmc: add DMA SG synchronisation

Message ID Pine.LNX.4.64.1401311249390.3234@axis700.grange (mailing list archive)
State New, archived
Headers show

Commit Message

Guennadi Liakhovetski Jan. 31, 2014, 11:54 a.m. UTC
According to the DMA API data has to be synchronised before starting
a DMA transfer to device and after completing a DMA transfer from device.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
 drivers/mmc/host/mxcmmc.c |   18 ++++++++++++------
 1 files changed, 12 insertions(+), 6 deletions(-)
diff mbox

Patch

diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c
index f7199c8..31dfc7b 100644
--- a/drivers/mmc/host/mxcmmc.c
+++ b/drivers/mmc/host/mxcmmc.c
@@ -326,6 +326,7 @@  static inline void mxcmci_swap_buffers(struct mmc_data *data) {}
 
 static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
 {
+	struct device *dev = host->dma->device->dev;
 	unsigned int nob = data->blocks;
 	unsigned int blksz = data->blksz;
 	unsigned int datasize = nob * blksz;
@@ -363,18 +364,20 @@  static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
 		mxcmci_swap_buffers(data);
 	}
 
-	nents = dma_map_sg(host->dma->device->dev, data->sg,
-				     data->sg_len,  host->dma_dir);
+	nents = dma_map_sg(dev, data->sg, data->sg_len,  host->dma_dir);
 	if (nents != data->sg_len)
 		return -EINVAL;
 
+	if (data->flags & MMC_DATA_WRITE)
+		dma_sync_sg_for_device(dev, data->sg, data->sg_len,
+				       host->dma_dir);
+
 	host->desc = dmaengine_prep_slave_sg(host->dma,
 		data->sg, data->sg_len, slave_dirn,
 		DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 
 	if (!host->desc) {
-		dma_unmap_sg(host->dma->device->dev, data->sg, data->sg_len,
-				host->dma_dir);
+		dma_unmap_sg(dev, data->sg, data->sg_len, host->dma_dir);
 		host->do_dma = 0;
 		return 0; /* Fall back to PIO */
 	}
@@ -487,8 +490,11 @@  static int mxcmci_finish_data(struct mxcmci_host *host, unsigned int stat)
 	int data_error;
 
 	if (mxcmci_use_dma(host)) {
-		dma_unmap_sg(host->dma->device->dev, data->sg, data->sg_len,
-				host->dma_dir);
+		struct device *dev = host->dma->device->dev;
+		dma_unmap_sg(dev, data->sg, data->sg_len, host->dma_dir);
+		if (host->dma_dir == DMA_FROM_DEVICE)
+			dma_sync_sg_for_cpu(dev, data->sg, data->sg_len,
+					    host->dma_dir);
 		mxcmci_swap_buffers(data);
 	}