[PATCH v7 01/10] dmaengine: Allow drivers to assign static channel IDs

From: Koichiro Den

Date: Thu Aug 13 2026 - 02:40:55 EST


The dmaengine core assigns channel IDs in registration order. If a driver
skips a hardware channel, chan_id can differ from the hardware numbering
and a client cannot reliably correlate a requested channel with hardware
resources.

Let a driver request an exact channel ID before device registration.
Reserve static IDs through the existing IDA so they remain unique, while
retaining automatic IDA allocation as the default.

Use direction-flattened IDs for dw-edma channels. Unlike the
direction-local hardware channel number, these IDs are unique within the
DMA device.

Suggested-by: Frank Li <Frank.Li@xxxxxxx>
Signed-off-by: Koichiro Den <den@xxxxxxxxxxxxx>
---
Changes in v7:
- New patch. (Frank)
https://lore.kernel.org/r/lm7tadnxsyrypu4mypptlkx5qkytex4qxsijdr5ydud2n3anvf@yakjfjg5ng4u/

drivers/dma/dmaengine.c | 13 ++++++++-----
drivers/dma/dw-edma/dw-edma-core.c | 1 +
include/linux/dmaengine.h | 20 ++++++++++++++++++++
3 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 6ffd8bd82154..cc64a4679e6f 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -1078,6 +1078,7 @@ static int __dma_async_device_channel_register(struct dma_device *device,
struct dma_chan *chan,
const char *name)
{
+ unsigned int id;
int rc;

chan->local = alloc_percpu(typeof(*chan->local));
@@ -1089,11 +1090,13 @@ static int __dma_async_device_channel_register(struct dma_device *device,
goto err_free_local;
}

- /*
- * When the chan_id is a negative value, we are dynamically adding
- * the channel. Otherwise we are static enumerating.
- */
- chan->chan_id = ida_alloc(&device->chan_ida, GFP_KERNEL);
+ if (chan->chan_id & DMA_CHAN_ID_STATIC) {
+ id = chan->chan_id & ~DMA_CHAN_ID_STATIC;
+ chan->chan_id = ida_alloc_range(&device->chan_ida, id, id,
+ GFP_KERNEL);
+ } else {
+ chan->chan_id = ida_alloc(&device->chan_ida, GFP_KERNEL);
+ }
if (chan->chan_id < 0) {
pr_err("%s: unable to alloc ida for chan: %d\n",
__func__, chan->chan_id);
diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
index 1f893dc54c79..d214df55da3c 100644
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -987,6 +987,7 @@ static int dw_edma_channel_setup(struct dw_edma *dw, u32 wr_alloc, u32 rd_alloc)
&dw->chip->dt_region_rd[chan->id];

vchan_init(&chan->vc, dma);
+ dmaengine_set_static_chan_id(&chan->vc.chan, i);

dw_edma_core_ch_config(chan);
}
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index fe33a20abc61..f669b79d7731 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -369,6 +369,26 @@ struct dma_chan {
void *private;
};

+#define DMA_CHAN_ID_STATIC BIT(30)
+
+/**
+ * dmaengine_set_static_chan_id - request an exact DMA engine channel ID
+ * @chan: DMA channel
+ * @id: channel ID, unique within the DMA device
+ *
+ * Drivers may call this after initializing @chan and before registering its
+ * DMA device. The dmaengine core reserves @id from the device IDA instead of
+ * assigning the next available ID.
+ */
+static inline void dmaengine_set_static_chan_id(struct dma_chan *chan,
+ unsigned int id)
+{
+ if (WARN_ON_ONCE(id >= DMA_CHAN_ID_STATIC))
+ return;
+
+ chan->chan_id = DMA_CHAN_ID_STATIC | id;
+}
+
/**
* struct dma_chan_dev - relate sysfs device node to backing channel device
* @chan: driver channel device
--
2.51.0