dma fence 相关操作函数

1: dma_dence_init

void
dma_fence_init(struct dma_fence *fence, const struct dma_fence_ops *ops,
	       spinlock_t *lock, u64 context, unsigned seqno)
{
	BUG_ON(!lock);
	BUG_ON(!ops || !ops->wait || !ops->enable_signaling ||
	       !ops->get_driver_name || !ops->get_timeline_name);

	kref_init(&fence->refcount);
	fence->ops = ops;
	INIT_LIST_HEAD(&fence->cb_list);
	fence->lock = lock;
	fence->context = context;
	fence->seqno = seqno;
	fence->flags = 0UL;
	fence->error = 0;

	trace_dma_fence_init(fence);
}
EXPORT_SYMBOL(dma_fence_init);

参数:

struct dma_fence *fence - 要初始化的fence
const struct dma_fence_ops *ops - 用于该fence的操作函数
spinlock_t *lock - 该fence的自旋锁
u64 context - 在这个fence运行的执行上下文中
unsigned seqno - 针对此上下文的一个递增序列号

作用:

本质上就是为fence结构的成员进行赋值

2:dma fence 完成函数

dma_fence_signal

int dma_fence_signal(struct dma_fence *fence)
{
	unsigned long flags;

	if (!fence)
		return -EINVAL;
     /*设置fence状态标记为SIGNEALED,其余接口通过查询此状态标记检查fence是否处于out-fence状态*/
	if (test_and_set_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
		return -EINVAL;

	fence->timestamp = ktime_get();
	set_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags);
	trace_dma_fence_signaled(fence);

	if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &fence->flags)) {
		struct dma_fence_cb *cur, *tmp;

		spin_lock_irqsave(fence->lock, flags);
		/*对fence感兴趣的其它模块通过向cb_list添加回调函数,可以让fence在完成后执行该回调。这里就是fence完成后的回调*/
		list_for_each_entry_safe(cur, tmp, &fence->cb_list, node) {
			list_del_init(&cur->node); // 从fence链表中删除cur节点
			cur->func(fence, cur);//执行回调函数
		}
		spin_unlock_irqrestore(fence->lock, flags);
	}
	return 0;
}
EXPORT_SYMBOL(dma_fence_signal);

dma_fence_signal_locked

int dma_fence_signal_locked(struct dma_fence *fence)
{
	struct dma_fence_cb *cur, *tmp;
	int ret = 0;

	lockdep_assert_held(fence->lock); //判定锁是否处于锁定状态。就是锁必须在此处被持有,否则就通过打印警告信息
	if (WARN_ON(!fence)) //fence为空,打印告警信息
		return -EINVAL;
	
	/*设置fence状态标记为SIGNEALED,其余接口通过查询此状态标记检查fence是否处于out-fence状态*/
	if (test_and_set_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) { //置位,并返回原来这个位的值
		ret = -EINVAL; //如果原本得fence已经被置位,返回错误

		/*
		 * we might have raced with the unlocked dma_fence_signal,
		 * still run through all callbacks
		 */
	} else { 
		fence->timestamp = ktime_get(); //获取内核时间赋值给fence的时间戳
		set_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags); //把时间戳标志位置位
		trace_dma_fence_signaled(fence);
	}
/*对fence感兴趣的其它模块通过向cb_list添加回调函数,可以让fence在完成后执行该回调。这里就是fence完成后的回调*/
	list_for_each_entry_safe(cur, tmp, &fence->cb_list, node) {
		list_del_init(&cur->node);
		cur->func(fence, cur); //执行回调函数
	}
	return ret;
}
EXPORT_SYMBOL(dma_fence_signal_locked);

与dma_fence_signal不同,这个函数必须在持有fence->lock的情况下被调用。

3:fence使用的含义

分两个视角看,cpu侧和gpu侧。 当cpu需要gpu执行渲染命令时,会把渲染命令放到buffer中去,告知GPU去哪里操作,以及有多少。然后在最后会在命令buffer中放一个指令EOP,这个用于告知GPU,当渲染完成后怎么通知cpu,这里指令的数据内容是让GPU向一个地址写入指定数据的。当cpu检测到这个地址有这个数据时,就可以知道gpu完成了什么渲染命令。

这一切需要在驱动需要用fence来表示。cpu下发渲染指令会创建一个fence用来标记这个job,当GPU完成工作,在指定地址写入数据,触发中断。在中断例程函数中会通过dma_fence_signal修改fence的状态为完成态。用于表示下发渲染指令被执行的状态。并执行fence内部回调函数链表下的各个函数。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值