linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 00/14] V4L2 Explicit Synchronization support
@ 2017-09-01  1:50 Gustavo Padovan
  2017-09-01  1:50 ` [PATCH v2 01/14] [media] vb2: add explicit fence user API Gustavo Padovan
                   ` (13 more replies)
  0 siblings, 14 replies; 20+ messages in thread
From: Gustavo Padovan @ 2017-09-01  1:50 UTC (permalink / raw)
  To: linux-media
  Cc: Hans Verkuil, Mauro Carvalho Chehab, Shuah Khan, Gustavo Padovan

From: Gustavo Padovan <gustavo.padovan@collabora.com>

Hi,

Explicit Synchronization allows us to control the synchronization of
shared buffers from userspace by passing fences to the kernel and/or
receiving them from it. Fences passed to the kernel are named in-fences
and the kernel should wait them to signal before using the buffer, i.e.,
queueing it to the driver. On the other side, the kernel can create
out-fences for the buffers it queues to the drivers, out-fences signal
when the driver is finished with buffer, that is, the buffer is ready.

The in-fences and out-fences are communicated at the VIDIOC_QBUF ioctl
using the V4L2_BUF_FLAG_IN_FENCE and V4L2_BUF_FLAG_OUT_FENCE buffer
flags and the fence_fd field. If an in-fence needs to be passed to the
kernel, fence_fd should be set to the fence file descriptor number and
the V4L2_BUF_FLAG_IN_FENCE should be set as well.

To get an out-fence back from V4L2 the V4L2_BUF_FLAG_OUT_FENCE flag
should be set and the fence_fd field will be returned with out-fence
file descriptor related to the next fence to be queued internally to the
V4L2 driver. That means the out-fence may not be associated with the
buffer in the current VIDIOC_QBUF ioctl call because the ordering in
which videobuf2 core queues the buffer to the drivers can’t be
guaranteed. To become aware of the buffer with which the out-fence will
be attached the V4L2_EVENT_BUF_QUEUED should be used. It will trigger an
event for every buffer queued to the V4L2 driver.

Note that the fence_fd field is both an input and output argument here
with different meaning on each direction. As input argument it carries
an in-fence and as output argument it carries an out-fence.

It only works for ordered queues for now, see open question at the end
of the letter.

Test tool can be found at:
https://git.collabora.com/cgit/user/padovan/v4l2-test.git/

The Patches
-----------

The first patch proposes an userspace API for fences, then on patch 2 we
prepare to the addition of in-fences in patch 3, by introducing the
infrastructure on vb2 to wait on an in-fence signal before queueing the
buffer in the driver.

Patch 4 fix uvc v4l2 event handling and patch 5 configure q->dev for
vivid drivers to enable to subscribe and dequeue events on it.

Patches 6-8 enables support to notify BUF_QUEUED events, i.e., let
userspace know that particular buffer was enqueued in the driver. This
is needed, because we return the out-fence fd as an out argument in
QBUF, but at the time it returns we don't know to which buffer the fence
will be attached thus the BUF_QUEUED event tells which buffer is
associated to the fence received in QBUF by userspace.

Patches 9-10 add support to mark queues as ordered. Finally patches 11
and 12 add more fence infrastructure to support out-fences and patch 13
adds support to out-fences. Patch 14 adds overall Documentation about
Explicit Synchronization.

Main Changes
------------

* There is now a .buffer_queued hook on vb2_ops to support notification to
  V4L2 users of buffer queued events
* When handling in-fences we never call vb2_start_streaming() in the fence
  callback, so on the QBUF that is going to trigger the start of the streaming
  we wait synchronously  for the fence to signal before calling
  vb2_start_streaming()
* out-fences: change in behavior: now the out-fence returned via  QBUF
  represents the out-fence of the next buffer to be queued
  to the driver. The buffer id comes out of the BUF_QUEUED event.

All other changes are recorded on the patches' commit messages.

Open Questions
--------------

* non-ordered devices, like m2m: I've been thinking a lot about those
  and one possibility is to have a way to tell userspace that the queue
  is not ordered and then associate the fence with the current buffer in
  QBUF instead of the next one to be queued. Of course, there won't be
  any ordering between the fences. But it may be enough for userspace to
  take advantage of Explicit Synchronization in such cases. Any
  thoughts?

* OUTPUT devices and in-fence. If I understood OUTPUT devices correctly
  it is desirable to queue the buffers to the driver in the same order
  we received them from userspace. If that is correct, shouldn't we add
  some mechanism to prevent buffer whose fence signaled to jump ahead of
  others?

TODO
----

* Gstreamer patch to support fences for some real testing


Gustavo Padovan (13):
  [media] vb2: add explicit fence user API
  [media] vb2: check earlier if stream can be started
  [media] vb2: add in-fence support to QBUF
  [media] uvc: enable subscriptions to other events
  [media] vivid: assign the specific device to the vb2_queue->dev
  [media] v4l: add V4L2_EVENT_BUF_QUEUED event
  [media] vb2: add .buffer_queued() to notify queueing in the driver
  [media] v4l: add support to BUF_QUEUED event
  [media] vb2: add 'ordered' property to queues
  [media] vivid: mark vivid queues as ordered
  [media] vb2: add infrastructure to support out-fences
  [media] vb2: add out-fence support to QBUF
  [media] v4l: Document explicit synchronization behaviour

Javier Martinez Canillas (1):
  [media] vb2: add videobuf2 dma-buf fence helpers

 Documentation/media/uapi/v4l/buffer.rst         |  19 +++
 Documentation/media/uapi/v4l/vidioc-dqevent.rst |  18 ++
 Documentation/media/uapi/v4l/vidioc-qbuf.rst    |  30 ++++
 Documentation/media/videodev2.h.rst.exceptions  |   1 +
 drivers/media/platform/vivid/vivid-core.c       |  15 +-
 drivers/media/usb/cpia2/cpia2_v4l.c             |   2 +-
 drivers/media/usb/uvc/uvc_v4l2.c                |   2 +-
 drivers/media/v4l2-core/Kconfig                 |   1 +
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c   |   4 +-
 drivers/media/v4l2-core/v4l2-ctrls.c            |   6 +-
 drivers/media/v4l2-core/videobuf2-core.c        | 213 ++++++++++++++++++++++--
 drivers/media/v4l2-core/videobuf2-v4l2.c        |  51 +++++-
 include/media/videobuf2-core.h                  |  35 +++-
 include/media/videobuf2-fence.h                 |  49 ++++++
 include/uapi/linux/videodev2.h                  |  14 +-
 15 files changed, 428 insertions(+), 32 deletions(-)
 create mode 100644 include/media/videobuf2-fence.h

-- 
2.13.5

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v2 01/14] [media] vb2: add explicit fence user API
  2017-09-01  1:50 [PATCH v2 00/14] V4L2 Explicit Synchronization support Gustavo Padovan
@ 2017-09-01  1:50 ` Gustavo Padovan
  2017-09-01  1:50 ` [PATCH v2 02/14] [media] vb2: check earlier if stream can be started Gustavo Padovan
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Gustavo Padovan @ 2017-09-01  1:50 UTC (permalink / raw)
  To: linux-media
  Cc: Hans Verkuil, Mauro Carvalho Chehab, Shuah Khan, Gustavo Padovan

From: Gustavo Padovan <gustavo.padovan@collabora.com>

Turn the reserved2 field into fence_fd that we will use to send
an in-fence to the kernel and return an out-fence from the kernel to
userspace.

Two new flags were added, V4L2_BUF_FLAG_IN_FENCE, that should be used
when sending a fence to the kernel to be waited on, and
V4L2_BUF_FLAG_OUT_FENCE, to ask the kernel to give back an out-fence.

v2: add documentation

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
---
 Documentation/media/uapi/v4l/buffer.rst       | 19 +++++++++++++++++++
 drivers/media/usb/cpia2/cpia2_v4l.c           |  2 +-
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c |  4 ++--
 drivers/media/v4l2-core/videobuf2-v4l2.c      |  2 +-
 include/uapi/linux/videodev2.h                |  4 +++-
 5 files changed, 26 insertions(+), 5 deletions(-)

diff --git a/Documentation/media/uapi/v4l/buffer.rst b/Documentation/media/uapi/v4l/buffer.rst
index ae6ee73f151c..664507ad06c6 100644
--- a/Documentation/media/uapi/v4l/buffer.rst
+++ b/Documentation/media/uapi/v4l/buffer.rst
@@ -648,6 +648,25 @@ Buffer Flags
       - Start Of Exposure. The buffer timestamp has been taken when the
 	exposure of the frame has begun. This is only valid for the
 	``V4L2_BUF_TYPE_VIDEO_CAPTURE`` buffer type.
+    * .. _`V4L2-BUF-FLAG-IN-FENCE`:
+
+      - ``V4L2_BUF_FLAG_IN_FENCE``
+      - 0x00200000
+      - Ask V4L2 to wait on fence passed in ``fence_fd`` field. The buffer
+	won't be queued to the driver until the fence signals.
+
+    * .. _`V4L2-BUF-FLAG-OUT-FENCE`:
+
+      - ``V4L2_BUF_FLAG_OUT_FENCE``
+      - 0x00400000
+      - Request a fence for the next buffer to be queued to V4L2 driver.
+	The fence received back through the ``fence_fd`` field  doesn't
+	necessarily relate to the current buffer in the
+	:ref:`VIDIOC_QBUF <VIDIOC_QBUF>` ioctl. Although, most of the time
+	the fence will relate to the current buffer it can't be guaranteed.
+	So to tell userspace which buffer is associated to the out_fence,
+	one should listen for the ``V4L2_EVENT_BUF_QUEUED`` event that
+	provide the id of the buffer when it is queued to the V4L2 driver.
 
 
 
diff --git a/drivers/media/usb/cpia2/cpia2_v4l.c b/drivers/media/usb/cpia2/cpia2_v4l.c
index 3dedd83f0b19..6cde686bf44c 100644
--- a/drivers/media/usb/cpia2/cpia2_v4l.c
+++ b/drivers/media/usb/cpia2/cpia2_v4l.c
@@ -948,7 +948,7 @@ static int cpia2_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
 	buf->sequence = cam->buffers[buf->index].seq;
 	buf->m.offset = cam->buffers[buf->index].data - cam->frame_buffer;
 	buf->length = cam->frame_size;
-	buf->reserved2 = 0;
+	buf->fence_fd = -1;
 	buf->reserved = 0;
 	memset(&buf->timecode, 0, sizeof(buf->timecode));
 
diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 821f2aa299ae..d624fb5df130 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -370,7 +370,7 @@ struct v4l2_buffer32 {
 		__s32		fd;
 	} m;
 	__u32			length;
-	__u32			reserved2;
+	__s32			fence_fd;
 	__u32			reserved;
 };
 
@@ -533,8 +533,8 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user
 		put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec) ||
 		copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) ||
 		put_user(kp->sequence, &up->sequence) ||
-		put_user(kp->reserved2, &up->reserved2) ||
 		put_user(kp->reserved, &up->reserved) ||
+		put_user(kp->fence_fd, &up->fence_fd) ||
 		put_user(kp->length, &up->length))
 			return -EFAULT;
 
diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
index 0c0669976bdc..110fb45fef6f 100644
--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -203,7 +203,7 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb)
 	b->timestamp = ns_to_timeval(vb->timestamp);
 	b->timecode = vbuf->timecode;
 	b->sequence = vbuf->sequence;
-	b->reserved2 = 0;
+	b->fence_fd = -1;
 	b->reserved = 0;
 
 	if (q->is_multiplanar) {
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 185d6a0acc06..e5abab9a908c 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -924,7 +924,7 @@ struct v4l2_buffer {
 		__s32		fd;
 	} m;
 	__u32			length;
-	__u32			reserved2;
+	__s32			fence_fd;
 	__u32			reserved;
 };
 
