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)
committerSeungchul Kim <sc377.kim@samsung.com>
Mon, 28 May 2018 05:28:45 +0000 (14:28 +0900)
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 46657ea6b957d4b293003837db4b0abc2071a7fb..8da921c6dbd7570dab049e58b31433d80dd76392 100644 (file)
@@ -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) ||
index 131133cba30df1a5edea67d1770d27b397ce07ad..9a43ebaec60d799fbc01d6daa2e91475b2759655 100644 (file)
@@ -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);
index b9592e611da2258c74b48cbe7128f6ebde45dcd7..1bdd105516e3327175f17ce66b1fd1a3e6e99634 100644 (file)
@@ -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 */