mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-07 03:18:31 +00:00
dmaengine: edma: special case slot limit workaround
Currently drivers are limited to 19 slots for cyclic transfers. However, if the DMA burst size is the same as the period size, the period size can be changed to the full buffer size and intermediate interrupts activated. Since intermediate interrupts will trigger for each burst and the burst size is the same as the period size, the driver will get interrupts each period as expected. This has the benefit of allowing the functionality of many more slots, but only uses 2 slots. This workaround is only active if more than 19 slots are needed and the burst size matches the period size. Acked-by: Peter Ujfalusi <peter.ujfalusi@ti.com> Signed-off-by: John Ogness <john.ogness@linutronix.de> Signed-off-by: Sekhar Nori <nsekhar@ti.com> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
This commit is contained in:
parent
23f49fd2ea
commit
a482f4e0d8
1 changed files with 22 additions and 3 deletions
|
@ -1238,6 +1238,7 @@ static struct dma_async_tx_descriptor *edma_prep_dma_cyclic(
|
||||||
struct edma_desc *edesc;
|
struct edma_desc *edesc;
|
||||||
dma_addr_t src_addr, dst_addr;
|
dma_addr_t src_addr, dst_addr;
|
||||||
enum dma_slave_buswidth dev_width;
|
enum dma_slave_buswidth dev_width;
|
||||||
|
bool use_intermediate = false;
|
||||||
u32 burst;
|
u32 burst;
|
||||||
int i, ret, nslots;
|
int i, ret, nslots;
|
||||||
|
|
||||||
|
@ -1279,8 +1280,21 @@ static struct dma_async_tx_descriptor *edma_prep_dma_cyclic(
|
||||||
* but the synchronization is difficult to achieve with Cyclic and
|
* but the synchronization is difficult to achieve with Cyclic and
|
||||||
* cannot be guaranteed, so we error out early.
|
* cannot be guaranteed, so we error out early.
|
||||||
*/
|
*/
|
||||||
if (nslots > MAX_NR_SG)
|
if (nslots > MAX_NR_SG) {
|
||||||
return NULL;
|
/*
|
||||||
|
* If the burst and period sizes are the same, we can put
|
||||||
|
* the full buffer into a single period and activate
|
||||||
|
* intermediate interrupts. This will produce interrupts
|
||||||
|
* after each burst, which is also after each desired period.
|
||||||
|
*/
|
||||||
|
if (burst == period_len) {
|
||||||
|
period_len = buf_len;
|
||||||
|
nslots = 2;
|
||||||
|
use_intermediate = true;
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
edesc = kzalloc(sizeof(*edesc) + nslots * sizeof(edesc->pset[0]),
|
edesc = kzalloc(sizeof(*edesc) + nslots * sizeof(edesc->pset[0]),
|
||||||
GFP_ATOMIC);
|
GFP_ATOMIC);
|
||||||
|
@ -1358,8 +1372,13 @@ static struct dma_async_tx_descriptor *edma_prep_dma_cyclic(
|
||||||
/*
|
/*
|
||||||
* Enable period interrupt only if it is requested
|
* Enable period interrupt only if it is requested
|
||||||
*/
|
*/
|
||||||
if (tx_flags & DMA_PREP_INTERRUPT)
|
if (tx_flags & DMA_PREP_INTERRUPT) {
|
||||||
edesc->pset[i].param.opt |= TCINTEN;
|
edesc->pset[i].param.opt |= TCINTEN;
|
||||||
|
|
||||||
|
/* Also enable intermediate interrupts if necessary */
|
||||||
|
if (use_intermediate)
|
||||||
|
edesc->pset[i].param.opt |= ITCINTEN;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Place the cyclic channel to highest priority queue */
|
/* Place the cyclic channel to highest priority queue */
|
||||||
|
|
Loading…
Reference in a new issue