@@ -961,6 +961,8 @@ struct v4l2_buffer {
 #define V4L2_BUF_FLAG_TSTAMP_SRC_SOE		0x00010000
 /* mem2mem encoder/decoder */
 #define V4L2_BUF_FLAG_LAST			0x00100000
+#define V4L2_BUF_FLAG_IN_FENCE			0x00200000
+#define V4L2_BUF_FLAG_OUT_FENCE			0x00400000
 
 /**
  * struct v4l2_exportbuffer - export of video buffer as DMABUF file descriptor
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v2 02/14] [media] vb2: check earlier if stream can be started
  2017-09-01  1:50 [PATCH v2 00/14] V4L2 Explicit Synchronization support Gustavo Padovan
  2017-09-01  1:50 ` [PATCH v2 01/14] [media] vb2: add explicit fence user API Gustavo Padovan
@ 2017-09-01  1:50 ` Gustavo Padovan
  2017-09-01  1:50 ` [PATCH v2 03/14] [media] vb2: add in-fence support to QBUF Gustavo Padovan
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Gustavo Padovan @ 2017-09-01  1:50 UTC (permalink / raw)
  To: linux-media
  Cc: Hans Verkuil, Mauro Carvalho Chehab, Shuah Khan, Gustavo Padovan

From: Gustavo Padovan <gustavo.padovan@collabora.com>

To support explicit synchronization we need to run all operations that can
fail before we queue the buffer to the driver. With fences the queueing
will be delayed if the fence is not signaled yet and it will be better if
such callback do not fail.

For that we move the vb2_start_streaming() before the queuing for the
buffer may happen.

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
---
 drivers/media/v4l2-core/videobuf2-core.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index cb115ba6a1d2..60f8b582396a 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -1399,29 +1399,27 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb)
 	trace_vb2_qbuf(q, vb);
 
 	/*
-	 * If already streaming, give the buffer to driver for processing.
-	 * If not, the buffer will be given to driver on next streamon.
-	 */
-	if (q->start_streaming_called)
-		__enqueue_in_driver(vb);
-
-	/* Fill buffer information for the userspace */
-	if (pb)
-		call_void_bufop(q, fill_user_buffer, vb, pb);
-
-	/*
 	 * If streamon has been called, and we haven't yet called
 	 * start_streaming() since not enough buffers were queued, and
 	 * we now have reached the minimum number of queued buffers,
 	 * then we can finally call start_streaming().
+	 *
+	 * If already streaming, give the buffer to driver for processing.
+	 * If not, the buffer will be given to driver on next streamon.
 	 */
 	if (q->streaming && !q->start_streaming_called &&
 	    q->queued_count >= q->min_buffers_needed) {
 		ret = vb2_start_streaming(q);
 		if (ret)
 			return ret;
+	} else if (q->start_streaming_called) {
+		__enqueue_in_driver(vb);
 	}
 
+	/* Fill buffer information for the userspace */
+	if (pb)
+		call_void_bufop(q, fill_user_buffer, vb, pb);
+
 	dprintk(2, "qbuf of buffer %d succeeded\n", vb->index);
 	return 0;
 }
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v2 03/14] [media] vb2: add in-fence support to QBUF
  2017-09-01  1:50 [PATCH v2 00/14] V4L2 Explicit Synchronization support Gustavo Padovan
  2017-09-01  1:50 ` [PATCH v2 01/14] [media] vb2: add explicit fence user API Gustavo Padovan
  2017-09-01  1:50 ` [PATCH v2 02/14] [media] vb2: check earlier if stream can be started Gustavo Padovan
@ 2017-09-01  1:50 ` Gustavo Padovan
  2017-09-01  1:50 ` [PATCH v2 04/14] [media] uvc: enable subscriptions to other events Gustavo Padovan
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Gustavo Padovan @ 2017-09-01  1:50 UTC (permalink / raw)
  To: linux-media
  Cc: Hans Verkuil, Mauro Carvalho Chehab, Shuah Khan, Gustavo Padovan

From: Gustavo Padovan <gustavo.padovan@collabora.com>

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 <gustavo.padovan@collabora.com>
---
 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           |   8 ++-
 4 files changed, 124 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)
 		call_void_bufop(q, copy_timestamp, vb, pb);
@@ -1399,6 +1431,16 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb)
 	trace_vb2_qbuf(q, vb);
 
 	/*
+	 * If it is time to call vb2_start_streaming() wait for the fence
+	 * to signal first. Of course, this happens only once per streaming.
+	 * We want to run any step that might fail before we set the callback
+	 * to queue the fence when it signals.
+	 */
+	if (fence && !q->start_streaming_called &&
+	    __get_num_ready_buffers(q) == q->min_buffers_needed - 1)
+		dma_fence_wait(fence, true);
+
+	/*
 	 * If streamon has been called, and we haven't yet called
 	 * start_streaming() since not enough buffers were queued, and
 	 * we now have reached the minimum number of queued buffers,
@@ -1408,20 +1450,48 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb)
 	 * If not, the buffer will be given to driver on next streamon.
 	 */
 	if (q->streaming && !q->start_streaming_called &&
-	    q->queued_count >= q->min_buffers_needed) {
+	    __get_num_ready_buffers(q) >= q->min_buffers_needed) {
 		ret = vb2_start_streaming(q);
 		if (ret)
-			return ret;
-	} else if (q->start_streaming_called) {
-		__enqueue_in_driver(vb);
+			goto err;
 	}
 
+	/*
+	 * For explicit synchronization: If the fence didn't signal
+	 * yet we setup a callback to queue the buffer once the fence
+	 * signals, and then, return successfully. But if the fence
+	 * already signaled we lose the reference we held and queue the
+	 * buffer to the driver.
+	 */
+	if (fence) {
+		ret = dma_fence_add_callback(fence, &vb->fence_cb,
+					     vb2_qbuf_fence_cb);
+		if (!ret)
+			goto fill;
+
+		dma_fence_put(fence);
+		vb->in_fence = NULL;
+	}
+
+fill:
+	if (q->start_streaming_called && !vb->in_fence)
+		__enqueue_in_driver(vb);
+
 	/* Fill buffer information for the userspace */
 	if (pb)
 		call_void_bufop(q, fill_user_buffer, vb, pb);
 
 	dprintk(2, "qbuf of buffer %d succeeded\n", vb->index);
 	return 0;
+
+err:
+	if (vb->in_fence) {
+		dma_fence_put(vb->in_fence);
+		vb->in_fence = NULL;
+	}
+
+	return ret;
+
 }
 EXPORT_SYMBOL_GPL(vb2_core_qbuf);
 
