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

Configure Feed

Select the types of activity you want to include in your feed.

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

+41 -3
+39 -3
drivers/dma/at_xdmac.c
··· 176 176 #define AT_XDMAC_MAX_CHAN 0x20 177 177 #define AT_XDMAC_MAX_CSIZE 16 /* 16 data */ 178 178 #define AT_XDMAC_MAX_DWIDTH 8 /* 64 bits */ 179 + #define AT_XDMAC_RESIDUE_MAX_RETRIES 5 179 180 180 181 #define AT_XDMAC_DMA_BUSWIDTHS\ 181 182 (BIT(DMA_SLAVE_BUSWIDTH_UNDEFINED) |\ ··· 1396 1395 struct at_xdmac_desc *desc, *_desc; 1397 1396 struct list_head *descs_list; 1398 1397 enum dma_status ret; 1399 - int residue; 1400 - u32 cur_nda, mask, value; 1398 + int residue, retry; 1399 + u32 cur_nda, check_nda, cur_ubc, mask, value; 1401 1400 u8 dwidth = 0; 1402 1401 unsigned long flags; 1403 1402 ··· 1434 1433 cpu_relax(); 1435 1434 } 1436 1435 1436 + /* 1437 + * When processing the residue, we need to read two registers but we 1438 + * can't do it in an atomic way. AT_XDMAC_CNDA is used to find where 1439 + * we stand in the descriptor list and AT_XDMAC_CUBC is used 1440 + * to know how many data are remaining for the current descriptor. 1441 + * Since the dma channel is not paused to not loose data, between the 1442 + * AT_XDMAC_CNDA and AT_XDMAC_CUBC read, we may have change of 1443 + * descriptor. 1444 + * For that reason, after reading AT_XDMAC_CUBC, we check if we are 1445 + * still using the same descriptor by reading a second time 1446 + * AT_XDMAC_CNDA. If AT_XDMAC_CNDA has changed, it means we have to 1447 + * read again AT_XDMAC_CUBC. 1448 + * Memory barriers are used to ensure the read order of the registers. 1449 + * A max number of retries is set because unlikely it can never ends if 1450 + * we are transferring a lot of data with small buffers. 1451 + */ 1437 1452 cur_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc; 1453 + rmb(); 1454 + cur_ubc = at_xdmac_chan_read(atchan, AT_XDMAC_CUBC); 1455 + for (retry = 0; retry < AT_XDMAC_RESIDUE_MAX_RETRIES; retry++) { 1456 + rmb(); 1457 + check_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc; 1458 + 1459 + if (likely(cur_nda == check_nda)) 1460 + break; 1461 + 1462 + cur_nda = check_nda; 1463 + rmb(); 1464 + cur_ubc = at_xdmac_chan_read(atchan, AT_XDMAC_CUBC); 1465 + } 1466 + 1467 + if (unlikely(retry >= AT_XDMAC_RESIDUE_MAX_RETRIES)) { 1468 + ret = DMA_ERROR; 1469 + goto spin_unlock; 1470 + } 1471 + 1438 1472 /* 1439 1473 * Remove size of all microblocks already transferred and the current 1440 1474 * one. Then add the remaining size to transfer of the current ··· 1482 1446 if ((desc->lld.mbr_nda & 0xfffffffc) == cur_nda) 1483 1447 break; 1484 1448 } 1485 - residue += at_xdmac_chan_read(atchan, AT_XDMAC_CUBC) << dwidth; 1449 + residue += cur_ubc << dwidth; 1486 1450 1487 1451 dma_set_residue(txstate, residue); 1488 1452
+2
drivers/dma/fsldma.c
··· 522 522 chan_dbg(chan, "LD %p callback\n", desc); 523 523 txd->callback(txd->callback_param); 524 524 } 525 + 526 + dma_descriptor_unmap(txd); 525 527 } 526 528 527 529 /* Run any dependencies */