Skip to content

Commit f883b92

Browse files
ldesrochesgregkh
authored andcommitted
dmaengine: at_xdmac: double FIFO flush needed to compute residue
commit 9295c41 upstream. Due to the way CUBC register is updated, a double flush is needed to compute an accurate residue. First flush aim is to get data from the DMA FIFO and second one ensures that we won't report data which are not in memory. Signed-off-by: Ludovic Desroches <[email protected]> Fixes: e1f7c9e ("dmaengine: at_xdmac: creation of the atmel eXtended DMA Controller driver") Reviewed-by: Nicolas Ferre <[email protected]> Signed-off-by: Vinod Koul <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent d1a4116 commit f883b92

File tree

1 file changed

+23
-1
lines changed

1 file changed

+23
-1
lines changed

drivers/dma/at_xdmac.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1425,7 +1425,16 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
14251425
residue = desc->xfer_size;
14261426
/*
14271427
* Flush FIFO: only relevant when the transfer is source peripheral
1428-
* synchronized.
1428+
* synchronized. Flush is needed before reading CUBC because data in
1429+
* the FIFO are not reported by CUBC. Reporting a residue of the
1430+
* transfer length while we have data in FIFO can cause issue.
1431+
* Usecase: atmel USART has a timeout which means I have received
1432+
* characters but there is no more character received for a while. On
1433+
* timeout, it requests the residue. If the data are in the DMA FIFO,
1434+
* we will return a residue of the transfer length. It means no data
1435+
* received. If an application is waiting for these data, it will hang
1436+
* since we won't have another USART timeout without receiving new
1437+
* data.
14291438
*/
14301439
mask = AT_XDMAC_CC_TYPE | AT_XDMAC_CC_DSYNC;
14311440
value = AT_XDMAC_CC_TYPE_PER_TRAN | AT_XDMAC_CC_DSYNC_PER2MEM;
@@ -1480,6 +1489,19 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
14801489
goto spin_unlock;
14811490
}
14821491

1492+
/*
1493+
* Flush FIFO: only relevant when the transfer is source peripheral
1494+
* synchronized. Another flush is needed here because CUBC is updated
1495+
* when the controller sends the data write command. It can lead to
1496+
* report data that are not written in the memory or the device. The
1497+
* FIFO flush ensures that data are really written.
1498+
*/
1499+
if ((desc->lld.mbr_cfg & mask) == value) {
1500+
at_xdmac_write(atxdmac, AT_XDMAC_GSWF, atchan->mask);
1501+
while (!(at_xdmac_chan_read(atchan, AT_XDMAC_CIS) & AT_XDMAC_CIS_FIS))
1502+
cpu_relax();
1503+
}
1504+
14831505
/*
14841506
* Remove size of all microblocks already transferred and the current
14851507
* one. Then add the remaining size to transfer of the current

0 commit comments

Comments
 (0)