@@ -1632,6 +1702,7 @@ EXPORT_SYMBOL_GPL(vb2_core_dqbuf);
 static void __vb2_queue_cancel(struct vb2_queue *q)
 {
 	unsigned int i;
+	struct vb2_buffer *vb;
 
 	/*
 	 * Tell driver to stop all transactions and release all queued
@@ -1654,6 +1725,14 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
 		WARN_ON(atomic_read(&q->owned_by_drv_count));
 	}
 
+	list_for_each_entry(vb, &q->queued_list, queued_entry) {
+		if (vb->in_fence) {
+			dma_fence_remove_callback(vb->in_fence, &vb->fence_cb);
+			dma_fence_put(vb->in_fence);
+			vb->in_fence = NULL;
+		}
+	}
+
 	q->streaming = 0;
 	q->start_streaming_called = 0;
 	q->queued_count = 0;
@@ -1720,7 +1799,7 @@ int vb2_core_streamon(struct vb2_queue *q, unsigned int type)
 	 * Tell driver to start streaming provided sufficient buffers
 	 * are available.
 	 */
-	if (q->queued_count >= q->min_buffers_needed) {
+	if (__get_num_ready_buffers(q) >= q->min_buffers_needed) {
 		ret = v4l_vb2q_enable_media_source(q);
 		if (ret)
 			return ret;
@@ -2240,7 +2319,7 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
 		 * Queue all buffers.
 		 */
 		for (i = 0; i < q->num_buffers; i++) {
-			ret = vb2_core_qbuf(q, i, NULL);
+			ret = vb2_core_qbuf(q, i, NULL, NULL);
 			if (ret)
 				goto err_reqbufs;
 			fileio->bufs[i].queued = 1;
@@ -2419,7 +2498,7 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
 
 		if (copy_timestamp)
 			b->timestamp = ktime_get_ns();
-		ret = vb2_core_qbuf(q, index, NULL);
+		ret = vb2_core_qbuf(q, index, NULL, NULL);
 		dprintk(5, "vb2_dbuf result: %d\n", ret);
 		if (ret)
 			return ret;
@@ -2522,7 +2601,7 @@ static int vb2_thread(void *data)
 		if (copy_timestamp)
 			vb->timestamp = ktime_get_ns();;
 		if (!threadio->stop)
-			ret = vb2_core_qbuf(q, vb->index, NULL);
+			ret = vb2_core_qbuf(q, vb->index, NULL, NULL);
 		call_void_qop(q, wait_prepare, q);
 		if (ret || threadio->stop)
 			break;
diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
index 110fb45fef6f..8c322cd1b346 100644
--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -23,6 +23,7 @@
 #include <linux/sched.h>
 #include <linux/freezer.h>
 #include <linux/kthread.h>
+#include <linux/sync_file.h>
 
 #include <media/v4l2-dev.h>
 #include <media/v4l2-fh.h>
@@ -178,6 +179,11 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b,
 		return -EINVAL;
 	}
 
+	if ((b->fence_fd != -1) && !(b->flags & V4L2_BUF_FLAG_IN_FENCE)) {
+		dprintk(1, "%s: fence_fd set without IN_FENCE flag\n", opname);
+		return -EINVAL;
+	}
+
 	return __verify_planes_array(q->bufs[b->index], b);
 }
 
@@ -203,9 +209,14 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb)
 	b->timestamp = ns_to_timeval(vb->timestamp);
 	b->timecode = vbuf->timecode;
 	b->sequence = vbuf->sequence;
-	b->fence_fd = -1;
 	b->reserved = 0;
 
+	b->fence_fd = -1;
+	if (vb->in_fence)
+		b->flags |= V4L2_BUF_FLAG_IN_FENCE;
+	else
+		b->flags &= ~V4L2_BUF_FLAG_IN_FENCE;
+
 	if (q->is_multiplanar) {
 		/*
 		 * Fill in plane-related data if userspace provided an array
@@ -560,6 +571,7 @@ EXPORT_SYMBOL_GPL(vb2_create_bufs);
 
 int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
 {
+	struct dma_fence *fence = NULL;
 	int ret;
 
 	if (vb2_fileio_is_active(q)) {
@@ -568,7 +580,18 @@ int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
 	}
 
 	ret = vb2_queue_or_prepare_buf(q, b, "qbuf");
-	return ret ? ret : vb2_core_qbuf(q, b->index, b);
+	if (ret)
+		return ret;
+
+	if (b->flags & V4L2_BUF_FLAG_IN_FENCE) {
+		fence = sync_file_get_fence(b->fence_fd);
+		if (!fence) {
+			dprintk(1, "failed to get in-fence from fd\n");
+			return -EINVAL;
+		}
+	}
+
+	return vb2_core_qbuf(q, b->index, b, fence);
 }
 EXPORT_SYMBOL_GPL(vb2_qbuf);
 
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index ef9b64398c8c..cad45e49a46d 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -16,6 +16,7 @@
 #include <linux/mutex.h>
 #include <linux/poll.h>
 #include <linux/dma-buf.h>
+#include <linux/dma-fence.h>
 
 #define VB2_MAX_FRAME	(32)
 #define VB2_MAX_PLANES	(8)
@@ -259,6 +260,9 @@ struct vb2_buffer {
 
 	struct list_head	queued_entry;
 	struct list_head	done_entry;
+
+	struct dma_fence	*in_fence;
+	struct dma_fence_cb	fence_cb;
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	/*
 	 * Counters for how often these buffer-related ops are
@@ -726,6 +730,7 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb);
  * @index:	id number of the buffer
  * @pb:		buffer structure passed from userspace to vidioc_qbuf handler
  *		in driver
+ * @fence:	in-fence to wait on before queueing the buffer
  *
  * Should be called from vidioc_qbuf ioctl handler of a driver.
  * The passed buffer should have been verified.
@@ -740,7 +745,8 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb);
  * The return values from this function are intended to be directly returned
  * from vidioc_qbuf handler in driver.
  */
-int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb);
+int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
+		  struct dma_fence *fence);
 
 /**
  * vb2_core_dqbuf() - Dequeue a buffer to the userspace
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v2 04/14] [media] uvc: enable subscriptions to other events
  2017-09-01  1:50 [PATCH v2 00/14] V4L2 Explicit Synchronization support Gustavo Padovan
                   ` (2 preceding siblings ...)
  2017-09-01  1:50 ` [PATCH v2 03/14] [media] vb2: add in-fence support to QBUF Gustavo Padovan
@ 2017-09-01  1:50 ` Gustavo Padovan
  2017-09-01  1:50 ` [PATCH v2 05/14] [media] vivid: assign the specific device to the vb2_queue->dev Gustavo Padovan
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Gustavo Padovan @ 2017-09-01  1:50 UTC (permalink / raw)
  To: linux-media
  Cc: Hans Verkuil, Mauro Carvalho Chehab, Shuah Khan, Gustavo Padovan

From: Gustavo Padovan <gustavo.padovan@collabora.com>

Call v4l2_ctrl_subscribe_event to subscribe to the BUF_QUEUED event as
well.

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
---
 drivers/media/usb/uvc/uvc_v4l2.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c
index 3e7e283a44a8..dfa0ccdcf849 100644
--- a/drivers/media/usb/uvc/uvc_v4l2.c
+++ b/drivers/media/usb/uvc/uvc_v4l2.c
@@ -1240,7 +1240,7 @@ static int uvc_ioctl_subscribe_event(struct v4l2_fh *fh,
 	case V4L2_EVENT_CTRL:
 		return v4l2_event_subscribe(fh, sub, 0, &uvc_ctrl_sub_ev_ops);
 	default:
-		return -EINVAL;
+		return v4l2_ctrl_subscribe_event(fh, sub);
 	}
 }
 
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v2 05/14] [media] vivid: assign the specific device to the vb2_queue->dev
  2017-09-01  1:50 [PATCH v2 00/14] V4L2 Explicit Synchronization support Gustavo Padovan
                   ` (3 preceding siblings ...)
  2017-09-01  1:50 ` [PATCH v2 04/14] [media] uvc: enable subscriptions to other events Gustavo Padovan
@ 2017-09-01  1:50 ` Gustavo Padovan
  2017-09-01  1:50 ` [PATCH v2 06/14] [media] v4l: add V4L2_EVENT_BUF_QUEUED event Gustavo Padovan
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Gustavo Padovan @ 2017-09-01  1:50 UTC (permalink / raw)
  To: linux-media
  Cc: Hans Verkuil, Mauro Carvalho Chehab, Shuah Khan, Gustavo Padovan

From: Gustavo Padovan <gustavo.padovan@collabora.com>

Instead of assigning the global v4l2 device, assign the specific device.
This was causing trouble when using using V4L2 events with vivid
devices. The device's queue should be the same we opened in userspace.

This is needed for the upcoming V4L2_EVENT_BUF_QUEUED support. The current
vivid code isn't wrong, it just needs to be changed so V4L2_EVENT_BUF_QUEUED
can be supported. The change doesn't affect any other behaviour of vivid.

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-core.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c
index 5f316a5e38db..608bcceed463 100644
--- a/drivers/media/platform/vivid/vivid-core.c
+++ b/drivers/media/platform/vivid/vivid-core.c
@@ -1070,7 +1070,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
 		q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 		q->min_buffers_needed = 2;
 		q->lock = &dev->mutex;
-		q->dev = dev->v4l2_dev.dev;
+		q->dev = &dev->vid_cap_dev.dev;
 
 		ret = vb2_queue_init(q);
 		if (ret)
@@ -1090,7 +1090,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
 		q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 		q->min_buffers_needed = 2;
 		q->lock = &dev->mutex;
-		q->dev = dev->v4l2_dev.dev;
+		q->dev = &dev->vid_out_dev.dev;
 
 		ret = vb2_queue_init(q);
 		if (ret)
@@ -1110,7 +1110,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
 		q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 		q->min_buffers_needed = 2;
 		q->lock = &dev->mutex;
-		q->dev = dev->v4l2_dev.dev;
+		q->dev = &dev->vbi_cap_dev.dev;
 
 		ret = vb2_queue_init(q);
 		if (ret)
@@ -1130,7 +1130,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
 		q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 		q->min_buffers_needed = 2;
 		q->lock = &dev->mutex;
-		q->dev = dev->v4l2_dev.dev;
+		q->dev = &dev->vbi_out_dev.dev;
 
 		ret = vb2_queue_init(q);
 		if (ret)
@@ -1149,7 +1149,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
 		q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
 		q->min_buffers_needed = 8;
 		q->lock = &dev->mutex;
-		q->dev = dev->v4l2_dev.dev;
+		q->dev = &dev->sdr_cap_dev.dev;
 
 		ret = vb2_queue_init(q);
 		if (ret)
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v2 06/14] [media] v4l: add V4L2_EVENT_BUF_QUEUED event
  2017-09-01  1:50 [PATCH v2 00/14] V4L2 Explicit Synchronization support Gustavo Padovan
                   ` (4 preceding siblings ...)
  2017-09-01  1:50 ` [PATCH v2 05/14] [media] vivid: assign the specific device to the vb2_queue->dev Gustavo Padovan
@ 2017-09-01  1:50 ` Gustavo Padovan
  2017-09-01  1:50 ` [PATCH v2 07/14] [media] vb2: add .buffer_queued() to notify queueing in the driver Gustavo Padovan
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Gustavo Padovan @ 2017-09-01  1:50 UTC (permalink / raw)
  To: linux-media
  Cc: Hans Verkuil, Mauro Carvalho Chehab, Shuah Khan, Gustavo Padovan

From: Gustavo Padovan <gustavo.padovan@collabora.com>

Add a new event the userspace can subscribe to receive notifications
when a buffer is queued onto the driver. The event provides the index of
the queued buffer.

v2: - Add missing Documentation (Mauro)

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
---
 Documentation/media/uapi/v4l/vidioc-dqevent.rst | 18 ++++++++++++++++++
 Documentation/media/videodev2.h.rst.exceptions  |  1 +
 include/uapi/linux/videodev2.h                  | 10 ++++++++++
 3 files changed, 29 insertions(+)

diff --git a/Documentation/media/uapi/v4l/vidioc-dqevent.rst b/Documentation/media/uapi/v4l/vidioc-dqevent.rst
index fcd9c933870d..362d82153312 100644
--- a/Documentation/media/uapi/v4l/vidioc-dqevent.rst
+++ b/Documentation/media/uapi/v4l/vidioc-dqevent.rst
@@ -78,6 +78,10 @@ call.
       - ``src_change``
       - Event data for event V4L2_EVENT_SOURCE_CHANGE.
     * -
+      - struct :c:type:`v4l2_event_buf_queued`
+      - ``buf_queued``
+      - Event data for event V4L2_EVENT_BUF_QUEUED.
+    * -
       - __u8
       - ``data``\ [64]
       - Event data. Defined by the event type. The union should be used to
@@ -337,6 +341,20 @@ call.
 	each cell in the motion detection grid, then that all cells are
 	automatically assigned to the default region 0.
 
+.. c:type:: v4l2_event_buf_queued
+
+.. flat-table:: struct v4l2_event_buf_queued
+    :header-rows:  0
+    :stub-columns: 0
+    :widths:       1 1 2
+
+    * - __u32
+      - ``index``
+      - The index of the buffer that was queued to the driver.
+
+
+
+.. tabularcolumns:: |p{4.4cm}|p{4.4cm}|p{8.7cm}|
 
 
 .. tabularcolumns:: |p{6.6cm}|p{2.2cm}|p{8.7cm}|
diff --git a/Documentation/media/videodev2.h.rst.exceptions b/Documentation/media/videodev2.h.rst.exceptions
index a5cb0a8686ac..4e014b1d0317 100644
--- a/Documentation/media/videodev2.h.rst.exceptions
+++ b/Documentation/media/videodev2.h.rst.exceptions
@@ -462,6 +462,7 @@ replace define V4L2_EVENT_CTRL event-type
 replace define V4L2_EVENT_FRAME_SYNC event-type
 replace define V4L2_EVENT_SOURCE_CHANGE event-type
 replace define V4L2_EVENT_MOTION_DET event-type
+replace define V4L2_EVENT_BUF_QUEUED event-type
 replace define V4L2_EVENT_PRIVATE_START event-type
 
 replace define V4L2_EVENT_CTRL_CH_VALUE ctrl-changes-flags
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index e5abab9a908c..4a7a68ecc709 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -2158,6 +2158,7 @@ struct v4l2_streamparm {
 #define V4L2_EVENT_FRAME_SYNC			4
 #define V4L2_EVENT_SOURCE_CHANGE		5
 #define V4L2_EVENT_MOTION_DET			6
+#define V4L2_EVENT_BUF_QUEUED			7
 #define V4L2_EVENT_PRIVATE_START		0x08000000
 
 /* Payload for V4L2_EVENT_VSYNC */
@@ -2210,6 +2211,14 @@ struct v4l2_event_motion_det {
 	__u32 region_mask;
 };
 
