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);
相关推荐
JeffersonZU6 分钟前
Linux/Unix文件IO(文件描述符、原子操作、文件数据结构、open、read、write、fcntl、dup)
linux·c语言·unix·gnu
szekl1 小时前
HDMI 2.0 4×2矩阵切换器412HN——多信号输入输出的高清解决方案
linux·矩阵·计算机外设·电脑·ekl
weixin_399380691 小时前
k8s一键部署tongweb企业版7049m6(by why+lqw)
java·linux·运维·服务器·云原生·容器·kubernetes
阿巴~阿巴~1 小时前
Linux基本命令篇 —— uname命令
linux·运维·服务器
天空之城夢主1 小时前
KVM高级功能部署
linux·服务器
pipip.3 小时前
UDP————套接字socket
linux·网络·c++·网络协议·udp
朱包林6 小时前
day45-nginx复杂跳转与https
linux·运维·服务器·网络·云计算
孙克旭_6 小时前
day045-nginx跳转功能补充与https
linux·运维·nginx·https
孞㐑¥7 小时前
Linux之Socket 编程 UDP
linux·服务器·c++·经验分享·笔记·网络协议·udp
M4K011 小时前
Linux百度网盘优化三板斧
linux