Re: [PATCH v3 04/15] [media] vb2: add in-fence support to QBUF
Hi, On Thu, Sep 07, 2017 at 03:42:15PM -0300, Gustavo Padovan wrote: From: Gustavo Padovan Receive in-fence from userspace and add support for waiting on them before queueing the buffer to the driver. Buffers are only queued to the driver once they are ready. A buffer is ready when its in-fence signals. v4: - Add a comment about dma_fence_add_callback() not returning a error (Hans) - Call dma_fence_put(vb->in_fence) if fence signaled (Hans) - select SYNC_FILE under config VIDEOBUF2_CORE (Hans) - Move dma_fence_is_signaled() check to __enqueue_in_driver() (Hans) - Remove list_for_each_entry() in __vb2_core_qbuf() (Hans) - Remove if (vb->state != VB2_BUF_STATE_QUEUED) from vb2_start_streaming() (Hans) - set IN_FENCE flags on __fill_v4l2_buffer (Hans) - Queue buffers to the driver as soon as they are ready (Hans) - call fill_user_buffer() after queuing the buffer (Hans) - add err: label to clean up fence - add dma_fence_wait() before calling vb2_start_streaming() v3: - document fence parameter - remove ternary if at vb2_qbuf() return (Mauro) - do not change if conditions behaviour (Mauro) v2: - fix vb2_queue_or_prepare_buf() ret check - remove check for VB2_MEMORY_DMABUF only (Javier) - check num of ready buffers to start streaming - when queueing, start from the first ready buffer - handle queue cancel Signed-off-by: Gustavo Padovan --- drivers/media/v4l2-core/Kconfig | 1 + drivers/media/v4l2-core/videobuf2-core.c | 103 +++ drivers/media/v4l2-core/videobuf2-v4l2.c | 27 +++- include/media/videobuf2-core.h | 11 +++- 4 files changed, 127 insertions(+), 15 deletions(-) diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig index a35c33686abf..3f988c407c80 100644 --- a/drivers/media/v4l2-core/Kconfig +++ b/drivers/media/v4l2-core/Kconfig @@ -83,6 +83,7 @@ config VIDEOBUF_DVB # Used by drivers that need Videobuf2 modules config VIDEOBUF2_CORE select DMA_SHARED_BUFFER + select SYNC_FILE tristate config VIDEOBUF2_MEMOPS diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 60f8b582396a..b19c1bc4b083 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -1222,6 +1222,9 @@ static void __enqueue_in_driver(struct vb2_buffer *vb) { struct vb2_queue *q = vb->vb2_queue; + if (vb->in_fence && !dma_fence_is_signaled(vb->in_fence)) + return; + vb->state = VB2_BUF_STATE_ACTIVE; atomic_inc(&q->owned_by_drv_count); @@ -1273,6 +1276,20 @@ static int __buf_prepare(struct vb2_buffer *vb, const void *pb) return 0; } +static int __get_num_ready_buffers(struct vb2_queue *q) +{ + struct vb2_buffer *vb; + int ready_count = 0; + + /* count num of buffers ready in front of the queued_list */ + list_for_each_entry(vb, &q->queued_list, queued_entry) { + if (!vb->in_fence || dma_fence_is_signaled(vb->in_fence)) + ready_count++; + } + + return ready_count; +} + int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb) { struct vb2_buffer *vb; @@ -1361,7 +1378,19 @@ static int vb2_start_streaming(struct vb2_queue *q) return ret; } -int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb) +static void vb2_qbuf_fence_cb(struct dma_fence *f, struct dma_fence_cb *cb) +{ + struct vb2_buffer *vb = container_of(cb, struct vb2_buffer, fence_cb); + + dma_fence_put(vb->in_fence); + vb->in_fence = NULL; + + if (vb->vb2_queue->start_streaming_called) + __enqueue_in_driver(vb); +} + +int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb, + struct dma_fence *fence) { struct vb2_buffer *vb; int ret; @@ -1372,16 +1401,18 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb) case VB2_BUF_STATE_DEQUEUED: ret = __buf_prepare(vb, pb); if (ret) - return ret; + goto err; break; case VB2_BUF_STATE_PREPARED: break; case VB2_BUF_STATE_PREPARING: dprintk(1, "buffer still being prepared\n"); - return -EINVAL; + ret = -EINVAL; + goto err; default: dprintk(1, "invalid buffer state %d\n", vb->state); - return -EINVAL; + ret = -EINVAL; + goto err; } /* @@ -1392,6 +1423,7 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb) q->queued_count++; q->waiting_for_buffers = false; vb->state = VB2_BUF_STATE_QUEUED; + vb->i
[PATCH v3 04/15] [media] vb2: add in-fence support to QBUF
From: Gustavo Padovan Receive in-fence from userspace and add support for waiting on them before queueing the buffer to the driver. Buffers are only queued to the driver once they are ready. A buffer is ready when its in-fence signals. v4: - Add a comment about dma_fence_add_callback() not returning a error (Hans) - Call dma_fence_put(vb->in_fence) if fence signaled (Hans) - select SYNC_FILE under config VIDEOBUF2_CORE (Hans) - Move dma_fence_is_signaled() check to __enqueue_in_driver() (Hans) - Remove list_for_each_entry() in __vb2_core_qbuf() (Hans) - Remove if (vb->state != VB2_BUF_STATE_QUEUED) from vb2_start_streaming() (Hans) - set IN_FENCE flags on __fill_v4l2_buffer (Hans) - Queue buffers to the driver as soon as they are ready (Hans) - call fill_user_buffer() after queuing the buffer (Hans) - add err: label to clean up fence - add dma_fence_wait() before calling vb2_start_streaming() v3: - document fence parameter - remove ternary if at vb2_qbuf() return (Mauro) - do not change if conditions behaviour (Mauro) v2: - fix vb2_queue_or_prepare_buf() ret check - remove check for VB2_MEMORY_DMABUF only (Javier) - check num of ready buffers to start streaming - when queueing, start from the first ready buffer - handle queue cancel Signed-off-by: Gustavo Padovan --- drivers/media/v4l2-core/Kconfig | 1 + drivers/media/v4l2-core/videobuf2-core.c | 103 +++ drivers/media/v4l2-core/videobuf2-v4l2.c | 27 +++- include/media/videobuf2-core.h | 11 +++- 4 files changed, 127 insertions(+), 15 deletions(-) diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig index a35c33686abf..3f988c407c80 100644 --- a/drivers/media/v4l2-core/Kconfig +++ b/drivers/media/v4l2-core/Kconfig @@ -83,6 +83,7 @@ config VIDEOBUF_DVB # Used by drivers that need Videobuf2 modules config VIDEOBUF2_CORE select DMA_SHARED_BUFFER + select SYNC_FILE tristate config VIDEOBUF2_MEMOPS diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 60f8b582396a..b19c1bc4b083 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -1222,6 +1222,9 @@ static void __enqueue_in_driver(struct vb2_buffer *vb) { struct vb2_queue *q = vb->vb2_queue; + if (vb->in_fence && !dma_fence_is_signaled(vb->in_fence)) + return; + vb->state = VB2_BUF_STATE_ACTIVE; atomic_inc(&q->owned_by_drv_count); @@ -1273,6 +1276,20 @@ static int __buf_prepare(struct vb2_buffer *vb, const void *pb) return 0; } +static int __get_num_ready_buffers(struct vb2_queue *q) +{ + struct vb2_buffer *vb; + int ready_count = 0; + + /* count num of buffers ready in front of the queued_list */ + list_for_each_entry(vb, &q->queued_list, queued_entry) { + if (!vb->in_fence || dma_fence_is_signaled(vb->in_fence)) + ready_count++; + } + + return ready_count; +} + int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb) { struct vb2_buffer *vb; @@ -1361,7 +1378,19 @@ static int vb2_start_streaming(struct vb2_queue *q) return ret; } -int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb) +static void vb2_qbuf_fence_cb(struct dma_fence *f, struct dma_fence_cb *cb) +{ + struct vb2_buffer *vb = container_of(cb, struct vb2_buffer, fence_cb); + + dma_fence_put(vb->in_fence); + vb->in_fence = NULL; + + if (vb->vb2_queue->start_streaming_called) + __enqueue_in_driver(vb); +} + +int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb, + struct dma_fence *fence) { struct vb2_buffer *vb; int ret; @@ -1372,16 +1401,18 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb) case VB2_BUF_STATE_DEQUEUED: ret = __buf_prepare(vb, pb); if (ret) - return ret; + goto err; break; case VB2_BUF_STATE_PREPARED: break; case VB2_BUF_STATE_PREPARING: dprintk(1, "buffer still being prepared\n"); - return -EINVAL; + ret = -EINVAL; + goto err; default: dprintk(1, "invalid buffer state %d\n", vb->state); - return -EINVAL; + ret = -EINVAL; + goto err; } /* @@ -1392,6 +1423,7 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb) q->queued_count++; q->waiting_for_buffers = false; vb->state = VB2_BUF_STATE_QUEUED; + vb->in_fence = fence; if (pb) c