From 7a1326cf5f85d223511b912f96fa9db0ee7daf00 Mon Sep 17 00:00:00 2001 From: Janghyuck Kim Date: Tue, 3 Apr 2018 15:47:28 +0900 Subject: [PATCH] media: v4l2-core: fix v4l2-core to use fence V4L2 explicit synchronization is supported by v4l2-core, however, some changes were needed for compatiblity of other v4l2 driver. fence_fd in v4l2_buffer is changed from reserved2 to reserved. reserved2 field has been used for other driver, and legacy scaler driver used reserved field for their fence information. This change could guarantee compatibility of previous user API. Some spinlock location of fence_cb_lock were moved to avoid running buf_queue callback in interrupt context. Finally, additional check routine was removed in vb2_buffer_done(). This routine made invalid address access, and it is used for unordered queue. Currently it is not needed, so it will be reverted later after find the reason of invalid address access. Change-Id: I618b1d4320cfb95508727fc418ebe0f9fae7183a Signed-off-by: Janghyuck Kim --- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 8 ++++-- drivers/media/v4l2-core/videobuf2-core.c | 27 ++++++------------- include/uapi/linux/videodev2.h | 4 +-- 3 files changed, 16 insertions(+), 23 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index 46657ea6b957..8da921c6dbd7 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -386,8 +386,11 @@ struct v4l2_buffer32 { __s32 fd; } m; __u32 length; - __s32 fence_fd; - __u32 reserved; + __s32 reserved2; + union { + __u32 fence_fd; + __u32 reserved; + }; }; static int get_v4l2_plane32(struct v4l2_plane __user *up, @@ -506,6 +509,7 @@ static int get_v4l2_buffer32(struct v4l2_buffer __user *kp, if (V4L2_TYPE_IS_OUTPUT(type)) if (assign_in_user(&kp->bytesused, &up->bytesused) || assign_in_user(&kp->reserved2, &up->reserved2) || + assign_in_user(&kp->fence_fd, &up->fence_fd) || assign_in_user(&kp->field, &up->field) || assign_in_user(&kp->timestamp.tv_sec, &up->timestamp.tv_sec) || diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 131133cba30d..9a43ebaec60d 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -963,21 +963,6 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state) state = VB2_BUF_STATE_ERROR; vb2_process_buffer_done(vb, state); - - /* - * Check if there is any buffer with error in the next position of the queue, - * buffers whose in-fence signaled with error are not queued to the driver - * and kept on the queue until the buffer before them is done, so to not - * delivery buffers back to userspace in the wrong order. Here we process - * any existing buffers with errors and wake up userspace. - */ - for (;;) { - vb = list_next_entry(vb, queued_entry); - if (!vb || vb->state != VB2_BUF_STATE_ERROR) - break; - - vb2_process_buffer_done(vb, VB2_BUF_STATE_ERROR); - } } EXPORT_SYMBOL_GPL(vb2_buffer_done); @@ -1261,9 +1246,14 @@ err: static void __enqueue_in_driver(struct vb2_buffer *vb) { struct vb2_queue *q = vb->vb2_queue; + unsigned long flags; - if (vb->in_fence && !dma_fence_is_signaled(vb->in_fence)) + spin_lock_irqsave(&vb->fence_cb_lock, flags); + if (vb->in_fence && !dma_fence_is_signaled(vb->in_fence)) { + spin_unlock_irqrestore(&vb->fence_cb_lock, flags); return; + } + spin_unlock_irqrestore(&vb->fence_cb_lock, flags); vb->state = VB2_BUF_STATE_ACTIVE; atomic_inc(&q->owned_by_drv_count); @@ -1448,10 +1438,10 @@ static void vb2_qbuf_fence_cb(struct dma_fence *f, struct dma_fence_cb *cb) spin_unlock_irqrestore(&vb->fence_cb_lock, flags); return; } + spin_unlock_irqrestore(&vb->fence_cb_lock, flags); if (q->start_streaming_called) __enqueue_in_driver(vb); - spin_unlock_irqrestore(&vb->fence_cb_lock, flags); } int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb, @@ -1516,6 +1506,7 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb, goto unlock; } } + spin_unlock_irqrestore(&vb->fence_cb_lock, flags); /* * If already streaming and there is no fence to wait on @@ -1546,8 +1537,6 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb, goto unlock; } - spin_unlock_irqrestore(&vb->fence_cb_lock, flags); - /* Fill buffer information for the userspace */ if (pb) call_void_bufop(q, fill_user_buffer, vb, pb); diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index b9592e611da2..1bdd105516e3 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -927,11 +927,11 @@ struct v4l2_buffer { __s32 fd; } m; __u32 length; + __u32 reserved2; union { __s32 fence_fd; - __u32 reserved2; + __u32 reserved; }; - __u32 reserved; }; /* Flags for 'flags' field */ -- 2.20.1