On Thu, Feb 18, 2016 at 02:10:56PM +0100, David Engraf wrote: > Hi Ludovic, > > Am 18.02.2016 um 11:48 schrieb Ludovic Desroches: > >--- > > drivers/dma/at_xdmac.c | 25 ++++++++++++++++++++++--- > > 1 file changed, 22 insertions(+), 3 deletions(-) > > > >Hi David, > > > >I tried to adpat the fix Cyrille did for at_hdmac. I think it was exactly the > >same issue. We have to read two registers, one to know the descriptor currently > >used and one to know the residue for this descriptor. Unfortunately, between > >the two reads, the descriptor currently used can change. > > > >Could you try this draft patch? > > It works as well with your patch. I did several runs without loosing any > bytes or a wrong residue. I've also checked how often the loop needs to > retry when check_nda and cur_nda is different and in all cases one more read > was enough. So trying up to 5 times is a good value. Good news, thanks for testing it. I will send a new version with comments, commit message, etc. > > Tested-by: David Engraf <david.engraf@xxxxxxxxx> > > Best regards > - David > > > >Regards > > > >Ludovic > > > >diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c > >index 6b512a2..a38356e 100644 > >--- a/drivers/dma/at_xdmac.c > >+++ b/drivers/dma/at_xdmac.c > >@@ -1395,8 +1395,8 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie, > > struct at_xdmac_desc *desc, *_desc; > > struct list_head *descs_list; > > enum dma_status ret; > >- int residue; > >- u32 cur_nda, mask, value; > >+ int residue, i; > >+ u32 cur_nda, check_nda, cur_ubc, mask, value; > > u8 dwidth = 0; > > unsigned long flags; > > > >@@ -1434,6 +1434,25 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie, > > } > > > > cur_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc; > >+ rmb(); > >+ cur_ubc = at_xdmac_chan_read(atchan, AT_XDMAC_CUBC); > >+ for (i = 0; i < 5; i++) { > >+ rmb(); > >+ check_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc; > >+ > >+ if (likely (cur_nda == check_nda)) > >+ break; > >+ > >+ cur_nda = check_nda; > >+ rmb(); > >+ cur_ubc = at_xdmac_chan_read(atchan, AT_XDMAC_CUBC); > >+ } > >+ > >+ if (unlikely(i >= 5)) { > >+ ret = DMA_ERROR; > >+ goto spin_unlock; > >+ } > >+ > > /* > > * Remove size of all microblocks already transferred and the current > > * one. Then add the remaining size to transfer of the current > >@@ -1446,7 +1465,7 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie, > > if ((desc->lld.mbr_nda & 0xfffffffc) == cur_nda) > > break; > > } > >- residue += at_xdmac_chan_read(atchan, AT_XDMAC_CUBC) << dwidth; > >+ residue += cur_ubc << dwidth; > > > > dma_set_residue(txstate, residue); > > > > > > -- > To unsubscribe from this list: send the line "unsubscribe dmaengine" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe dmaengine" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html