+/**
+ * struct v4l2_event_buf_queued - buffer queued in the driver event
+ * @index:		index of the buffer queued in the driver
+ */
+struct v4l2_event_buf_queued {
+	__u32 index;
+};
+
 struct v4l2_event {
 	__u32				type;
 	union {
@@ -2218,6 +2227,7 @@ struct v4l2_event {
 		struct v4l2_event_frame_sync	frame_sync;
 		struct v4l2_event_src_change	src_change;
 		struct v4l2_event_motion_det	motion_det;
+		struct v4l2_event_buf_queued	buf_queued;
 		__u8				data[64];
 	} u;
 	__u32				pending;
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v2 07/14] [media] vb2: add .buffer_queued() to notify queueing in the driver
  2017-09-01  1:50 [PATCH v2 00/14] V4L2 Explicit Synchronization support Gustavo Padovan
                   ` (5 preceding siblings ...)
  2017-09-01  1:50 ` [PATCH v2 06/14] [media] v4l: add V4L2_EVENT_BUF_QUEUED event Gustavo Padovan
@ 2017-09-01  1:50 ` Gustavo Padovan
  2017-09-01  1:50 ` [PATCH v2 08/14] [media] v4l: add support to BUF_QUEUED event Gustavo Padovan
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Gustavo Padovan @ 2017-09-01  1:50 UTC (permalink / raw)
  To: linux-media
  Cc: Hans Verkuil, Mauro Carvalho Chehab, Shuah Khan, Gustavo Padovan

From: Gustavo Padovan <gustavo.padovan@collabora.com>

With the upcoming explicit synchronization support to V4L2 we need a
way to notify userspace when buffers are queued to the driver - buffers
with fences attached to it can only be queued once the fence signal, so
the queueing to the driver might be deferred.

Yet, userspace still wants to be notified, so the buffer_queued() callback
was added to vb2_buf_ops for that purpose.

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
---
 include/media/videobuf2-core.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index cad45e49a46d..46049dec7f61 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -412,6 +412,8 @@ struct vb2_ops {
  *			will return an error.
  * @copy_timestamp:	copy the timestamp from a userspace structure to
  *			the vb2_buffer struct.
+ * @buffer_queued:	VB2 uses this to notify the VB2-client that the buffer
+ *			was queued to the driver.
  */
 struct vb2_buf_ops {
 	int (*verify_planes_array)(struct vb2_buffer *vb, const void *pb);
@@ -419,6 +421,7 @@ struct vb2_buf_ops {
 	int (*fill_vb2_buffer)(struct vb2_buffer *vb, const void *pb,
 				struct vb2_plane *planes);
 	void (*copy_timestamp)(struct vb2_buffer *vb, const void *pb);
+	void (*buffer_queued)(struct vb2_buffer *vb);
 };
 
 /**
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v2 08/14] [media] v4l: add support to BUF_QUEUED event
  2017-09-01  1:50 [PATCH v2 00/14] V4L2 Explicit Synchronization support Gustavo Padovan
                   ` (6 preceding siblings ...)
  2017-09-01  1:50 ` [PATCH v2 07/14] [media] vb2: add .buffer_queued() to notify queueing in the driver Gustavo Padovan
@ 2017-09-01  1:50 ` Gustavo Padovan
  2017-10-15 21:25   ` Sakari Ailus
  2017-09-01  1:50 ` [PATCH v2 09/14] [media] vb2: add 'ordered' property to queues Gustavo Padovan
                   ` (5 subsequent siblings)
  13 siblings, 1 reply; 20+ messages in thread
From: Gustavo Padovan @ 2017-09-01  1:50 UTC (permalink / raw)
  To: linux-media
  Cc: Hans Verkuil, Mauro Carvalho Chehab, Shuah Khan, Gustavo Padovan

From: Gustavo Padovan <gustavo.padovan@collabora.com>

Implement the needed pieces to let userspace subscribe for
V4L2_EVENT_BUF_QUEUED events. Videobuf2 will queue the event for the
DQEVENT ioctl.

v3:	- Do not call v4l2 event API from vb2 (Mauro)

v2:	- Use VIDEO_MAX_FRAME to allocate room for events at
	v4l2_event_subscribe() (Hans)

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
---
 drivers/media/v4l2-core/v4l2-ctrls.c     |  6 +++++-
 drivers/media/v4l2-core/videobuf2-core.c |  2 ++
 drivers/media/v4l2-core/videobuf2-v4l2.c | 13 +++++++++++++
 3 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index dd1db678718c..17d4b9e3eec6 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -3438,8 +3438,12 @@ EXPORT_SYMBOL(v4l2_ctrl_log_status);
 int v4l2_ctrl_subscribe_event(struct v4l2_fh *fh,
 				const struct v4l2_event_subscription *sub)
 {
-	if (sub->type == V4L2_EVENT_CTRL)
+	switch (sub->type) {
+	case V4L2_EVENT_CTRL:
 		return v4l2_event_subscribe(fh, sub, 0, &v4l2_ctrl_sub_ev_ops);
+	case V4L2_EVENT_BUF_QUEUED:
+		return v4l2_event_subscribe(fh, sub, VIDEO_MAX_FRAME, NULL);
+	}
 	return -EINVAL;
 }
 EXPORT_SYMBOL(v4l2_ctrl_subscribe_event);
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index b19c1bc4b083..bbbae0eed567 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -1231,6 +1231,8 @@ static void __enqueue_in_driver(struct vb2_buffer *vb)
 	trace_vb2_buf_queue(q, vb);
 
 	call_void_vb_qop(vb, buf_queue, vb);
+
+	call_void_bufop(q, buffer_queued, vb);
 }
 
 static int __buf_prepare(struct vb2_buffer *vb, const void *pb)
diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
index 8c322cd1b346..1c93bfedaffc 100644
--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -138,6 +138,18 @@ static void __copy_timestamp(struct vb2_buffer *vb, const void *pb)
 	}
 };
 
+static void __buffer_queued(struct vb2_buffer *vb)
+{
+	struct video_device *vdev = to_video_device(vb->vb2_queue->dev);
+	struct v4l2_event event;
+
+	memset(&event, 0, sizeof(event));
+	event.type = V4L2_EVENT_BUF_QUEUED;
+	event.u.buf_queued.index = vb->index;
+
+	v4l2_event_queue(vdev, &event);
+}
+
 static void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
 {
 	static bool check_once;
@@ -455,6 +467,7 @@ static const struct vb2_buf_ops v4l2_buf_ops = {
 	.fill_user_buffer	= __fill_v4l2_buffer,
 	.fill_vb2_buffer	= __fill_vb2_buffer,
 	.copy_timestamp		= __copy_timestamp,
+	.buffer_queued		= __buffer_queued,
 };
 
 /**
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v2 09/14] [media] vb2: add 'ordered' property to queues
  2017-09-01  1:50 [PATCH v2 00/14] V4L2 Explicit Synchronization support Gustavo Padovan
                   ` (7 preceding siblings ...)
  2017-09-01  1:50 ` [PATCH v2 08/14] [media] v4l: add support to BUF_QUEUED event Gustavo Padovan
@ 2017-09-01  1:50 ` Gustavo Padovan
  2017-09-01  1:50 ` [PATCH v2 10/14] [media] vivid: mark vivid queues as ordered Gustavo Padovan
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Gustavo Padovan @ 2017-09-01  1:50 UTC (permalink / raw)
  To: linux-media
  Cc: Hans Verkuil, Mauro Carvalho Chehab, Shuah Khan, Gustavo Padovan

From: Gustavo Padovan <gustavo.padovan@collabora.com>

For explicit synchronization (and soon for HAL3/Request API) we need
the v4l2-driver to guarantee the ordering in which the buffers were queued
by userspace. This is already true for many drivers, but we never needed
to say it.

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
---
 include/media/videobuf2-core.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 46049dec7f61..ad419f7204a2 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -505,6 +505,9 @@ struct vb2_buf_ops {
  * @last_buffer_dequeued: used in poll() and DQBUF to immediately return if the
  *		last decoded buffer was already dequeued. Set for capture queues
  *		when a buffer with the V4L2_BUF_FLAG_LAST is dequeued.
+ * @ordered: if the driver can guarantee that the queue will be ordered or not.
+ *		The default is not ordered unless the driver sets this flag. It
+ *		is mandatory for using explicit fences.
  * @fileio:	file io emulator internal data, used only if emulator is active
  * @threadio:	thread io internal data, used only if thread is active
  */
@@ -557,6 +560,7 @@ struct vb2_queue {
 	unsigned int			is_output:1;
 	unsigned int			copy_timestamp:1;
 	unsigned int			last_buffer_dequeued:1;
+	unsigned int			ordered:1;
 
 	struct vb2_fileio_data		*fileio;
 	struct vb2_threadio_data	*threadio;
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v2 10/14] [media] vivid: mark vivid queues as ordered
  2017-09-01  1:50 [PATCH v2 00/14] V4L2 Explicit Synchronization support Gustavo Padovan
                   ` (8 preceding siblings ...)
  2017-09-01  1:50 ` [PATCH v2 09/14] [media] vb2: add 'ordered' property to queues Gustavo Padovan
@ 2017-09-01  1:50 ` Gustavo Padovan
  2017-09-01  1:50 ` [PATCH v2 11/14] [media] vb2: add videobuf2 dma-buf fence helpers Gustavo Padovan
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Gustavo Padovan @ 2017-09-01  1:50 UTC (permalink / raw)
  To: linux-media
  Cc: Hans Verkuil, Mauro Carvalho Chehab, Shuah Khan, Gustavo Padovan

From: Gustavo Padovan <gustavo.padovan@collabora.com>

To enable vivid to be used with explicit synchronization we need
to mark its queues as ordered. vivid queues are already ordered by
default so we no changes are needed.

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-core.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c
index 608bcceed463..239790e8ccc6 100644
--- a/drivers/media/platform/vivid/vivid-core.c
+++ b/drivers/media/platform/vivid/vivid-core.c
@@ -1063,6 +1063,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
 		q->type = dev->multiplanar ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
 			V4L2_BUF_TYPE_VIDEO_CAPTURE;
 		q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
+		q->ordered = 1;
 		q->drv_priv = dev;
 		q->buf_struct_size = sizeof(struct vivid_buffer);
 		q->ops = &vivid_vid_cap_qops;
@@ -1083,6 +1084,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
 		q->type = dev->multiplanar ? V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE :
 			V4L2_BUF_TYPE_VIDEO_OUTPUT;
 		q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_WRITE;
+		q->ordered = 1;
 		q->drv_priv = dev;
 		q->buf_struct_size = sizeof(struct vivid_buffer);
 		q->ops = &vivid_vid_out_qops;
@@ -1103,6 +1105,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
 		q->type = dev->has_raw_vbi_cap ? V4L2_BUF_TYPE_VBI_CAPTURE :
 					      V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
 		q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
+		q->ordered = 1;
 		q->drv_priv = dev;
 		q->buf_struct_size = sizeof(struct vivid_buffer);
 		q->ops = &vivid_vbi_cap_qops;
@@ -1123,6 +1126,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
 		q->type = dev->has_raw_vbi_out ? V4L2_BUF_TYPE_VBI_OUTPUT :
 					      V4L2_BUF_TYPE_SLICED_VBI_OUTPUT;
 		q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_WRITE;
+		q->ordered = 1;
 		q->drv_priv = dev;
 		q->buf_struct_size = sizeof(struct vivid_buffer);
 		q->ops = &vivid_vbi_out_qops;
@@ -1142,6 +1146,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
 		q = &dev->vb_sdr_cap_q;
 		q->type = V4L2_BUF_TYPE_SDR_CAPTURE;
 		q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
+		q->ordered = 1;
 		q->drv_priv = dev;
 		q->buf_struct_size = sizeof(struct vivid_buffer);
 		q->ops = &vivid_sdr_cap_qops;
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v2 11/14] [media] vb2: add videobuf2 dma-buf fence helpers
  2017-09-01  1:50 [PATCH v2 00/14] V4L2 Explicit Synchronization support Gustavo Padovan
                   ` (9 preceding siblings ...)
  2017-09-01  1:50 ` [PATCH v2 10/14] [media] vivid: mark vivid queues as ordered Gustavo Padovan
@ 2017-09-01  1:50 ` Gustavo Padovan
  2017-09-01  1:50 ` [PATCH v2 12/14] [media] vb2: add infrastructure to support out-fences Gustavo Padovan
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Gustavo Padovan @ 2017-09-01  1:50 UTC (permalink / raw)
  To: linux-media
  Cc: Hans Verkuil, Mauro Carvalho Chehab, Shuah Khan,
	Javier Martinez Canillas

From: Javier Martinez Canillas <javier@osg.samsung.com>

Add a videobuf2-fence.h header file that contains different helpers
for DMA buffer sharing explicit fence support in videobuf2.

Signed-off-by: Javier Martinez Canillas <javier@osg.samsung.com>
Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
---
 include/media/videobuf2-fence.h | 49 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 49 insertions(+)
 create mode 100644 include/media/videobuf2-fence.h

diff --git a/include/media/videobuf2-fence.h b/include/media/videobuf2-fence.h
new file mode 100644
index 000000000000..ed5612ca03d6
--- /dev/null
+++ b/include/media/videobuf2-fence.h
@@ -0,0 +1,49 @@
+/*
+ * videobuf2-fence.h - DMA buffer sharing fence helpers for videobuf 2
+ *
+ * Copyright (C) 2016 Samsung Electronics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/dma-fence.h>
+#include <linux/slab.h>
+
+static DEFINE_SPINLOCK(vb2_fence_lock);
+
+static inline const char *vb2_fence_get_driver_name(struct dma_fence *fence)
+{
+	return "vb2_fence";
+}
+
+static inline const char *vb2_fence_get_timeline_name(struct dma_fence *fence)
+{
+	return "vb2_fence_timeline";
+}
+
+static inline bool vb2_fence_enable_signaling(struct dma_fence *fence)
+{
+	return true;
+}
+
+static const struct dma_fence_ops vb2_fence_ops = {
+	.get_driver_name = vb2_fence_get_driver_name,
+	.get_timeline_name = vb2_fence_get_timeline_name,
+	.enable_signaling = vb2_fence_enable_signaling,
+	.wait = dma_fence_default_wait,
+};
+
+static inline struct dma_fence *vb2_fence_alloc(void)
+{
+	struct dma_fence *vb2_fence = kzalloc(sizeof(*vb2_fence), GFP_KERNEL);
+
+	if (!vb2_fence)
+		return NULL;
+
+	dma_fence_init(vb2_fence, &vb2_fence_ops, &vb2_fence_lock,
+		       dma_fence_context_alloc(1), 1);
+
+	return vb2_fence;
+}
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v2 12/14] [media] vb2: add infrastructure to support out-fences
  2017-09-01  1:50 [PATCH v2 00/14] V4L2 Explicit Synchronization support Gustavo Padovan
                   ` (10 preceding siblings ...)
  2017-09-01  1:50 ` [PATCH v2 11/14] [media] vb2: add videobuf2 dma-buf fence helpers Gustavo Padovan
@ 2017-09-01  1:50 ` Gustavo Padovan
  2017-09-01  1:50 ` [PATCH v2 13/14] [media] vb2: add out-fence support to QBUF Gustavo Padovan
  2017-09-01  1:50 ` [PATCH v2 14/14] [media] v4l: Document explicit synchronization behaviour Gustavo Padovan
  13 siblings, 0 replies; 20+ messages in thread
From: Gustavo Padovan @ 2017-09-01  1:50 UTC (permalink / raw)
  To: linux-media
  Cc: Hans Verkuil, Mauro Carvalho Chehab, Shuah Khan, Gustavo Padovan

From: Gustavo Padovan <gustavo.padovan@collabora.com>

Add vb2_setup_out_fence() and the needed members to struct vb2_buffer.

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
---
 drivers/media/v4l2-core/videobuf2-core.c | 31 +++++++++++++++++++++++++++++++
 include/media/videobuf2-core.h           |  5 +++++
 2 files changed, 36 insertions(+)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index bbbae0eed567..2b9ba3dc23f0 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -23,8 +23,11 @@
 #include <linux/sched.h>
 #include <linux/freezer.h>
 #include <linux/kthread.h>
+#include <linux/sync_file.h>
+#include <linux/dma-fence.h>
 
 #include <media/videobuf2-core.h>
+#include <media/videobuf2-fence.h>
 #include <media/v4l2-mc.h>
 
 #include <trace/events/vb2.h>
@@ -1317,6 +1320,34 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb)
 }
 EXPORT_SYMBOL_GPL(vb2_core_prepare_buf);
 
+int vb2_setup_out_fence(struct vb2_queue *q, unsigned int index)
+{
+	struct vb2_buffer *vb = q->bufs[index];
+
+	vb->out_fence_fd = get_unused_fd_flags(O_CLOEXEC);
+	if (vb->out_fence_fd < 0)
+		return vb->out_fence_fd;
+
+	vb->out_fence = vb2_fence_alloc();
+	if (!vb->out_fence)
+		goto err;
+
+	vb->sync_file = sync_file_create(vb->out_fence);
+	if (!vb->sync_file) {
+		dma_fence_put(vb->out_fence);
+		vb->out_fence = NULL;
+		goto err;
+	}
+
+	return 0;
+
+err:
+	put_unused_fd(vb->out_fence_fd);
+	vb->out_fence_fd = -1;
+	return -ENOMEM;
+}
+EXPORT_SYMBOL_GPL(vb2_setup_out_fence);
+
 /**
  * vb2_start_streaming() - Attempt to start streaming.
  * @q:		videobuf2 queue
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index ad419f7204a2..bf2f0499c737 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -263,6 +263,10 @@ struct vb2_buffer {
 
 	struct dma_fence	*in_fence;
 	struct dma_fence_cb	fence_cb;
+
+	struct dma_fence	*out_fence;
+	struct sync_file	*sync_file;
+	int			out_fence_fd;
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	/*
 	 * Counters for how often these buffer-related ops are
@@ -730,6 +734,7 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory,
  */
 int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb);
 
+int vb2_setup_out_fence(struct vb2_queue *q, unsigned int index);
 /**
  * vb2_core_qbuf() - Queue a buffer from userspace
  *
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v2 13/14] [media] vb2: add out-fence support to QBUF
  2017-09-01  1:50 [PATCH v2 00/14] V4L2 Explicit Synchronization support Gustavo Padovan
                   ` (11 preceding siblings ...)
  2017-09-01  1:50 ` [PATCH v2 12/14] [media] vb2: add infrastructure to support out-fences Gustavo Padovan
@ 2017-09-01  1:50 ` Gustavo Padovan
  2017-09-01  1:50 ` [PATCH v2 14/14] [media] v4l: Document explicit synchronization behaviour Gustavo Padovan
  13 siblings, 0 replies; 20+ messages in thread
From: Gustavo Padovan @ 2017-09-01  1:50 UTC (permalink / raw)
  To: linux-media
  Cc: Hans Verkuil, Mauro Carvalho Chehab, Shuah Khan, Gustavo Padovan

From: Gustavo Padovan <gustavo.padovan@collabora.com>

If V4L2_BUF_FLAG_OUT_FENCE flag is present on the QBUF call we create
an out_fence and return it to userspace on the fence_fd field.

The out fence fd returned references the next buffer to be queued to the
driver and not the buffer in the actual QBUF call. So there a list in
videobuf2 core to keep track of the sync_file and fence created and assign
them to buffers when they are queued to the V4L2 driver.

The fence is signaled on buffer_done(), when the job on the buffer is
finished.

v3:	- add WARN_ON_ONCE(q->ordered) on requeueing (Hans)
	- set the OUT_FENCE flag if there is a fence pending (Hans)
	- call fd_install() after vb2_core_qbuf() (Hans)
	- clean up fence if vb2_core_qbuf() fails (Hans)
	- add list to store sync_file and fence for the next queued buffer

v2: check if the queue is ordered.

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
---
 drivers/media/v4l2-core/videobuf2-core.c | 85 ++++++++++++++++++++++++++++----
 drivers/media/v4l2-core/videobuf2-v4l2.c | 13 ++++-
 include/media/videobuf2-core.h           | 17 ++++++-
 3 files changed, 104 insertions(+), 11 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index 2b9ba3dc23f0..07493c846a8d 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -353,6 +353,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum vb2_memory memory,
 			vb->planes[plane].length = plane_sizes[plane];
 			vb->planes[plane].min_length = plane_sizes[plane];
 		}
+		vb->out_fence_fd = -1;
 		q->bufs[vb->index] = vb;
 
 		/* Allocate video buffer memory for the MMAP type */
@@ -933,10 +934,22 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
 	case VB2_BUF_STATE_QUEUED:
 		return;
 	case VB2_BUF_STATE_REQUEUEING:
+		/*
+		 * Explicit synchronization requires ordered queues for now,
+		 * so WARN_ON if we are requeuing on an ordered queue.
+		 */
+		if (vb->out_fence)
+			WARN_ON_ONCE(q->ordered);
+
 		if (q->start_streaming_called)
 			__enqueue_in_driver(vb);
 		return;
 	default:
+		dma_fence_signal(vb->out_fence);
+		dma_fence_put(vb->out_fence);
+		vb->out_fence = NULL;
+		vb->out_fence_fd = -1;
+
 		/* Inform any processes that may be waiting for buffers */
 		wake_up(&q->done_wq);
 		break;
@@ -1224,10 +1237,20 @@ static int __prepare_dmabuf(struct vb2_buffer *vb, const void *pb)
 static void __enqueue_in_driver(struct vb2_buffer *vb)
 {
 	struct vb2_queue *q = vb->vb2_queue;
+	struct vb2_fence *fence;
 
 	if (vb->in_fence && !dma_fence_is_signaled(vb->in_fence))
 		return;
 
+	spin_lock(&q->out_fence_lock);
+	fence = list_first_entry(&q->out_fence_list, struct vb2_fence, entry);
+	if (fence) {
+		vb->out_fence = dma_fence_get(fence->out_fence);
+		list_del(&fence->entry);
+		kfree(fence);
+	}
+	spin_unlock(&q->out_fence_lock);
+
 	vb->state = VB2_BUF_STATE_ACTIVE;
 	atomic_inc(&q->owned_by_drv_count);
 
@@ -1323,25 +1346,36 @@ EXPORT_SYMBOL_GPL(vb2_core_prepare_buf);
 int vb2_setup_out_fence(struct vb2_queue *q, unsigned int index)
 {
 	struct vb2_buffer *vb = q->bufs[index];
+	struct vb2_fence *fence;
 
 	vb->out_fence_fd = get_unused_fd_flags(O_CLOEXEC);
 	if (vb->out_fence_fd < 0)
 		return vb->out_fence_fd;
 
-	vb->out_fence = vb2_fence_alloc();
-	if (!vb->out_fence)
-		goto err;
+	fence = kzalloc(sizeof(*fence), GFP_KERNEL);
+	if (!fence)
+		goto err_fd;
 
-	vb->sync_file = sync_file_create(vb->out_fence);
-	if (!vb->sync_file) {
-		dma_fence_put(vb->out_fence);
-		vb->out_fence = NULL;
-		goto err;
+	fence->out_fence = vb2_fence_alloc();
+	if (!fence->out_fence)
+		goto err_fence;
+
+	fence->sync_file = sync_file_create(fence->out_fence);
+	if (!fence->sync_file) {
+		dma_fence_put(fence->out_fence);
+		goto err_fence;
 	}
 
+	spin_lock(&q->out_fence_lock);
+	list_add_tail(&fence->entry, &q->out_fence_list);
+	spin_unlock(&q->out_fence_lock);
+
 	return 0;
 
-err:
+err_fence:
+	kfree(fence);
+
+err_fd:
 	put_unused_fd(vb->out_fence_fd);
 	vb->out_fence_fd = -1;
 	return -ENOMEM;
@@ -1425,6 +1459,7 @@ static void vb2_qbuf_fence_cb(struct dma_fence *f, struct dma_fence_cb *cb)
 int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
 		  struct dma_fence *fence)
 {
+	struct vb2_fence *vb2_fence;
 	struct vb2_buffer *vb;
 	int ret;
 
@@ -1506,6 +1541,16 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
 		vb->in_fence = NULL;
 	}
 
+	if (vb->out_fence_fd >= 0) {
+		spin_lock(&q->out_fence_lock);
+		vb2_fence = list_last_entry(&q->out_fence_list,
+					    struct vb2_fence, entry);
+		spin_unlock(&q->out_fence_lock);
+		fd_install(vb->out_fence_fd, vb2_fence->sync_file->file);
+
+		vb2_fence->sync_file = NULL;
+	}
+
 fill:
 	if (q->start_streaming_called && !vb->in_fence)
 		__enqueue_in_driver(vb);
@@ -1523,6 +1568,17 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
 		vb->in_fence = NULL;
 	}
 
+	if (vb->out_fence_fd >= 0) {
+		spin_lock(&q->out_fence_lock);
+		vb2_fence = list_last_entry(&q->out_fence_list,
+					    struct vb2_fence, entry);
+		fput(vb2_fence->sync_file->file);
+		list_del(&vb2_fence->entry);
+		kfree(vb2_fence);
+		spin_unlock(&q->out_fence_lock);
+		put_unused_fd(vb->out_fence_fd);
+	}
+
 	return ret;
 
 }
@@ -1736,6 +1792,7 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
 {
 	unsigned int i;
 	struct vb2_buffer *vb;
+	struct vb2_fence *fence, *tmp;
 
 	/*
 	 * Tell driver to stop all transactions and release all queued
@@ -1766,6 +1823,13 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
 		}
 	}
 
+	spin_lock(&q->out_fence_lock);
+	list_for_each_entry_safe(fence, tmp, &q->out_fence_list, entry) {
+		list_del(&fence->entry);
+		kfree(fence);
+	}
+	spin_unlock(&q->out_fence_lock);
+
 	q->streaming = 0;
 	q->start_streaming_called = 0;
 	q->queued_count = 0;
@@ -1780,6 +1844,7 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
 	 * has not already dequeued before initiating cancel.
 	 */
 	INIT_LIST_HEAD(&q->done_list);
+	INIT_LIST_HEAD(&q->out_fence_list);
 	atomic_set(&q->owned_by_drv_count, 0);
 	wake_up_all(&q->done_wq);
 
@@ -2101,6 +2166,8 @@ int vb2_core_queue_init(struct vb2_queue *q)
 	INIT_LIST_HEAD(&q->queued_list);
 	INIT_LIST_HEAD(&q->done_list);
 	spin_lock_init(&q->done_lock);
+	INIT_LIST_HEAD(&q->out_fence_list);
+	spin_lock_init(&q->out_fence_lock);
 	mutex_init(&q->mmap_lock);
 	init_waitqueue_head(&q->done_wq);
 
diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
index 1c93bfedaffc..788372e4d0c9 100644
--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -223,7 +223,9 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb)
 	b->sequence = vbuf->sequence;
 	b->reserved = 0;
 
-	b->fence_fd = -1;
+	b->fence_fd = vb->out_fence_fd;
+	if (vb->out_fence_fd)
+		b->flags |= V4L2_BUF_FLAG_OUT_FENCE;
 	if (vb->in_fence)
 		b->flags |= V4L2_BUF_FLAG_IN_FENCE;
 	else
@@ -604,6 +606,15 @@ int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
 		}
 	}
 
