[PATCH v5 14/24] dmaengine: dw-edma: Add LL interrupt placement policy
Koichiro Den <[email protected]>
| Newsgroups | org.kernel.vger.dmaengine,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
Choose LL interrupt positions in the common core. Always request one at descriptor ends, at the last free slot, and before each link. Add one every four entries while the rest of the descriptor does not fit in the current free space. Four entries is an empirically chosen coalescing interval. Suggested-by: Frank Li <[email protected]> Signed-off-by: Koichiro Den <[email protected]> --- Changes in v5: - No changes. drivers/dma/dw-edma/dw-edma-core.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c index 363993c64c44..13c45549e08b 100644 --- a/drivers/dma/dw-edma/dw-edma-core.c +++ b/drivers/dma/dw-edma/dw-edma-core.c @@ -25,6 +25,9 @@ #include "../dmaengine.h" #include "../virt-dma.h" +/* Empirically chosen progress interval. */ +#define DW_EDMA_LL_PROGRESS_INTERVAL 4 + static inline struct dw_edma_desc *vd2dw_edma_desc(struct virt_dma_desc *vd) { @@ -244,6 +247,26 @@ static bool dw_edma_ll_done_is_stopped(struct dw_edma_chan *chan) dw_edma_core_ch_transfer_size(chan) == 0; } +static bool dw_edma_core_enable_ll_irq(struct dw_edma_desc *desc, u32 i, + u32 free) +{ + struct dw_edma_chan *chan = desc->chan; + + /* Always report descriptor ends and the last free slot. */ + if (i == desc->nburst - 1 || free == 1) + return true; + + /* Keep one progress point per physical ring lap. */ + if (chan->ll_head == chan->ll_max - 1) + return true; + + /* Add periodic progress points only while this descriptor does not fit. */ + if (desc->nburst - i <= free) + return false; + + return (chan->ll_head + 1) % DW_EDMA_LL_PROGRESS_INTERVAL == 0; +} + static void dw_edma_core_ll_start(struct dw_edma_desc *desc) { struct dw_edma_chan *chan = desc->chan; @@ -265,7 +288,7 @@ static void dw_edma_core_ll_start(struct dw_edma_desc *desc) dw_edma_core_ll_data(chan, &desc->burst[i], chan->ll_head, chan->cb, - i == desc->nburst - 1 || free == 1); + dw_edma_core_enable_ll_irq(desc, i, free)); chan->ll_head++; -- 2.51.0