media: v4l2-core: fix v4l2-core to use fence
authorJanghyuck Kim <janghyuck.kim@samsung.com>
Tue, 3 Apr 2018 06:47:28 +0000 (15:47 +0900)
committerCosmin Tanislav <demonsingur@gmail.com>
Mon, 22 Apr 2024 17:22:17 +0000 (20:22 +0300)
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 <janghyuck.kim@samsung.com>
drivers/media/v4l2-core/v4l2-compat-ioctl32.c
drivers/media/v4l2-core/videobuf2-core.c
include/uapi/linux/videodev2.h

index c717f265e4fe5e63770e0cd059a68a2cba1b094d..eeb71a5d9c85dcc081a000893616a7c5bd72d9d7 100644 (file)
@@ -388,8 +388,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,
@@ -508,6 +511,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) ||
index e2231df787f40ff1c786bd1c76944bd0b9f5d261..dc7879406c4734a165e086f3d32f96eb13861ea7 100644 (file)
@@ -970,21 +970,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);
 
@@ -1268,9 +1253,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);
@@ -1455,10 +1445,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,
@@ -1528,6 +1518,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
@@ -1558,8 +1549,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);
index feee7e900b2037c427eb585fc413dd1a815c9610..ef1e7bb5ab8da74c3947119eec0051c56a3597e4 100644 (file)
@@ -926,11 +926,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 */