+	if (b->flags & V4L2_BUF_FLAG_OUT_FENCE) {
+		ret = vb2_setup_out_fence(q, b->index);
+		if (ret) {
+			dprintk(1, "failed to set up out-fence\n");
+			dma_fence_put(fence);
+			return ret;
+		}
+	}
+
 	return vb2_core_qbuf(q, b->index, b, fence);
 }
 EXPORT_SYMBOL_GPL(vb2_qbuf);
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index bf2f0499c737..a13a080d6c51 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -265,7 +265,6 @@ struct vb2_buffer {
 	struct dma_fence_cb	fence_cb;
 
 	struct dma_fence	*out_fence;
-	struct sync_file	*sync_file;
 	int			out_fence_fd;
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	/*
@@ -428,6 +427,17 @@ struct vb2_buf_ops {
 	void (*buffer_queued)(struct vb2_buffer *vb);
 };
 
+/*
+ * struct vb2_fence - fence related data
+ *
+ * XXX
+ */
+struct vb2_fence {
+	struct dma_fence *out_fence;
+	struct sync_file *sync_file;
+	struct list_head entry;
+};
+
 /**
  * struct vb2_queue - a videobuf queue
  *
@@ -495,6 +505,8 @@ struct vb2_buf_ops {
  * @done_list:	list of buffers ready to be dequeued to userspace
  * @done_lock:	lock to protect done_list list
  * @done_wq:	waitqueue for processes waiting for buffers ready to be dequeued
+ * @out_fence_list: list of out fences waiting to be assigned to a buffer
+ * @out_fence_lock: lock to protect out_fence_list
  * @alloc_devs:	memory type/allocator-specific per-plane device
  * @streaming:	current streaming state
  * @start_streaming_called: @start_streaming was called successfully and we
@@ -554,6 +566,9 @@ struct vb2_queue {
 	spinlock_t			done_lock;
 	wait_queue_head_t		done_wq;
 
+	struct list_head		out_fence_list;
+	spinlock_t			out_fence_lock;
+
 	struct device			*alloc_devs[VB2_MAX_PLANES];
 
 	unsigned int			streaming:1;
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v2 14/14] [media] v4l: Document explicit synchronization behaviour
  2017-09-01  1:50 [PATCH v2 00/14] V4L2 Explicit Synchronization support Gustavo Padovan
                   ` (12 preceding siblings ...)
  2017-09-01  1:50 ` [PATCH v2 13/14] [media] vb2: add out-fence support to QBUF Gustavo Padovan
@ 2017-09-01  1:50 ` Gustavo Padovan
  2017-09-01 12:50   ` Hans Verkuil
  13 siblings, 1 reply; 20+ messages in thread
From: Gustavo Padovan @ 2017-09-01  1:50 UTC (permalink / raw)
  To: linux-media
  Cc: Hans Verkuil, Mauro Carvalho Chehab, Shuah Khan, Gustavo Padovan

From: Gustavo Padovan <gustavo.padovan@collabora.com>

Add section to VIDIOC_QBUF about it

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
---
 Documentation/media/uapi/v4l/vidioc-qbuf.rst | 30 ++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/Documentation/media/uapi/v4l/vidioc-qbuf.rst b/Documentation/media/uapi/v4l/vidioc-qbuf.rst
index 1f3612637200..6bd960d3972b 100644
--- a/Documentation/media/uapi/v4l/vidioc-qbuf.rst
+++ b/Documentation/media/uapi/v4l/vidioc-qbuf.rst
@@ -117,6 +117,36 @@ immediately with an ``EAGAIN`` error code when no buffer is available.
 The struct :c:type:`v4l2_buffer` structure is specified in
 :ref:`buffer`.
 
+Explicit Synchronization
+------------------------
+
+Explicit Synchronization allows us to control the synchronization of
+shared buffers from userspace by passing fences to the kernel and/or
+receiving them from it. Fences passed to the kernel are named in-fences and
+the kernel should wait them to signal before using the buffer, i.e., queueing
+it to the driver. On the other side, the kernel can create out-fences for the
+buffers it queues to the drivers, out-fences signal when the driver is
+finished with buffer, that is the buffer is ready.
+
+The in-fences and out-fences are communicated at the ``VIDIOC_QBUF`` ioctl
+using the ``V4L2_BUF_FLAG_IN_FENCE`` and ``V4L2_BUF_FLAG_OUT_FENCE`` buffer
+flags and the `fence_fd` field. If an in-fence needs to be passed to the kernel,
+`fence_fd` should be set to the fence file descriptor number and the
+``V4L2_BUF_FLAG_IN_FENCE`` should be set as well.
+
+To get a out-fence back from V4L2 the ``V4L2_BUF_FLAG_OUT_FENCE`` flag should
+be set and the `fence_fd` field will be returned with the out-fence file
+descriptor related to the next buffer to be queued internally to the V4L2
+driver. That means the out-fence may not be associated with the buffer in the
+current ``VIDIOC_QBUF`` ioctl call because the ordering in which videobuf2 core
+queues the buffers to the drivers can't be guaranteed. To become aware of the
+buffer with which the out-fence will be attached the ``V4L2_EVENT_BUF_QUEUED``
+should be used. It will trigger an event for every buffer queued to the V4L2
+driver.
+
+Note that the `fence_fd` field is both an input and output argument here with
+different meaning on each direction. As input argument it carries an in-fence
+and as output argument it carries an out-fence.
 
 Return Value
 ============
-- 
2.13.5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 14/14] [media] v4l: Document explicit synchronization behaviour
  2017-09-01  1:50 ` [PATCH v2 14/14] [media] v4l: Document explicit synchronization behaviour Gustavo Padovan
@ 2017-09-01 12:50   ` Hans Verkuil
  2017-09-01 18:21     ` Gustavo Padovan
  0 siblings, 1 reply; 20+ messages in thread
From: Hans Verkuil @ 2017-09-01 12:50 UTC (permalink / raw)
  To: Gustavo Padovan, linux-media
  Cc: Mauro Carvalho Chehab, Shuah Khan, Gustavo Padovan

Hi Gustavo,

I think I concentrate on this last patch first. Once I fully understand this
I can review the code. Remember, it's been a while for me since I last looked
at fences, so forgive me if I ask stupid questions. On the other hand, others
with a similar lack of understanding of fences probably have similar questions,
so it is a good indication where the documentation needs improvement :-)

On 01/09/17 03:50, Gustavo Padovan wrote:
> From: Gustavo Padovan <gustavo.padovan@collabora.com>
> 
> Add section to VIDIOC_QBUF about it
> 
> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
> ---
>  Documentation/media/uapi/v4l/vidioc-qbuf.rst | 30 ++++++++++++++++++++++++++++
>  1 file changed, 30 insertions(+)
> 
> diff --git a/Documentation/media/uapi/v4l/vidioc-qbuf.rst b/Documentation/media/uapi/v4l/vidioc-qbuf.rst
> index 1f3612637200..6bd960d3972b 100644
> --- a/Documentation/media/uapi/v4l/vidioc-qbuf.rst
> +++ b/Documentation/media/uapi/v4l/vidioc-qbuf.rst
> @@ -117,6 +117,36 @@ immediately with an ``EAGAIN`` error code when no buffer is available.
>  The struct :c:type:`v4l2_buffer` structure is specified in
>  :ref:`buffer`.
>  
> +Explicit Synchronization
> +------------------------
> +
> +Explicit Synchronization allows us to control the synchronization of
> +shared buffers from userspace by passing fences to the kernel and/or
> +receiving them from it. Fences passed to the kernel are named in-fences and
> +the kernel should wait them to signal before using the buffer, i.e., queueing
> +it to the driver. On the other side, the kernel can create out-fences for the
> +buffers it queues to the drivers, out-fences signal when the driver is
> +finished with buffer, that is the buffer is ready.

This should add a line explaining that fences are represented by file descriptors.

> +
> +The in-fences and out-fences are communicated at the ``VIDIOC_QBUF`` ioctl
> +using the ``V4L2_BUF_FLAG_IN_FENCE`` and ``V4L2_BUF_FLAG_OUT_FENCE`` buffer
> +flags and the `fence_fd` field. If an in-fence needs to be passed to the kernel,
> +`fence_fd` should be set to the fence file descriptor number and the
> +``V4L2_BUF_FLAG_IN_FENCE`` should be set as well.

Is it possible to have both flags at the same time? Or are they mutually exclusive?

If only V4L2_BUF_FLAG_IN_FENCE is set, then what is the value of fence_fd after
the QBUF call? -1?

> +
> +To get a out-fence back from V4L2 the ``V4L2_BUF_FLAG_OUT_FENCE`` flag should
> +be set and the `fence_fd` field will be returned with the out-fence file
> +descriptor related to the next buffer to be queued internally to the V4L2
> +driver. That means the out-fence may not be associated with the buffer in the
> +current ``VIDIOC_QBUF`` ioctl call because the ordering in which videobuf2 core
> +queues the buffers to the drivers can't be guaranteed. To become aware of the
> +buffer with which the out-fence will be attached the ``V4L2_EVENT_BUF_QUEUED``
> +should be used. It will trigger an event for every buffer queued to the V4L2
> +driver.

General question: does it even make sense to use an out-fence if you don't know with
what buffer is it associated? I mean, QBUF returns an out fence, but only some
time later are you informed about a buffer being queued. It also looks like userspace
has to keep track of the issued out-fences and the queued buffers and map them
accordingly.

If the out-fence cannot be used until you know the buffer as well, then wouldn't
it make more sense if the out-fence and the buffer index are both sent by the
event? Of course, in that case the event can only be sent to the owner file handle
of the streaming device node, but that's OK, we have that.

Setting the OUT_FENCE flag will just cause this event to be sent whenever that
buffer is queued internally.

Sorry if this just shows a complete lack of understanding of fences on my side,
that's perfectly possible.

It could be that when the out-fence triggers the listener is informed about the
associated buffer information, and in that case it makes a bit more sense.
Although in that case I don't see the reason for the event. Regardless, this
should be documented better.

This documentation should also clarify what happens with fences if the streaming
stops, either by a STREAMOFF, closing the filehandle or a crash or whatever.
Do they signal? What about out-fences not yet associated with a buffer?

> +
> +Note that the `fence_fd` field is both an input and output argument here with
> +different meaning on each direction. As input argument it carries an in-fence
> +and as output argument it carries an out-fence.
>  
>  Return Value
>  ============
> 

Regards,

	Hans

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 14/14] [media] v4l: Document explicit synchronization behaviour
  2017-09-01 12:50   ` Hans Verkuil
@ 2017-09-01 18:21     ` Gustavo Padovan
  2017-09-02  8:14       ` Hans Verkuil
  0 siblings, 1 reply; 20+ messages in thread
From: Gustavo Padovan @ 2017-09-01 18:21 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: linux-media, Mauro Carvalho Chehab, Shuah Khan, Gustavo Padovan

Hi Hans,

2017-09-01 Hans Verkuil <hverkuil@xs4all.nl>:

> Hi Gustavo,
> 
> I think I concentrate on this last patch first. Once I fully understand this
> I can review the code. Remember, it's been a while for me since I last looked
> at fences, so forgive me if I ask stupid questions. On the other hand, others
> with a similar lack of understanding of fences probably have similar questions,
> so it is a good indication where the documentation needs improvement :-)

Please ask as many as you want, those are the best questions. :)

> 
> On 01/09/17 03:50, Gustavo Padovan wrote:
> > From: Gustavo Padovan <gustavo.padovan@collabora.com>
> > 
> > Add section to VIDIOC_QBUF about it
> > 
> > Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
> > ---q
> >  Documentation/media/uapi/v4l/vidioc-qbuf.rst | 30 ++++++++++++++++++++++++++++
> >  1 file changed, 30 insertions(+)
> > 
> > diff --git a/Documentation/media/uapi/v4l/vidioc-qbuf.rst b/Documentation/media/uapi/v4l/vidioc-qbuf.rst
> > index 1f3612637200..6bd960d3972b 100644
> > --- a/Documentation/media/uapi/v4l/vidioc-qbuf.rst
> > +++ b/Documentation/media/uapi/v4l/vidioc-qbuf.rst
> > @@ -117,6 +117,36 @@ immediately with an ``EAGAIN`` error code when no buffer is available.
> >  The struct :c:type:`v4l2_buffer` structure is specified in
> >  :ref:`buffer`.
> >  
> > +Explicit Synchronization
> > +------------------------
> > +
> > +Explicit Synchronization allows us to control the synchronization of
> > +shared buffers from userspace by passing fences to the kernel and/or
> > +receiving them from it. Fences passed to the kernel are named in-fences and
> > +the kernel should wait them to signal before using the buffer, i.e., queueing
> > +it to the driver. On the other side, the kernel can create out-fences for the
> > +buffers it queues to the drivers, out-fences signal when the driver is
> > +finished with buffer, that is the buffer is ready.
> 
> This should add a line explaining that fences are represented by file descriptors.

Okay.

> 
> > +
> > +The in-fences and out-fences are communicated at the ``VIDIOC_QBUF`` ioctl
> > +using the ``V4L2_BUF_FLAG_IN_FENCE`` and ``V4L2_BUF_FLAG_OUT_FENCE`` buffer
> > +flags and the `fence_fd` field. If an in-fence needs to be passed to the kernel,
> > +`fence_fd` should be set to the fence file descriptor number and the
> > +``V4L2_BUF_FLAG_IN_FENCE`` should be set as well.
> 
> Is it possible to have both flags at the same time? Or are they mutually exclusive?
> 
> If only V4L2_BUF_FLAG_IN_FENCE is set, then what is the value of fence_fd after
> the QBUF call? -1?

Yes, it is -1.

> 
> > +
> > +To get a out-fence back from V4L2 the ``V4L2_BUF_FLAG_OUT_FENCE`` flag should
> > +be set and the `fence_fd` field will be returned with the out-fence file
> > +descriptor related to the next buffer to be queued internally to the V4L2
> > +driver. That means the out-fence may not be associated with the buffer in the
> > +current ``VIDIOC_QBUF`` ioctl call because the ordering in which videobuf2 core
> > +queues the buffers to the drivers can't be guaranteed. To become aware of the
> > +buffer with which the out-fence will be attached the ``V4L2_EVENT_BUF_QUEUED``
> > +should be used. It will trigger an event for every buffer queued to the V4L2
> > +driver.
> 
> General question: does it even make sense to use an out-fence if you don't know with
> what buffer is it associated? I mean, QBUF returns an out fence, but only some
> time later are you informed about a buffer being queued. It also looks like userspace
> has to keep track of the issued out-fences and the queued buffers and map them
> accordingly.
> 
> If the out-fence cannot be used until you know the buffer as well, then wouldn't
> it make more sense if the out-fence and the buffer index are both sent by the
> event? Of course, in that case the event can only be sent to the owner file handle
> of the streaming device node, but that's OK, we have that.
> 
> Setting the OUT_FENCE flag will just cause this event to be sent whenever that
> buffer is queued internally.
> 
> Sorry if this just shows a complete lack of understanding of fences on my side,
> that's perfectly possible.

Right, I can not think of anything that prevents what you are saying to
work. I built it this way initially because on my lack of understanding
of V4L2 (seems we complement each other here :) because I thought we
needed to keep the QBUF ordering. In the last review you talked me away
of this misconception but I really didn't took that to the
implementation.

If there is no care about ordering, there is no need to receive the
fence before and we could just do as you say. That makes sense to me.
We could do it that way but I have one question, maybe a stupid one. :)

If a specific driver can guarantee the ordering of vb2 buffer, and
userspace has a way to become aware of that. In this case we will
receive the out-fence in QBUF knowing the buffer already (it is
ordered!). Thus we can proceed right away and send it to the next
driver. Does that makes sense? Is this a optmization we need? In your
proposal we will have the timeframe between the queueing to the driver
and buffer_done() to make the out_fence arrive on the next driver. If
that is sufficient then we can just do as you propose.

> 
> It could be that when the out-fence triggers the listener is informed about the
> associated buffer information, and in that case it makes a bit more sense.
> Although in that case I don't see the reason for the event. Regardless, this
> should be documented better.
> 
> This documentation should also clarify what happens with fences if the streaming
> stops, either by a STREAMOFF, closing the filehandle or a crash or whatever.
> Do they signal? What about out-fences not yet associated with a buffer?

I'll write about that. It will also change if we go with your proposal.

	Gustavo

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 14/14] [media] v4l: Document explicit synchronization behaviour
  2017-09-01 18:21     ` Gustavo Padovan
@ 2017-09-02  8:14       ` Hans Verkuil
  2017-09-04 15:44         ` Gustavo Padovan
  0 siblings, 1 reply; 20+ messages in thread
From: Hans Verkuil @ 2017-09-02  8:14 UTC (permalink / raw)
  To: Gustavo Padovan
  Cc: linux-media, Mauro Carvalho Chehab, Shuah Khan, Gustavo Padovan

On 09/01/2017 08:21 PM, Gustavo Padovan wrote:
> Hi Hans,
> 
> 2017-09-01 Hans Verkuil <hverkuil@xs4all.nl>:
> 
>> Hi Gustavo,
>>
>> I think I concentrate on this last patch first. Once I fully understand this
>> I can review the code. Remember, it's been a while for me since I last looked
>> at fences, so forgive me if I ask stupid questions. On the other hand, others
>> with a similar lack of understanding of fences probably have similar questions,
>> so it is a good indication where the documentation needs improvement :-)
> 
> Please ask as many as you want, those are the best questions. :)
> 
>>
>> On 01/09/17 03:50, Gustavo Padovan wrote:
>>> From: Gustavo Padovan <gustavo.padovan@collabora.com>
>>>
>>> Add section to VIDIOC_QBUF about it
>>>
>>> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
>>> ---q
>>>  Documentation/media/uapi/v4l/vidioc-qbuf.rst | 30 ++++++++++++++++++++++++++++
>>>  1 file changed, 30 insertions(+)
>>>
>>> diff --git a/Documentation/media/uapi/v4l/vidioc-qbuf.rst b/Documentation/media/uapi/v4l/vidioc-qbuf.rst
>>> index 1f3612637200..6bd960d3972b 100644
>>> --- a/Documentation/media/uapi/v4l/vidioc-qbuf.rst
>>> +++ b/Documentation/media/uapi/v4l/vidioc-qbuf.rst
>>> @@ -117,6 +117,36 @@ immediately with an ``EAGAIN`` error code when no buffer is available.
>>>  The struct :c:type:`v4l2_buffer` structure is specified in
>>>  :ref:`buffer`.
>>>  
>>> +Explicit Synchronization
>>> +------------------------
>>> +
>>> +Explicit Synchronization allows us to control the synchronization of
>>> +shared buffers from userspace by passing fences to the kernel and/or
>>> +receiving them from it. Fences passed to the kernel are named in-fences and
>>> +the kernel should wait them to signal before using the buffer, i.e., queueing
>>> +it to the driver. On the other side, the kernel can create out-fences for the
>>> +buffers it queues to the drivers, out-fences signal when the driver is
>>> +finished with buffer, that is the buffer is ready.
>>
>> This should add a line explaining that fences are represented by file descriptors.
> 
> Okay.
> 
>>
>>> +
>>> +The in-fences and out-fences are communicated at the ``VIDIOC_QBUF`` ioctl
>>> +using the ``V4L2_BUF_FLAG_IN_FENCE`` and ``V4L2_BUF_FLAG_OUT_FENCE`` buffer
>>> +flags and the `fence_fd` field. If an in-fence needs to be passed to the kernel,
>>> +`fence_fd` should be set to the fence file descriptor number and the
>>> +``V4L2_BUF_FLAG_IN_FENCE`` should be set as well.
>>
>> Is it possible to have both flags at the same time? Or are they mutually exclusive?
>>
>> If only V4L2_BUF_FLAG_IN_FENCE is set, then what is the value of fence_fd after
>> the QBUF call? -1?
> 
> Yes, it is -1.
> 
>>
>>> +
>>> +To get a out-fence back from V4L2 the ``V4L2_BUF_FLAG_OUT_FENCE`` flag should
>>> +be set and the `fence_fd` field will be returned with the out-fence file
>>> +descriptor related to the next buffer to be queued internally to the V4L2
>>> +driver. That means the out-fence may not be associated with the buffer in the
>>> +current ``VIDIOC_QBUF`` ioctl call because the ordering in which videobuf2 core
>>> +queues the buffers to the drivers can't be guaranteed. To become aware of the
>>> +buffer with which the out-fence will be attached the ``V4L2_EVENT_BUF_QUEUED``
>>> +should be used. It will trigger an event for every buffer queued to the V4L2
>>> +driver.
>>
>> General question: does it even make sense to use an out-fence if you don't know with
>> what buffer is it associated? I mean, QBUF returns an out fence, but only some
>> time later are you informed about a buffer being queued. It also looks like userspace
>> has to keep track of the issued out-fences and the queued buffers and map them
>> accordingly.
>>
>> If the out-fence cannot be used until you know the buffer as well, then wouldn't
>> it make more sense if the out-fence and the buffer index are both sent by the
>> event? Of course, in that case the event can only be sent to the owner file handle
>> of the streaming device node, but that's OK, we have that.
>>
>> Setting the OUT_FENCE flag will just cause this event to be sent whenever that
>> buffer is queued internally.
>>
>> Sorry if this just shows a complete lack of understanding of fences on my side,
>> that's perfectly possible.
> 
> Right, I can not think of anything that prevents what you are saying to
> work. I built it this way initially because on my lack of understanding
> of V4L2 (seems we complement each other here :) because I thought we
> needed to keep the QBUF ordering. In the last review you talked me away
> of this misconception but I really didn't took that to the
> implementation.
> 
> If there is no care about ordering, there is no need to receive the
> fence before and we could just do as you say. That makes sense to me.
> We could do it that way but I have one question, maybe a stupid one. :)
> 
> If a specific driver can guarantee the ordering of vb2 buffer, and
> userspace has a way to become aware of that. In this case we will
> receive the out-fence in QBUF knowing the buffer already (it is
> ordered!). Thus we can proceed right away and send it to the next
> driver. Does that makes sense? Is this a optmization we need? In your
> proposal we will have the timeframe between the queueing to the driver
> and buffer_done() to make the out_fence arrive on the next driver. If
> that is sufficient then we can just do as you propose.

If it is ordered, then you can just send the event immediately from the
vb2 qbuf function. But you shouldn't return the out fence in the fence_fd
field.

The fence_fd field can be renamed to in_fence_fd. The field in the event
struct can then be out_fence_fd.

This is much cleaner since the fence_fd field is no longer used for both
in and out fence (that was very confusing!).

Regards,

	Hans

> 
>>
>> It could be that when the out-fence triggers the listener is informed about the
>> associated buffer information, and in that case it makes a bit more sense.
>> Although in that case I don't see the reason for the event. Regardless, this
>> should be documented better.
>>
>> This documentation should also clarify what happens with fences if the streaming
>> stops, either by a STREAMOFF, closing the filehandle or a crash or whatever.
>> Do they signal? What about out-fences not yet associated with a buffer?
> 
> I'll write about that. It will also change if we go with your proposal.
> 
> 	Gustavo
> 

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 14/14] [media] v4l: Document explicit synchronization behaviour
  2017-09-02  8:14       ` Hans Verkuil
@ 2017-09-04 15:44         ` Gustavo Padovan
  0 siblings, 0 replies; 20+ messages in thread
From: Gustavo Padovan @ 2017-09-04 15:44 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: linux-media, Mauro Carvalho Chehab, Shuah Khan, Gustavo Padovan

2017-09-02 Hans Verkuil <hverkuil@xs4all.nl>:

> On 09/01/2017 08:21 PM, Gustavo Padovan wrote:
> > Hi Hans,
> > 
> > 2017-09-01 Hans Verkuil <hverkuil@xs4all.nl>:
> > 
> >> Hi Gustavo,
> >>
> >> I think I concentrate on this last patch first. Once I fully understand this
> >> I can review the code. Remember, it's been a while for me since I last looked
> >> at fences, so forgive me if I ask stupid questions. On the other hand, others
> >> with a similar lack of understanding of fences probably have similar questions,
> >> so it is a good indication where the documentation needs improvement :-)
> > 
> > Please ask as many as you want, those are the best questions. :)
> > 
> >>
> >> On 01/09/17 03:50, Gustavo Padovan wrote:
> >>> From: Gustavo Padovan <gustavo.padovan@collabora.com>
> >>>
> >>> Add section to VIDIOC_QBUF about it
> >>>
> >>> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
> >>> ---q
> >>>  Documentation/media/uapi/v4l/vidioc-qbuf.rst | 30 ++++++++++++++++++++++++++++
> >>>  1 file changed, 30 insertions(+)
> >>>
> >>> diff --git a/Documentation/media/uapi/v4l/vidioc-qbuf.rst b/Documentation/media/uapi/v4l/vidioc-qbuf.rst
> >>> index 1f3612637200..6bd960d3972b 100644
> >>> --- a/Documentation/media/uapi/v4l/vidioc-qbuf.rst
> >>> +++ b/Documentation/media/uapi/v4l/vidioc-qbuf.rst
> >>> @@ -117,6 +117,36 @@ immediately with an ``EAGAIN`` error code when no buffer is available.
> >>>  The struct :c:type:`v4l2_buffer` structure is specified in
> >>>  :ref:`buffer`.
> >>>  
> >>> +Explicit Synchronization
> >>> +------------------------
> >>> +
> >>> +Explicit Synchronization allows us to control the synchronization of
> >>> +shared buffers from userspace by passing fences to the kernel and/or
> >>> +receiving them from it. Fences passed to the kernel are named in-fences and
> >>> +the kernel should wait them to signal before using the buffer, i.e., queueing
> >>> +it to the driver. On the other side, the kernel can create out-fences for the
> >>> +buffers it queues to the drivers, out-fences signal when the driver is
> >>> +finished with buffer, that is the buffer is ready.
> >>
> >> This should add a line explaining that fences are represented by file descriptors.
> > 
> > Okay.
> > 
> >>
> >>> +
> >>> +The in-fences and out-fences are communicated at the ``VIDIOC_QBUF`` ioctl
> >>> +using the ``V4L2_BUF_FLAG_IN_FENCE`` and ``V4L2_BUF_FLAG_OUT_FENCE`` buffer
> >>> +flags and the `fence_fd` field. If an in-fence needs to be passed to the kernel,
> >>> +`fence_fd` should be set to the fence file descriptor number and the
> >>> +``V4L2_BUF_FLAG_IN_FENCE`` should be set as well.
> >>
> >> Is it possible to have both flags at the same time? Or are they mutually exclusive?
> >>
> >> If only V4L2_BUF_FLAG_IN_FENCE is set, then what is the value of fence_fd after
> >> the QBUF call? -1?
> > 
> > Yes, it is -1.
> > 
> >>
> >>> +
> >>> +To get a out-fence back from V4L2 the ``V4L2_BUF_FLAG_OUT_FENCE`` flag should
> >>> +be set and the `fence_fd` field will be returned with the out-fence file
> >>> +descriptor related to the next buffer to be queued internally to the V4L2
> >>> +driver. That means the out-fence may not be associated with the buffer in the
> >>> +current ``VIDIOC_QBUF`` ioctl call because the ordering in which videobuf2 core
> >>> +queues the buffers to the drivers can't be guaranteed. To become aware of the
> >>> +buffer with which the out-fence will be attached the ``V4L2_EVENT_BUF_QUEUED``
> >>> +should be used. It will trigger an event for every buffer queued to the V4L2
> >>> +driver.
> >>
> >> General question: does it even make sense to use an out-fence if you don't know with
> >> what buffer is it associated? I mean, QBUF returns an out fence, but only some
> >> time later are you informed about a buffer being queued. It also looks like userspace
> >> has to keep track of the issued out-fences and the queued buffers and map them
> >> accordingly.
> >>
> >> If the out-fence cannot be used until you know the buffer as well, then wouldn't
> >> it make more sense if the out-fence and the buffer index are both sent by the
> >> event? Of course, in that case the event can only be sent to the owner file handle
> >> of the streaming device node, but that's OK, we have that.
> >>
> >> Setting the OUT_FENCE flag will just cause this event to be sent whenever that
> >> buffer is queued internally.
> >>
> >> Sorry if this just shows a complete lack of understanding of fences on my side,
> >> that's perfectly possible.
> > 
> > Right, I can not think of anything that prevents what you are saying to
> > work. I built it this way initially because on my lack of understanding
> > of V4L2 (seems we complement each other here :) because I thought we
> > needed to keep the QBUF ordering. In the last review you talked me away
> > of this misconception but I really didn't took that to the
> > implementation.
> > 
> > If there is no care about ordering, there is no need to receive the
> > fence before and we could just do as you say. That makes sense to me.
> > We could do it that way but I have one question, maybe a stupid one. :)
> > 
> > If a specific driver can guarantee the ordering of vb2 buffer, and
> > userspace has a way to become aware of that. In this case we will
> > receive the out-fence in QBUF knowing the buffer already (it is
> > ordered!). Thus we can proceed right away and send it to the next
> > driver. Does that makes sense? Is this a optmization we need? In your
> > proposal we will have the timeframe between the queueing to the driver
> > and buffer_done() to make the out_fence arrive on the next driver. If
> > that is sufficient then we can just do as you propose.
> 
> If it is ordered, then you can just send the event immediately from the
> vb2 qbuf function. But you shouldn't return the out fence in the fence_fd
> field.
> 
> The fence_fd field can be renamed to in_fence_fd. The field in the event
> struct can then be out_fence_fd.
> 
> This is much cleaner since the fence_fd field is no longer used for both
> in and out fence (that was very confusing!).

That makes sense. I'll work on a new version with this modification and
send it out as soon as possible. Thanks for reviewing!

Gustavo

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 08/14] [media] v4l: add support to BUF_QUEUED event
  2017-09-01  1:50 ` [PATCH v2 08/14] [media] v4l: add support to BUF_QUEUED event Gustavo Padovan
@ 2017-10-15 21:25   ` Sakari Ailus
  0 siblings, 0 replies; 20+ messages in thread
From: Sakari Ailus @ 2017-10-15 21:25 UTC (permalink / raw)
  To: Gustavo Padovan
  Cc: linux-media, Hans Verkuil, Mauro Carvalho Chehab, Shuah Khan,
	Gustavo Padovan

Hi Gustavo,

On Thu, Aug 31, 2017 at 10:50:35PM -0300, Gustavo Padovan wrote:
> From: Gustavo Padovan <gustavo.padovan@collabora.com>
> 
> Implement the needed pieces to let userspace subscribe for
> V4L2_EVENT_BUF_QUEUED events. Videobuf2 will queue the event for the
> DQEVENT ioctl.
> 
> v3:	- Do not call v4l2 event API from vb2 (Mauro)
> 
> v2:	- Use VIDEO_MAX_FRAME to allocate room for events at
> 	v4l2_event_subscribe() (Hans)
> 
> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com>
> ---
>  drivers/media/v4l2-core/v4l2-ctrls.c     |  6 +++++-
>  drivers/media/v4l2-core/videobuf2-core.c |  2 ++
>  drivers/media/v4l2-core/videobuf2-v4l2.c | 13 +++++++++++++
>  3 files changed, 20 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
> index dd1db678718c..17d4b9e3eec6 100644
> --- a/drivers/media/v4l2-core/v4l2-ctrls.c
> +++ b/drivers/media/v4l2-core/v4l2-ctrls.c
> @@ -3438,8 +3438,12 @@ EXPORT_SYMBOL(v4l2_ctrl_log_status);
>  int v4l2_ctrl_subscribe_event(struct v4l2_fh *fh,
>  				const struct v4l2_event_subscription *sub)
>  {
> -	if (sub->type == V4L2_EVENT_CTRL)
> +	switch (sub->type) {
> +	case V4L2_EVENT_CTRL:
>  		return v4l2_event_subscribe(fh, sub, 0, &v4l2_ctrl_sub_ev_ops);
> +	case V4L2_EVENT_BUF_QUEUED:
> +		return v4l2_event_subscribe(fh, sub, VIDEO_MAX_FRAME, NULL);

While I think this is probably the correct place to add the event
subscription handling, the name of the function no longer corresponds what
it does, nor it belongs to v4l2-ctrls.c.

v4l2_ctrl_subscribe_event() is also used for subscribing control events on
sub-devices. BUF_QUEUED events will be available only on video nodes.

BUF_QUEUED events presumably should be availble on all video nodes that
support V4L2_CAP_STREAMING capability. Perhaps this could be handled by
moving v4l2_ctrl_subscribe_event() to v4l2-event.c and renaming it e.g.
v4l2_event_subscribe_v4l2(), for these events originate from specific
conditions the V4L2 framework is aware of.
v4l2_ctrl_subdev_subscribe_event() handling needs to be addressed as well.

A separate patch would be nice. 

> +	}
>  	return -EINVAL;
>  }
>  EXPORT_SYMBOL(v4l2_ctrl_subscribe_event);
> diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
> index b19c1bc4b083..bbbae0eed567 100644
> --- a/drivers/media/v4l2-core/videobuf2-core.c
> +++ b/drivers/media/v4l2-core/videobuf2-core.c
> @@ -1231,6 +1231,8 @@ static void __enqueue_in_driver(struct vb2_buffer *vb)
>  	trace_vb2_buf_queue(q, vb);
>  
>  	call_void_vb_qop(vb, buf_queue, vb);
> +
> +	call_void_bufop(q, buffer_queued, vb);
>  }
>  
>  static int __buf_prepare(struct vb2_buffer *vb, const void *pb)
> diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
> index 8c322cd1b346..1c93bfedaffc 100644
> --- a/drivers/media/v4l2-core/videobuf2-v4l2.c
> +++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
> @@ -138,6 +138,18 @@ static void __copy_timestamp(struct vb2_buffer *vb, const void *pb)
>  	}
>  };
>  
> +static void __buffer_queued(struct vb2_buffer *vb)
> +{
> +	struct video_device *vdev = to_video_device(vb->vb2_queue->dev);
> +	struct v4l2_event event;
> +
> +	memset(&event, 0, sizeof(event));
> +	event.type = V4L2_EVENT_BUF_QUEUED;
> +	event.u.buf_queued.index = vb->index;
> +
> +	v4l2_event_queue(vdev, &event);
> +}
> +
>  static void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
>  {
>  	static bool check_once;
> @@ -455,6 +467,7 @@ static const struct vb2_buf_ops v4l2_buf_ops = {
>  	.fill_user_buffer	= __fill_v4l2_buffer,
>  	.fill_vb2_buffer	= __fill_vb2_buffer,
>  	.copy_timestamp		= __copy_timestamp,
> +	.buffer_queued		= __buffer_queued,
>  };
>  
>  /**

-- 
Kind regards,

Sakari Ailus
e-mail: sakari.ailus@iki.fi

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2017-10-15 21:25 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-09-01  1:50 [PATCH v2 00/14] V4L2 Explicit Synchronization support Gustavo Padovan
2017-09-01  1:50 ` [PATCH v2 01/14] [media] vb2: add explicit fence user API Gustavo Padovan
2017-09-01  1:50 ` [PATCH v2 02/14] [media] vb2: check earlier if stream can be started Gustavo Padovan
2017-09-01  1:50 ` [PATCH v2 03/14] [media] vb2: add in-fence support to QBUF Gustavo Padovan
2017-09-01  1:50 ` [PATCH v2 04/14] [media] uvc: enable subscriptions to other events Gustavo Padovan
2017-09-01  1:50 ` [PATCH v2 05/14] [media] vivid: assign the specific device to the vb2_queue->dev Gustavo Padovan
2017-09-01  1:50 ` [PATCH v2 06/14] [media] v4l: add V4L2_EVENT_BUF_QUEUED event Gustavo Padovan
2017-09-01  1:50 ` [PATCH v2 07/14] [media] vb2: add .buffer_queued() to notify queueing in the driver Gustavo Padovan
2017-09-01  1:50 ` [PATCH v2 08/14] [media] v4l: add support to BUF_QUEUED event Gustavo Padovan
2017-10-15 21:25   ` Sakari Ailus
2017-09-01  1:50 ` [PATCH v2 09/14] [media] vb2: add 'ordered' property to queues Gustavo Padovan
2017-09-01  1:50 ` [PATCH v2 10/14] [media] vivid: mark vivid queues as ordered Gustavo Padovan
2017-09-01  1:50 ` [PATCH v2 11/14] [media] vb2: add videobuf2 dma-buf fence helpers Gustavo Padovan
2017-09-01  1:50 ` [PATCH v2 12/14] [media] vb2: add infrastructure to support out-fences Gustavo Padovan
2017-09-01  1:50 ` [PATCH v2 13/14] [media] vb2: add out-fence support to QBUF Gustavo Padovan
2017-09-01  1:50 ` [PATCH v2 14/14] [media] v4l: Document explicit synchronization behaviour Gustavo Padovan
2017-09-01 12:50   ` Hans Verkuil
2017-09-01 18:21     ` Gustavo Padovan
2017-09-02  8:14       ` Hans Verkuil
2017-09-04 15:44         ` Gustavo Padovan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).