Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Nandor Han and committed by
Vinod Koul
85f57752 c44da03d

+9 -4
+9 -4
drivers/dma/imx-sdma.c
··· 298 298 * @event_id1 for channels that use 2 events 299 299 * @word_size peripheral access size 300 300 * @buf_tail ID of the buffer that was processed 301 + * @buf_ptail ID of the previous buffer that was processed 301 302 * @num_bd max NUM_BD. number of descriptors currently handling 302 303 */ 303 304 struct sdma_channel { ··· 310 309 unsigned int event_id1; 311 310 enum dma_slave_buswidth word_size; 312 311 unsigned int buf_tail; 312 + unsigned int buf_ptail; 313 313 unsigned int num_bd; 314 314 unsigned int period_len; 315 315 struct sdma_buffer_descriptor *bd; ··· 702 700 sdmac->chn_real_count = bd->mode.count; 703 701 bd->mode.status |= BD_DONE; 704 702 bd->mode.count = sdmac->period_len; 703 + sdmac->buf_ptail = sdmac->buf_tail; 704 + sdmac->buf_tail = (sdmac->buf_tail + 1) % sdmac->num_bd; 705 705 706 706 /* 707 707 * The callback is called from the interrupt context in order ··· 713 709 */ 714 710 715 711 dmaengine_desc_get_callback_invoke(&sdmac->desc, NULL); 716 - 717 - sdmac->buf_tail++; 718 - sdmac->buf_tail %= sdmac->num_bd; 719 712 720 713 if (error) 721 714 sdmac->status = old_status; ··· 1187 1186 sdmac->flags = 0; 1188 1187 1189 1188 sdmac->buf_tail = 0; 1189 + sdmac->buf_ptail = 0; 1190 + sdmac->chn_real_count = 0; 1190 1191 1191 1192 dev_dbg(sdma->dev, "setting up %d entries for channel %d.\n", 1192 1193 sg_len, channel); ··· 1291 1288 sdmac->status = DMA_IN_PROGRESS; 1292 1289 1293 1290 sdmac->buf_tail = 0; 1291 + sdmac->buf_ptail = 0; 1292 + sdmac->chn_real_count = 0; 1294 1293 sdmac->period_len = period_len; 1295 1294 1296 1295 sdmac->flags |= IMX_DMA_SG_LOOP; ··· 1390 1385 u32 residue; 1391 1386 1392 1387 if (sdmac->flags & IMX_DMA_SG_LOOP) 1393 - residue = (sdmac->num_bd - sdmac->buf_tail) * 1388 + residue = (sdmac->num_bd - sdmac->buf_ptail) * 1394 1389 sdmac->period_len - sdmac->chn_real_count; 1395 1390 else 1396 1391 residue = sdmac->chn_count - sdmac->chn_real_count;