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);
相关推荐
一人一萧十只猫�3 小时前
Linux SSH 远程连接全攻略:从加密原理到实战配置(含图解)
linux·服务器·网络
人间不清醒ab3 小时前
Ubuntu ping网络没有问题,但是浏览器无法访问到网络
linux·运维·ubuntu
babytiger4 小时前
为 Windows 和 Ubuntu 中设定代理服务器的详细方法
linux·windows·ubuntu
默心4 小时前
centos把jar包配置成服务并设置开机自启
linux·centos·jar
秦jh_4 小时前
【Linux网络】传输层协议UDP
linux·运维·服务器·网络·udp
饼干ovo4 小时前
Linux下软件安装实战
linux·运维·服务器
2302_799525745 小时前
【Linux】第十八章 调优系统性能
linux·运维·服务器
特立独行的猫a5 小时前
linux下的 xargs命令使用详解
linux·服务器·网络·linux命令·xargs
不二一5 小时前
linux c++头文件生成源文件 使用python脚本 配置vim快捷键
linux·c++·python
咖喱年糕5 小时前
【VMware】虚拟机运行 Linux Ubuntu、MAC 安装和配置
linux·ubuntu·macos·ssh·vmware·unlocker·vmware tools