aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNandor Han <nandor.han@ge.com>2016-10-11 07:13:41 -0400
committerVinod Koul <vinod.koul@intel.com>2016-11-25 00:35:14 -0500
commit85f57752b33cf12f1d583f0c10b752292de00abe (patch)
treeeb1d1bf3c9bd96e908d54d4d944f23d10fbcc7a2
parentc44da03dd517c11c2b3525937b0a241fc1c69399 (diff)
dmaengine: imx-sdma - correct the dma transfer residue calculation
The residue calculation was taking in consideration that dma transaction status will be always retrieved in the dma callback used to inform that dma transfer is complete. However this is not the case for all subsystems that use dma. Some subsystems use a timer to check the dma status periodically. Therefore the calculation was updated and residue is calculated accordingly by a) update the residue calculation taking in consideration the last used buffer index by using *buf_ptail* variable and b) chn_real_count (number of bytes transferred) is initialized to zero, when dma channel is created, to avoid using an uninitialized value in residue calculation when dma status is checked without waiting dma complete event. Signed-off-by: Nandor Han <nandor.han@ge.com> Acked-by: Peter Senna Tschudin <peter.senna@collabora.com> Tested-by: Peter Senna Tschudin <peter.senna@collabora.com> Tested-by: Marek Vasut <marex@denx.de> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
-rw-r--r--drivers/dma/imx-sdma.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index b9629b2bfc05..d1651a50c349 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -298,6 +298,7 @@ struct sdma_engine;
298 * @event_id1 for channels that use 2 events 298 * @event_id1 for channels that use 2 events
299 * @word_size peripheral access size 299 * @word_size peripheral access size
300 * @buf_tail ID of the buffer that was processed 300 * @buf_tail ID of the buffer that was processed
301 * @buf_ptail ID of the previous buffer that was processed
301 * @num_bd max NUM_BD. number of descriptors currently handling 302 * @num_bd max NUM_BD. number of descriptors currently handling
302 */ 303 */
303struct sdma_channel { 304struct sdma_channel {
@@ -309,6 +310,7 @@ struct sdma_channel {
309 unsigned int event_id1; 310 unsigned int event_id1;
310 enum dma_slave_buswidth word_size; 311 enum dma_slave_buswidth word_size;
311 unsigned int buf_tail; 312 unsigned int buf_tail;
313 unsigned int buf_ptail;
312 unsigned int num_bd; 314 unsigned int num_bd;
313 unsigned int period_len; 315 unsigned int period_len;
314 struct sdma_buffer_descriptor *bd; 316 struct sdma_buffer_descriptor *bd;
@@ -700,6 +702,8 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
700 sdmac->chn_real_count = bd->mode.count; 702 sdmac->chn_real_count = bd->mode.count;
701 bd->mode.status |= BD_DONE; 703 bd->mode.status |= BD_DONE;
702 bd->mode.count = sdmac->period_len; 704 bd->mode.count = sdmac->period_len;
705 sdmac->buf_ptail = sdmac->buf_tail;
706 sdmac->buf_tail = (sdmac->buf_tail + 1) % sdmac->num_bd;
703 707
704 /* 708 /*
705 * The callback is called from the interrupt context in order 709 * The callback is called from the interrupt context in order
@@ -710,9 +714,6 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
710 714
711 dmaengine_desc_get_callback_invoke(&sdmac->desc, NULL); 715 dmaengine_desc_get_callback_invoke(&sdmac->desc, NULL);
712 716
713 sdmac->buf_tail++;
714 sdmac->buf_tail %= sdmac->num_bd;
715
716 if (error) 717 if (error)
717 sdmac->status = old_status; 718 sdmac->status = old_status;
718 } 719 }
@@ -1186,6 +1187,8 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
1186 sdmac->flags = 0; 1187 sdmac->flags = 0;
1187 1188
1188 sdmac->buf_tail = 0; 1189 sdmac->buf_tail = 0;
1190 sdmac->buf_ptail = 0;
1191 sdmac->chn_real_count = 0;
1189 1192
1190 dev_dbg(sdma->dev, "setting up %d entries for channel %d.\n", 1193 dev_dbg(sdma->dev, "setting up %d entries for channel %d.\n",
1191 sg_len, channel); 1194 sg_len, channel);
@@ -1288,6 +1291,8 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
1288 sdmac->status = DMA_IN_PROGRESS; 1291 sdmac->status = DMA_IN_PROGRESS;
1289 1292
1290 sdmac->buf_tail = 0; 1293 sdmac->buf_tail = 0;
1294 sdmac->buf_ptail = 0;
1295 sdmac->chn_real_count = 0;
1291 sdmac->period_len = period_len; 1296 sdmac->period_len = period_len;
1292 1297
1293 sdmac->flags |= IMX_DMA_SG_LOOP; 1298 sdmac->flags |= IMX_DMA_SG_LOOP;
@@ -1385,7 +1390,7 @@ static enum dma_status sdma_tx_status(struct dma_chan *chan,
1385 u32 residue; 1390 u32 residue;
1386 1391
1387 if (sdmac->flags & IMX_DMA_SG_LOOP) 1392 if (sdmac->flags & IMX_DMA_SG_LOOP)
1388 residue = (sdmac->num_bd - sdmac->buf_tail) * 1393 residue = (sdmac->num_bd - sdmac->buf_ptail) *
1389 sdmac->period_len - sdmac->chn_real_count; 1394 sdmac->period_len - sdmac->chn_real_count;
1390 else 1395 else
1391 residue = sdmac->chn_count - sdmac->chn_real_count; 1396 residue = sdmac->chn_count - sdmac->chn_real_count;