1. 概述
DMA-Buf 是 Linux 内核中用于在多个设备之间共享缓冲区的框架。主要用于:
- GPU 渲染与显示
- 视频编解码
- 摄像头数据处理
- 跨设备内存共享
2. 核心数据结构
2.1 struct dma_buf
c
复制代码
struct dma_buf {
struct mutex lock;
struct file *file;
struct dma_buf_ops *ops;
struct dma_resv *resv; /* 预留对象 - 包含fence */
struct list_head attachments;
const char *name;
size_t size;
struct device *dev;
void *priv;
struct list_head list_node;
/* ... 其他字段 */
};
2.2 struct dma_fence
c
复制代码
struct dma_fence {
struct kref refcount;
const struct dma_fence_ops *ops;
spinlock_t *lock;
struct list_head cb_list;
u64 context; /* 围栏上下文 */
u64 seqno; /* 序列号 */
unsigned long flags;
int error;
ktime_t timestamp;
};
2.3 struct dma_resv
c
复制代码
struct dma_resv {
struct ww_mutex lock;
struct dma_fence __rcu *fence;
struct dma_fence __rcu *fence_excl;
};
2.4 struct dma_heap
c
复制代码
struct dma_heap {
const char *name;
struct device *dev;
struct dma_heap_ops *ops;
void *priv;
struct kref refcount;
struct list_head list_node;
};
3. DMA-Buffer API
3.1 导出/创建缓冲区
dma_buf_export()
c
复制代码
struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
| 项目 |
说明 |
| 作用 |
导出内核缓冲区到用户空间,创建 dma_buf 对象,使缓冲区可在进程间共享 |
| 输入 |
exp_info: 导出信息结构体,包含: ops(操作函数集), size(大小), flags(标志), priv(私有数据), name(名称), dev(设备) |
| 输出 |
无 |
| 返回 |
成功返回 dma_buf 指针,失败返回 NULL |
dma_buf_fd()
c
复制代码
int dma_buf_fd(struct dma_buf *dmabuf, int flags)
| 项目 |
说明 |
| 作用 |
将 dma_buf 绑定到匿名 inode,创建文件描述符供用户空间使用 |
| 输入 |
dmabuf: DMA buffer 指针; flags: 文件标志 (如 O_CLOEXEC, O_RDWR) |
| 输出 |
无 |
| 返回 |
成功返回文件描述符(>=0),失败返回负值 errno (-EINVAL, -ENOMEM, -ERESTARTSYS) |
3.2 获取/释放缓冲区
dma_buf_get()
c
复制代码
struct dma_buf *dma_buf_get(int fd)
| 项目 |
说明 |
| 作用 |
通过文件描述符获取 dma_buf,增加引用计数 |
| 输入 |
fd: 文件描述符 |
| 输出 |
无 |
| 返回 |
成功返回 dma_buf 指针,失败返回 NULL |
dma_buf_put()
c
复制代码
void dma_buf_put(struct dma_buf *dmabuf)
| 项目 |
说明 |
| 作用 |
减少 dma_buf 引用计数,当计数为0时触发释放回调 |
| 输入 |
dmabuf: DMA buffer 指针 |
| 输出 |
无 |
| 返回 |
无 |
3.3 设备附件
dma_buf_attach()
c
复制代码
struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
struct device *dev)
| 项目 |
说明 |
| 作用 |
将设备附加到 dma_buf,为设备创建 attachment,用于后续 DMA 映射 |
| 输入 |
dmabuf: DMA buffer; dev: 设备指针 |
| 输出 |
无 |
| 返回 |
成功返回 attachment 指针,失败返回 NULL |
dma_buf_detach()
c
复制代码
void dma_buf_detach(struct dma_buf *dmabuf,
struct dma_buf_attachment *attach)
| 项目 |
说明 |
| 作用 |
分离设备与 dma_buf,释放 attachment,调用驱动的 detach 回调 |
| 输入 |
dmabuf: DMA buffer; attach: attachment 指针 |
| 输出 |
无 |
| 返回 |
无 |
dma_buf_dynamic_attach()
c
复制代码
struct dma_buf_attachment *dma_buf_dynamic_attach(struct dma_buf *dmabuf,
struct device *dev,
int (*dma_map_offs)(...),
void *dma_map_data)
| 项目 |
说明 |
| 作用 |
动态附加设备,支持自定义偏移映射回调,用于处理非连续内存布局 |
| 输入 |
dmabuf: DMA buffer; dev: 设备; dma_map_offs: 偏移映射回调; dma_map_data: 回调私有数据 |
| 输出 |
无 |
| 返回 |
成功返回 attachment 指针,失败返回 NULL |
3.4 DMA 映射
dma_buf_map_attachment()
c
复制代码
struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
enum dma_data_direction dir)
| 项目 |
说明 |
| 作用 |
映射 attachment 获取散列表(sg_table),用于 DMA 硬件访问 |
| 输入 |
attach: attachment; dir: 数据方向 (DMA_TO_DEVICE, DMA_FROM_DEVICE, DMA_BIDIRECTIONAL) |
| 输出 |
无 |
| 返回 |
成功返回 sg_table 指针,失败返回 NULL |
dma_buf_unmap_attachment()
c
复制代码
void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
struct sg_table *sgt,
enum dma_data_direction dir)
| 项目 |
说明 |
| 作用 |
取消 DMA 映射,释放散列表 |
| 输入 |
attach: attachment; sgt: 散列表; dir: 数据方向 |
| 输出 |
无 |
| 返回 |
无 |
3.5 CPU 访问
dma_buf_begin_cpu_access()
c
复制代码
int dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
enum dma_data_direction dir)
| 项目 |
说明 |
| 作用 |
开始 CPU 访问缓冲区,同步缓存,确保 CPU 能看到最新数据 |
| 输入 |
dmabuf: DMA buffer; dir: 数据方向 |
| 输出 |
无 |
| 返回 |
成功返回 0,失败返回负值 errno |
dma_buf_end_cpu_access()
c
复制代码
int dma_buf_end_cpu_access(struct dma_buf *dmabuf,
enum dma_data_direction dir)
| 项目 |
说明 |
| 作用 |
结束 CPU 访问缓冲区,同步缓存,使 DMA 硬件能看到 CPU 修改 |
| 输入 |
dmabuf: DMA buffer; dir: 数据方向 |
| 输出 |
无 |
| 返回 |
成功返回 0,失败返回负值 errno |
dma_buf_begin_cpu_access_partial()
c
复制代码
int dma_buf_begin_cpu_access_partial(struct dma_buf *dmabuf,
enum dma_data_direction dir,
size_t offset, size_t len)
| 项目 |
说明 |
| 作用 |
开始部分区域 CPU 访问,只同步指定偏移和大小的区域 |
| 输入 |
dmabuf: DMA buffer; dir: 数据方向; offset: 偏移; len: 长度 |
| 输出 |
无 |
| 返回 |
成功返回 0,失败返回负值 errno |
dma_buf_end_cpu_access_partial()
c
复制代码
int dma_buf_end_cpu_access_partial(struct dma_buf *dmabuf,
enum dma_data_direction dir,
size_t offset, size_t len)
| 项目 |
说明 |
| 作用 |
结束部分区域 CPU 访问 |
| 输入 |
dmabuf: DMA buffer; dir: 数据方向; offset: 偏移; len: 长度 |
| 输出 |
无 |
| 返回 |
成功返回 0,失败返回负值 errno |
3.6 Pin/Unpin
dma_buf_pin()
c
复制代码
int dma_buf_pin(struct dma_buf_attachment *attach)
| 项目 |
说明 |
| 作用 |
固定缓冲区,防止内存被换出或移动,确保 DMA 地址稳定 |
| 输入 |
attach: attachment |
| 输出 |
无 |
| 返回 |
成功返回 0,失败返回负值 errno |
dma_buf_unpin()
c
复制代码
void dma_buf_unpin(struct dma_buf_attachment *attach)
| 项目 |
说明 |
| 作用 |
解固定缓冲区,允许内存被换出或移动 |
| 输入 |
attach: attachment |
| 输出 |
无 |
| 返回 |
无 |
3.7 虚拟内存映射
dma_buf_mmap()
c
复制代码
int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma,
unsigned long pgoff)
| 项目 |
说明 |
| 作用 |
将缓冲区映射到用户空间虚拟地址 |
| 输入 |
dmabuf: DMA buffer; vma: 虚拟内存区域; pgoff: 页偏移 |
| 输出 |
修改 vma |
| 返回 |
成功返回 0,失败返回负值 errno |
dma_buf_vmap()
c
复制代码
void *dma_buf_vmap(struct dma_buf *dmabuf)
| 项目 |
说明 |
| 作用 |
获取内核虚拟地址映射,用于内核空间直接访问缓冲区 |
| 输入 |
dmabuf: DMA buffer |
| 输出 |
无 |
| 返回 |
成功返回虚拟地址,失败返回 NULL |
dma_buf_vunmap()
c
复制代码
void dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr)
| 项目 |
说明 |
| 作用 |
释放虚拟地址映射 |
| 输入 |
dmabuf: DMA buffer; vaddr: 虚拟地址 |
| 输出 |
无 |
| 返回 |
无 |
3.8 其他 API
dma_buf_set_name()
c
复制代码
void dma_buf_set_name(struct dma_buf *dmabuf, const char *name)
| 项目 |
说明 |
| 作用 |
设置缓冲区名称,用于调试和追踪 |
| 输入 |
dmabuf: DMA buffer; name: 名称字符串 |
| 输出 |
无 |
| 返回 |
无 |
dma_buf_move_notify()
c
复制代码
void dma_buf_move_notify(struct dma_buf *dmabuf)
| 项目 |
说明 |
| 作用 |
通知缓冲区地址已变更,刷新所有 attachment 的缓存 |
| 输入 |
dmabuf: DMA buffer |
| 输出 |
无 |
| 返回 |
无 |
is_dma_buf_file()
c
复制代码
bool is_dma_buf_file(struct file *file)
| 项目 |
说明 |
| 作用 |
检查文件是否为 dma_buf 文件 |
| 输入 |
file: 文件指针 |
| 输出 |
无 |
| 返回 |
是 dma_buf 返回 true,否则返回 false |
4. DMA-Fence API
4.1 初始化与创建
dma_fence_init()
c
复制代码
void dma_fence_init(struct dma_fence *fence,
const struct dma_fence_ops *ops,
spinlock_t *lock,
u64 context, u64 seqno)
| 项目 |
说明 |
| 作用 |
初始化围栏结构体,设置操作函数集、锁、上下文和序列号 |
| 输入 |
fence: 围栏指针; ops: 操作函数集; lock: 自旋锁; context: 执行上下文; seqno: 序列号 |
| 输出 |
初始化 fence 结构 |
| 返回 |
无 |
dma_fence_context_alloc()
c
复制代码
u64 dma_fence_context_alloc(unsigned int num)
| 项目 |
说明 |
| 作用 |
分配唯一围栏上下文,用于标识同一设备的不同执行队列 |
| 输入 |
num: 需要分配的上下文数量 |
| 输出 |
无 |
| 返回 |
第一个上下文的编号,后续 num 个上下文被分配 |
4.2 信号与等待
dma_fence_signal()
c
复制代码
int dma_fence_signal(struct dma_fence *fence)
| 项目 |
说明 |
| 作用 |
标记围栏为已信号状态,唤醒等待队列,执行回调函数 |
| 输入 |
fence: 围栏指针 |
| 输出 |
修改 fence 状态 |
| 返回 |
成功返回 0,已经信号返回 -EINVAL |
dma_fence_signal_locked()
c
复制代码
int dma_fence_signal_locked(struct dma_fence *fence)
| 项目 |
说明 |
| 作用 |
在持有围栏锁的情况下信号围栏 |
| 输入 |
fence: 围栏指针(需已持有锁) |
| 输出 |
修改 fence 状态 |
| 返回 |
成功返回 0,已经信号返回 -EINVAL |
dma_fence_signal_timestamp()
c
复制代码
int dma_fence_signal_timestamp(struct dma_fence *fence, ktime_t timestamp)
| 项目 |
说明 |
| 作用 |
带时间戳信号围栏,记录围栏完成的具体时间 |
| 输入 |
fence: 围栏指针; timestamp: 信号时间 (CLOCK_MONOTONIC) |
| 输出 |
修改 fence 状态和时间戳 |
| 返回 |
成功返回 0,已经信号返回 -EINVAL |
dma_fence_wait_timeout()
c
复制代码
signed long dma_fence_wait_timeout(struct dma_fence *fence,
bool intr, signed long timeout)
| 项目 |
说明 |
| 作用 |
同步等待围栏信号,支持超时和中断 |
| 输入 |
fence: 围栏指针; intr: 是否可中断等待; timeout: 超时时间 (jiffies,0=立即返回,MAX_SCHEDULE_TIMEOUT=无限等待) |
| 输出 |
无 |
| 返回** |
>0: 成功,剩余 jiffies; 0: 超时; -ERESTARTSYS: 中断; 其他负值: 错误 |
dma_fence_default_wait()
c
复制代码
signed long dma_fence_default_wait(struct dma_fence *fence,
bool intr, signed long timeout)
| 项目 |
说明 |
| 作用 |
默认的围栏等待实现,使用软件回调机制 |
| 输入 |
fence: 围栏指针; intr: 是否可中断; timeout: 超时 |
| 输出 |
无 |
| 返回 |
>0 成功,0 超时,-ERESTARTSYS 中断 |
dma_fence_wait_any_timeout()
c
复制代码
signed long dma_fence_wait_any_timeout(struct dma_fence **fences,
uint32_t count, bool intr,
signed long timeout, uint32_t *idx)
| 项目 |
说明 |
| 作用 |
等待任意一个围栏信号(先到先等待) |
| 输入 |
fences: 围栏数组; count: 数量; intr: 可中断; timeout: 超时; idx: 输出第一个信号的围栏索引 |
| 输出 |
idx: 第一个信号围栏的索引 |
| 返回 |
>0 成功,0 超时,-EINVAL 错误 |
4.3 回调
dma_fence_add_callback()
c
复制代码
int dma_fence_add_callback(struct dma_fence *fence,
struct dma_fence_cb *cb,
dma_fence_func_t func)
| 项目 |
说明 |
| 作用 |
添加围栏信号回调,当围栏信号时自动调用回调函数 |
| 输入 |
fence: 围栏指针; cb: 回调结构; func: 回调函数 |
| 输出 |
添加回调到围栏 |
| 返回 |
成功返回 0,已信号返回 -ENOENT,无效参数返回 -EINVAL |
dma_fence_remove_callback()
c
复制代码
bool dma_fence_remove_callback(struct dma_fence *fence,
struct dma_fence_cb *cb)
| 项目 |
说明 |
| 作用 |
移除围栏回调,取消尚未执行的回调 |
| 输入 |
fence: 围栏指针; cb: 回调结构 |
| 输出 |
从围栏移除回调 |
| 返回 |
成功移除返回 true,已执行或不存在返回 false |
4.4 引用计数
dma_fence_get()
c
复制代码
struct dma_fence *dma_fence_get(struct dma_fence *fence)
| 项目 |
说明 |
| 作用 |
增加围栏引用计数,防止围栏被释放 |
| 输入 |
fence: 围栏指针 |
| 输出 |
增加引用计数 |
| 返回 |
返回输入的围栏指针 |
dma_fence_put()
c
复制代码
void dma_fence_put(struct dma_fence *fence)
| 项目 |
说明 |
| 作用 |
减少围栏引用计数,当计数为0时释放围栏 |
| 输入 |
fence: 围栏指针 |
| 输出 |
减少引用计数,可能释放围栏 |
| 返回 |
无 |
dma_fence_enable_sw_signaling()
c
复制代码
void dma_fence_enable_sw_signaling(struct dma_fence *fence)
| 项目 |
说明 |
| 作用 |
启用软件信号机制,确保围栏最终会被信号(硬件围栏需要) |
| 输入 |
fence: 围栏指针 |
| 输出 |
设置启用信号标志 |
| 返回 |
无 |
4.5 状态查询
dma_fence_is_signaled()
c
复制代码
bool dma_fence_is_signaled(struct dma_fence *fence)
| 项目 |
说明 |
| 作用 |
检查围栏是否已信号(非阻塞快速检查) |
| 输入 |
fence: 围栏指针 |
| 输出 |
无 |
| 返回 |
已信号返回 true,未信号返回 false |
dma_fence_get_status()
c
复制代码
int dma_fence_get_status(struct dma_fence *fence)
| 项目 |
说明 |
| 作用 |
获取围栏完成状态,包括错误信息 |
| 输入 |
fence: 围栏指针 |
| 输出 |
无 |
| 返回 |
1: 正常信号; 0: 未信号; 负值: 错误代码 |
dma_fence_describe()
c
复制代码
void dma_fence_describe(struct dma_fence *fence, struct seq_file *seq)
| 项目 |
说明 |
| 作用 |
输出围栏描述信息到 seq_file,用于调试 |
| 输入 |
fence: 围栏指针; seq: 序列文件 |
| 输出 |
写入描述到 seq |
| 返回 |
无 |
4.6 Deadline
dma_fence_set_deadline()
c
复制代码
void dma_fence_set_deadline(struct dma_fence *fence, ktime_t deadline)
| 项目 |
说明 |
| 作用 |
设置期望完成截止时间,通知信号方尽快完成 |
| 输入 |
fence: 围栏指针; deadline: 截止时间 (CLOCK_MONOTONIC) |
| 输出 |
设置截止时间 |
| 返回 |
无 |
4.7 Stub Fence
dma_fence_get_stub()
c
复制代码
struct dma_fence *dma_fence_get_stub(void)
| 项目 |
说明 |
| 作用 |
获取全局已信号 stub 围栏,用于立即完成场景 |
| 输入 |
无 |
| 输出 |
无 |
| 返回 |
已信号的 stub 围栏(全局单例) |
dma_fence_allocate_private_stub()
c
复制代码
struct dma_fence *dma_fence_allocate_private_stub(ktime_t timestamp)
| 项目 |
说明 |
| 作用 |
分配私有的已信号围栏,带指定时间戳 |
| 输入 |
timestamp: 信号时间 |
| 输出 |
分配新的围栏 |
| 返回 |
已信号的围栏指针 |
4.8 Lockdep 支持
dma_fence_begin_signalling()
c
复制代码
bool dma_fence_begin_signalling(void)
| 项目 |
说明 |
| 作用 |
开始信号关键段,用于 lockdep 锁顺序验证 |
| 输入 |
无 |
| 输出 |
注册锁 |
| 返回 |
cookie 值,需传递给 end_signalling |
dma_fence_end_signalling()
c
复制代码
void dma_fence_end_signalling(bool cookie)
| 项目 |
说明 |
| 作用 |
结束信号关键段 |
| 输入 |
cookie: begin_signalling 返回的 cookie |
| 输出 |
释放锁 |
| 返回 |
无 |
5. DMA-Resv API
5.1 初始化/销毁
dma_resv_init()
c
复制代码
void dma_resv_init(struct dma_resv *obj)
| 项目 |
说明 |
| 作用 |
初始化预留对象,创建互斥锁,初始化围栏列表 |
| 输入 |
obj: 预留对象指针 |
| 输出 |
初始化 obj |
| 返回 |
无 |
dma_resv_fini()
c
复制代码
void dma_resv_fini(struct dma_resv *obj)
| 项目 |
说明 |
| 作用 |
销毁预留对象,释放所有围栏,销毁互斥锁 |
| 输入 |
obj: 预留对象指针 |
| 输出 |
释放资源 |
| 返回 |
无 |
5.2 Fence 管理
dma_resv_add_fence()
c
复制代码
void dma_resv_add_fence(struct dma_resv *obj,
struct dma_fence *fence,
enum dma_resv_usage usage)
| 项目 |
说明 |
| 作用 |
添加围栏到预留对象,管理缓冲区的同步状态 |
| 输入 |
obj: 预留对象; fence: 围栏; usage: 使用类型 (READ/WRITE/BOOKKEEP) |
| 输出 |
添加围栏到 obj |
| 返回 |
无 |
dma_resv_replace_fences()
c
复制代码
void dma_resv_replace_fences(struct dma_resv *obj, uint64_t context,
struct dma_fence *replacement,
enum dma_resv_usage usage)
| 项目 |
说明 |
| 作用 |
替换指定上下文的围栏,用于预emption 场景 |
| 输入 |
obj: 预留对象; context: 上下文; replacement: 新围栏; usage: 使用类型 |
| 输出 |
替换围栏 |
| 返回 |
无 |
dma_resv_reserve_fences()
c
复制代码
int dma_resv_reserve_fences(struct dma_resv *obj, unsigned int num_fences)
| 项目 |
说明 |
| 作用 |
预分配围栏槽位,避免添加时动态分配内存 |
| 输入 |
obj: 预留对象; num_fences: 预期围栏数量 |
| 输出 |
分配围栏数组 |
| 返回 |
成功返回 0,失败返回 -ENOMEM |
5.3 迭代遍历
dma_resv_iter_first()
c
复制代码
struct dma_fence *dma_resv_iter_first(struct dma_resv_iter *cursor)
| 项目 |
说明 |
| 作用 |
获取第一个围栏(需持有锁),用于安全遍历 |
| 输入 |
cursor: 迭代器(需先用 dma_resv_iter_begin 初始化) |
| 输出 |
填充 cursor |
| 返回 |
第一个围栏指针或 NULL |
dma_resv_iter_next()
c
复制代码
struct dma_fence *dma_resv_iter_next(struct dma_resv_iter *cursor)
| 项目 |
说明 |
| 作用 |
获取下一个围栏 |
| 输入 |
cursor: 迭代器 |
| 输出 |
更新 cursor |
| 返回 |
下一个围栏指针或 NULL |
dma_resv_iter_first_unlocked()
c
复制代码
struct dma_fence *dma_resv_iter_first_unlocked(struct dma_resv_iter *cursor)
| 项目 |
说明 |
| 作用 |
获取第一个围栏(不持有锁),使用 RCU 保护 |
| 输入 |
cursor: 迭代器 |
| 输出 |
填充 cursor |
| 返回 |
第一个围栏指针或 NULL |
dma_resv_iter_next_unlocked()
c
复制代码
struct dma_fence *dma_resv_iter_next_unlocked(struct dma_resv_iter *cursor)
| 项目 |
说明 |
| 作用 |
获取下一个围栏(不持有锁) |
| 输入 |
cursor: 迭代器 |
| 输出 |
更新 cursor |
| 返回 |
下一个围栏指针或 NULL |
5.4 围栏获取
dma_resv_get_fences()
c
复制代码
int dma_resv_get_fences(struct dma_resv *obj, enum dma_resv_usage usage,
unsigned int *num_fences, struct dma_fence ***fences)
| 项目 |
说明 |
| 作用 |
获取所有围栏到数组,复制围栏引用 |
| 输入 |
obj: 预留对象; usage: 过滤类型 |
| 输出 |
num_fences: 数量; fences: 围栏数组(需释放) |
| 返回 |
成功返回 0,失败返回 -ENOMEM |
dma_resv_get_singleton()
c
复制代码
int dma_resv_get_singleton(struct dma_resv *obj, enum dma_resv_usage usage,
struct dma_fence **fence)
| 项目 |
说明 |
| 作用 |
获取单一合成围栏,将多个围栏合并为一个 |
| 输入 |
obj: 预留对象; usage: 过滤类型 |
| 输出 |
fence: 合成围栏或单一围栏 |
| 返回 |
成功返回 0,失败返回负值 |
dma_resv_copy_fences()
c
复制代码
int dma_resv_copy_fences(struct dma_resv *dst, struct dma_resv *src)
| 项目 |
说明 |
| 作用 |
复制所有围栏从一个预留对象到另一个 |
| 输入 |
dst: 目标; src: 源(需持有锁) |
| 输出 |
复制围栏到 dst |
| 返回 |
成功返回 0,失败返回 -ENOMEM |
5.5 等待与状态
dma_resv_wait_timeout()
c
复制代码
long dma_resv_wait_timeout(struct dma_resv *obj, enum dma_resv_usage usage,
bool intr, unsigned long timeout)
| 项目 |
说明 |
| 作用 |
等待所有围栏信号,按 usage 过滤 |
| 输入 |
obj: 预留对象; usage: 过滤类型; intr: 可中断; timeout: 超时 |
| 输出 |
无 |
| 返回 |
>0 成功,0 超时,负值错误 |
dma_resv_test_signaled()
c
复制代码
bool dma_resv_test_signaled(struct dma_resv *obj, enum dma_resv_usage usage)
| 项目 |
说明 |
| 作用 |
快速测试所有围栏是否已信号 |
| 输入 |
obj: 预留对象; usage: 过滤类型 |
| 输出 |
无 |
| 返回 |
全部信号返回 true,否则返回 false |
dma_resv_set_deadline()
c
复制代码
void dma_resv_set_deadline(struct dma_resv *obj, enum dma_resv_usage usage,
ktime_t deadline)
| 项目 |
说明 |
| 作用 |
设置截止时间到所有围栏 |
| 输入 |
obj: 预留对象; usage: 过滤类型; deadline: 截止时间 |
| 输出 |
设置截止时间 |
| 返回 |
无 |
5.6 调试
dma_resv_describe()
c
复制代码
void dma_resv_describe(struct dma_resv *obj, struct seq_file *seq)
| 项目 |
说明 |
| 作用 |
输出预留对象描述信息 |
| 输入 |
obj: 预留对象; seq: 序列文件 |
| 输出 |
写入描述 |
| 返回 |
无 |
5.7 锁操作
c
复制代码
// 在 <linux/dma-resv.h> 中定义
dma_resv_lock(struct dma_resv *resv, struct ww_acquire_ctx *ctx)
dma_resv_unlock(struct dma_resv *resv)
dma_resv_lock_slow(struct dma_resv *resv, struct ww_acquire_ctx *ctx)
| 函数 |
作用 |
dma_resv_lock |
获取预留对象锁(w/w 锁) |
dma_resv_unlock |
释放预留对象锁 |
dma_resv_lock_slow |
慢速获取锁(处理死锁情况) |
6. DMA-Heap API
6.1 堆查找
dma_heap_find()
c
复制代码
struct dma_heap *dma_heap_find(const char *name)
| 项目 |
说明 |
| 作用 |
通过名称查找已注册的 DMA 堆 |
| 输入 |
name: 堆名称(如 "system", " carveout") |
| 输出 |
无 |
| 返回 |
成功返回堆指针,失败返回 NULL |
6.2 缓冲区分配
dma_heap_buffer_alloc()
c
复制代码
struct dma_buf *dma_heap_buffer_alloc(struct dma_heap *heap, size_t len,
int flags, u64 phys_align)
| 项目 |
说明 |
| 作用 |
从指定堆分配缓冲区,返回 dma_buf 供驱动使用 |
| 输入 |
heap: 堆指针; len: 大小; flags: 标志; phys_align: 物理对齐 |
| 输出 |
无 |
| 返回 |
成功返回 dma_buf,失败返回 NULL |
dma_heap_bufferfd_alloc()
c
复制代码
int dma_heap_bufferfd_alloc(struct dma_heap *heap, size_t len, int flags)
| 项目 |
说明 |
| 作用 |
从堆分配缓冲区并返回文件描述符,用户空间直接使用 |
| 输入 |
heap: 堆指针; len: 大小; flags: 标志 |
| 输出 |
无 |
| 返回 |
成功返回 fd,失败返回负值 errno |
dma_heap_buffer_free()
c
复制代码
void dma_heap_buffer_free(struct dma_buf *dmabuf)
| 项目 |
说明 |
| 作用 |
释放堆分配的缓冲区 |
| 输入 |
dmabuf: 从堆分配的 buffer |
| 输出 |
释放资源 |
| 返回 |
无 |
6.3 堆属性
dma_heap_get_dev()
c
复制代码
struct device *dma_heap_get_dev(struct dma_heap *heap)
| 项目 |
说明 |
| 作用 |
获取堆关联的设备,用于驱动操作 |
| 输入 |
heap: 堆指针 |
| 输出 |
无 |
| 返回 |
设备指针 |
dma_heap_get_name()
c
复制代码
const char *dma_heap_get_name(struct dma_heap *heap)
| 项目 |
说明 |
| 作用 |
获取堆名称 |
| 输入 |
heap: 堆指针 |
| 输出 |
无 |
| 返回 |
堆名称字符串 |
dma_heap_get_drvdata()
c
复制代码
void *dma_heap_get_drvdata(struct dma_heap *heap)
| 项目 |
说明 |
| 作用 |
获取驱动的私有数据 |
| 输入 |
heap: 堆指针 |
| 输出 |
无 |
| 返回 |
私有数据指针 |
6.4 引用计数
dma_heap_put()
c
复制代码
void dma_heap_put(struct dma_heap *heap)
| 项目 |
说明 |
| 作用 |
减少堆引用计数 |
| 输入 |
heap: 堆指针 |
| 输出 |
减少引用 |
| 返回 |
无 |
6.5 堆注册
dma_heap_add()
c
复制代码
struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info)
| 项目 |
说明 |
| 作用 |
注册新的 DMA 堆到系统 |
| 输入 |
exp_info: 导出信息(名称、设备、操作、私有数据) |
| 输出 |
创建堆到 sysfs |
| 返回 |
成功返回堆指针,失败返回 NULL |
6.6 调试
dma_heap_try_get_pool_size_kb()
c
复制代码
u64 dma_heap_try_get_pool_size_kb(void)
| 项目 |
说明 |
| 作用 |
获取所有内存池的总大小(KB) |
| 输入 |
无 |
| 输出 |
无 |
| 返回 |
池大小(KB) |
7. Sync-File API
7.1 创建
sync_file_create()
c
复制代码
struct sync_file *sync_file_create(struct dma_fence *fence)
| 项目 |
说明 |
| 作用 |
从围栏创建 sync_file 对象,用于用户空间同步 |
| 输入 |
fence: 围栏指针 |
| 输出 |
创建 sync_file |
| 返回 |
成功返回 sync_file,失败返回 NULL |
7.2 获取围栏
sync_file_get_fence()
c
复制代码
struct dma_fence *sync_file_get_fence(int fd)
| 项目 |
说明 |
| 作用 |
从文件描述符获取围栏,增加引用计数 |
| 输入 |
fd: sync_file 文件描述符 |
| 输出 |
无 |
| 返回 |
成功返回围栏指针,失败返回 NULL |