概述
vb2_buffer_done 是驱动与videobuf2 交互的关键接口,驱动将一帧图像放入vb2 buffer时,再利用vb2_buffer_done将vb2 buffer送入videobuf2中;此函数的调用可以在中断中执行,也可以在进程中调用。
参数说明
/**
* vb:vb2 buffer,此时驱动将一帧图像已经放入vb2 buffer
* state:vb2 buffer状态,state为VB2_BUF_STATE_DONE时,通知 videobuf2取走buffer,state为VB2_BUF_STATE_ERROR时 通知videobuf2 buffer出错
*/
void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state);
函数原型
void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
{
struct vb2_queue *q = vb->vb2_queue;
unsigned long flags;
if (WARN_ON(vb->state != VB2_BUF_STATE_ACTIVE))
return;
if (WARN_ON(state != VB2_BUF_STATE_DONE &&
state != VB2_BUF_STATE_ERROR &&
state != VB2_BUF_STATE_QUEUED))
state = VB2_BUF_STATE_ERROR; //check vb2 buffer状态
#ifdef CONFIG_VIDEO_ADV_DEBUG
/*
* Although this is not a callback, it still does have to balance
* with the buf_queue op. So update this counter manually.
*/
vb->cnt_buf_done++;
#endif
dprintk(q, 4, "done processing on buffer %d, state: %s\n",
vb->index, vb2_state_name(state));
if (state != VB2_BUF_STATE_QUEUED)
__vb2_buf_mem_finish(vb); //finish on buffer's private memory to sync caches,这里调用了vb2_queue->mem_ops->finish,最终执行函数为 vb2_cma_sg_finish(取决于vb2_queue->mem_ops的初始化)
spin_lock_irqsave(&q->done_lock, flags); //获取自旋锁,保存中断标志
if (state == VB2_BUF_STATE_QUEUED) {
vb->state = VB2_BUF_STATE_QUEUED;
} else {
/* Add the buffer to the done buffers list */
list_add_tail(&vb->done_entry, &q->done_list); //new entry to be added done_list
vb->state = state;
}
atomic_dec(&q->owned_by_drv_count); //驱动缓冲区的数量减去1
if (state != VB2_BUF_STATE_QUEUED && vb->req_obj.req) {
media_request_object_unbind(&vb->req_obj);
media_request_object_put(&vb->req_obj);
}
spin_unlock_irqrestore(&q->done_lock, flags); //释放自旋锁,恢复中断标志
trace_vb2_buf_done(q, vb);
switch (state) {
case VB2_BUF_STATE_QUEUED:
return;
default:
/* Inform any processes that may be waiting for buffers */
wake_up(&q->done_wq); //唤醒等待该缓冲区的进程,如果video_device->fops->poll = vb2_fop_poll, vb2_fop_poll中会收到通知(poll_wait捕获状态)
break;
}
}
vb2_buffer_done 在v4l2驱动中至关重要,比如isp硬件出来的图像都需要通过vb2_buffer_done送入videobuf2.