Skip to content

Commit 20698c9

Browse files
committed
Merge tag 'dmaengine-fix-4.5' of git://git.infradead.org/users/vkoul/slave-dma
Pull dmaengine fixes from Vinod Koul: "Two fixes showed up in last few days, and they should be included in 4.5. Summary: Two more late fixes to drivers, nothing major here: - A memory leak fix in fsdma unmap the dma descriptors on freeup - A fix in xdmac driver for residue calculation of dma descriptor" * tag 'dmaengine-fix-4.5' of git://git.infradead.org/users/vkoul/slave-dma: dmaengine: at_xdmac: fix residue computation dmaengine: fsldma: fix memory leak
2 parents 7ae9c76 + 25c5e96 commit 20698c9

File tree

2 files changed

+41
-3
lines changed

2 files changed

+41
-3
lines changed

drivers/dma/at_xdmac.c

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@
176176
#define AT_XDMAC_MAX_CHAN 0x20
177177
#define AT_XDMAC_MAX_CSIZE 16 /* 16 data */
178178
#define AT_XDMAC_MAX_DWIDTH 8 /* 64 bits */
179+
#define AT_XDMAC_RESIDUE_MAX_RETRIES 5
179180

180181
#define AT_XDMAC_DMA_BUSWIDTHS\
181182
(BIT(DMA_SLAVE_BUSWIDTH_UNDEFINED) |\
@@ -1395,8 +1396,8 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
13951396
struct at_xdmac_desc *desc, *_desc;
13961397
struct list_head *descs_list;
13971398
enum dma_status ret;
1398-
int residue;
1399-
u32 cur_nda, mask, value;
1399+
int residue, retry;
1400+
u32 cur_nda, check_nda, cur_ubc, mask, value;
14001401
u8 dwidth = 0;
14011402
unsigned long flags;
14021403

@@ -1433,7 +1434,42 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
14331434
cpu_relax();
14341435
}
14351436

1437+
/*
1438+
* When processing the residue, we need to read two registers but we
1439+
* can't do it in an atomic way. AT_XDMAC_CNDA is used to find where
1440+
* we stand in the descriptor list and AT_XDMAC_CUBC is used
1441+
* to know how many data are remaining for the current descriptor.
1442+
* Since the dma channel is not paused to not loose data, between the
1443+
* AT_XDMAC_CNDA and AT_XDMAC_CUBC read, we may have change of
1444+
* descriptor.
1445+
* For that reason, after reading AT_XDMAC_CUBC, we check if we are
1446+
* still using the same descriptor by reading a second time
1447+
* AT_XDMAC_CNDA. If AT_XDMAC_CNDA has changed, it means we have to
1448+
* read again AT_XDMAC_CUBC.
1449+
* Memory barriers are used to ensure the read order of the registers.
1450+
* A max number of retries is set because unlikely it can never ends if
1451+
* we are transferring a lot of data with small buffers.
1452+
*/
14361453
cur_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc;
1454+
rmb();
1455+
cur_ubc = at_xdmac_chan_read(atchan, AT_XDMAC_CUBC);
1456+
for (retry = 0; retry < AT_XDMAC_RESIDUE_MAX_RETRIES; retry++) {
1457+
rmb();
1458+
check_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc;
1459+
1460+
if (likely(cur_nda == check_nda))
1461+
break;
1462+
1463+
cur_nda = check_nda;
1464+
rmb();
1465+
cur_ubc = at_xdmac_chan_read(atchan, AT_XDMAC_CUBC);
1466+
}
1467+
1468+
if (unlikely(retry >= AT_XDMAC_RESIDUE_MAX_RETRIES)) {
1469+
ret = DMA_ERROR;
1470+
goto spin_unlock;
1471+
}
1472+
14371473
/*
14381474
* Remove size of all microblocks already transferred and the current
14391475
* one. Then add the remaining size to transfer of the current
@@ -1446,7 +1482,7 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
14461482
if ((desc->lld.mbr_nda & 0xfffffffc) == cur_nda)
14471483
break;
14481484
}
1449-
residue += at_xdmac_chan_read(atchan, AT_XDMAC_CUBC) << dwidth;
1485+
residue += cur_ubc << dwidth;
14501486

14511487
dma_set_residue(txstate, residue);
14521488

drivers/dma/fsldma.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,8 @@ static dma_cookie_t fsldma_run_tx_complete_actions(struct fsldma_chan *chan,
522522
chan_dbg(chan, "LD %p callback\n", desc);
523523
txd->callback(txd->callback_param);
524524
}
525+
526+
dma_descriptor_unmap(txd);
525527
}
526528

527529
/* Run any dependencies */

0 commit comments

Comments
 (0)