Patch "dmaengine: at_xdmac: fix residue computation" has been added to the 4.4-stable tree
Subsystems (3)
This is a note to let you know that I've just added the patch titled
dmaengine: at_xdmac: fix residue computation
to the 4.4-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
dmaengine-at_xdmac-fix-residue-computation.patch
and it can be found in the queue-4.4 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
25c5e9626ca4d40928dc9c44f009ce2ed0a739e7Mon Sep 17 00:00:00 2001
From: Ludovic Desroches <[email protected]>
Date: Thu, 10 Mar 2016 10:17:55 +0100
Subject: dmaengine: at_xdmac: fix residue computation
From: Ludovic Desroches <[email protected]>
commit 25c5e9626ca4d40928dc9c44f009ce2ed0a739e7 upstream.
When computing the residue we need two pieces of information: the current descriptor and the remaining data of the current descriptor. To get that information, we need to read consecutively two registers but we can't do it in an atomic way. For that reason, we have to check manually that current descriptor has not changed.
eXtended DMA Controller driver")
--- drivers/dma/at_xdmac.c | 42 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-)
drivers/dma/at_xdmac.c +39 -3
@@ -176,6 +176,7 @@#define AT_XDMAC_MAX_CHAN 0x20#define AT_XDMAC_MAX_CSIZE 16/* 16 data */ #define AT_XDMAC_MAX_DWIDTH 8/* 64 bits */ +#define AT_XDMAC_RESIDUE_MAX_RETRIES 5#define AT_XDMAC_DMA_BUSWIDTHS \ (BIT(DMA_SLAVE_BUSWIDTH_UNDEFINED) |\
@@ -1383,8 +1384,8 @@ at_xdmac_tx_status(struct dma_chan *chanstruct at_xdmac_desc *desc, *_desc;struct list_head *descs_list;enum dma_status ret; -int residue; -u32 cur_nda, mask, value; +int residue, retry; +u32 cur_nda, check_nda, cur_ubc, mask, value;u8 dwidth =0 ;unsigned long flags;
@@ -1421,7 +1422,42 @@ at_xdmac_tx_status(struct dma_chan *chancpu_relax (); } +/* +* When processing the residue, we need to read two registers but we +* can't do it in an atomic way. AT_XDMAC_CNDA is used to find where +* we stand in the descriptor list and AT_XDMAC_CUBC is used +* to know how many data are remaining for the current descriptor. +* Since the dma channel is not paused to not loose data, between the +* AT_XDMAC_CNDA and AT_XDMAC_CUBC read, we may have change of +* descriptor. +* For that reason, after reading AT_XDMAC_CUBC, we check if we are +* still using the same descriptor by reading a second time +* AT_XDMAC_CNDA. If AT_XDMAC_CNDA has changed, it means we have to +* read again AT_XDMAC_CUBC. +* Memory barriers are used to ensure the read order of the registers. +* A max number of retries is set because unlikely it can never ends if +* we are transferring a lot of data with small buffers. +*/ cur_nda =at_xdmac_chan_read (atchan,AT_XDMAC_CNDA ) &0xfffffffc ; +rmb (); + cur_ubc =at_xdmac_chan_read (atchan,AT_XDMAC_CUBC ); +for (retry =0 ; retry <AT_XDMAC_RESIDUE_MAX_RETRIES ; retry++) { +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 (retry >=AT_XDMAC_RESIDUE_MAX_RETRIES )) { + 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
@@ -1434,7 +1470,7 @@ at_xdmac_tx_status(struct dma_chan *chanif ((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);
Patches currently in stable-queue which might be from [email protected] are
queue-4.4/dmaengine-at_xdmac-fix-residue-computation.patch