dma_request_slave_channel_compat 与 dma_request_channel 的区别

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);
相关推荐
A小辣椒19 小时前
TShark:Wireshark CLI 功能
linux
A小辣椒1 天前
TShark:基础知识
linux
AlfredZhao1 天前
OCI 明明分配了 200G 系统盘,为什么 df 只看到 30G?
linux·oci
AlfredZhao2 天前
vi 删除指定范围的行,不用再反复按 dd
linux·vi
用户9718356334662 天前
银河麒麟 KY10 申威(SW64) 安装 nginx-1.16.1-2.p01.ky10.sw_64.rpm 详细步骤
linux
猪脚踏浪2 天前
linux 拷贝文件或目录到指定的位置
linux
摇滚侠3 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
bush43 天前
嵌入式linux学习记录十四、术语
linux·嵌入式
载数而行5203 天前
Linux 11 动态监控指令top
linux
不会C语言的男孩3 天前
Linux 系统编程 · 第 8 章:进程基础
linux·c语言