1.代码示例
dma_request_channel
#define dma_request_channel(mask, x, y) \
__dma_request_channel(&(mask), x, y, NULL)
struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
dma_filter_fn fn, void *fn_param,
struct device_node *np)
{
struct dma_device *device, *_d;
struct dma_chan *chan = NULL;
/* Find a channel */
mutex_lock(&dma_list_mutex);
list_for_each_entry_safe(device, _d, &dma_device_list, global_node) {
/* Finds a DMA controller with matching device node */
if (np && device->dev->of_node && np != device->dev->of_node)
continue;
chan = find_candidate(device, mask, fn, fn_param);
if (!IS_ERR(chan))
break;
chan = NULL;
}
mutex_unlock(&dma_list_mutex);
pr_debug("%s: %s (%s)\n",
__func__,
chan ? "success" : "fail",
chan ? dma_chan_name(chan) : NULL);
return chan;
}
dma_request_slave_channel_compat
#define dma_request_slave_channel_compat(mask, x, y, dev, name) \
__dma_request_slave_channel_compat(&(mask), x, y, dev, name)
static inline struct dma_chan
*__dma_request_slave_channel_compat(const dma_cap_mask_t *mask,
dma_filter_fn fn, void *fn_param,
struct device *dev, const char *name)
{
struct dma_chan *chan;
chan = dma_request_slave_channel(dev, name);
if (chan)
return chan;
if (!fn || !fn_param)
return NULL;
return __dma_request_channel(mask, fn, fn_param, NULL);
}
struct dma_chan *dma_request_chan(struct device *dev, const char *name)
{
struct dma_device *d, *_d;
struct dma_chan *chan = NULL;
/* If device-tree is present get slave info from here */
if (dev->of_node)
chan = of_dma_request_slave_channel(dev->of_node, name);
/* If device was enumerated by ACPI get slave info from here */
if (has_acpi_companion(dev) && !chan)
chan = acpi_dma_request_slave_chan_by_name(dev, name);
if (chan) {
/* Valid channel found or requester needs to be deferred */
if (!IS_ERR(chan) || PTR_ERR(chan) == -EPROBE_DEFER)
return chan;
}
/* Try to find the channel via the DMA filter map(s) */
mutex_lock(&dma_list_mutex);
list_for_each_entry_safe(d, _d, &dma_device_list, global_node) {
dma_cap_mask_t mask;
const struct dma_slave_map *map = dma_filter_match(d, name, dev);
if (!map)
continue;
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
chan = find_candidate(d, &mask, d->filter.fn, map->param);
if (!IS_ERR(chan))
break;
}
mutex_unlock(&dma_list_mutex);
return chan ? chan : ERR_PTR(-EPROBE_DEFER);
}
EXPORT_SYMBOL_GPL(dma_request_chan);
/**
* dma_request_slave_channel - try to allocate an exclusive slave channel
* @dev: pointer to client device structure
* @name: slave channel name
*
* Returns pointer to appropriate DMA channel on success or NULL.
*/
struct dma_chan *dma_request_slave_channel(struct device *dev,
const char *name)
{
struct dma_chan *ch = dma_request_chan(dev, name);
if (IS_ERR(ch))
return NULL;
return ch;
}
EXPORT_SYMBOL_GPL(dma_request_slave_channel);
2. 参数与匹配机制
dma_request_slave_channel_compat
参数包含设备节点(struct device *)、通道名称(const char *name),通过以下步骤匹配:
根据 name 匹配设备树中的 dma-names 值;
返回绑定的 dma_chan 结构。
dma_request_channel
参数需指定 dma_cap_mask_t(通道能力掩码)和自定义过滤函数(dma_filter_fn),通过以下步骤筛选:
遍历所有 DMA 控制器,筛选出支持指定能力的通道(如 DMA_MEMCPY、DMA_SLAVE);
调用过滤函数进一步校验通道参数;
返回满足条件的通道。
3. 主从关系处理
dma_request_slave_channel_compat
隐含从设备(Slave)与 DMA 主控制器(Master)的绑定关系,需依赖设备树中 dmas 属性指向的主控制器节点。
dma_request_channel
不强制绑定主从关系,适用于内存到内存的传输(DMA_MEM_TO_MEM)或自定义主控制器场景。
4. 代码实现差异
设备树支持
dma_request_slave_channel_compat 内部调用 of_dma_request_slave_channel,直接解析设备树节点;
dma_request_channel 基于 dma_cap_mask 和过滤函数动态匹配,不依赖设备树。
兼容性处理
dma_request_slave_channel_compat 的 compat 参数可用于支持旧版设备树或不同厂商的控制器兼容;
dma_request_channel 无此机制,需通过过滤函数手动实现兼容性校验。
5.关键区别

6.dma_request_channel 匹配主机逻辑

示例
bool filter_by_fifo_size(struct dma_chan *chan, void *param) {
struct dma_device *dma_dev = chan->device;
return (dma_dev->max_fifo_size >= *(int *)param); // 校验 FIFO 容量
}
// 调用示例:筛选支持 128B FIFO 的控制器
int fifo_size = 128;
dma_request_channel(mask, filter_by_fifo_size, &fifo_size);