mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
dmaengine: Allow drivers to assign static channel IDs
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. For example, idma32 uses chan_id to select DMA_CTL_CH() and DMA_XBAR_SEL(), so it relies on ascending registration order to match chan_id with the hardware channel number. 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@nxp.com> Reviewed-by: Frank Li <Frank.Li@nxp.com> Signed-off-by: Koichiro Den <den@valinux.co.jp> Link: https://lore.kernel.org/r/lm7tadnxsyrypu4mypptlkx5qkytex4qxsijdr5ydud2n3anvf@yakjfjg5ng4u/ Link: https://lore.kernel.org/r/20260813063757.3131865-2-den@valinux.co.jp/ Link: https://lore.kernel.org/r/an4TXwT37vWYEzCn@SMW015318/ Link: https://patch.msgid.link/20260912174023.1227397-2-den@valinux.co.jp Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
parent
7b6aa7904a
commit
f54701da5c
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -1119,6 +1119,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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -377,6 +377,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
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user