[PATCH v4 14/24] dmaengine: dw-edma: Add LL interrupt placement policy
From: Koichiro Den
Date: Wed Jul 29 2026 - 10:45:44 EST
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 <Frank.li@xxxxxxxxxxx>
Signed-off-by: Koichiro Den <den@xxxxxxxxxxxxx>
---
Changes in v4:
- Move the "more issued work follows" condition to the dynamic append
patch, resolving the bisectability issue pointed out by Sashiko.
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 75d659f65a6d..16d3d2a8d1c2 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)
{
@@ -250,6 +253,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;
@@ -271,7 +294,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