All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv8 00/26] Integration of videobuf2 with DMABUF
@ 2012-08-14 15:34 Tomasz Stanislawski
  2012-08-14 15:34 ` [PATCHv8 01/26] v4l: Add DMABUF as a memory type Tomasz Stanislawski
                   ` (25 more replies)
  0 siblings, 26 replies; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-08-14 15:34 UTC (permalink / raw)
  To: linux-media, dri-devel
  Cc: airlied, m.szyprowski, t.stanislaws, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, hverkuil, remi, subashrp,
	mchehab, g.liakhovetski, dmitriyz, s.nawrocki, k.debski

Hello everyone,
This patchset adds support for DMABUF [2] importing and exporting to V4L2
stack.  The importer and exporter part were merged because DMA mapping
redesign [3] was scheduled for merge to mainline.

v8:
- rebased on 3.6-rc1
- merged importer and exporter patchsets
- fixed missing fields in v4l2_plane32 and v4l2_buffer32 structs
- fixed typos/style in documentation
- significant reduction of warnings from checkpatch.pl
- fixed STREAMOFF issues reported by Dima Zavin [4] by adding
  __vb2_dqbuf helper to vb2-core
- DC fails if userptr is not correctly aligned
- add support for DMA attributes in DC
- add support for buffers with no kernel mapping
- add reference counting on device from allocator context
- dummy support for mmap
- use dma_get_sgtable, drop vb2_dc_kaddr_to_pages hack and
  vb2_dc_get_base_sgt helper

v7:
- support for V4L2_MEMORY_DMABUF in v4l2-compact-ioctl32.c
- cosmetic fixes to the documentation
- added importing for vmalloc because vmap support in dmabuf for 3.5
  was pull-requested
- support for dmabuf importing for VIVI
- resurrect allocation of dma-contig context
- remove reference of alloc_ctx in dma-contig buffer
- use sg_alloc_table_from_pages
- fix DMA scatterlist calls to use orig_nents instead of nents
- fix memleak in vb2_dc_sgt_foreach_page (use orig_nents instead of nents)

v6:
- fixed missing entry in v4l2_memory_names
- fixed a bug occuring after get_user_pages failure
- fixed a bug caused by using invalid vma for get_user_pages
- prepare/finish no longer call dma_sync for dmabuf buffers

v5:
- removed change of importer/exporter behaviour
- fixes vb2_dc_pages_to_sgt basing on Laurent's hints
- changed pin/unpin words to lock/unlock in Doc

v4:
- rebased on mainline 3.4-rc2
- included missing importing support for s5p-fimc and s5p-tv
- added patch for changing map/unmap for importers
- fixes to Documentation part
- coding style fixes
- pairing {map/unmap}_dmabuf in vb2-core
- fixing variable types and semantic of arguments in videobufb2-dma-contig.c

v3:
- rebased on mainline 3.4-rc1
- split 'code refactor' patch to multiple smaller patches
- squashed fixes to Sumit's patches
- patchset is no longer dependant on 'DMA mapping redesign'
- separated path for handling IO and non-IO mappings
- add documentation for DMABUF importing to V4L
- removed all DMABUF exporter related code
- removed usage of dma_get_pages extension

v2:
- extended VIDIOC_EXPBUF argument from integer memoffset to struct
  v4l2_exportbuffer
- added patch that breaks DMABUF spec on (un)map_atachment callcacks but allows
  to work with existing implementation of DMABUF prime in DRM
- all dma-contig code refactoring patches were squashed
- bugfixes

v1: List of changes since [1].
- support for DMA api extension dma_get_pages, the function is used to retrieve
  pages used to create DMA mapping.
- small fixes/code cleanup to videobuf2
- added prepare and finish callbacks to vb2 allocators, it is used keep
  consistency between dma-cpu acess to the memory (by Marek Szyprowski)
- support for exporting of DMABUF buffer in V4L2 and Videobuf2, originated from
  [3].
- support for dma-buf exporting in vb2-dma-contig allocator
- support for DMABUF for s5p-tv and s5p-fimc (capture interface) drivers,
  originated from [3]
- changed handling for userptr buffers (by Marek Szyprowski, Andrzej
  Pietrasiewicz)
- let mmap method to use dma_mmap_writecombine call (by Marek Szyprowski)

[1] http://thread.gmane.org/gmane.linux.drivers.video-input-infrastructure/42966/focus=42968
[2] https://lkml.org/lkml/2011/12/26/29
[3] http://thread.gmane.org/gmane.linux.kernel.cross-arch/12819
[4] http://article.gmane.org/gmane.linux.drivers.video-input-infrastructure/49700

Laurent Pinchart (2):
  v4l: vb2-dma-contig: Shorten vb2_dma_contig prefix to vb2_dc
  v4l: vb2-dma-contig: Reorder functions

Marek Szyprowski (5):
  v4l: vb2: add prepare/finish callbacks to allocators
  v4l: vb2-dma-contig: add prepare/finish to dma-contig allocator
  v4l: vb2-dma-contig: let mmap method to use dma_mmap_coherent call
  media: vb2: fail if user ptr buffer is not correctly aligned
  v4l: vb2: add support for DMA_ATTR_NO_KERNEL_MAPPING

Sumit Semwal (4):
  v4l: Add DMABUF as a memory type
  v4l: vb2: add support for shared buffer (dma_buf)
  v4l: vb: remove warnings about MEMORY_DMABUF
  v4l: vb2-dma-contig: add support for dma_buf importing

Tomasz Stanislawski (15):
  Documentation: media: description of DMABUF importing in V4L2
  v4l: vb2-dma-contig: remove reference of alloc_ctx from a buffer
  v4l: vb2-dma-contig: add support for scatterlist in userptr mode
  v4l: vb2-vmalloc: add support for dmabuf importing
  v4l: vivi: support for dmabuf importing
  v4l: s5p-tv: mixer: support for dmabuf importing
  v4l: s5p-fimc: support for dmabuf importing
  Documentation: media: description of DMABUF exporting in V4L2
  v4l: add buffer exporting via dmabuf
  v4l: vb2: add buffer exporting via dmabuf
  v4l: vb2-dma-contig: add support for DMABUF exporting
  v4l: vb2-dma-contig: add reference counting for a device from
    allocator context
  v4l: s5p-fimc: support for dmabuf exporting
  v4l: s5p-tv: mixer: support for dmabuf exporting
  v4l: s5p-mfc: support for dmabuf exporting

 Documentation/DocBook/media/v4l/compat.xml         |    7 +
 Documentation/DocBook/media/v4l/io.xml             |  183 +++++
 Documentation/DocBook/media/v4l/v4l2.xml           |    1 +
 .../DocBook/media/v4l/vidioc-create-bufs.xml       |    3 +-
 Documentation/DocBook/media/v4l/vidioc-expbuf.xml  |  223 ++++++
 Documentation/DocBook/media/v4l/vidioc-qbuf.xml    |   15 +
 Documentation/DocBook/media/v4l/vidioc-reqbufs.xml |   47 +-
 drivers/media/video/Kconfig                        |    1 +
 drivers/media/video/atmel-isi.c                    |    2 +-
 drivers/media/video/blackfin/bfin_capture.c        |    2 +-
 drivers/media/video/marvell-ccic/mcam-core.c       |    3 +-
 drivers/media/video/mx2_camera.c                   |    2 +-
 drivers/media/video/mx2_emmaprp.c                  |    2 +-
 drivers/media/video/mx3_camera.c                   |    2 +-
 drivers/media/video/s5p-fimc/Kconfig               |    1 +
 drivers/media/video/s5p-fimc/fimc-capture.c        |   11 +-
 drivers/media/video/s5p-fimc/fimc-core.c           |    2 +-
 drivers/media/video/s5p-fimc/fimc-lite.c           |    2 +-
 drivers/media/video/s5p-g2d/g2d.c                  |    2 +-
 drivers/media/video/s5p-jpeg/jpeg-core.c           |    2 +-
 drivers/media/video/s5p-mfc/s5p_mfc.c              |    5 +-
 drivers/media/video/s5p-mfc/s5p_mfc_dec.c          |   18 +
 drivers/media/video/s5p-mfc/s5p_mfc_enc.c          |   18 +
 drivers/media/video/s5p-tv/Kconfig                 |    1 +
 drivers/media/video/s5p-tv/mixer_video.c           |   14 +-
 drivers/media/video/sh_mobile_ceu_camera.c         |    2 +-
 drivers/media/video/v4l2-compat-ioctl32.c          |   19 +
 drivers/media/video/v4l2-dev.c                     |    1 +
 drivers/media/video/v4l2-ioctl.c                   |   16 +
 drivers/media/video/videobuf-core.c                |    4 +
 drivers/media/video/videobuf2-core.c               |  275 +++++++-
 drivers/media/video/videobuf2-dma-contig.c         |  719 ++++++++++++++++++--
 drivers/media/video/videobuf2-memops.c             |   40 --
 drivers/media/video/videobuf2-vmalloc.c            |   56 ++
 drivers/media/video/vivi.c                         |    2 +-
 drivers/staging/media/dt3155v4l/dt3155v4l.c        |    2 +-
 include/linux/videodev2.h                          |   33 +
 include/media/v4l2-ioctl.h                         |    2 +
 include/media/videobuf2-core.h                     |   36 +
 include/media/videobuf2-dma-contig.h               |    4 +-
 include/media/videobuf2-memops.h                   |    5 -
 41 files changed, 1639 insertions(+), 146 deletions(-)
 create mode 100644 Documentation/DocBook/media/v4l/vidioc-expbuf.xml

-- 
1.7.9.5


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

* [PATCHv8 01/26] v4l: Add DMABUF as a memory type
  2012-08-14 15:34 [PATCHv8 00/26] Integration of videobuf2 with DMABUF Tomasz Stanislawski
@ 2012-08-14 15:34 ` Tomasz Stanislawski
  2012-08-22 10:27   ` Hans Verkuil
  2012-08-14 15:34 ` [PATCHv8 02/26] Documentation: media: description of DMABUF importing in V4L2 Tomasz Stanislawski
                   ` (24 subsequent siblings)
  25 siblings, 1 reply; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-08-14 15:34 UTC (permalink / raw)
  To: linux-media, dri-devel
  Cc: airlied, m.szyprowski, t.stanislaws, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, hverkuil, remi, subashrp,
	mchehab, g.liakhovetski, dmitriyz, s.nawrocki, k.debski,
	Sumit Semwal

From: Sumit Semwal <sumit.semwal@ti.com>

Adds DMABUF memory type to v4l framework. Also adds the related file
descriptor in v4l2_plane and v4l2_buffer.

Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
   [original work in the PoC for buffer sharing]
Signed-off-by: Sumit Semwal <sumit.semwal@ti.com>
Signed-off-by: Sumit Semwal <sumit.semwal@linaro.org>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/video/v4l2-compat-ioctl32.c |   18 ++++++++++++++++++
 drivers/media/video/v4l2-ioctl.c          |    1 +
 include/linux/videodev2.h                 |    7 +++++++
 3 files changed, 26 insertions(+)

diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c
index 9ebd5c5..a2e0549 100644
--- a/drivers/media/video/v4l2-compat-ioctl32.c
+++ b/drivers/media/video/v4l2-compat-ioctl32.c
@@ -304,6 +304,7 @@ struct v4l2_plane32 {
 	union {
 		__u32		mem_offset;
 		compat_long_t	userptr;
+		__u32		fd;
 	} m;
 	__u32			data_offset;
 	__u32			reserved[11];
@@ -325,6 +326,7 @@ struct v4l2_buffer32 {
 		__u32           offset;
 		compat_long_t   userptr;
 		compat_caddr_t  planes;
+		__u32		fd;
 	} m;
 	__u32			length;
 	__u32			reserved2;
@@ -348,6 +350,9 @@ static int get_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32,
 		up_pln = compat_ptr(p);
 		if (put_user((unsigned long)up_pln, &up->m.userptr))
 			return -EFAULT;
+	} else if (memory == V4L2_MEMORY_DMABUF) {
+		if (copy_in_user(&up->m.fd, &up32->m.fd, sizeof(int)))
+			return -EFAULT;
 	} else {
 		if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset,
 					sizeof(__u32)))
@@ -371,6 +376,11 @@ static int put_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32,
 		if (copy_in_user(&up32->m.mem_offset, &up->m.mem_offset,
 					sizeof(__u32)))
 			return -EFAULT;
+	/* For DMABUF, driver might've set up the fd, so copy it back. */
+	if (memory == V4L2_MEMORY_DMABUF)
+		if (copy_in_user(&up32->m.fd, &up->m.fd,
+					sizeof(int)))
+			return -EFAULT;
 
 	return 0;
 }
@@ -453,6 +463,10 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user
 			if (get_user(kp->m.offset, &up->m.offset))
 				return -EFAULT;
 			break;
+		case V4L2_MEMORY_DMABUF:
+			if (get_user(kp->m.fd, &up->m.fd))
+				return -EFAULT;
+			break;
 		}
 	}
 
@@ -517,6 +531,10 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user
 			if (put_user(kp->m.offset, &up->m.offset))
 				return -EFAULT;
 			break;
+		case V4L2_MEMORY_DMABUF:
+			if (put_user(kp->m.fd, &up->m.fd))
+				return -EFAULT;
+			break;
 		}
 	}
 
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
index 6bc47fc..dffd3c9 100644
--- a/drivers/media/video/v4l2-ioctl.c
+++ b/drivers/media/video/v4l2-ioctl.c
@@ -155,6 +155,7 @@ static const char *v4l2_memory_names[] = {
 	[V4L2_MEMORY_MMAP]    = "mmap",
 	[V4L2_MEMORY_USERPTR] = "userptr",
 	[V4L2_MEMORY_OVERLAY] = "overlay",
+	[V4L2_MEMORY_DMABUF] = "dmabuf",
 };
 
 #define prt_names(a, arr) ((((a) >= 0) && ((a) < ARRAY_SIZE(arr))) ? \
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 7a147c8..7f918dc 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -186,6 +186,7 @@ enum v4l2_memory {
 	V4L2_MEMORY_MMAP             = 1,
 	V4L2_MEMORY_USERPTR          = 2,
 	V4L2_MEMORY_OVERLAY          = 3,
+	V4L2_MEMORY_DMABUF           = 4,
 };
 
 /* see also http://vektor.theorem.ca/graphics/ycbcr/ */
@@ -596,6 +597,8 @@ struct v4l2_requestbuffers {
  *			should be passed to mmap() called on the video node)
  * @userptr:		when memory is V4L2_MEMORY_USERPTR, a userspace pointer
  *			pointing to this plane
+ * @fd:			when memory is V4L2_MEMORY_DMABUF, a userspace file
+ *			descriptor associated with this plane
  * @data_offset:	offset in the plane to the start of data; usually 0,
  *			unless there is a header in front of the data
  *
@@ -610,6 +613,7 @@ struct v4l2_plane {
 	union {
 		__u32		mem_offset;
 		unsigned long	userptr;
+		int		fd;
 	} m;
 	__u32			data_offset;
 	__u32			reserved[11];
@@ -634,6 +638,8 @@ struct v4l2_plane {
  *		(or a "cookie" that should be passed to mmap() as offset)
  * @userptr:	for non-multiplanar buffers with memory == V4L2_MEMORY_USERPTR;
  *		a userspace pointer pointing to this buffer
+ * @fd:		for non-multiplanar buffers with memory == V4L2_MEMORY_DMABUF;
+ *		a userspace file descriptor associated with this buffer
  * @planes:	for multiplanar buffers; userspace pointer to the array of plane
  *		info structs for this buffer
  * @length:	size in bytes of the buffer (NOT its payload) for single-plane
@@ -660,6 +666,7 @@ struct v4l2_buffer {
 		__u32           offset;
 		unsigned long   userptr;
 		struct v4l2_plane *planes;
+		int		fd;
 	} m;
 	__u32			length;
 	__u32			reserved2;
-- 
1.7.9.5


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

* [PATCHv8 02/26] Documentation: media: description of DMABUF importing in V4L2
  2012-08-14 15:34 [PATCHv8 00/26] Integration of videobuf2 with DMABUF Tomasz Stanislawski
  2012-08-14 15:34 ` [PATCHv8 01/26] v4l: Add DMABUF as a memory type Tomasz Stanislawski
@ 2012-08-14 15:34 ` Tomasz Stanislawski
  2012-08-22 10:47   ` Hans Verkuil
  2012-08-14 15:34 ` [PATCHv8 03/26] v4l: vb2: add support for shared buffer (dma_buf) Tomasz Stanislawski
                   ` (23 subsequent siblings)
  25 siblings, 1 reply; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-08-14 15:34 UTC (permalink / raw)
  To: linux-media, dri-devel
  Cc: airlied, m.szyprowski, t.stanislaws, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, hverkuil, remi, subashrp,
	mchehab, g.liakhovetski, dmitriyz, s.nawrocki, k.debski,
	linux-doc

This patch adds description and usage examples for importing
DMABUF file descriptor in V4L2.

Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
CC: linux-doc@vger.kernel.org
---
 Documentation/DocBook/media/v4l/compat.xml         |    4 +
 Documentation/DocBook/media/v4l/io.xml             |  180 ++++++++++++++++++++
 .../DocBook/media/v4l/vidioc-create-bufs.xml       |    3 +-
 Documentation/DocBook/media/v4l/vidioc-qbuf.xml    |   15 ++
 Documentation/DocBook/media/v4l/vidioc-reqbufs.xml |   47 ++---
 5 files changed, 226 insertions(+), 23 deletions(-)

diff --git a/Documentation/DocBook/media/v4l/compat.xml b/Documentation/DocBook/media/v4l/compat.xml
index 98e8d08..ff45330 100644
--- a/Documentation/DocBook/media/v4l/compat.xml
+++ b/Documentation/DocBook/media/v4l/compat.xml
@@ -2605,6 +2605,10 @@ ioctls.</para>
         <listitem>
 	  <para>Support for frequency band enumeration: &VIDIOC-ENUM-FREQ-BANDS; ioctl.</para>
         </listitem>
+        <listitem>
+	  <para>Importing DMABUF file descriptors as a new IO method described
+	  in <xref linkend="dmabuf" />.</para>
+        </listitem>
       </itemizedlist>
     </section>
 
diff --git a/Documentation/DocBook/media/v4l/io.xml b/Documentation/DocBook/media/v4l/io.xml
index 1885cc0..98253ee 100644
--- a/Documentation/DocBook/media/v4l/io.xml
+++ b/Documentation/DocBook/media/v4l/io.xml
@@ -472,6 +472,163 @@ rest should be evident.</para>
       </footnote></para>
   </section>
 
+  <section id="dmabuf">
+    <title>Streaming I/O (DMA buffer importing)</title>
+
+    <note>
+      <title>Experimental</title>
+      <para>This is an <link linkend="experimental"> experimental </link>
+      interface and may change in the future.</para>
+    </note>
+
+<para>The DMABUF framework provides a generic mean for sharing buffers between
+ multiple devices. Device drivers that support DMABUF can export a DMA buffer
+to userspace as a file descriptor (known as the exporter role), import a DMA
+buffer from userspace using a file descriptor previously exported for a
+different or the same device (known as the importer role), or both. This
+section describes the DMABUF importer role API in V4L2.</para>
+
+<para>Input and output devices support the streaming I/O method when the
+<constant>V4L2_CAP_STREAMING</constant> flag in the
+<structfield>capabilities</structfield> field of &v4l2-capability; returned by
+the &VIDIOC-QUERYCAP; ioctl is set. Whether importing DMA buffers through
+DMABUF file descriptors is supported is determined by calling the
+&VIDIOC-REQBUFS; ioctl with the memory type set to
+<constant>V4L2_MEMORY_DMABUF</constant>.</para>
+
+    <para>This I/O method is dedicated for sharing DMA buffers between V4L and
+other APIs.  Buffers (planes) are allocated by a driver on behalf of the
+application, and exported to the application as file descriptors using an API
+specific to the allocator driver.  Only those file descriptor are exchanged,
+these files and meta-information are passed in &v4l2-buffer; (or in
+&v4l2-plane; in the multi-planar API case).  The driver must be switched into
+DMABUF I/O mode by calling the &VIDIOC-REQBUFS; with the desired buffer type.
+No buffers (planes) are allocated beforehand, consequently they are not indexed
+and cannot be queried like mapped buffers with the
+<constant>VIDIOC_QUERYBUF</constant> ioctl.</para>
+
+    <example>
+      <title>Initiating streaming I/O with DMABUF file descriptors</title>
+
+      <programlisting>
+&v4l2-requestbuffers; reqbuf;
+
+memset (&amp;reqbuf, 0, sizeof (reqbuf));
+reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+reqbuf.memory = V4L2_MEMORY_DMABUF;
+reqbuf.count = 1;
+
+if (ioctl (fd, &VIDIOC-REQBUFS;, &amp;reqbuf) == -1) {
+	if (errno == EINVAL)
+		printf ("Video capturing or DMABUF streaming is not supported\n");
+	else
+		perror ("VIDIOC_REQBUFS");
+
+	exit (EXIT_FAILURE);
+}
+      </programlisting>
+    </example>
+
+    <para>Buffer (plane) file descriptor is passed on the fly with the
+&VIDIOC-QBUF; ioctl. In case of multiplanar buffers, every plane can be
+associated with a different DMABUF descriptor. Although buffers are commonly
+cycled, applications can pass a different DMABUF descriptor at each
+<constant>VIDIOC_QBUF</constant> call.</para>
+
+    <example>
+      <title>Queueing DMABUF using single plane API</title>
+
+      <programlisting>
+int buffer_queue(int v4lfd, int index, int dmafd)
+{
+	&v4l2-buffer; buf;
+
+	memset(&amp;buf, 0, sizeof buf);
+	buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	buf.memory = V4L2_MEMORY_DMABUF;
+	buf.index = index;
+	buf.m.fd = dmafd;
+
+	if (ioctl (v4lfd, &VIDIOC-QBUF;, &amp;buf) == -1) {
+		perror ("VIDIOC_QBUF");
+		return -1;
+	}
+
+	return 0;
+}
+      </programlisting>
+    </example>
+
+    <example>
+      <title>Queueing DMABUF using multi plane API</title>
+
+      <programlisting>
+int buffer_queue_mp(int v4lfd, int index, int dmafd[], int n_planes)
+{
+	&v4l2-buffer; buf;
+	&v4l2-plane; planes[VIDEO_MAX_PLANES];
+	int i;
+
+	memset(&amp;buf, 0, sizeof buf);
+	buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+	buf.memory = V4L2_MEMORY_DMABUF;
+	buf.index = index;
+	buf.m.planes = planes;
+	buf.length = n_planes;
+
+	memset(&amp;planes, 0, sizeof planes);
+
+	for (i = 0; i &lt; n_planes; ++i)
+		buf.m.planes[i].m.fd = dmafd[i];
+
+	if (ioctl (v4lfd, &VIDIOC-QBUF;, &amp;buf) == -1) {
+		perror ("VIDIOC_QBUF");
+		return -1;
+	}
+
+	return 0;
+}
+      </programlisting>
+    </example>
+
+    <para>Filled or displayed buffers are dequeued with the
+&VIDIOC-DQBUF; ioctl. The driver can unlock the buffer at any
+time between the completion of the DMA and this ioctl. The memory is
+also unlocked when &VIDIOC-STREAMOFF; is called, &VIDIOC-REQBUFS;, or
+when the device is closed.</para>
+
+    <para>For capturing applications it is customary to enqueue a
+number of empty buffers, to start capturing and enter the read loop.
+Here the application waits until a filled buffer can be dequeued, and
+re-enqueues the buffer when the data is no longer needed. Output
+applications fill and enqueue buffers, when enough buffers are stacked
+up output is started. In the write loop, when the application
+runs out of free buffers it must wait until an empty buffer can be
+dequeued and reused. Two methods exist to suspend execution of the
+application until one or more buffers can be dequeued. By default
+<constant>VIDIOC_DQBUF</constant> blocks when no buffer is in the
+outgoing queue. When the <constant>O_NONBLOCK</constant> flag was
+given to the &func-open; function, <constant>VIDIOC_DQBUF</constant>
+returns immediately with an &EAGAIN; when no buffer is available. The
+&func-select; or &func-poll; function are always available.</para>
+
+    <para>To start and stop capturing or output applications call the
+&VIDIOC-STREAMON; and &VIDIOC-STREAMOFF; ioctls. Note that
+<constant>VIDIOC_STREAMOFF</constant> removes all buffers from both queues and
+unlocks all buffers as a side effect. Since there is no notion of doing
+anything "now" on a multitasking system, if an application needs to synchronize
+with another event it should examine the &v4l2-buffer;
+<structfield>timestamp</structfield> of captured buffers, or set the field
+before enqueuing buffers for output.</para>
+
+    <para>Drivers implementing DMABUF importing I/O must support the
+<constant>VIDIOC_REQBUFS</constant>, <constant>VIDIOC_QBUF</constant>,
+<constant>VIDIOC_DQBUF</constant>, <constant>VIDIOC_STREAMON</constant> and
+<constant>VIDIOC_STREAMOFF</constant> ioctls, and the
+<function>select()</function> and <function>poll()</function> functions.</para>
+
+  </section>
+
   <section id="async">
     <title>Asynchronous I/O</title>
 
@@ -673,6 +830,14 @@ memory, set by the application. See <xref linkend="userp" /> for details.
 	    <structname>v4l2_buffer</structname> structure.</entry>
 	  </row>
 	  <row>
+	    <entry></entry>
+	    <entry>int</entry>
+	    <entry><structfield>fd</structfield></entry>
+	    <entry>For the single-plane API and when
+<structfield>memory</structfield> is <constant>V4L2_MEMORY_DMABUF</constant> this
+is the file descriptor associated with a DMABUF buffer.</entry>
+	  </row>
+	  <row>
 	    <entry>__u32</entry>
 	    <entry><structfield>length</structfield></entry>
 	    <entry></entry>
@@ -746,6 +911,15 @@ should set this to 0.</entry>
 	      </entry>
 	  </row>
 	  <row>
+	    <entry></entry>
+	    <entry>int</entry>
+	    <entry><structfield>fd</structfield></entry>
+	    <entry>When the memory type in the containing &v4l2-buffer; is
+		<constant>V4L2_MEMORY_DMABUF</constant>, this is a file
+		descriptor associated with a DMABUF buffer, similar to the
+		<structfield>fd</structfield> field in &v4l2-buffer;.</entry>
+	  </row>
+	  <row>
 	    <entry>__u32</entry>
 	    <entry><structfield>data_offset</structfield></entry>
 	    <entry></entry>
@@ -973,6 +1147,12 @@ pointer</link> I/O.</entry>
 	    <entry>3</entry>
 	    <entry>[to do]</entry>
 	  </row>
+	  <row>
+	    <entry><constant>V4L2_MEMORY_DMABUF</constant></entry>
+	    <entry>4</entry>
+	    <entry>The buffer is used for <link linkend="dmabuf">DMA shared
+buffer</link> I/O.</entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>
diff --git a/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml b/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
index a8cda1a..1125468 100644
--- a/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
@@ -109,7 +109,8 @@ information.</para>
 	    <entry>__u32</entry>
 	    <entry><structfield>memory</structfield></entry>
 	    <entry>Applications set this field to
-<constant>V4L2_MEMORY_MMAP</constant> or
+<constant>V4L2_MEMORY_MMAP</constant>,
+<constant>V4L2_MEMORY_DMABUF</constant> or
 <constant>V4L2_MEMORY_USERPTR</constant>. See <xref linkend="v4l2-memory"
 /></entry>
 	  </row>
diff --git a/Documentation/DocBook/media/v4l/vidioc-qbuf.xml b/Documentation/DocBook/media/v4l/vidioc-qbuf.xml
index 77ff5be..436d21c 100644
--- a/Documentation/DocBook/media/v4l/vidioc-qbuf.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-qbuf.xml
@@ -109,6 +109,21 @@ they cannot be swapped out to disk. Buffers remain locked until
 dequeued, until the &VIDIOC-STREAMOFF; or &VIDIOC-REQBUFS; ioctl is
 called, or until the device is closed.</para>
 
+    <para>To enqueue a <link linkend="dmabuf">DMABUF</link> buffer applications
+set the <structfield>memory</structfield> field to
+<constant>V4L2_MEMORY_DMABUF</constant> and the <structfield>m.fd</structfield>
+field to a file descriptor associated with a DMABUF buffer. When the
+multi-planar API is used <structfield>m.fd</structfield> of the passed array of
+&v4l2-plane; have to be used instead. When <constant>VIDIOC_QBUF</constant> is
+called with a pointer to this structure the driver sets the
+<constant>V4L2_BUF_FLAG_QUEUED</constant> flag and clears the
+<constant>V4L2_BUF_FLAG_MAPPED</constant> and
+<constant>V4L2_BUF_FLAG_DONE</constant> flags in the
+<structfield>flags</structfield> field, or it returns an error code.  This
+ioctl locks the buffer. Buffers remain locked until dequeued, until the
+&VIDIOC-STREAMOFF; or &VIDIOC-REQBUFS; ioctl is called, or until the device is
+closed.</para>
+
     <para>Applications call the <constant>VIDIOC_DQBUF</constant>
 ioctl to dequeue a filled (capturing) or displayed (output) buffer
 from the driver's outgoing queue. They just set the
diff --git a/Documentation/DocBook/media/v4l/vidioc-reqbufs.xml b/Documentation/DocBook/media/v4l/vidioc-reqbufs.xml
index d7c9505..20f4323 100644
--- a/Documentation/DocBook/media/v4l/vidioc-reqbufs.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-reqbufs.xml
@@ -48,28 +48,30 @@
   <refsect1>
     <title>Description</title>
 
-    <para>This ioctl is used to initiate <link linkend="mmap">memory
-mapped</link> or <link linkend="userp">user pointer</link>
-I/O. Memory mapped buffers are located in device memory and must be
-allocated with this ioctl before they can be mapped into the
-application's address space. User buffers are allocated by
-applications themselves, and this ioctl is merely used to switch the
-driver into user pointer I/O mode and to setup some internal structures.</para>
+<para>This ioctl is used to initiate <link linkend="mmap">memory mapped</link>,
+<link linkend="userp">user pointer</link> or <link
+linkend="dmabuf">DMABUF</link> based I/O.  Memory mapped buffers are located in
+device memory and must be allocated with this ioctl before they can be mapped
+into the application's address space. User buffers are allocated by
+applications themselves, and this ioctl is merely used to switch the driver
+into user pointer I/O mode and to setup some internal structures.
+Similarly, DMABUF buffers are allocated by applications through a device
+driver, and this ioctl only configures the driver into DMABUF I/O mode without
+performing any direct allocation.</para>
 
-    <para>To allocate device buffers applications initialize all
-fields of the <structname>v4l2_requestbuffers</structname> structure.
-They set the <structfield>type</structfield> field to the respective
-stream or buffer type, the <structfield>count</structfield> field to
-the desired number of buffers, <structfield>memory</structfield>
-must be set to the requested I/O method and the <structfield>reserved</structfield> array
-must be zeroed. When the ioctl
-is called with a pointer to this structure the driver will attempt to allocate
-the requested number of buffers and it stores the actual number
-allocated in the <structfield>count</structfield> field. It can be
-smaller than the number requested, even zero, when the driver runs out
-of free memory. A larger number is also possible when the driver requires
-more buffers to function correctly. For example video output requires at least two buffers,
-one displayed and one filled by the application.</para>
+    <para>To allocate device buffers applications initialize all fields of the
+<structname>v4l2_requestbuffers</structname> structure.  They set the
+<structfield>type</structfield> field to the respective stream or buffer type,
+the <structfield>count</structfield> field to the desired number of buffers,
+<structfield>memory</structfield> must be set to the requested I/O method and
+the <structfield>reserved</structfield> array must be zeroed. When the ioctl is
+called with a pointer to this structure the driver will attempt to allocate the
+requested number of buffers and it stores the actual number allocated in the
+<structfield>count</structfield> field. It can be smaller than the number
+requested, even zero, when the driver runs out of free memory. A larger number
+is also possible when the driver requires more buffers to function correctly.
+For example video output requires at least two buffers, one displayed and one
+filled by the application.</para>
     <para>When the I/O method is not supported the ioctl
 returns an &EINVAL;.</para>
 
@@ -102,7 +104,8 @@ as the &v4l2-format; <structfield>type</structfield> field. See <xref
 	    <entry>__u32</entry>
 	    <entry><structfield>memory</structfield></entry>
 	    <entry>Applications set this field to
-<constant>V4L2_MEMORY_MMAP</constant> or
+<constant>V4L2_MEMORY_MMAP</constant>,
+<constant>V4L2_MEMORY_DMABUF</constant> or
 <constant>V4L2_MEMORY_USERPTR</constant>. See <xref linkend="v4l2-memory"
 />.</entry>
 	  </row>
-- 
1.7.9.5


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

* [PATCHv8 03/26] v4l: vb2: add support for shared buffer (dma_buf)
  2012-08-14 15:34 [PATCHv8 00/26] Integration of videobuf2 with DMABUF Tomasz Stanislawski
  2012-08-14 15:34 ` [PATCHv8 01/26] v4l: Add DMABUF as a memory type Tomasz Stanislawski
  2012-08-14 15:34 ` [PATCHv8 02/26] Documentation: media: description of DMABUF importing in V4L2 Tomasz Stanislawski
@ 2012-08-14 15:34 ` Tomasz Stanislawski
  2012-08-14 15:34 ` [PATCHv8 04/26] v4l: vb: remove warnings about MEMORY_DMABUF Tomasz Stanislawski
                   ` (22 subsequent siblings)
  25 siblings, 0 replies; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-08-14 15:34 UTC (permalink / raw)
  To: linux-media, dri-devel
  Cc: airlied, m.szyprowski, t.stanislaws, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, hverkuil, remi, subashrp,
	mchehab, g.liakhovetski, dmitriyz, s.nawrocki, k.debski,
	Sumit Semwal

From: Sumit Semwal <sumit.semwal@ti.com>

This patch adds support for DMABUF memory type in videobuf2. It calls relevant
APIs of dma_buf for v4l reqbuf / qbuf / dqbuf operations.

For this version, the support is for videobuf2 as a user of the shared buffer;
so the allocation of the buffer is done outside of V4L2. [A sample allocator of
dma-buf shared buffer is given at [1]]

[1]: Rob Clark's DRM:
   https://github.com/robclark/kernel-omap4/commits/drmplane-dmabuf

Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
   [original work in the PoC for buffer sharing]
Signed-off-by: Sumit Semwal <sumit.semwal@ti.com>
Signed-off-by: Sumit Semwal <sumit.semwal@linaro.org>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/video/videobuf2-core.c |  197 +++++++++++++++++++++++++++++++++-
 include/media/videobuf2-core.h       |   27 +++++
 2 files changed, 221 insertions(+), 3 deletions(-)

diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c
index 4da3df6..a5d5081 100644
--- a/drivers/media/video/videobuf2-core.c
+++ b/drivers/media/video/videobuf2-core.c
@@ -109,6 +109,36 @@ static void __vb2_buf_userptr_put(struct vb2_buffer *vb)
 }
 
 /**
+ * __vb2_plane_dmabuf_put() - release memory associated with
+ * a DMABUF shared plane
+ */
+static void __vb2_plane_dmabuf_put(struct vb2_queue *q, struct vb2_plane *p)
+{
+	if (!p->mem_priv)
+		return;
+
+	if (p->dbuf_mapped)
+		call_memop(q, unmap_dmabuf, p->mem_priv);
+
+	call_memop(q, detach_dmabuf, p->mem_priv);
+	dma_buf_put(p->dbuf);
+	memset(p, 0, sizeof(*p));
+}
+
+/**
+ * __vb2_buf_dmabuf_put() - release memory associated with
+ * a DMABUF shared buffer
+ */
+static void __vb2_buf_dmabuf_put(struct vb2_buffer *vb)
+{
+	struct vb2_queue *q = vb->vb2_queue;
+	unsigned int plane;
+
+	for (plane = 0; plane < vb->num_planes; ++plane)
+		__vb2_plane_dmabuf_put(q, &vb->planes[plane]);
+}
+
+/**
  * __setup_offsets() - setup unique offsets ("cookies") for every plane in
  * every buffer on the queue
  */
@@ -230,6 +260,8 @@ static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
 		/* Free MMAP buffers or release USERPTR buffers */
 		if (q->memory == V4L2_MEMORY_MMAP)
 			__vb2_buf_mem_free(vb);
+		else if (q->memory == V4L2_MEMORY_DMABUF)
+			__vb2_buf_dmabuf_put(vb);
 		else
 			__vb2_buf_userptr_put(vb);
 	}
@@ -352,6 +384,12 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
 		 */
 		memcpy(b->m.planes, vb->v4l2_planes,
 			b->length * sizeof(struct v4l2_plane));
+
+		if (q->memory == V4L2_MEMORY_DMABUF) {
+			unsigned int plane;
+			for (plane = 0; plane < vb->num_planes; ++plane)
+				b->m.planes[plane].m.fd = 0;
+		}
 	} else {
 		/*
 		 * We use length and offset in v4l2_planes array even for
@@ -363,6 +401,8 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
 			b->m.offset = vb->v4l2_planes[0].m.mem_offset;
 		else if (q->memory == V4L2_MEMORY_USERPTR)
 			b->m.userptr = vb->v4l2_planes[0].m.userptr;
+		else if (q->memory == V4L2_MEMORY_DMABUF)
+			b->m.fd = 0;
 	}
 
 	/*
@@ -454,13 +494,28 @@ static int __verify_mmap_ops(struct vb2_queue *q)
 }
 
 /**
+ * __verify_dmabuf_ops() - verify that all memory operations required for
+ * DMABUF queue type have been provided
+ */
+static int __verify_dmabuf_ops(struct vb2_queue *q)
+{
+	if (!(q->io_modes & VB2_DMABUF) || !q->mem_ops->attach_dmabuf ||
+	    !q->mem_ops->detach_dmabuf  || !q->mem_ops->map_dmabuf ||
+	    !q->mem_ops->unmap_dmabuf)
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
  * __verify_memory_type() - Check whether the memory type and buffer type
  * passed to a buffer operation are compatible with the queue.
  */
 static int __verify_memory_type(struct vb2_queue *q,
 		enum v4l2_memory memory, enum v4l2_buf_type type)
 {
-	if (memory != V4L2_MEMORY_MMAP && memory != V4L2_MEMORY_USERPTR) {
+	if (memory != V4L2_MEMORY_MMAP && memory != V4L2_MEMORY_USERPTR &&
+	    memory != V4L2_MEMORY_DMABUF) {
 		dprintk(1, "reqbufs: unsupported memory type\n");
 		return -EINVAL;
 	}
@@ -484,6 +539,11 @@ static int __verify_memory_type(struct vb2_queue *q,
 		return -EINVAL;
 	}
 
+	if (memory == V4L2_MEMORY_DMABUF && __verify_dmabuf_ops(q)) {
+		dprintk(1, "reqbufs: DMABUF for current setup unsupported\n");
+		return -EINVAL;
+	}
+
 	/*
 	 * Place the busy tests at the end: -EBUSY can be ignored when
 	 * create_bufs is called with count == 0, but count == 0 should still
@@ -853,6 +913,11 @@ static int __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b,
 					b->m.planes[plane].length;
 			}
 		}
+		if (b->memory == V4L2_MEMORY_DMABUF) {
+			for (plane = 0; plane < vb->num_planes; ++plane)
+				v4l2_planes[plane].m.fd =
+					b->m.planes[plane].m.fd;
+		}
 	} else {
 		/*
 		 * Single-planar buffers do not use planes array,
@@ -867,6 +932,10 @@ static int __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b,
 			v4l2_planes[0].m.userptr = b->m.userptr;
 			v4l2_planes[0].length = b->length;
 		}
+
+		if (b->memory == V4L2_MEMORY_DMABUF)
+			v4l2_planes[0].m.fd = b->m.fd;
+
 	}
 
 	vb->v4l2_buf.field = b->field;
@@ -970,6 +1039,100 @@ static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 }
 
 /**
+ * __qbuf_dmabuf() - handle qbuf of a DMABUF buffer
+ */
+static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
+{
+	struct v4l2_plane planes[VIDEO_MAX_PLANES];
+	struct vb2_queue *q = vb->vb2_queue;
+	void *mem_priv;
+	unsigned int plane;
+	int ret;
+	int write = !V4L2_TYPE_IS_OUTPUT(q->type);
+
+	/* Verify and copy relevant information provided by the userspace */
+	ret = __fill_vb2_buffer(vb, b, planes);
+	if (ret)
+		return ret;
+
+	for (plane = 0; plane < vb->num_planes; ++plane) {
+		struct dma_buf *dbuf = dma_buf_get(planes[plane].m.fd);
+
+		if (IS_ERR_OR_NULL(dbuf)) {
+			dprintk(1, "qbuf: invalid dmabuf fd for plane %d\n",
+				plane);
+			ret = -EINVAL;
+			goto err;
+		}
+
+		/* use dmabuf's size as a plane length */
+		planes[plane].length = dbuf->size;
+
+		/* Skip the plane if already verified */
+		if (dbuf == vb->planes[plane].dbuf) {
+			dma_buf_put(dbuf);
+			continue;
+		}
+
+		dprintk(1, "qbuf: buffer for plane %d changed\n", plane);
+
+		/* Release previously acquired memory if present */
+		__vb2_plane_dmabuf_put(q, &vb->planes[plane]);
+
+		/* Acquire each plane's memory */
+		mem_priv = call_memop(q, attach_dmabuf, q->alloc_ctx[plane],
+			dbuf, q->plane_sizes[plane], write);
+		if (IS_ERR(mem_priv)) {
+			dprintk(1, "qbuf: failed to attach dmabuf\n");
+			ret = PTR_ERR(mem_priv);
+			dma_buf_put(dbuf);
+			goto err;
+		}
+
+		vb->planes[plane].dbuf = dbuf;
+		vb->planes[plane].mem_priv = mem_priv;
+	}
+
+	/* TODO: This pins the buffer(s) with  dma_buf_map_attachment()).. but
+	 * really we want to do this just before the DMA, not while queueing
+	 * the buffer(s)..
+	 */
+	for (plane = 0; plane < vb->num_planes; ++plane) {
+		ret = call_memop(q, map_dmabuf, vb->planes[plane].mem_priv);
+		if (ret) {
+			dprintk(1, "qbuf: failed to map dmabuf for plane %d\n",
+				plane);
+			goto err;
+		}
+		vb->planes[plane].dbuf_mapped = 1;
+	}
+
+	/*
+	 * Call driver-specific initialization on the newly acquired buffer,
+	 * if provided.
+	 */
+	ret = call_qop(q, buf_init, vb);
+	if (ret) {
+		dprintk(1, "qbuf: buffer initialization failed\n");
+		goto err;
+	}
+
+	/*
+	 * Now that everything is in order, copy relevant information
+	 * provided by userspace.
+	 */
+	for (plane = 0; plane < vb->num_planes; ++plane)
+		vb->v4l2_planes[plane] = planes[plane];
+
+	return 0;
+err:
+	/* In case of errors, release planes that were already acquired */
+	__vb2_buf_dmabuf_put(vb);
+
+	return ret;
+}
+
+/**
  * __enqueue_in_driver() - enqueue a vb2_buffer in driver for processing
  */
 static void __enqueue_in_driver(struct vb2_buffer *vb)
@@ -993,6 +1156,9 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 	case V4L2_MEMORY_USERPTR:
 		ret = __qbuf_userptr(vb, b);
 		break;
+	case V4L2_MEMORY_DMABUF:
+		ret = __qbuf_dmabuf(vb, b);
+		break;
 	default:
 		WARN(1, "Invalid queue type\n");
 		ret = -EINVAL;
@@ -1301,6 +1467,30 @@ int vb2_wait_for_all_buffers(struct vb2_queue *q)
 EXPORT_SYMBOL_GPL(vb2_wait_for_all_buffers);
 
 /**
+ * __vb2_dqbuf() - bring back the buffer to the DEQUEUED state
+ */
+static void __vb2_dqbuf(struct vb2_buffer *vb)
+{
+	struct vb2_queue *q = vb->vb2_queue;
+	unsigned int i;
+
+	/* nothing to do if the buffer is already dequeued */
+	if (vb->state == VB2_BUF_STATE_DEQUEUED)
+		return;
+
+	vb->state = VB2_BUF_STATE_DEQUEUED;
+
+	/* unmap DMABUF buffer */
+	if (q->memory == V4L2_MEMORY_DMABUF)
+		for (i = 0; i < vb->num_planes; ++i) {
+			if (!vb->planes[i].dbuf_mapped)
+				continue;
+			call_memop(q, unmap_dmabuf, vb->planes[i].mem_priv);
+			vb->planes[i].dbuf_mapped = 0;
+		}
+}
+
+/**
  * vb2_dqbuf() - Dequeue a buffer to the userspace
  * @q:		videobuf2 queue
  * @b:		buffer structure passed from userspace to vidioc_dqbuf handler
@@ -1364,11 +1554,12 @@ int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
 	__fill_v4l2_buffer(vb, b);
 	/* Remove from videobuf queue */
 	list_del(&vb->queued_entry);
+	/* go back to dequeued state */
+	__vb2_dqbuf(vb);
 
 	dprintk(1, "dqbuf of buffer %d, with state %d\n",
 			vb->v4l2_buf.index, vb->state);
 
-	vb->state = VB2_BUF_STATE_DEQUEUED;
 	return 0;
 }
 EXPORT_SYMBOL_GPL(vb2_dqbuf);
@@ -1407,7 +1598,7 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
 	 * Reinitialize all buffers for next use.
 	 */
 	for (i = 0; i < q->num_buffers; ++i)
-		q->bufs[i]->state = VB2_BUF_STATE_DEQUEUED;
+		__vb2_dqbuf(q->bufs[i]);
 }
 
 /**
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 8dd9b6c..84f11f2 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/videodev2.h>
+#include <linux/dma-buf.h>
 
 struct vb2_alloc_ctx;
 struct vb2_fileio_data;
@@ -41,6 +42,20 @@ struct vb2_fileio_data;
  *		 argument to other ops in this structure
  * @put_userptr: inform the allocator that a USERPTR buffer will no longer
  *		 be used
+ * @attach_dmabuf: attach a shared struct dma_buf for a hardware operation;
+ *		   used for DMABUF memory types; alloc_ctx is the alloc context
+ *		   dbuf is the shared dma_buf; returns NULL on failure;
+ *		   allocator private per-buffer structure on success;
+ *		   this needs to be used for further accesses to the buffer
+ * @detach_dmabuf: inform the exporter of the buffer that the current DMABUF
+ *		   buffer is no longer used; the buf_priv argument is the
+ *		   allocator private per-buffer structure previously returned
+ *		   from the attach_dmabuf callback
+ * @map_dmabuf: request for access to the dmabuf from allocator; the allocator
+ *		of dmabuf is informed that this driver is going to use the
+ *		dmabuf
+ * @unmap_dmabuf: releases access control to the dmabuf - allocator is notified
+ *		  that this driver is done using the dmabuf for now
  * @vaddr:	return a kernel virtual address to a given memory buffer
  *		associated with the passed private structure or NULL if no
  *		such mapping exists
@@ -56,6 +71,8 @@ struct vb2_fileio_data;
  * Required ops for USERPTR types: get_userptr, put_userptr.
  * Required ops for MMAP types: alloc, put, num_users, mmap.
  * Required ops for read/write access types: alloc, put, num_users, vaddr
+ * Required ops for DMABUF types: attach_dmabuf, detach_dmabuf, map_dmabuf,
+ *				  unmap_dmabuf.
  */
 struct vb2_mem_ops {
 	void		*(*alloc)(void *alloc_ctx, unsigned long size);
@@ -65,6 +82,12 @@ struct vb2_mem_ops {
 					unsigned long size, int write);
 	void		(*put_userptr)(void *buf_priv);
 
+	void		*(*attach_dmabuf)(void *alloc_ctx, struct dma_buf *dbuf,
+				unsigned long size, int write);
+	void		(*detach_dmabuf)(void *buf_priv);
+	int		(*map_dmabuf)(void *buf_priv);
+	void		(*unmap_dmabuf)(void *buf_priv);
+
 	void		*(*vaddr)(void *buf_priv);
 	void		*(*cookie)(void *buf_priv);
 
@@ -75,6 +98,8 @@ struct vb2_mem_ops {
 
 struct vb2_plane {
 	void			*mem_priv;
+	struct dma_buf		*dbuf;
+	unsigned int		dbuf_mapped;
 };
 
 /**
@@ -83,12 +108,14 @@ struct vb2_plane {
  * @VB2_USERPTR:	driver supports USERPTR with streaming API
  * @VB2_READ:		driver supports read() style access
  * @VB2_WRITE:		driver supports write() style access
+ * @VB2_DMABUF:		driver supports DMABUF with streaming API
  */
 enum vb2_io_modes {
 	VB2_MMAP	= (1 << 0),
 	VB2_USERPTR	= (1 << 1),
 	VB2_READ	= (1 << 2),
 	VB2_WRITE	= (1 << 3),
+	VB2_DMABUF	= (1 << 4),
 };
 
 /**
-- 
1.7.9.5


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

* [PATCHv8 04/26] v4l: vb: remove warnings about MEMORY_DMABUF
  2012-08-14 15:34 [PATCHv8 00/26] Integration of videobuf2 with DMABUF Tomasz Stanislawski
                   ` (2 preceding siblings ...)
  2012-08-14 15:34 ` [PATCHv8 03/26] v4l: vb2: add support for shared buffer (dma_buf) Tomasz Stanislawski
@ 2012-08-14 15:34 ` Tomasz Stanislawski
  2012-08-14 15:34 ` [PATCHv8 05/26] v4l: vb2-dma-contig: Shorten vb2_dma_contig prefix to vb2_dc Tomasz Stanislawski
                   ` (21 subsequent siblings)
  25 siblings, 0 replies; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-08-14 15:34 UTC (permalink / raw)
  To: linux-media, dri-devel
  Cc: airlied, m.szyprowski, t.stanislaws, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, hverkuil, remi, subashrp,
	mchehab, g.liakhovetski, dmitriyz, s.nawrocki, k.debski

From: Sumit Semwal <sumit.semwal@ti.com>

Adding DMABUF memory type causes videobuf to complain about not using it
in some switch cases. This patch removes these warnings.

Signed-off-by: Sumit Semwal <sumit.semwal@ti.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/video/videobuf-core.c |    4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c
index bf7a326..5449e8a 100644
--- a/drivers/media/video/videobuf-core.c
+++ b/drivers/media/video/videobuf-core.c
@@ -335,6 +335,9 @@ static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b,
 	case V4L2_MEMORY_OVERLAY:
 		b->m.offset  = vb->boff;
 		break;
+	case V4L2_MEMORY_DMABUF:
+		/* DMABUF is not handled in videobuf framework */
+		break;
 	}
 
 	b->flags    = 0;
@@ -405,6 +408,7 @@ int __videobuf_mmap_setup(struct videobuf_queue *q,
 			break;
 		case V4L2_MEMORY_USERPTR:
 		case V4L2_MEMORY_OVERLAY:
+		case V4L2_MEMORY_DMABUF:
 			/* nothing */
 			break;
 		}
-- 
1.7.9.5


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

* [PATCHv8 05/26] v4l: vb2-dma-contig: Shorten vb2_dma_contig prefix to vb2_dc
  2012-08-14 15:34 [PATCHv8 00/26] Integration of videobuf2 with DMABUF Tomasz Stanislawski
                   ` (3 preceding siblings ...)
  2012-08-14 15:34 ` [PATCHv8 04/26] v4l: vb: remove warnings about MEMORY_DMABUF Tomasz Stanislawski
@ 2012-08-14 15:34 ` Tomasz Stanislawski
  2012-08-14 15:34 ` [PATCHv8 06/26] v4l: vb2-dma-contig: remove reference of alloc_ctx from a buffer Tomasz Stanislawski
                   ` (20 subsequent siblings)
  25 siblings, 0 replies; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-08-14 15:34 UTC (permalink / raw)
  To: linux-media, dri-devel
  Cc: airlied, m.szyprowski, t.stanislaws, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, hverkuil, remi, subashrp,
	mchehab, g.liakhovetski, dmitriyz, s.nawrocki, k.debski

From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/video/videobuf2-dma-contig.c |   36 ++++++++++++++--------------
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/drivers/media/video/videobuf2-dma-contig.c b/drivers/media/video/videobuf2-dma-contig.c
index 4b71326..a05784f 100644
--- a/drivers/media/video/videobuf2-dma-contig.c
+++ b/drivers/media/video/videobuf2-dma-contig.c
@@ -32,9 +32,9 @@ struct vb2_dc_buf {
 	struct vb2_vmarea_handler	handler;
 };
 
-static void vb2_dma_contig_put(void *buf_priv);
+static void vb2_dc_put(void *buf_priv);
 
-static void *vb2_dma_contig_alloc(void *alloc_ctx, unsigned long size)
+static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size)
 {
 	struct vb2_dc_conf *conf = alloc_ctx;
 	struct vb2_dc_buf *buf;
@@ -56,7 +56,7 @@ static void *vb2_dma_contig_alloc(void *alloc_ctx, unsigned long size)
 	buf->size = size;
 
 	buf->handler.refcount = &buf->refcount;
-	buf->handler.put = vb2_dma_contig_put;
+	buf->handler.put = vb2_dc_put;
 	buf->handler.arg = buf;
 
 	atomic_inc(&buf->refcount);
@@ -64,7 +64,7 @@ static void *vb2_dma_contig_alloc(void *alloc_ctx, unsigned long size)
 	return buf;
 }
 
-static void vb2_dma_contig_put(void *buf_priv)
+static void vb2_dc_put(void *buf_priv)
 {
 	struct vb2_dc_buf *buf = buf_priv;
 
@@ -75,14 +75,14 @@ static void vb2_dma_contig_put(void *buf_priv)
 	}
 }
 
-static void *vb2_dma_contig_cookie(void *buf_priv)
+static void *vb2_dc_cookie(void *buf_priv)
 {
 	struct vb2_dc_buf *buf = buf_priv;
 
 	return &buf->dma_addr;
 }
 
-static void *vb2_dma_contig_vaddr(void *buf_priv)
+static void *vb2_dc_vaddr(void *buf_priv)
 {
 	struct vb2_dc_buf *buf = buf_priv;
 	if (!buf)
@@ -91,14 +91,14 @@ static void *vb2_dma_contig_vaddr(void *buf_priv)
 	return buf->vaddr;
 }
 
-static unsigned int vb2_dma_contig_num_users(void *buf_priv)
+static unsigned int vb2_dc_num_users(void *buf_priv)
 {
 	struct vb2_dc_buf *buf = buf_priv;
 
 	return atomic_read(&buf->refcount);
 }
 
-static int vb2_dma_contig_mmap(void *buf_priv, struct vm_area_struct *vma)
+static int vb2_dc_mmap(void *buf_priv, struct vm_area_struct *vma)
 {
 	struct vb2_dc_buf *buf = buf_priv;
 
@@ -111,7 +111,7 @@ static int vb2_dma_contig_mmap(void *buf_priv, struct vm_area_struct *vma)
 				  &vb2_common_vm_ops, &buf->handler);
 }
 
-static void *vb2_dma_contig_get_userptr(void *alloc_ctx, unsigned long vaddr,
+static void *vb2_dc_get_userptr(void *alloc_ctx, unsigned long vaddr,
 					unsigned long size, int write)
 {
 	struct vb2_dc_buf *buf;
@@ -138,7 +138,7 @@ static void *vb2_dma_contig_get_userptr(void *alloc_ctx, unsigned long vaddr,
 	return buf;
 }
 
-static void vb2_dma_contig_put_userptr(void *mem_priv)
+static void vb2_dc_put_userptr(void *mem_priv)
 {
 	struct vb2_dc_buf *buf = mem_priv;
 
@@ -150,14 +150,14 @@ static void vb2_dma_contig_put_userptr(void *mem_priv)
 }
 
 const struct vb2_mem_ops vb2_dma_contig_memops = {
-	.alloc		= vb2_dma_contig_alloc,
-	.put		= vb2_dma_contig_put,
-	.cookie		= vb2_dma_contig_cookie,
-	.vaddr		= vb2_dma_contig_vaddr,
-	.mmap		= vb2_dma_contig_mmap,
-	.get_userptr	= vb2_dma_contig_get_userptr,
-	.put_userptr	= vb2_dma_contig_put_userptr,
-	.num_users	= vb2_dma_contig_num_users,
+	.alloc		= vb2_dc_alloc,
+	.put		= vb2_dc_put,
+	.cookie		= vb2_dc_cookie,
+	.vaddr		= vb2_dc_vaddr,
+	.mmap		= vb2_dc_mmap,
+	.get_userptr	= vb2_dc_get_userptr,
+	.put_userptr	= vb2_dc_put_userptr,
+	.num_users	= vb2_dc_num_users,
 };
 EXPORT_SYMBOL_GPL(vb2_dma_contig_memops);
 
-- 
1.7.9.5


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

* [PATCHv8 06/26] v4l: vb2-dma-contig: remove reference of alloc_ctx from a buffer
  2012-08-14 15:34 [PATCHv8 00/26] Integration of videobuf2 with DMABUF Tomasz Stanislawski
                   ` (4 preceding siblings ...)
  2012-08-14 15:34 ` [PATCHv8 05/26] v4l: vb2-dma-contig: Shorten vb2_dma_contig prefix to vb2_dc Tomasz Stanislawski
@ 2012-08-14 15:34 ` Tomasz Stanislawski
  2012-08-15 18:24   ` Laurent Pinchart
  2012-08-14 15:34 ` [PATCHv8 07/26] v4l: vb2-dma-contig: Reorder functions Tomasz Stanislawski
                   ` (19 subsequent siblings)
  25 siblings, 1 reply; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-08-14 15:34 UTC (permalink / raw)
  To: linux-media, dri-devel
  Cc: airlied, m.szyprowski, t.stanislaws, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, hverkuil, remi, subashrp,
	mchehab, g.liakhovetski, dmitriyz, s.nawrocki, k.debski

This patch removes a reference to alloc_ctx from an instance of a DMA
contiguous buffer. It helps to avoid a risk of a dangling pointer if the
context is released while the buffer is still valid. Moreover it removes one
dereference step while accessing a device structure.

Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 drivers/media/video/videobuf2-dma-contig.c |   13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/media/video/videobuf2-dma-contig.c b/drivers/media/video/videobuf2-dma-contig.c
index a05784f..20c95da 100644
--- a/drivers/media/video/videobuf2-dma-contig.c
+++ b/drivers/media/video/videobuf2-dma-contig.c
@@ -23,7 +23,7 @@ struct vb2_dc_conf {
 };
 
 struct vb2_dc_buf {
-	struct vb2_dc_conf		*conf;
+	struct device			*dev;
 	void				*vaddr;
 	dma_addr_t			dma_addr;
 	unsigned long			size;
@@ -37,22 +37,21 @@ static void vb2_dc_put(void *buf_priv);
 static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size)
 {
 	struct vb2_dc_conf *conf = alloc_ctx;
+	struct device *dev = conf->dev;
 	struct vb2_dc_buf *buf;
 
 	buf = kzalloc(sizeof *buf, GFP_KERNEL);
 	if (!buf)
 		return ERR_PTR(-ENOMEM);
 
-	buf->vaddr = dma_alloc_coherent(conf->dev, size, &buf->dma_addr,
-					GFP_KERNEL);
+	buf->vaddr = dma_alloc_coherent(dev, size, &buf->dma_addr, GFP_KERNEL);
 	if (!buf->vaddr) {
-		dev_err(conf->dev, "dma_alloc_coherent of size %ld failed\n",
-			size);
+		dev_err(dev, "dma_alloc_coherent of size %ld failed\n", size);
 		kfree(buf);
 		return ERR_PTR(-ENOMEM);
 	}
 
-	buf->conf = conf;
+	buf->dev = dev;
 	buf->size = size;
 
 	buf->handler.refcount = &buf->refcount;
@@ -69,7 +68,7 @@ static void vb2_dc_put(void *buf_priv)
 	struct vb2_dc_buf *buf = buf_priv;
 
 	if (atomic_dec_and_test(&buf->refcount)) {
-		dma_free_coherent(buf->conf->dev, buf->size, buf->vaddr,
+		dma_free_coherent(buf->dev, buf->size, buf->vaddr,
 				  buf->dma_addr);
 		kfree(buf);
 	}
-- 
1.7.9.5


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

* [PATCHv8 07/26] v4l: vb2-dma-contig: Reorder functions
  2012-08-14 15:34 [PATCHv8 00/26] Integration of videobuf2 with DMABUF Tomasz Stanislawski
                   ` (5 preceding siblings ...)
  2012-08-14 15:34 ` [PATCHv8 06/26] v4l: vb2-dma-contig: remove reference of alloc_ctx from a buffer Tomasz Stanislawski
@ 2012-08-14 15:34 ` Tomasz Stanislawski
  2012-08-14 15:34 ` [PATCHv8 08/26] v4l: vb2-dma-contig: add support for scatterlist in userptr mode Tomasz Stanislawski
                   ` (18 subsequent siblings)
  25 siblings, 0 replies; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-08-14 15:34 UTC (permalink / raw)
  To: linux-media, dri-devel
  Cc: airlied, m.szyprowski, t.stanislaws, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, hverkuil, remi, subashrp,
	mchehab, g.liakhovetski, dmitriyz, s.nawrocki, k.debski

From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Group functions by buffer type.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/video/videobuf2-dma-contig.c |   92 ++++++++++++++++------------
 1 file changed, 54 insertions(+), 38 deletions(-)

diff --git a/drivers/media/video/videobuf2-dma-contig.c b/drivers/media/video/videobuf2-dma-contig.c
index 20c95da..daac2b2 100644
--- a/drivers/media/video/videobuf2-dma-contig.c
+++ b/drivers/media/video/videobuf2-dma-contig.c
@@ -25,14 +25,56 @@ struct vb2_dc_conf {
 struct vb2_dc_buf {
 	struct device			*dev;
 	void				*vaddr;
-	dma_addr_t			dma_addr;
 	unsigned long			size;
-	struct vm_area_struct		*vma;
-	atomic_t			refcount;
+	dma_addr_t			dma_addr;
+
+	/* MMAP related */
 	struct vb2_vmarea_handler	handler;
+	atomic_t			refcount;
+
+	/* USERPTR related */
+	struct vm_area_struct		*vma;
 };
 
-static void vb2_dc_put(void *buf_priv);
+/*********************************************/
+/*         callbacks for all buffers         */
+/*********************************************/
+
+static void *vb2_dc_cookie(void *buf_priv)
+{
+	struct vb2_dc_buf *buf = buf_priv;
+
+	return &buf->dma_addr;
+}
+
+static void *vb2_dc_vaddr(void *buf_priv)
+{
+	struct vb2_dc_buf *buf = buf_priv;
+
+	return buf->vaddr;
+}
+
+static unsigned int vb2_dc_num_users(void *buf_priv)
+{
+	struct vb2_dc_buf *buf = buf_priv;
+
+	return atomic_read(&buf->refcount);
+}
+
+/*********************************************/
+/*        callbacks for MMAP buffers         */
+/*********************************************/
+
+static void vb2_dc_put(void *buf_priv)
+{
+	struct vb2_dc_buf *buf = buf_priv;
+
+	if (!atomic_dec_and_test(&buf->refcount))
+		return;
+
+	dma_free_coherent(buf->dev, buf->size, buf->vaddr, buf->dma_addr);
+	kfree(buf);
+}
 
 static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size)
 {
@@ -63,40 +105,6 @@ static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size)
 	return buf;
 }
 
-static void vb2_dc_put(void *buf_priv)
-{
-	struct vb2_dc_buf *buf = buf_priv;
-
-	if (atomic_dec_and_test(&buf->refcount)) {
-		dma_free_coherent(buf->dev, buf->size, buf->vaddr,
-				  buf->dma_addr);
-		kfree(buf);
-	}
-}
-
-static void *vb2_dc_cookie(void *buf_priv)
-{
-	struct vb2_dc_buf *buf = buf_priv;
-
-	return &buf->dma_addr;
-}
-
-static void *vb2_dc_vaddr(void *buf_priv)
-{
-	struct vb2_dc_buf *buf = buf_priv;
-	if (!buf)
-		return NULL;
-
-	return buf->vaddr;
-}
-
-static unsigned int vb2_dc_num_users(void *buf_priv)
-{
-	struct vb2_dc_buf *buf = buf_priv;
-
-	return atomic_read(&buf->refcount);
-}
-
 static int vb2_dc_mmap(void *buf_priv, struct vm_area_struct *vma)
 {
 	struct vb2_dc_buf *buf = buf_priv;
@@ -110,6 +118,10 @@ static int vb2_dc_mmap(void *buf_priv, struct vm_area_struct *vma)
 				  &vb2_common_vm_ops, &buf->handler);
 }
 
+/*********************************************/
+/*       callbacks for USERPTR buffers       */
+/*********************************************/
+
 static void *vb2_dc_get_userptr(void *alloc_ctx, unsigned long vaddr,
 					unsigned long size, int write)
 {
@@ -148,6 +160,10 @@ static void vb2_dc_put_userptr(void *mem_priv)
 	kfree(buf);
 }
 
+/*********************************************/
+/*       DMA CONTIG exported functions       */
+/*********************************************/
+
 const struct vb2_mem_ops vb2_dma_contig_memops = {
 	.alloc		= vb2_dc_alloc,
 	.put		= vb2_dc_put,
-- 
1.7.9.5


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

* [PATCHv8 08/26] v4l: vb2-dma-contig: add support for scatterlist in userptr mode
  2012-08-14 15:34 [PATCHv8 00/26] Integration of videobuf2 with DMABUF Tomasz Stanislawski
                   ` (6 preceding siblings ...)
  2012-08-14 15:34 ` [PATCHv8 07/26] v4l: vb2-dma-contig: Reorder functions Tomasz Stanislawski
@ 2012-08-14 15:34 ` Tomasz Stanislawski
  2012-08-14 15:34 ` [PATCHv8 09/26] v4l: vb2: add prepare/finish callbacks to allocators Tomasz Stanislawski
                   ` (17 subsequent siblings)
  25 siblings, 0 replies; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-08-14 15:34 UTC (permalink / raw)
  To: linux-media, dri-devel
  Cc: airlied, m.szyprowski, t.stanislaws, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, hverkuil, remi, subashrp,
	mchehab, g.liakhovetski, dmitriyz, s.nawrocki, k.debski

This patch introduces usage of dma_map_sg to map memory behind
a userspace pointer to a device as dma-contiguous mapping.

This patch contains some of the code kindly provided by Marek Szyprowski
<m.szyprowski@samsung.com> and Kamil Debski <k.debski@samsung.com> and Andrzej
Pietrasiewicz <andrzej.p@samsung.com>. Kind thanks for bug reports from Laurent
Pinchart <laurent.pinchart@ideasonboard.com> and Seung-Woo Kim
<sw0312.kim@samsung.com>.

Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/video/videobuf2-dma-contig.c |  226 ++++++++++++++++++++++++++--
 1 file changed, 210 insertions(+), 16 deletions(-)

diff --git a/drivers/media/video/videobuf2-dma-contig.c b/drivers/media/video/videobuf2-dma-contig.c
index daac2b2..8486e06 100644
--- a/drivers/media/video/videobuf2-dma-contig.c
+++ b/drivers/media/video/videobuf2-dma-contig.c
@@ -11,6 +11,8 @@
  */
 
 #include <linux/module.h>
+#include <linux/scatterlist.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
 
@@ -27,6 +29,8 @@ struct vb2_dc_buf {
 	void				*vaddr;
 	unsigned long			size;
 	dma_addr_t			dma_addr;
+	enum dma_data_direction		dma_dir;
+	struct sg_table			*dma_sgt;
 
 	/* MMAP related */
 	struct vb2_vmarea_handler	handler;
@@ -37,6 +41,44 @@ struct vb2_dc_buf {
 };
 
 /*********************************************/
+/*        scatterlist table functions        */
+/*********************************************/
+
+
+static void vb2_dc_sgt_foreach_page(struct sg_table *sgt,
+	void (*cb)(struct page *pg))
+{
+	struct scatterlist *s;
+	unsigned int i;
+
+	for_each_sg(sgt->sgl, s, sgt->orig_nents, i) {
+		struct page *page = sg_page(s);
+		unsigned int n_pages = PAGE_ALIGN(s->offset + s->length)
+			>> PAGE_SHIFT;
+		unsigned int j;
+
+		for (j = 0; j < n_pages; ++j, ++page)
+			cb(page);
+	}
+}
+
+static unsigned long vb2_dc_get_contiguous_size(struct sg_table *sgt)
+{
+	struct scatterlist *s;
+	dma_addr_t expected = sg_dma_address(sgt->sgl);
+	unsigned int i;
+	unsigned long size = 0;
+
+	for_each_sg(sgt->sgl, s, sgt->nents, i) {
+		if (sg_dma_address(s) != expected)
+			break;
+		expected = sg_dma_address(s) + sg_dma_len(s);
+		size += sg_dma_len(s);
+	}
+	return size;
+}
+
+/*********************************************/
 /*         callbacks for all buffers         */
 /*********************************************/
 
@@ -122,42 +164,194 @@ static int vb2_dc_mmap(void *buf_priv, struct vm_area_struct *vma)
 /*       callbacks for USERPTR buffers       */
 /*********************************************/
 
+static inline int vma_is_io(struct vm_area_struct *vma)
+{
+	return !!(vma->vm_flags & (VM_IO | VM_PFNMAP));
+}
+
+static int vb2_dc_get_user_pages(unsigned long start, struct page **pages,
+	int n_pages, struct vm_area_struct *vma, int write)
+{
+	if (vma_is_io(vma)) {
+		unsigned int i;
+
+		for (i = 0; i < n_pages; ++i, start += PAGE_SIZE) {
+			unsigned long pfn;
+			int ret = follow_pfn(vma, start, &pfn);
+
+			if (ret) {
+				pr_err("no page for address %lu\n", start);
+				return ret;
+			}
+			pages[i] = pfn_to_page(pfn);
+		}
+	} else {
+		int n;
+
+		n = get_user_pages(current, current->mm, start & PAGE_MASK,
+			n_pages, write, 1, pages, NULL);
+		/* negative error means that no page was pinned */
+		n = max(n, 0);
+		if (n != n_pages) {
+			pr_err("got only %d of %d user pages\n", n, n_pages);
+			while (n)
+				put_page(pages[--n]);
+			return -EFAULT;
+		}
+	}
+
+	return 0;
+}
+
+static void vb2_dc_put_dirty_page(struct page *page)
+{
+	set_page_dirty_lock(page);
+	put_page(page);
+}
+
+static void vb2_dc_put_userptr(void *buf_priv)
+{
+	struct vb2_dc_buf *buf = buf_priv;
+	struct sg_table *sgt = buf->dma_sgt;
+
+	dma_unmap_sg(buf->dev, sgt->sgl, sgt->orig_nents, buf->dma_dir);
+	if (!vma_is_io(buf->vma))
+		vb2_dc_sgt_foreach_page(sgt, vb2_dc_put_dirty_page);
+
+	sg_free_table(sgt);
+	kfree(sgt);
+	vb2_put_vma(buf->vma);
+	kfree(buf);
+}
+
 static void *vb2_dc_get_userptr(void *alloc_ctx, unsigned long vaddr,
-					unsigned long size, int write)
+	unsigned long size, int write)
 {
+	struct vb2_dc_conf *conf = alloc_ctx;
 	struct vb2_dc_buf *buf;
+	unsigned long start;
+	unsigned long end;
+	unsigned long offset;
+	struct page **pages;
+	int n_pages;
+	int ret = 0;
 	struct vm_area_struct *vma;
-	dma_addr_t dma_addr = 0;
-	int ret;
+	struct sg_table *sgt;
+	unsigned long contig_size;
 
 	buf = kzalloc(sizeof *buf, GFP_KERNEL);
 	if (!buf)
 		return ERR_PTR(-ENOMEM);
 
-	ret = vb2_get_contig_userptr(vaddr, size, &vma, &dma_addr);
+	buf->dev = conf->dev;
+	buf->dma_dir = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+
+	start = vaddr & PAGE_MASK;
+	offset = vaddr & ~PAGE_MASK;
+	end = PAGE_ALIGN(vaddr + size);
+	n_pages = (end - start) >> PAGE_SHIFT;
+
+	pages = kmalloc(n_pages * sizeof(pages[0]), GFP_KERNEL);
+	if (!pages) {
+		ret = -ENOMEM;
+		pr_err("failed to allocate pages table\n");
+		goto fail_buf;
+	}
+
+	/* current->mm->mmap_sem is taken by videobuf2 core */
+	vma = find_vma(current->mm, vaddr);
+	if (!vma) {
+		pr_err("no vma for address %lu\n", vaddr);
+		ret = -EFAULT;
+		goto fail_pages;
+	}
+
+	if (vma->vm_end < vaddr + size) {
+		pr_err("vma at %lu is too small for %lu bytes\n", vaddr, size);
+		ret = -EFAULT;
+		goto fail_pages;
+	}
+
+	buf->vma = vb2_get_vma(vma);
+	if (!buf->vma) {
+		pr_err("failed to copy vma\n");
+		ret = -ENOMEM;
+		goto fail_pages;
+	}
+
+	/* extract page list from userspace mapping */
+	ret = vb2_dc_get_user_pages(start, pages, n_pages, vma, write);
 	if (ret) {
-		printk(KERN_ERR "Failed acquiring VMA for vaddr 0x%08lx\n",
-				vaddr);
-		kfree(buf);
-		return ERR_PTR(ret);
+		pr_err("failed to get user pages\n");
+		goto fail_vma;
+	}
+
+	sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
+	if (!sgt) {
+		pr_err("failed to allocate sg table\n");
+		ret = -ENOMEM;
+		goto fail_get_user_pages;
+	}
+
+	ret = sg_alloc_table_from_pages(sgt, pages, n_pages,
+		offset, size, GFP_KERNEL);
+	if (ret) {
+		pr_err("failed to initialize sg table\n");
+		goto fail_sgt;
+	}
+
+	/* pages are no longer needed */
+	kfree(pages);
+	pages = NULL;
+
+	sgt->nents = dma_map_sg(buf->dev, sgt->sgl, sgt->orig_nents,
+		buf->dma_dir);
+	if (sgt->nents <= 0) {
+		pr_err("failed to map scatterlist\n");
+		ret = -EIO;
+		goto fail_sgt_init;
+	}
+
+	contig_size = vb2_dc_get_contiguous_size(sgt);
+	if (contig_size < size) {
+		pr_err("contiguous mapping is too small %lu/%lu\n",
+			contig_size, size);
+		ret = -EFAULT;
+		goto fail_map_sg;
 	}
 
+	buf->dma_addr = sg_dma_address(sgt->sgl);
 	buf->size = size;
-	buf->dma_addr = dma_addr;
-	buf->vma = vma;
+	buf->dma_sgt = sgt;
 
 	return buf;
-}
 
-static void vb2_dc_put_userptr(void *mem_priv)
-{
-	struct vb2_dc_buf *buf = mem_priv;
+fail_map_sg:
+	dma_unmap_sg(buf->dev, sgt->sgl, sgt->orig_nents, buf->dma_dir);
 
-	if (!buf)
-		return;
+fail_sgt_init:
+	if (!vma_is_io(buf->vma))
+		vb2_dc_sgt_foreach_page(sgt, put_page);
+	sg_free_table(sgt);
+
+fail_sgt:
+	kfree(sgt);
 
+fail_get_user_pages:
+	if (pages && !vma_is_io(buf->vma))
+		while (n_pages)
+			put_page(pages[--n_pages]);
+
+fail_vma:
 	vb2_put_vma(buf->vma);
+
+fail_pages:
+	kfree(pages); /* kfree is NULL-proof */
+
+fail_buf:
 	kfree(buf);
+
+	return ERR_PTR(ret);
 }
 
 /*********************************************/
-- 
1.7.9.5


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

* [PATCHv8 09/26] v4l: vb2: add prepare/finish callbacks to allocators
  2012-08-14 15:34 [PATCHv8 00/26] Integration of videobuf2 with DMABUF Tomasz Stanislawski
                   ` (7 preceding siblings ...)
  2012-08-14 15:34 ` [PATCHv8 08/26] v4l: vb2-dma-contig: add support for scatterlist in userptr mode Tomasz Stanislawski
@ 2012-08-14 15:34 ` Tomasz Stanislawski
  2012-08-14 15:34 ` [PATCHv8 10/26] v4l: vb2-dma-contig: add prepare/finish to dma-contig allocator Tomasz Stanislawski
                   ` (16 subsequent siblings)
  25 siblings, 0 replies; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-08-14 15:34 UTC (permalink / raw)
  To: linux-media, dri-devel
  Cc: airlied, m.szyprowski, t.stanislaws, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, hverkuil, remi, subashrp,
	mchehab, g.liakhovetski, dmitriyz, s.nawrocki, k.debski

From: Marek Szyprowski <m.szyprowski@samsung.com>

This patch adds support for prepare/finish callbacks in VB2 allocators. These
callback are used for buffer flushing.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/video/videobuf2-core.c |   11 +++++++++++
 include/media/videobuf2-core.h       |    7 +++++++
 2 files changed, 18 insertions(+)

diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c
index a5d5081..aed21e4 100644
--- a/drivers/media/video/videobuf2-core.c
+++ b/drivers/media/video/videobuf2-core.c
@@ -850,6 +850,7 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
 {
 	struct vb2_queue *q = vb->vb2_queue;
 	unsigned long flags;
+	unsigned int plane;
 
 	if (vb->state != VB2_BUF_STATE_ACTIVE)
 		return;
@@ -860,6 +861,10 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
 	dprintk(4, "Done processing on buffer %d, state: %d\n",
 			vb->v4l2_buf.index, vb->state);
 
+	/* sync buffers */
+	for (plane = 0; plane < vb->num_planes; ++plane)
+		call_memop(q, finish, vb->planes[plane].mem_priv);
+
 	/* Add the buffer to the done buffers list */
 	spin_lock_irqsave(&q->done_lock, flags);
 	vb->state = state;
@@ -1138,9 +1143,15 @@ err:
 static void __enqueue_in_driver(struct vb2_buffer *vb)
 {
 	struct vb2_queue *q = vb->vb2_queue;
+	unsigned int plane;
 
 	vb->state = VB2_BUF_STATE_ACTIVE;
 	atomic_inc(&q->queued_count);
+
+	/* sync buffers */
+	for (plane = 0; plane < vb->num_planes; ++plane)
+		call_memop(q, prepare, vb->planes[plane].mem_priv);
+
 	q->ops->buf_queue(vb);
 }
 
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 84f11f2..c306fec 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -56,6 +56,10 @@ struct vb2_fileio_data;
  *		dmabuf
  * @unmap_dmabuf: releases access control to the dmabuf - allocator is notified
  *		  that this driver is done using the dmabuf for now
+ * @prepare:	called everytime the buffer is passed from userspace to the
+ *		driver, usefull for cache synchronisation, optional
+ * @finish:	called everytime the buffer is passed back from the driver
+ *		to the userspace, also optional
  * @vaddr:	return a kernel virtual address to a given memory buffer
  *		associated with the passed private structure or NULL if no
  *		such mapping exists
@@ -82,6 +86,9 @@ struct vb2_mem_ops {
 					unsigned long size, int write);
 	void		(*put_userptr)(void *buf_priv);
 
+	void		(*prepare)(void *buf_priv);
+	void		(*finish)(void *buf_priv);
+
 	void		*(*attach_dmabuf)(void *alloc_ctx, struct dma_buf *dbuf,
 				unsigned long size, int write);
 	void		(*detach_dmabuf)(void *buf_priv);
-- 
1.7.9.5


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

* [PATCHv8 10/26] v4l: vb2-dma-contig: add prepare/finish to dma-contig allocator
  2012-08-14 15:34 [PATCHv8 00/26] Integration of videobuf2 with DMABUF Tomasz Stanislawski
                   ` (8 preceding siblings ...)
  2012-08-14 15:34 ` [PATCHv8 09/26] v4l: vb2: add prepare/finish callbacks to allocators Tomasz Stanislawski
@ 2012-08-14 15:34 ` Tomasz Stanislawski
  2012-08-15 18:35   ` Laurent Pinchart
  2012-08-14 15:34 ` [PATCHv8 11/26] v4l: vb2-dma-contig: add support for dma_buf importing Tomasz Stanislawski
                   ` (15 subsequent siblings)
  25 siblings, 1 reply; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-08-14 15:34 UTC (permalink / raw)
  To: linux-media, dri-devel
  Cc: airlied, m.szyprowski, t.stanislaws, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, hverkuil, remi, subashrp,
	mchehab, g.liakhovetski, dmitriyz, s.nawrocki, k.debski

From: Marek Szyprowski <m.szyprowski@samsung.com>

Add prepare/finish callbacks to vb2-dma-contig allocator.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/media/video/videobuf2-dma-contig.c |   24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/drivers/media/video/videobuf2-dma-contig.c b/drivers/media/video/videobuf2-dma-contig.c
index 8486e06..494a824 100644
--- a/drivers/media/video/videobuf2-dma-contig.c
+++ b/drivers/media/video/videobuf2-dma-contig.c
@@ -103,6 +103,28 @@ static unsigned int vb2_dc_num_users(void *buf_priv)
 	return atomic_read(&buf->refcount);
 }
 
+static void vb2_dc_prepare(void *buf_priv)
+{
+	struct vb2_dc_buf *buf = buf_priv;
+	struct sg_table *sgt = buf->dma_sgt;
+
+	if (!sgt)
+		return;
+
+	dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
+}
+
+static void vb2_dc_finish(void *buf_priv)
+{
+	struct vb2_dc_buf *buf = buf_priv;
+	struct sg_table *sgt = buf->dma_sgt;
+
+	if (!sgt)
+		return;
+
+	dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
+}
+
 /*********************************************/
 /*        callbacks for MMAP buffers         */
 /*********************************************/
@@ -366,6 +388,8 @@ const struct vb2_mem_ops vb2_dma_contig_memops = {
 	.mmap		= vb2_dc_mmap,
 	.get_userptr	= vb2_dc_get_userptr,
 	.put_userptr	= vb2_dc_put_userptr,
+	.prepare	= vb2_dc_prepare,
+	.finish		= vb2_dc_finish,
 	.num_users	= vb2_dc_num_users,
 };
 EXPORT_SYMBOL_GPL(vb2_dma_contig_memops);
-- 
1.7.9.5


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

* [PATCHv8 11/26] v4l: vb2-dma-contig: add support for dma_buf importing
  2012-08-14 15:34 [PATCHv8 00/26] Integration of videobuf2 with DMABUF Tomasz Stanislawski
                   ` (9 preceding siblings ...)
  2012-08-14 15:34 ` [PATCHv8 10/26] v4l: vb2-dma-contig: add prepare/finish to dma-contig allocator Tomasz Stanislawski
@ 2012-08-14 15:34 ` Tomasz Stanislawski
  2012-08-14 15:34 ` [PATCHv8 12/26] v4l: vb2-vmalloc: add support for dmabuf importing Tomasz Stanislawski
                   ` (14 subsequent siblings)
  25 siblings, 0 replies; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-08-14 15:34 UTC (permalink / raw)
  To: linux-media, dri-devel
  Cc: airlied, m.szyprowski, t.stanislaws, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, hverkuil, remi, subashrp,
	mchehab, g.liakhovetski, dmitriyz, s.nawrocki, k.debski,
	Sumit Semwal

From: Sumit Semwal <sumit.semwal@ti.com>

This patch makes changes for adding dma-contig as a dma_buf user. It provides
function implementations for the {attach, detach, map, unmap}_dmabuf()
mem_ops of DMABUF memory type.

Signed-off-by: Sumit Semwal <sumit.semwal@ti.com>
Signed-off-by: Sumit Semwal <sumit.semwal@linaro.org>
	[author of the original patch]
Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
	[integration with refactored dma-contig allocator]
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/video/videobuf2-dma-contig.c |  120 +++++++++++++++++++++++++++-
 1 file changed, 118 insertions(+), 2 deletions(-)

diff --git a/drivers/media/video/videobuf2-dma-contig.c b/drivers/media/video/videobuf2-dma-contig.c
index 494a824..a5804cf 100644
--- a/drivers/media/video/videobuf2-dma-contig.c
+++ b/drivers/media/video/videobuf2-dma-contig.c
@@ -10,6 +10,7 @@
  * the Free Software Foundation.
  */
 
+#include <linux/dma-buf.h>
 #include <linux/module.h>
 #include <linux/scatterlist.h>
 #include <linux/sched.h>
@@ -38,6 +39,9 @@ struct vb2_dc_buf {
 
 	/* USERPTR related */
 	struct vm_area_struct		*vma;
+
+	/* DMABUF related */
+	struct dma_buf_attachment	*db_attach;
 };
 
 /*********************************************/
@@ -108,7 +112,8 @@ static void vb2_dc_prepare(void *buf_priv)
 	struct vb2_dc_buf *buf = buf_priv;
 	struct sg_table *sgt = buf->dma_sgt;
 
-	if (!sgt)
+	/* DMABUF exporter will flush the cache for us */
+	if (!sgt || buf->db_attach)
 		return;
 
 	dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
@@ -119,7 +124,8 @@ static void vb2_dc_finish(void *buf_priv)
 	struct vb2_dc_buf *buf = buf_priv;
 	struct sg_table *sgt = buf->dma_sgt;
 
-	if (!sgt)
+	/* DMABUF exporter will flush the cache for us */
+	if (!sgt || buf->db_attach)
 		return;
 
 	dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
@@ -377,6 +383,112 @@ fail_buf:
 }
 
 /*********************************************/
+/*       callbacks for DMABUF buffers        */
+/*********************************************/
+
+static int vb2_dc_map_dmabuf(void *mem_priv)
+{
+	struct vb2_dc_buf *buf = mem_priv;
+	struct sg_table *sgt;
+	unsigned long contig_size;
+
+	if (WARN_ON(!buf->db_attach)) {
+		pr_err("trying to pin a non attached buffer\n");
+		return -EINVAL;
+	}
+
+	if (WARN_ON(buf->dma_sgt)) {
+		pr_err("dmabuf buffer is already pinned\n");
+		return 0;
+	}
+
+	/* get the associated scatterlist for this buffer */
+	sgt = dma_buf_map_attachment(buf->db_attach, buf->dma_dir);
+	if (IS_ERR_OR_NULL(sgt)) {
+		pr_err("Error getting dmabuf scatterlist\n");
+		return -EINVAL;
+	}
+
+	/* checking if dmabuf is big enough to store contiguous chunk */
+	contig_size = vb2_dc_get_contiguous_size(sgt);
+	if (contig_size < buf->size) {
+		pr_err("contiguous chunk is too small %lu/%lu b\n",
+			contig_size, buf->size);
+		dma_buf_unmap_attachment(buf->db_attach, sgt, buf->dma_dir);
+		return -EFAULT;
+	}
+
+	buf->dma_addr = sg_dma_address(sgt->sgl);
+	buf->dma_sgt = sgt;
+
+	return 0;
+}
+
+static void vb2_dc_unmap_dmabuf(void *mem_priv)
+{
+	struct vb2_dc_buf *buf = mem_priv;
+	struct sg_table *sgt = buf->dma_sgt;
+
+	if (WARN_ON(!buf->db_attach)) {
+		pr_err("trying to unpin a not attached buffer\n");
+		return;
+	}
+
+	if (WARN_ON(!sgt)) {
+		pr_err("dmabuf buffer is already unpinned\n");
+		return;
+	}
+
+	dma_buf_unmap_attachment(buf->db_attach, sgt, buf->dma_dir);
+
+	buf->dma_addr = 0;
+	buf->dma_sgt = NULL;
+}
+
+static void vb2_dc_detach_dmabuf(void *mem_priv)
+{
+	struct vb2_dc_buf *buf = mem_priv;
+
+	/* if vb2 works correctly you should never detach mapped buffer */
+	if (WARN_ON(buf->dma_addr))
+		vb2_dc_unmap_dmabuf(buf);
+
+	/* detach this attachment */
+	dma_buf_detach(buf->db_attach->dmabuf, buf->db_attach);
+	kfree(buf);
+}
+
+static void *vb2_dc_attach_dmabuf(void *alloc_ctx, struct dma_buf *dbuf,
+	unsigned long size, int write)
+{
+	struct vb2_dc_conf *conf = alloc_ctx;
+	struct vb2_dc_buf *buf;
+	struct dma_buf_attachment *dba;
+
+	if (dbuf->size < size)
+		return ERR_PTR(-EFAULT);
+
+	buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+	if (!buf)
+		return ERR_PTR(-ENOMEM);
+
+	buf->dev = conf->dev;
+	/* create attachment for the dmabuf with the user device */
+	dba = dma_buf_attach(dbuf, buf->dev);
+	if (IS_ERR(dba)) {
+		pr_err("failed to attach dmabuf\n");
+		kfree(buf);
+		return dba;
+	}
+
+	buf->dma_dir = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+	buf->size = size;
+	buf->db_attach = dba;
+
+	return buf;
+}
+
+/*********************************************/
 /*       DMA CONTIG exported functions       */
 /*********************************************/
 
@@ -390,6 +502,10 @@ const struct vb2_mem_ops vb2_dma_contig_memops = {
 	.put_userptr	= vb2_dc_put_userptr,
 	.prepare	= vb2_dc_prepare,
 	.finish		= vb2_dc_finish,
+	.map_dmabuf	= vb2_dc_map_dmabuf,
+	.unmap_dmabuf	= vb2_dc_unmap_dmabuf,
+	.attach_dmabuf	= vb2_dc_attach_dmabuf,
+	.detach_dmabuf	= vb2_dc_detach_dmabuf,
 	.num_users	= vb2_dc_num_users,
 };
 EXPORT_SYMBOL_GPL(vb2_dma_contig_memops);
-- 
1.7.9.5


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

* [PATCHv8 12/26] v4l: vb2-vmalloc: add support for dmabuf importing
  2012-08-14 15:34 [PATCHv8 00/26] Integration of videobuf2 with DMABUF Tomasz Stanislawski
                   ` (10 preceding siblings ...)
  2012-08-14 15:34 ` [PATCHv8 11/26] v4l: vb2-dma-contig: add support for dma_buf importing Tomasz Stanislawski
@ 2012-08-14 15:34 ` Tomasz Stanislawski
  2012-08-15 18:39   ` Laurent Pinchart
  2012-08-14 15:34 ` [PATCHv8 13/26] v4l: vivi: " Tomasz Stanislawski
                   ` (13 subsequent siblings)
  25 siblings, 1 reply; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-08-14 15:34 UTC (permalink / raw)
  To: linux-media, dri-devel
  Cc: airlied, m.szyprowski, t.stanislaws, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, hverkuil, remi, subashrp,
	mchehab, g.liakhovetski, dmitriyz, s.nawrocki, k.debski

This patch adds support for importing DMABUF files for
vmalloc allocator in Videobuf2.

Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 drivers/media/video/videobuf2-vmalloc.c |   56 +++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/drivers/media/video/videobuf2-vmalloc.c b/drivers/media/video/videobuf2-vmalloc.c
index 94efa04..a47fd4f 100644
--- a/drivers/media/video/videobuf2-vmalloc.c
+++ b/drivers/media/video/videobuf2-vmalloc.c
@@ -30,6 +30,7 @@ struct vb2_vmalloc_buf {
 	unsigned int			n_pages;
 	atomic_t			refcount;
 	struct vb2_vmarea_handler	handler;
+	struct dma_buf			*dbuf;
 };
 
 static void vb2_vmalloc_put(void *buf_priv);
@@ -207,11 +208,66 @@ static int vb2_vmalloc_mmap(void *buf_priv, struct vm_area_struct *vma)
 	return 0;
 }
 
+/*********************************************/
+/*       callbacks for DMABUF buffers        */
+/*********************************************/
+
+static int vb2_vmalloc_map_dmabuf(void *mem_priv)
+{
+	struct vb2_vmalloc_buf *buf = mem_priv;
+
+	buf->vaddr = dma_buf_vmap(buf->dbuf);
+
+	return buf->vaddr ? 0 : -EFAULT;
+}
+
+static void vb2_vmalloc_unmap_dmabuf(void *mem_priv)
+{
+	struct vb2_vmalloc_buf *buf = mem_priv;
+
+	dma_buf_vunmap(buf->dbuf, buf->vaddr);
+	buf->vaddr = NULL;
+}
+
+static void vb2_vmalloc_detach_dmabuf(void *mem_priv)
+{
+	struct vb2_vmalloc_buf *buf = mem_priv;
+
+	if (buf->vaddr)
+		dma_buf_vunmap(buf->dbuf, buf->vaddr);
+
+	kfree(buf);
+}
+
+static void *vb2_vmalloc_attach_dmabuf(void *alloc_ctx, struct dma_buf *dbuf,
+	unsigned long size, int write)
+{
+	struct vb2_vmalloc_buf *buf;
+
+	if (dbuf->size < size)
+		return ERR_PTR(-EFAULT);
+
+	buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+	if (!buf)
+		return ERR_PTR(-ENOMEM);
+
+	buf->dbuf = dbuf;
+	buf->write = write;
+	buf->size = size;
+
+	return buf;
+}
+
+
 const struct vb2_mem_ops vb2_vmalloc_memops = {
 	.alloc		= vb2_vmalloc_alloc,
 	.put		= vb2_vmalloc_put,
 	.get_userptr	= vb2_vmalloc_get_userptr,
 	.put_userptr	= vb2_vmalloc_put_userptr,
+	.map_dmabuf	= vb2_vmalloc_map_dmabuf,
+	.unmap_dmabuf	= vb2_vmalloc_unmap_dmabuf,
+	.attach_dmabuf	= vb2_vmalloc_attach_dmabuf,
+	.detach_dmabuf	= vb2_vmalloc_detach_dmabuf,
 	.vaddr		= vb2_vmalloc_vaddr,
 	.mmap		= vb2_vmalloc_mmap,
 	.num_users	= vb2_vmalloc_num_users,
-- 
1.7.9.5


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

* [PATCHv8 13/26] v4l: vivi: support for dmabuf importing
  2012-08-14 15:34 [PATCHv8 00/26] Integration of videobuf2 with DMABUF Tomasz Stanislawski
                   ` (11 preceding siblings ...)
  2012-08-14 15:34 ` [PATCHv8 12/26] v4l: vb2-vmalloc: add support for dmabuf importing Tomasz Stanislawski
@ 2012-08-14 15:34 ` Tomasz Stanislawski
  2012-08-22 10:56   ` Hans Verkuil
  2012-08-14 15:34 ` [PATCHv8 14/26] v4l: s5p-tv: mixer: " Tomasz Stanislawski
                   ` (12 subsequent siblings)
  25 siblings, 1 reply; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-08-14 15:34 UTC (permalink / raw)
  To: linux-media, dri-devel
  Cc: airlied, m.szyprowski, t.stanislaws, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, hverkuil, remi, subashrp,
	mchehab, g.liakhovetski, dmitriyz, s.nawrocki, k.debski

This patch enhances VIVI driver with a support for importing a buffer
from DMABUF file descriptors.

Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 drivers/media/video/Kconfig |    1 +
 drivers/media/video/vivi.c  |    2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 966954d..8fa81be 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -653,6 +653,7 @@ config VIDEO_VIVI
 	depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE
 	select FONT_8x16
 	select VIDEOBUF2_VMALLOC
+	select DMA_SHARED_BUFFER
 	default n
 	---help---
 	  Enables a virtual video driver. This device shows a color bar
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
index a6351c4..37d8fd4 100644
--- a/drivers/media/video/vivi.c
+++ b/drivers/media/video/vivi.c
@@ -1308,7 +1308,7 @@ static int __init vivi_create_instance(int inst)
 	q = &dev->vb_vidq;
 	memset(q, 0, sizeof(dev->vb_vidq));
 	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
+	q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
 	q->drv_priv = dev;
 	q->buf_struct_size = sizeof(struct vivi_buffer);
 	q->ops = &vivi_video_qops;
-- 
1.7.9.5


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

* [PATCHv8 14/26] v4l: s5p-tv: mixer: support for dmabuf importing
  2012-08-14 15:34 [PATCHv8 00/26] Integration of videobuf2 with DMABUF Tomasz Stanislawski
                   ` (12 preceding siblings ...)
  2012-08-14 15:34 ` [PATCHv8 13/26] v4l: vivi: " Tomasz Stanislawski
@ 2012-08-14 15:34 ` Tomasz Stanislawski
  2012-08-14 15:34 ` [PATCHv8 15/26] v4l: s5p-fimc: " Tomasz Stanislawski
                   ` (11 subsequent siblings)
  25 siblings, 0 replies; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-08-14 15:34 UTC (permalink / raw)
  To: linux-media, dri-devel
  Cc: airlied, m.szyprowski, t.stanislaws, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, hverkuil, remi, subashrp,
	mchehab, g.liakhovetski, dmitriyz, s.nawrocki, k.debski

This patch enhances s5p-tv with support for DMABUF importing via
V4L2_MEMORY_DMABUF memory type.

Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 drivers/media/video/s5p-tv/Kconfig       |    1 +
 drivers/media/video/s5p-tv/mixer_video.c |    2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/media/video/s5p-tv/Kconfig b/drivers/media/video/s5p-tv/Kconfig
index f248b28..2e80126 100644
--- a/drivers/media/video/s5p-tv/Kconfig
+++ b/drivers/media/video/s5p-tv/Kconfig
@@ -10,6 +10,7 @@ config VIDEO_SAMSUNG_S5P_TV
 	bool "Samsung TV driver for S5P platform (experimental)"
 	depends on PLAT_S5P && PM_RUNTIME
 	depends on EXPERIMENTAL
+	select DMA_SHARED_BUFFER
 	default n
 	---help---
 	  Say Y here to enable selecting the TV output devices for
diff --git a/drivers/media/video/s5p-tv/mixer_video.c b/drivers/media/video/s5p-tv/mixer_video.c
index e0e02cc..da5b7a5 100644
--- a/drivers/media/video/s5p-tv/mixer_video.c
+++ b/drivers/media/video/s5p-tv/mixer_video.c
@@ -1091,7 +1091,7 @@ struct mxr_layer *mxr_base_layer_create(struct mxr_device *mdev,
 
 	layer->vb_queue = (struct vb2_queue) {
 		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
-		.io_modes = VB2_MMAP | VB2_USERPTR,
+		.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF,
 		.drv_priv = layer,
 		.buf_struct_size = sizeof(struct mxr_buffer),
 		.ops = &mxr_video_qops,
-- 
1.7.9.5


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

* [PATCHv8 15/26] v4l: s5p-fimc: support for dmabuf importing
  2012-08-14 15:34 [PATCHv8 00/26] Integration of videobuf2 with DMABUF Tomasz Stanislawski
                   ` (13 preceding siblings ...)
  2012-08-14 15:34 ` [PATCHv8 14/26] v4l: s5p-tv: mixer: " Tomasz Stanislawski
@ 2012-08-14 15:34 ` Tomasz Stanislawski
  2012-08-14 15:34 ` [PATCHv8 16/26] v4l: vb2-dma-contig: let mmap method to use dma_mmap_coherent call Tomasz Stanislawski
                   ` (10 subsequent siblings)
  25 siblings, 0 replies; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-08-14 15:34 UTC (permalink / raw)
  To: linux-media, dri-devel
  Cc: airlied, m.szyprowski, t.stanislaws, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, hverkuil, remi, subashrp,
	mchehab, g.liakhovetski, dmitriyz, s.nawrocki, k.debski

This patch enhances s5p-fimc with support for DMABUF importing via
V4L2_MEMORY_DMABUF memory type.

Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
 drivers/media/video/s5p-fimc/Kconfig        |    1 +
 drivers/media/video/s5p-fimc/fimc-capture.c |    2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/media/video/s5p-fimc/Kconfig b/drivers/media/video/s5p-fimc/Kconfig
index a564f7e..3106026 100644
--- a/drivers/media/video/s5p-fimc/Kconfig
+++ b/drivers/media/video/s5p-fimc/Kconfig
@@ -14,6 +14,7 @@ config VIDEO_S5P_FIMC
 	depends on I2C
 	select VIDEOBUF2_DMA_CONTIG
 	select V4L2_MEM2MEM_DEV
+	select DMA_SHARED_BUFFER
 	help
 	  This is a V4L2 driver for Samsung S5P and EXYNOS4 SoC camera host
 	  interface and video postprocessor (FIMC and FIMC-LITE) devices.
diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c
index 8e413dd..3fcaf7d 100644
--- a/drivers/media/video/s5p-fimc/fimc-capture.c
+++ b/drivers/media/video/s5p-fimc/fimc-capture.c
@@ -1634,7 +1634,7 @@ static int fimc_register_capture_device(struct fimc_dev *fimc,
 	q = &fimc->vid_cap.vbq;
 	memset(q, 0, sizeof(*q));
 	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-	q->io_modes = VB2_MMAP | VB2_USERPTR;
+	q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
 	q->drv_priv = fimc->vid_cap.ctx;
 	q->ops = &fimc_capture_qops;
 	q->mem_ops = &vb2_dma_contig_memops;
-- 
1.7.9.5


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

* [PATCHv8 16/26] v4l: vb2-dma-contig: let mmap method to use dma_mmap_coherent call
  2012-08-14 15:34 [PATCHv8 00/26] Integration of videobuf2 with DMABUF Tomasz Stanislawski
                   ` (14 preceding siblings ...)
  2012-08-14 15:34 ` [PATCHv8 15/26] v4l: s5p-fimc: " Tomasz Stanislawski
@ 2012-08-14 15:34 ` Tomasz Stanislawski
  2012-08-14 15:34 ` [PATCHv8 17/26] Documentation: media: description of DMABUF exporting in V4L2 Tomasz Stanislawski
                   ` (9 subsequent siblings)
  25 siblings, 0 replies; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-08-14 15:34 UTC (permalink / raw)
  To: linux-media, dri-devel
  Cc: airlied, m.szyprowski, t.stanislaws, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, hverkuil, remi, subashrp,
	mchehab, g.liakhovetski, dmitriyz, s.nawrocki, k.debski

From: Marek Szyprowski <m.szyprowski@samsung.com>

Let mmap method to use dma_mmap_coherent call.  Moreover, this patch removes
vb2_mmap_pfn_range from videobuf2 helpers as it was suggested by Laurent
Pinchart.  The function is no longer used in vb2 code.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/video/videobuf2-dma-contig.c |   28 +++++++++++++++++--
 drivers/media/video/videobuf2-memops.c     |   40 ----------------------------
 include/media/videobuf2-memops.h           |    5 ----
 3 files changed, 26 insertions(+), 47 deletions(-)

diff --git a/drivers/media/video/videobuf2-dma-contig.c b/drivers/media/video/videobuf2-dma-contig.c
index a5804cf..7fc71a0 100644
--- a/drivers/media/video/videobuf2-dma-contig.c
+++ b/drivers/media/video/videobuf2-dma-contig.c
@@ -178,14 +178,38 @@ static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size)
 static int vb2_dc_mmap(void *buf_priv, struct vm_area_struct *vma)
 {
 	struct vb2_dc_buf *buf = buf_priv;
+	int ret;
 
 	if (!buf) {
 		printk(KERN_ERR "No buffer to map\n");
 		return -EINVAL;
 	}
 
-	return vb2_mmap_pfn_range(vma, buf->dma_addr, buf->size,
-				  &vb2_common_vm_ops, &buf->handler);
+	/*
+	 * dma_mmap_* uses vm_pgoff as in-buffer offset, but we want to
+	 * map whole buffer
+	 */
+	vma->vm_pgoff = 0;
+
+	ret = dma_mmap_coherent(buf->dev, vma, buf->vaddr,
+		buf->dma_addr, buf->size);
+
+	if (ret) {
+		pr_err("Remapping memory failed, error: %d\n", ret);
+		return ret;
+	}
+
+	vma->vm_flags		|= VM_DONTEXPAND | VM_DONTDUMP;
+	vma->vm_private_data	= &buf->handler;
+	vma->vm_ops		= &vb2_common_vm_ops;
+
+	vma->vm_ops->open(vma);
+
+	pr_debug("%s: mapped dma addr 0x%08lx at 0x%08lx, size %ld\n",
+		__func__, (unsigned long)buf->dma_addr, vma->vm_start,
+		buf->size);
+
+	return 0;
 }
 
 /*********************************************/
diff --git a/drivers/media/video/videobuf2-memops.c b/drivers/media/video/videobuf2-memops.c
index 051ea35..81c1ad8 100644
--- a/drivers/media/video/videobuf2-memops.c
+++ b/drivers/media/video/videobuf2-memops.c
@@ -137,46 +137,6 @@ int vb2_get_contig_userptr(unsigned long vaddr, unsigned long size,
 EXPORT_SYMBOL_GPL(vb2_get_contig_userptr);
 
 /**
- * vb2_mmap_pfn_range() - map physical pages to userspace
- * @vma:	virtual memory region for the mapping
- * @paddr:	starting physical address of the memory to be mapped
- * @size:	size of the memory to be mapped
- * @vm_ops:	vm operations to be assigned to the created area
- * @priv:	private data to be associated with the area
- *
- * Returns 0 on success.
- */
-int vb2_mmap_pfn_range(struct vm_area_struct *vma, unsigned long paddr,
-				unsigned long size,
-				const struct vm_operations_struct *vm_ops,
-				void *priv)
-{
-	int ret;
-
-	size = min_t(unsigned long, vma->vm_end - vma->vm_start, size);
-
-	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-	ret = remap_pfn_range(vma, vma->vm_start, paddr >> PAGE_SHIFT,
-				size, vma->vm_page_prot);
-	if (ret) {
-		printk(KERN_ERR "Remapping memory failed, error: %d\n", ret);
-		return ret;
-	}
-
-	vma->vm_flags		|= VM_DONTEXPAND | VM_DONTDUMP;
-	vma->vm_private_data	= priv;
-	vma->vm_ops		= vm_ops;
-
-	vma->vm_ops->open(vma);
-
-	pr_debug("%s: mapped paddr 0x%08lx at 0x%08lx, size %ld\n",
-			__func__, paddr, vma->vm_start, size);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(vb2_mmap_pfn_range);
-
-/**
  * vb2_common_vm_open() - increase refcount of the vma
  * @vma:	virtual memory region for the mapping
  *
diff --git a/include/media/videobuf2-memops.h b/include/media/videobuf2-memops.h
index 84e1f6c..f05444c 100644
--- a/include/media/videobuf2-memops.h
+++ b/include/media/videobuf2-memops.h
@@ -33,11 +33,6 @@ extern const struct vm_operations_struct vb2_common_vm_ops;
 int vb2_get_contig_userptr(unsigned long vaddr, unsigned long size,
 			   struct vm_area_struct **res_vma, dma_addr_t *res_pa);
 
-int vb2_mmap_pfn_range(struct vm_area_struct *vma, unsigned long paddr,
-				unsigned long size,
-				const struct vm_operations_struct *vm_ops,
-				void *priv);
-
 struct vm_area_struct *vb2_get_vma(struct vm_area_struct *vma);
 void vb2_put_vma(struct vm_area_struct *vma);
 
-- 
1.7.9.5


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

* [PATCHv8 17/26] Documentation: media: description of DMABUF exporting in V4L2
  2012-08-14 15:34 [PATCHv8 00/26] Integration of videobuf2 with DMABUF Tomasz Stanislawski
                   ` (15 preceding siblings ...)
  2012-08-14 15:34 ` [PATCHv8 16/26] v4l: vb2-dma-contig: let mmap method to use dma_mmap_coherent call Tomasz Stanislawski
@ 2012-08-14 15:34 ` Tomasz Stanislawski
  2012-08-22 11:23   ` Hans Verkuil
  2012-08-14 15:34 ` [PATCHv8 18/26] v4l: add buffer exporting via dmabuf Tomasz Stanislawski
                   ` (8 subsequent siblings)
  25 siblings, 1 reply; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-08-14 15:34 UTC (permalink / raw)
  To: linux-media, dri-devel
  Cc: airlied, m.szyprowski, t.stanislaws, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, hverkuil, remi, subashrp,
	mchehab, g.liakhovetski, dmitriyz, s.nawrocki, k.debski,
	linux-doc

This patch adds description and usage examples for exporting
DMABUF file descriptor in V4L2.

Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
CC: linux-doc@vger.kernel.org
---
 Documentation/DocBook/media/v4l/compat.xml        |    3 +
 Documentation/DocBook/media/v4l/io.xml            |    3 +
 Documentation/DocBook/media/v4l/v4l2.xml          |    1 +
 Documentation/DocBook/media/v4l/vidioc-expbuf.xml |  223 +++++++++++++++++++++
 4 files changed, 230 insertions(+)
 create mode 100644 Documentation/DocBook/media/v4l/vidioc-expbuf.xml

diff --git a/Documentation/DocBook/media/v4l/compat.xml b/Documentation/DocBook/media/v4l/compat.xml
index ff45330..802c1ab 100644
--- a/Documentation/DocBook/media/v4l/compat.xml
+++ b/Documentation/DocBook/media/v4l/compat.xml
@@ -2609,6 +2609,9 @@ ioctls.</para>
 	  <para>Importing DMABUF file descriptors as a new IO method described
 	  in <xref linkend="dmabuf" />.</para>
         </listitem>
+        <listitem>
+	  <para>Exporting DMABUF files using &VIDIOC-EXPBUF; ioctl.</para>
+        </listitem>
       </itemizedlist>
     </section>
 
diff --git a/Documentation/DocBook/media/v4l/io.xml b/Documentation/DocBook/media/v4l/io.xml
index 98253ee..c27e59b 100644
--- a/Documentation/DocBook/media/v4l/io.xml
+++ b/Documentation/DocBook/media/v4l/io.xml
@@ -488,6 +488,9 @@ buffer from userspace using a file descriptor previously exported for a
 different or the same device (known as the importer role), or both. This
 section describes the DMABUF importer role API in V4L2.</para>
 
+    <para>Refer to <link linked="vidioc-expbuf"> DMABUF exporting </link> for
+details about exporting a V4L2 buffers as DMABUF file descriptors.</para>
+
 <para>Input and output devices support the streaming I/O method when the
 <constant>V4L2_CAP_STREAMING</constant> flag in the
 <structfield>capabilities</structfield> field of &v4l2-capability; returned by
diff --git a/Documentation/DocBook/media/v4l/v4l2.xml b/Documentation/DocBook/media/v4l/v4l2.xml
index 0292ed1..874c085 100644
--- a/Documentation/DocBook/media/v4l/v4l2.xml
+++ b/Documentation/DocBook/media/v4l/v4l2.xml
@@ -568,6 +568,7 @@ and discussions on the V4L mailing list.</revremark>
     &sub-overlay;
     &sub-prepare-buf;
     &sub-qbuf;
+    &sub-expbuf;
     &sub-querybuf;
     &sub-querycap;
     &sub-queryctrl;
diff --git a/Documentation/DocBook/media/v4l/vidioc-expbuf.xml b/Documentation/DocBook/media/v4l/vidioc-expbuf.xml
new file mode 100644
index 0000000..30ebf67
--- /dev/null
+++ b/Documentation/DocBook/media/v4l/vidioc-expbuf.xml
@@ -0,0 +1,223 @@
+<refentry id="vidioc-expbuf">
+
+  <refmeta>
+    <refentrytitle>ioctl VIDIOC_EXPBUF</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>VIDIOC_EXPBUF</refname>
+    <refpurpose>Export a buffer as a DMABUF file descriptor.</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcprototype>
+	<funcdef>int <function>ioctl</function></funcdef>
+	<paramdef>int <parameter>fd</parameter></paramdef>
+	<paramdef>int <parameter>request</parameter></paramdef>
+	<paramdef>struct v4l2_exportbuffer *<parameter>argp</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Arguments</title>
+
+    <variablelist>
+      <varlistentry>
+	<term><parameter>fd</parameter></term>
+	<listitem>
+	  <para>&fd;</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>request</parameter></term>
+	<listitem>
+	  <para>VIDIOC_EXPBUF</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>argp</parameter></term>
+	<listitem>
+	  <para></para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</title>
+
+    <note>
+      <title>Experimental</title>
+      <para>This is an <link linkend="experimental"> experimental </link>
+      interface and may change in the future.</para>
+    </note>
+
+<para>This ioctl is an extension to the <link linkend="mmap">memory
+mapping</link> I/O method therefore it is available only for
+<constant>V4L2_MEMORY_MMAP</constant> buffers.  It can be used to export a
+buffer as DMABUF file at any time after buffers have been allocated with the
+&VIDIOC-REQBUFS; ioctl.</para>
+
+<para>Prior to exporting an application calls <link
+linkend="vidioc-querybuf">VIDIOC_QUERYBUF</link> to obtain memory offsets. When
+using the <link linkend="planar-apis">multi-planar API</link> every plane has
+own offset.</para>
+
+<para>To export a buffer, the application fills &v4l2-exportbuffer;.  The
+<structfield> mem_offset </structfield> field is set to the offset obtained
+from <constant> VIDIOC_QUERYBUF </constant>.  Additional flags may be posted in
+the <structfield> flags </structfield> field.  Refer to manual for open syscall
+for details. Currently only O_CLOEXEC is guaranteed to be supported.  All other
+fields must be set to zero.  In a case of multi-planar API, every plane is
+exported separately using multiple <constant> VIDIOC_EXPBUF </constant>
+calls.</para>
+
+<para> After calling <constant>VIDIOC_EXPBUF</constant> the <structfield> fd
+</structfield> field will be set by a driver.  This is a DMABUF file
+descriptor. The application may pass it to other API. Refer to <link
+linkend="dmabuf">DMABUF importing</link> for details about importing DMABUF
+files into V4L2 nodes. A developer is encouraged to close a DMABUF file when it
+is no longer used.  </para>
+
+  </refsect1>
+  <refsect1>
+   <section>
+      <title>Examples</title>
+
+      <example>
+	<title>Exporting a buffer.</title>
+	<programlisting>
+int buffer_export(int v4lfd, &v4l2-buf-type; bt, int index, int *dmafd)
+{
+	&v4l2-buffer; buf;
+	&v4l2-exportbuffer; expbuf;
+
+	memset(&amp;buf, 0, sizeof buf);
+	buf.type = bt;
+	buf.memory = V4L2_MEMORY_MMAP;
+	buf.index = index;
+
+	if (ioctl (v4lfd, &VIDIOC-QUERYBUF;, &amp;buf) == -1) {
+		perror ("VIDIOC_QUERYBUF");
+		return -1;
+	}
+
+	memset(&amp;expbuf, 0, sizeof expbuf);
+	expbuf.mem_offset = buf.m.offset;
+	if (ioctl (v4lfd, &VIDIOC-EXPBUF;, &amp;expbuf) == -1) {
+		perror ("VIDIOC_EXPBUF");
+		return -1;
+	}
+
+	*dmafd = expbuf.fd;
+
+	return 0;
+}
+        </programlisting>
+      </example>
+
+      <example>
+	<title>Exporting a buffer using multi plane API.</title>
+	<programlisting>
+int buffer_export_mp(int v4lfd, &v4l2-buf-type; bt, int index,
+	int dmafd[], int n_planes)
+{
+	&v4l2-buffer; buf;
+	&v4l2-plane; planes[VIDEO_MAX_PLANES];
+	int i;
+
+	memset(&amp;buf, 0, sizeof buf);
+	buf.type = bt;
+	buf.memory = V4L2_MEMORY_MMAP;
+	buf.index = index;
+	buf.m.planes = planes;
+	buf.length = n_planes;
+	memset(&amp;planes, 0, sizeof planes);
+
+	if (ioctl (v4lfd, &VIDIOC-QUERYBUF;, &amp;buf) == -1) {
+		perror ("VIDIOC_QUERYBUF");
+		return -1;
+	}
+
+	for (i = 0; i &lt; n_planes; ++i) {
+		&v4l2-exportbuffer; expbuf;
+
+		memset(&amp;expbuf, 0, sizeof expbuf);
+		expbuf.mem_offset = plane[i].m.offset;
+		if (ioctl (v4lfd, &VIDIOC-EXPBUF;, &amp;expbuf) == -1) {
+			perror ("VIDIOC_EXPBUF");
+			while (i)
+				close(dmafd[--i]);
+			return -1;
+		}
+		dmafd[i] = expbuf.fd;
+	}
+
+	return 0;
+}
+        </programlisting>
+      </example>
+   </section>
+  </refsect1>
+
+  <refsect1>
+    <table pgwide="1" frame="none" id="v4l2-exportbuffer">
+      <title>struct <structname>v4l2_exportbuffer</structname></title>
+      <tgroup cols="3">
+	&cs-str;
+	<tbody valign="top">
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>fd</structfield></entry>
+	    <entry>The DMABUF file descriptor associated with a buffer. Set by
+		a driver.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>reserved0</structfield></entry>
+	    <entry>Reserved field for future use. Must be set to zero.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>mem_offset</structfield></entry>
+	    <entry>Buffer memory offset as returned by <constant>
+VIDIOC_QUERYBUF </constant> in &v4l2-buffer;<structfield> ::m.offset
+</structfield> (for single-plane formats) or &v4l2-plane;<structfield>
+::m.offset </structfield> (for multi-planar formats)</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>flags</structfield></entry>
+	    <entry>Flags for newly created file, currently only <constant>
+O_CLOEXEC </constant> is supported, refer to manual of open syscall for more
+details.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>reserved[12]</structfield></entry>
+	    <entry>Reserved field for future use. Must be set to zero.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+
+  </refsect1>
+
+  <refsect1>
+    &return-value;
+    <variablelist>
+      <varlistentry>
+	<term><errorcode>EINVAL</errorcode></term>
+	<listitem>
+	  <para>A queue is not in MMAP mode or DMABUF exporting is not
+supported or <structfield> flag </structfield> or <structfield> mem_offset
+</structfield> fields are invalid.</para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+</refentry>
-- 
1.7.9.5


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

* [PATCHv8 18/26] v4l: add buffer exporting via dmabuf
  2012-08-14 15:34 [PATCHv8 00/26] Integration of videobuf2 with DMABUF Tomasz Stanislawski
                   ` (16 preceding siblings ...)
  2012-08-14 15:34 ` [PATCHv8 17/26] Documentation: media: description of DMABUF exporting in V4L2 Tomasz Stanislawski
@ 2012-08-14 15:34 ` Tomasz Stanislawski
  2012-08-15 19:08   ` Laurent Pinchart
  2012-08-22 11:41   ` Hans Verkuil
  2012-08-14 15:34 ` [PATCHv8 19/26] v4l: vb2: " Tomasz Stanislawski
                   ` (7 subsequent siblings)
  25 siblings, 2 replies; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-08-14 15:34 UTC (permalink / raw)
  To: linux-media, dri-devel
  Cc: airlied, m.szyprowski, t.stanislaws, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, hverkuil, remi, subashrp,
	mchehab, g.liakhovetski, dmitriyz, s.nawrocki, k.debski

This patch adds extension to V4L2 api. It allow to export a mmap buffer as file
descriptor. New ioctl VIDIOC_EXPBUF is added. It takes a buffer offset used by
mmap and return a file descriptor on success.

Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 drivers/media/video/v4l2-compat-ioctl32.c |    1 +
 drivers/media/video/v4l2-dev.c            |    1 +
 drivers/media/video/v4l2-ioctl.c          |   15 +++++++++++++++
 include/linux/videodev2.h                 |   26 ++++++++++++++++++++++++++
 include/media/v4l2-ioctl.h                |    2 ++
 5 files changed, 45 insertions(+)

diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c
index a2e0549..7689c4a 100644
--- a/drivers/media/video/v4l2-compat-ioctl32.c
+++ b/drivers/media/video/v4l2-compat-ioctl32.c
@@ -971,6 +971,7 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
 	case VIDIOC_S_FBUF32:
 	case VIDIOC_OVERLAY32:
 	case VIDIOC_QBUF32:
+	case VIDIOC_EXPBUF:
 	case VIDIOC_DQBUF32:
 	case VIDIOC_STREAMON32:
 	case VIDIOC_STREAMOFF32:
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
index 71237f5..f6e7ea5 100644
--- a/drivers/media/video/v4l2-dev.c
+++ b/drivers/media/video/v4l2-dev.c
@@ -607,6 +607,7 @@ static void determine_valid_ioctls(struct video_device *vdev)
 	SET_VALID_IOCTL(ops, VIDIOC_REQBUFS, vidioc_reqbufs);
 	SET_VALID_IOCTL(ops, VIDIOC_QUERYBUF, vidioc_querybuf);
 	SET_VALID_IOCTL(ops, VIDIOC_QBUF, vidioc_qbuf);
+	SET_VALID_IOCTL(ops, VIDIOC_EXPBUF, vidioc_expbuf);
 	SET_VALID_IOCTL(ops, VIDIOC_DQBUF, vidioc_dqbuf);
 	SET_VALID_IOCTL(ops, VIDIOC_OVERLAY, vidioc_overlay);
 	SET_VALID_IOCTL(ops, VIDIOC_G_FBUF, vidioc_g_fbuf);
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
index dffd3c9..c4e8c7e 100644
--- a/drivers/media/video/v4l2-ioctl.c
+++ b/drivers/media/video/v4l2-ioctl.c
@@ -458,6 +458,14 @@ static void v4l_print_buffer(const void *arg, bool write_only)
 			tc->type, tc->flags, tc->frames, *(__u32 *)tc->userbits);
 }
 
+static void v4l_print_exportbuffer(const void *arg, bool write_only)
+{
+	const struct v4l2_exportbuffer *p = arg;
+
+	pr_cont("fd=%d, mem_offset=%lx, flags=%lx\n",
+		p->fd, (unsigned long)p->mem_offset, (unsigned long)p->flags);
+}
+
 static void v4l_print_create_buffers(const void *arg, bool write_only)
 {
 	const struct v4l2_create_buffers *p = arg;
@@ -1254,6 +1262,12 @@ static int v4l_streamoff(const struct v4l2_ioctl_ops *ops,
 	return ops->vidioc_streamoff(file, fh, *(unsigned int *)arg);
 }
 
+static int v4l_expbuf(const struct v4l2_ioctl_ops *ops,
+				struct file *file, void *fh, void *arg)
+{
+	return ops->vidioc_expbuf(file, fh, arg);
+}
+
 static int v4l_g_tuner(const struct v4l2_ioctl_ops *ops,
 				struct file *file, void *fh, void *arg)
 {
@@ -1947,6 +1961,7 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = {
 	IOCTL_INFO_STD(VIDIOC_S_FBUF, vidioc_s_fbuf, v4l_print_framebuffer, INFO_FL_PRIO),
 	IOCTL_INFO_STD(VIDIOC_OVERLAY, vidioc_overlay, v4l_print_u32, INFO_FL_PRIO),
 	IOCTL_INFO_FNC(VIDIOC_QBUF, v4l_qbuf, v4l_print_buffer, INFO_FL_QUEUE),
+	IOCTL_INFO_FNC(VIDIOC_EXPBUF, v4l_expbuf, v4l_print_exportbuffer, INFO_FL_CLEAR(v4l2_exportbuffer, flags)),
 	IOCTL_INFO_FNC(VIDIOC_DQBUF, v4l_dqbuf, v4l_print_buffer, INFO_FL_QUEUE),
 	IOCTL_INFO_FNC(VIDIOC_STREAMON, v4l_streamon, v4l_print_buftype, INFO_FL_PRIO | INFO_FL_QUEUE),
 	IOCTL_INFO_FNC(VIDIOC_STREAMOFF, v4l_streamoff, v4l_print_buftype, INFO_FL_PRIO | INFO_FL_QUEUE),
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 7f918dc..b5d058b 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -688,6 +688,31 @@ struct v4l2_buffer {
 #define V4L2_BUF_FLAG_NO_CACHE_INVALIDATE	0x0800
 #define V4L2_BUF_FLAG_NO_CACHE_CLEAN		0x1000
 
+/**
+ * struct v4l2_exportbuffer - export of video buffer as DMABUF file descriptor
+ *
+ * @fd:		file descriptor associated with DMABUF (set by driver)
+ * @mem_offset:	buffer memory offset as returned by VIDIOC_QUERYBUF in struct
+ *		v4l2_buffer::m.offset (for single-plane formats) or
+ *		v4l2_plane::m.offset (for multi-planar formats)
+ * @flags:	flags for newly created file, currently only O_CLOEXEC is
+ *		supported, refer to manual of open syscall for more details
+ *
+ * Contains data used for exporting a video buffer as DMABUF file descriptor.
+ * The buffer is identified by a 'cookie' returned by VIDIOC_QUERYBUF
+ * (identical to the cookie used to mmap() the buffer to userspace). All
+ * reserved fields must be set to zero. The field reserved0 is expected to
+ * become a structure 'type' allowing an alternative layout of the structure
+ * content. Therefore this field should not be used for any other extensions.
+ */
+struct v4l2_exportbuffer {
+	__u32		fd;
+	__u32		reserved0;
+	__u32		mem_offset;
+	__u32		flags;
+	__u32		reserved[12];
+};
+
 /*
  *	O V E R L A Y   P R E V I E W
  */
@@ -2558,6 +2583,7 @@ struct v4l2_create_buffers {
 #define VIDIOC_S_FBUF		 _IOW('V', 11, struct v4l2_framebuffer)
 #define VIDIOC_OVERLAY		 _IOW('V', 14, int)
 #define VIDIOC_QBUF		_IOWR('V', 15, struct v4l2_buffer)
+#define VIDIOC_EXPBUF		_IOWR('V', 16, struct v4l2_exportbuffer)
 #define VIDIOC_DQBUF		_IOWR('V', 17, struct v4l2_buffer)
 #define VIDIOC_STREAMON		 _IOW('V', 18, int)
 #define VIDIOC_STREAMOFF	 _IOW('V', 19, int)
diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
index e614c9c..38fb139 100644
--- a/include/media/v4l2-ioctl.h
+++ b/include/media/v4l2-ioctl.h
@@ -119,6 +119,8 @@ struct v4l2_ioctl_ops {
 	int (*vidioc_reqbufs) (struct file *file, void *fh, struct v4l2_requestbuffers *b);
 	int (*vidioc_querybuf)(struct file *file, void *fh, struct v4l2_buffer *b);
 	int (*vidioc_qbuf)    (struct file *file, void *fh, struct v4l2_buffer *b);
+	int (*vidioc_expbuf)  (struct file *file, void *fh,
+				struct v4l2_exportbuffer *e);
 	int (*vidioc_dqbuf)   (struct file *file, void *fh, struct v4l2_buffer *b);
 
 	int (*vidioc_create_bufs)(struct file *file, void *fh, struct v4l2_create_buffers *b);
-- 
1.7.9.5


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

* [PATCHv8 19/26] v4l: vb2: add buffer exporting via dmabuf
  2012-08-14 15:34 [PATCHv8 00/26] Integration of videobuf2 with DMABUF Tomasz Stanislawski
                   ` (17 preceding siblings ...)
  2012-08-14 15:34 ` [PATCHv8 18/26] v4l: add buffer exporting via dmabuf Tomasz Stanislawski
@ 2012-08-14 15:34 ` Tomasz Stanislawski
  2012-08-22 11:43   ` Hans Verkuil
  2012-08-14 15:34 ` [PATCHv8 20/26] v4l: vb2-dma-contig: add support for DMABUF exporting Tomasz Stanislawski
                   ` (6 subsequent siblings)
  25 siblings, 1 reply; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-08-14 15:34 UTC (permalink / raw)
  To: linux-media, dri-devel
  Cc: airlied, m.szyprowski, t.stanislaws, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, hverkuil, remi, subashrp,
	mchehab, g.liakhovetski, dmitriyz, s.nawrocki, k.debski

This patch adds extension to videobuf2-core. It allow to export a mmap buffer
as a file descriptor.

Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/video/videobuf2-core.c |   67 ++++++++++++++++++++++++++++++++++
 include/media/videobuf2-core.h       |    2 +
 2 files changed, 69 insertions(+)

diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c
index aed21e4..61354ec 100644
--- a/drivers/media/video/videobuf2-core.c
+++ b/drivers/media/video/videobuf2-core.c
@@ -1743,6 +1743,73 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
 }
 
 /**
+ * vb2_expbuf() - Export a buffer as a file descriptor
+ * @q:		videobuf2 queue
+ * @eb:		export buffer structure passed from userspace to vidioc_expbuf
+ *		handler in driver
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_expbuf handler in driver.
+ */
+int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
+{
+	struct vb2_buffer *vb = NULL;
+	struct vb2_plane *vb_plane;
+	unsigned int buffer, plane;
+	int ret;
+	struct dma_buf *dbuf;
+
+	if (q->memory != V4L2_MEMORY_MMAP) {
+		dprintk(1, "Queue is not currently set up for mmap\n");
+		return -EINVAL;
+	}
+
+	if (!q->mem_ops->get_dmabuf) {
+		dprintk(1, "Queue does not support DMA buffer exporting\n");
+		return -EINVAL;
+	}
+
+	if (eb->flags & ~O_CLOEXEC) {
+		dprintk(1, "Queue does support only O_CLOEXEC flag\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Find the plane corresponding to the offset passed by userspace.
+	 */
+	ret = __find_plane_by_offset(q, eb->mem_offset, &buffer, &plane);
+	if (ret) {
+		dprintk(1, "invalid offset %u\n", eb->mem_offset);
+		return ret;
+	}
+
+	vb = q->bufs[buffer];
+	vb_plane = &vb->planes[plane];
+
+	dbuf = call_memop(q, get_dmabuf, vb_plane->mem_priv);
+	if (IS_ERR_OR_NULL(dbuf)) {
+		dprintk(1, "Failed to export buffer %d, plane %d\n",
+			buffer, plane);
+		return -EINVAL;
+	}
+
+	ret = dma_buf_fd(dbuf, eb->flags);
+	if (ret < 0) {
+		dprintk(3, "buffer %d, plane %d failed to export (%d)\n",
+			buffer, plane, ret);
+		dma_buf_put(dbuf);
+		return ret;
+	}
+
+	dprintk(3, "buffer %d, plane %d exported as %d descriptor\n",
+		buffer, plane, ret);
+	eb->fd = ret;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(vb2_expbuf);
+
+/**
  * vb2_mmap() - map video buffers into application address space
  * @q:		videobuf2 queue
  * @vma:	vma passed to the mmap file operation handler in the driver
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index c306fec..b034424 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -81,6 +81,7 @@ struct vb2_fileio_data;
 struct vb2_mem_ops {
 	void		*(*alloc)(void *alloc_ctx, unsigned long size);
 	void		(*put)(void *buf_priv);
+	struct dma_buf *(*get_dmabuf)(void *buf_priv);
 
 	void		*(*get_userptr)(void *alloc_ctx, unsigned long vaddr,
 					unsigned long size, int write);
@@ -363,6 +364,7 @@ int vb2_queue_init(struct vb2_queue *q);
 void vb2_queue_release(struct vb2_queue *q);
 
 int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b);
+int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb);
 int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking);
 
 int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type);
-- 
1.7.9.5


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

* [PATCHv8 20/26] v4l: vb2-dma-contig: add support for DMABUF exporting
  2012-08-14 15:34 [PATCHv8 00/26] Integration of videobuf2 with DMABUF Tomasz Stanislawski
                   ` (18 preceding siblings ...)
  2012-08-14 15:34 ` [PATCHv8 19/26] v4l: vb2: " Tomasz Stanislawski
@ 2012-08-14 15:34 ` Tomasz Stanislawski
  2012-08-21 10:03   ` Laurent Pinchart
  2012-08-14 15:34 ` [PATCHv8 21/26] v4l: vb2-dma-contig: add reference counting for a device from allocator context Tomasz Stanislawski
                   ` (5 subsequent siblings)
  25 siblings, 1 reply; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-08-14 15:34 UTC (permalink / raw)
  To: linux-media, dri-devel
  Cc: airlied, m.szyprowski, t.stanislaws, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, hverkuil, remi, subashrp,
	mchehab, g.liakhovetski, dmitriyz, s.nawrocki, k.debski

This patch adds support for exporting a dma-contig buffer using
DMABUF interface.

Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 drivers/media/video/videobuf2-dma-contig.c |  204 ++++++++++++++++++++++++++++
 1 file changed, 204 insertions(+)

diff --git a/drivers/media/video/videobuf2-dma-contig.c b/drivers/media/video/videobuf2-dma-contig.c
index 7fc71a0..bb2b4ac8 100644
--- a/drivers/media/video/videobuf2-dma-contig.c
+++ b/drivers/media/video/videobuf2-dma-contig.c
@@ -36,6 +36,7 @@ struct vb2_dc_buf {
 	/* MMAP related */
 	struct vb2_vmarea_handler	handler;
 	atomic_t			refcount;
+	struct sg_table			*sgt_base;
 
 	/* USERPTR related */
 	struct vm_area_struct		*vma;
@@ -142,6 +143,10 @@ static void vb2_dc_put(void *buf_priv)
 	if (!atomic_dec_and_test(&buf->refcount))
 		return;
 
+	if (buf->sgt_base) {
+		sg_free_table(buf->sgt_base);
+		kfree(buf->sgt_base);
+	}
 	dma_free_coherent(buf->dev, buf->size, buf->vaddr, buf->dma_addr);
 	kfree(buf);
 }
@@ -213,6 +218,204 @@ static int vb2_dc_mmap(void *buf_priv, struct vm_area_struct *vma)
 }
 
 /*********************************************/
+/*         DMABUF ops for exporters          */
+/*********************************************/
+
+struct vb2_dc_attachment {
+	struct sg_table sgt;
+	enum dma_data_direction dir;
+};
+
+static int vb2_dc_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev,
+	struct dma_buf_attachment *dbuf_attach)
+{
+	struct vb2_dc_attachment *attach;
+	unsigned int i;
+	struct scatterlist *rd, *wr;
+	struct sg_table *sgt;
+	struct vb2_dc_buf *buf = dbuf->priv;
+	int ret;
+
+	attach = kzalloc(sizeof(*attach), GFP_KERNEL);
+	if (!attach)
+		return -ENOMEM;
+
+	sgt = &attach->sgt;
+	/* Copy the buf->base_sgt scatter list to the attachment, as we can't
+	 * map the same scatter list to multiple attachments at the same time.
+	 */
+	ret = sg_alloc_table(sgt, buf->sgt_base->orig_nents, GFP_KERNEL);
+	if (ret) {
+		kfree(attach);
+		return -ENOMEM;
+	}
+
+	rd = buf->sgt_base->sgl;
+	wr = sgt->sgl;
+	for (i = 0; i < sgt->orig_nents; ++i) {
+		sg_set_page(wr, sg_page(rd), rd->length, rd->offset);
+		rd = sg_next(rd);
+		wr = sg_next(wr);
+	}
+
+	attach->dir = DMA_NONE;
+	dbuf_attach->priv = attach;
+
+	return 0;
+}
+
+static void vb2_dc_dmabuf_ops_detach(struct dma_buf *dbuf,
+	struct dma_buf_attachment *db_attach)
+{
+	struct vb2_dc_attachment *attach = db_attach->priv;
+	struct sg_table *sgt;
+
+	if (!attach)
+		return;
+
+	sgt = &attach->sgt;
+
+	/* release the scatterlist cache */
+	if (attach->dir != DMA_NONE)
+		dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
+			attach->dir);
+	sg_free_table(sgt);
+	kfree(attach);
+	db_attach->priv = NULL;
+}
+
+static struct sg_table *vb2_dc_dmabuf_ops_map(
+	struct dma_buf_attachment *db_attach, enum dma_data_direction dir)
+{
+	struct vb2_dc_attachment *attach = db_attach->priv;
+	/* stealing dmabuf mutex to serialize map/unmap operations */
+	struct mutex *lock = &db_attach->dmabuf->lock;
+	struct sg_table *sgt;
+	int ret;
+
+	mutex_lock(lock);
+
+	sgt = &attach->sgt;
+	/* return previously mapped sg table */
+	if (attach->dir == dir) {
+		mutex_unlock(lock);
+		return sgt;
+	}
+
+	/* release any previous cache */
+	if (attach->dir != DMA_NONE) {
+		dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
+			attach->dir);
+		attach->dir = DMA_NONE;
+	}
+
+	/* mapping to the client with new direction */
+	ret = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, dir);
+	if (ret <= 0) {
+		pr_err("failed to map scatterlist\n");
+		mutex_unlock(lock);
+		return ERR_PTR(-EIO);
+	}
+
+	attach->dir = dir;
+
+	mutex_unlock(lock);
+
+	return sgt;
+}
+
+static void vb2_dc_dmabuf_ops_unmap(struct dma_buf_attachment *db_attach,
+	struct sg_table *sgt, enum dma_data_direction dir)
+{
+	/* nothing to be done here */
+}
+
+static void vb2_dc_dmabuf_ops_release(struct dma_buf *dbuf)
+{
+	/* drop reference obtained in vb2_dc_get_dmabuf */
+	vb2_dc_put(dbuf->priv);
+}
+
+static void *vb2_dc_dmabuf_ops_kmap(struct dma_buf *dbuf, unsigned long pgnum)
+{
+	struct vb2_dc_buf *buf = dbuf->priv;
+
+	return buf->vaddr + pgnum * PAGE_SIZE;
+}
+
+static void *vb2_dc_dmabuf_ops_vmap(struct dma_buf *dbuf)
+{
+	struct vb2_dc_buf *buf = dbuf->priv;
+
+	return buf->vaddr;
+}
+
+static int vb2_dc_dmabuf_ops_mmap(struct dma_buf *dbuf,
+	struct vm_area_struct *vma)
+{
+	/* Dummy support for mmap */
+	return -ENOTTY;
+}
+
+static struct dma_buf_ops vb2_dc_dmabuf_ops = {
+	.attach = vb2_dc_dmabuf_ops_attach,
+	.detach = vb2_dc_dmabuf_ops_detach,
+	.map_dma_buf = vb2_dc_dmabuf_ops_map,
+	.unmap_dma_buf = vb2_dc_dmabuf_ops_unmap,
+	.kmap = vb2_dc_dmabuf_ops_kmap,
+	.kmap_atomic = vb2_dc_dmabuf_ops_kmap,
+	.vmap = vb2_dc_dmabuf_ops_vmap,
+	.mmap = vb2_dc_dmabuf_ops_mmap,
+	.release = vb2_dc_dmabuf_ops_release,
+};
+
+static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf)
+{
+	int ret;
+	struct sg_table *sgt;
+
+	sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
+	if (!sgt) {
+		dev_err(buf->dev, "failed to alloc sg table\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	ret = dma_get_sgtable(buf->dev, sgt, buf->vaddr, buf->dma_addr,
+		buf->size);
+	if (ret < 0) {
+		dev_err(buf->dev, "failed to get scatterlist from DMA API\n");
+		kfree(sgt);
+		return ERR_PTR(ret);
+	}
+
+	return sgt;
+}
+
+static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv)
+{
+	struct vb2_dc_buf *buf = buf_priv;
+	struct dma_buf *dbuf;
+	struct sg_table *sgt = buf->sgt_base;
+
+	if (!sgt)
+		sgt = vb2_dc_get_base_sgt(buf);
+	if (WARN_ON(IS_ERR(sgt)))
+		return NULL;
+
+	/* cache base sgt for future use */
+	buf->sgt_base = sgt;
+
+	dbuf = dma_buf_export(buf, &vb2_dc_dmabuf_ops, buf->size, 0);
+	if (IS_ERR(dbuf))
+		return NULL;
+
+	/* dmabuf keeps reference to vb2 buffer */
+	atomic_inc(&buf->refcount);
+
+	return dbuf;
+}
+
+/*********************************************/
 /*       callbacks for USERPTR buffers       */
 /*********************************************/
 
@@ -519,6 +722,7 @@ static void *vb2_dc_attach_dmabuf(void *alloc_ctx, struct dma_buf *dbuf,
 const struct vb2_mem_ops vb2_dma_contig_memops = {
 	.alloc		= vb2_dc_alloc,
 	.put		= vb2_dc_put,
+	.get_dmabuf	= vb2_dc_get_dmabuf,
 	.cookie		= vb2_dc_cookie,
 	.vaddr		= vb2_dc_vaddr,
 	.mmap		= vb2_dc_mmap,
-- 
1.7.9.5


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

* [PATCHv8 21/26] v4l: vb2-dma-contig: add reference counting for a device from allocator context
  2012-08-14 15:34 [PATCHv8 00/26] Integration of videobuf2 with DMABUF Tomasz Stanislawski
                   ` (19 preceding siblings ...)
  2012-08-14 15:34 ` [PATCHv8 20/26] v4l: vb2-dma-contig: add support for DMABUF exporting Tomasz Stanislawski
@ 2012-08-14 15:34 ` Tomasz Stanislawski
  2012-08-15 20:04   ` Laurent Pinchart
  2012-08-14 15:34 ` [PATCHv8 22/26] media: vb2: fail if user ptr buffer is not correctly aligned Tomasz Stanislawski
                   ` (4 subsequent siblings)
  25 siblings, 1 reply; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-08-14 15:34 UTC (permalink / raw)
  To: linux-media, dri-devel
  Cc: airlied, m.szyprowski, t.stanislaws, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, hverkuil, remi, subashrp,
	mchehab, g.liakhovetski, dmitriyz, s.nawrocki, k.debski

This patch adds taking reference to the device for MMAP buffers.

Such buffers, may be exported using DMABUF mechanism. If the driver that
created a queue is unloaded then the queue is released, the device might be
released too.  However, buffers cannot be released if they are referenced by
DMABUF descriptor(s). The device pointer kept in a buffer must be valid for the
whole buffer's lifetime. Therefore MMAP buffers should take a reference to the
device to avoid risk of dangling pointers.

Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
---
 drivers/media/video/videobuf2-dma-contig.c |    5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/media/video/videobuf2-dma-contig.c b/drivers/media/video/videobuf2-dma-contig.c
index bb2b4ac8..d44766e 100644
--- a/drivers/media/video/videobuf2-dma-contig.c
+++ b/drivers/media/video/videobuf2-dma-contig.c
@@ -148,6 +148,7 @@ static void vb2_dc_put(void *buf_priv)
 		kfree(buf->sgt_base);
 	}
 	dma_free_coherent(buf->dev, buf->size, buf->vaddr, buf->dma_addr);
+	put_device(buf->dev);
 	kfree(buf);
 }
 
@@ -161,9 +162,13 @@ static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size)
 	if (!buf)
 		return ERR_PTR(-ENOMEM);
 
+	/* prevent the device from release while the buffer is exported */
+	get_device(dev);
+
 	buf->vaddr = dma_alloc_coherent(dev, size, &buf->dma_addr, GFP_KERNEL);
 	if (!buf->vaddr) {
 		dev_err(dev, "dma_alloc_coherent of size %ld failed\n", size);
+		put_device(dev);
 		kfree(buf);
 		return ERR_PTR(-ENOMEM);
 	}
-- 
1.7.9.5


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

* [PATCHv8 22/26] media: vb2: fail if user ptr buffer is not correctly aligned
  2012-08-14 15:34 [PATCHv8 00/26] Integration of videobuf2 with DMABUF Tomasz Stanislawski
                   ` (20 preceding siblings ...)
  2012-08-14 15:34 ` [PATCHv8 21/26] v4l: vb2-dma-contig: add reference counting for a device from allocator context Tomasz Stanislawski
@ 2012-08-14 15:34 ` Tomasz Stanislawski
  2012-08-15 20:20   ` Laurent Pinchart
  2012-08-14 15:34 ` [PATCHv8 23/26] v4l: vb2: add support for DMA_ATTR_NO_KERNEL_MAPPING Tomasz Stanislawski
                   ` (3 subsequent siblings)
  25 siblings, 1 reply; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-08-14 15:34 UTC (permalink / raw)
  To: linux-media, dri-devel
  Cc: airlied, m.szyprowski, t.stanislaws, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, hverkuil, remi, subashrp,
	mchehab, g.liakhovetski, dmitriyz, s.nawrocki, k.debski

From: Marek Szyprowski <m.szyprowski@samsung.com>

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/media/video/videobuf2-dma-contig.c |   10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/media/video/videobuf2-dma-contig.c b/drivers/media/video/videobuf2-dma-contig.c
index d44766e..11f4a46 100644
--- a/drivers/media/video/videobuf2-dma-contig.c
+++ b/drivers/media/video/videobuf2-dma-contig.c
@@ -498,6 +498,16 @@ static void *vb2_dc_get_userptr(void *alloc_ctx, unsigned long vaddr,
 	struct vm_area_struct *vma;
 	struct sg_table *sgt;
 	unsigned long contig_size;
+	unsigned long dma_align = dma_get_cache_alignment();
+
+	/*
+	 * DMA transfers are not reliable to buffers which
+	 * are not cache line aligned!
+	 */
+	if (vaddr & (dma_align - 1)) {
+		pr_err("userptr must be aligned to %lu bytes\n", dma_align);
+		return ERR_PTR(-EINVAL);
+	}
 
 	buf = kzalloc(sizeof *buf, GFP_KERNEL);
 	if (!buf)
-- 
1.7.9.5


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

* [PATCHv8 23/26] v4l: vb2: add support for DMA_ATTR_NO_KERNEL_MAPPING
  2012-08-14 15:34 [PATCHv8 00/26] Integration of videobuf2 with DMABUF Tomasz Stanislawski
                   ` (21 preceding siblings ...)
  2012-08-14 15:34 ` [PATCHv8 22/26] media: vb2: fail if user ptr buffer is not correctly aligned Tomasz Stanislawski
@ 2012-08-14 15:34 ` Tomasz Stanislawski
  2012-08-15 20:44   ` Laurent Pinchart
  2012-08-22 11:46   ` Hans Verkuil
  2012-08-14 15:34 ` [PATCHv8 24/26] v4l: s5p-fimc: support for dmabuf exporting Tomasz Stanislawski
                   ` (2 subsequent siblings)
  25 siblings, 2 replies; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-08-14 15:34 UTC (permalink / raw)
  To: linux-media, dri-devel
  Cc: airlied, m.szyprowski, t.stanislaws, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, hverkuil, remi, subashrp,
	mchehab, g.liakhovetski, dmitriyz, s.nawrocki, k.debski

From: Marek Szyprowski <m.szyprowski@samsung.com>

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/media/video/atmel-isi.c              |    2 +-
 drivers/media/video/blackfin/bfin_capture.c  |    2 +-
 drivers/media/video/marvell-ccic/mcam-core.c |    3 ++-
 drivers/media/video/mx2_camera.c             |    2 +-
 drivers/media/video/mx2_emmaprp.c            |    2 +-
 drivers/media/video/mx3_camera.c             |    2 +-
 drivers/media/video/s5p-fimc/fimc-core.c     |    2 +-
 drivers/media/video/s5p-fimc/fimc-lite.c     |    2 +-
 drivers/media/video/s5p-g2d/g2d.c            |    2 +-
 drivers/media/video/s5p-jpeg/jpeg-core.c     |    2 +-
 drivers/media/video/s5p-mfc/s5p_mfc.c        |    5 ++--
 drivers/media/video/s5p-tv/mixer_video.c     |    2 +-
 drivers/media/video/sh_mobile_ceu_camera.c   |    2 +-
 drivers/media/video/videobuf2-dma-contig.c   |   33 +++++++++++++++++++-------
 drivers/staging/media/dt3155v4l/dt3155v4l.c  |    2 +-
 include/media/videobuf2-dma-contig.h         |    4 +++-
 16 files changed, 44 insertions(+), 25 deletions(-)

diff --git a/drivers/media/video/atmel-isi.c b/drivers/media/video/atmel-isi.c
index 6274a91..9fb5283 100644
--- a/drivers/media/video/atmel-isi.c
+++ b/drivers/media/video/atmel-isi.c
@@ -1000,7 +1000,7 @@ static int __devinit atmel_isi_probe(struct platform_device *pdev)
 		list_add(&isi->dma_desc[i].list, &isi->dma_desc_head);
 	}
 
-	isi->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+	isi->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev, 0);
 	if (IS_ERR(isi->alloc_ctx)) {
 		ret = PTR_ERR(isi->alloc_ctx);
 		goto err_alloc_ctx;
diff --git a/drivers/media/video/blackfin/bfin_capture.c b/drivers/media/video/blackfin/bfin_capture.c
index 1677623..7e90b65 100644
--- a/drivers/media/video/blackfin/bfin_capture.c
+++ b/drivers/media/video/blackfin/bfin_capture.c
@@ -893,7 +893,7 @@ static int __devinit bcap_probe(struct platform_device *pdev)
 	}
 	bcap_dev->ppi->priv = bcap_dev;
 
-	bcap_dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+	bcap_dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev, 0);
 	if (IS_ERR(bcap_dev->alloc_ctx)) {
 		ret = PTR_ERR(bcap_dev->alloc_ctx);
 		goto err_free_ppi;
diff --git a/drivers/media/video/marvell-ccic/mcam-core.c b/drivers/media/video/marvell-ccic/mcam-core.c
index ce2b7b4..10d4db5 100644
--- a/drivers/media/video/marvell-ccic/mcam-core.c
+++ b/drivers/media/video/marvell-ccic/mcam-core.c
@@ -1111,7 +1111,8 @@ static int mcam_setup_vb2(struct mcam_camera *cam)
 #ifdef MCAM_MODE_DMA_CONTIG
 		vq->ops = &mcam_vb2_ops;
 		vq->mem_ops = &vb2_dma_contig_memops;
-		cam->vb_alloc_ctx = vb2_dma_contig_init_ctx(cam->dev);
+		cam->vb_alloc_ctx = vb2_dma_contig_init_ctx(cam->dev,
+			VB2_CREATE_VADDR);
 		vq->io_modes = VB2_MMAP | VB2_USERPTR;
 		cam->dma_setup = mcam_ctlr_dma_contig;
 		cam->frame_complete = mcam_dma_contig_done;
diff --git a/drivers/media/video/mx2_camera.c b/drivers/media/video/mx2_camera.c
index 637bde8..5c30302 100644
--- a/drivers/media/video/mx2_camera.c
+++ b/drivers/media/video/mx2_camera.c
@@ -1766,7 +1766,7 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)
 	if (cpu_is_mx25())
 		pcdev->soc_host.capabilities = SOCAM_HOST_CAP_STRIDE;
 
-	pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+	pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev, 0);
 	if (IS_ERR(pcdev->alloc_ctx)) {
 		err = PTR_ERR(pcdev->alloc_ctx);
 		goto eallocctx;
diff --git a/drivers/media/video/mx2_emmaprp.c b/drivers/media/video/mx2_emmaprp.c
index 2810015..23c6c42 100644
--- a/drivers/media/video/mx2_emmaprp.c
+++ b/drivers/media/video/mx2_emmaprp.c
@@ -962,7 +962,7 @@ static int emmaprp_probe(struct platform_device *pdev)
 			     0, MEM2MEM_NAME, pcdev) < 0)
 		goto rel_vdev;
 
-	pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+	pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev, 0);
 	if (IS_ERR(pcdev->alloc_ctx)) {
 		v4l2_err(&pcdev->v4l2_dev, "Failed to alloc vb2 context\n");
 		ret = PTR_ERR(pcdev->alloc_ctx);
diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c
index f13643d..882026f 100644
--- a/drivers/media/video/mx3_camera.c
+++ b/drivers/media/video/mx3_camera.c
@@ -1227,7 +1227,7 @@ static int __devinit mx3_camera_probe(struct platform_device *pdev)
 	soc_host->v4l2_dev.dev	= &pdev->dev;
 	soc_host->nr		= pdev->id;
 
-	mx3_cam->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+	mx3_cam->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev, 0);
 	if (IS_ERR(mx3_cam->alloc_ctx)) {
 		err = PTR_ERR(mx3_cam->alloc_ctx);
 		goto eallocctx;
diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c
index 1a44540..e1747f2 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.c
+++ b/drivers/media/video/s5p-fimc/fimc-core.c
@@ -929,7 +929,7 @@ static int fimc_probe(struct platform_device *pdev)
 	if (ret < 0)
 		goto err_sd;
 	/* Initialize contiguous memory allocator */
-	fimc->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+	fimc->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev, 0);
 	if (IS_ERR(fimc->alloc_ctx)) {
 		ret = PTR_ERR(fimc->alloc_ctx);
 		goto err_pm;
diff --git a/drivers/media/video/s5p-fimc/fimc-lite.c b/drivers/media/video/s5p-fimc/fimc-lite.c
index c5b57e8..ccc70a0 100644
--- a/drivers/media/video/s5p-fimc/fimc-lite.c
+++ b/drivers/media/video/s5p-fimc/fimc-lite.c
@@ -1459,7 +1459,7 @@ static int __devinit fimc_lite_probe(struct platform_device *pdev)
 	if (ret < 0)
 		goto err_sd;
 
-	fimc->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+	fimc->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev, 0);
 	if (IS_ERR(fimc->alloc_ctx)) {
 		ret = PTR_ERR(fimc->alloc_ctx);
 		goto err_pm;
diff --git a/drivers/media/video/s5p-g2d/g2d.c b/drivers/media/video/s5p-g2d/g2d.c
index 0edc2df..ad7837f 100644
--- a/drivers/media/video/s5p-g2d/g2d.c
+++ b/drivers/media/video/s5p-g2d/g2d.c
@@ -756,7 +756,7 @@ static int g2d_probe(struct platform_device *pdev)
 		goto put_clk_gate;
 	}
 
-	dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+	dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev, 0);
 	if (IS_ERR(dev->alloc_ctx)) {
 		ret = PTR_ERR(dev->alloc_ctx);
 		goto unprep_clk_gate;
diff --git a/drivers/media/video/s5p-jpeg/jpeg-core.c b/drivers/media/video/s5p-jpeg/jpeg-core.c
index be04d58..900059e 100644
--- a/drivers/media/video/s5p-jpeg/jpeg-core.c
+++ b/drivers/media/video/s5p-jpeg/jpeg-core.c
@@ -1372,7 +1372,7 @@ static int s5p_jpeg_probe(struct platform_device *pdev)
 		goto device_register_rollback;
 	}
 
-	jpeg->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+	jpeg->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev, VB2_CREATE_VADDR);
 	if (IS_ERR(jpeg->alloc_ctx)) {
 		v4l2_err(&jpeg->v4l2_dev, "Failed to init memory allocator\n");
 		ret = PTR_ERR(jpeg->alloc_ctx);
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc.c b/drivers/media/video/s5p-mfc/s5p_mfc.c
index e3e616d..9056a10 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/video/s5p-mfc/s5p_mfc.c
@@ -1018,12 +1018,13 @@ static int s5p_mfc_probe(struct platform_device *pdev)
 		goto err_res;
 	}
 
-	dev->alloc_ctx[0] = vb2_dma_contig_init_ctx(dev->mem_dev_l);
+	dev->alloc_ctx[0] = vb2_dma_contig_init_ctx(dev->mem_dev_l,
+		VB2_CREATE_VADDR);
 	if (IS_ERR_OR_NULL(dev->alloc_ctx[0])) {
 		ret = PTR_ERR(dev->alloc_ctx[0]);
 		goto err_res;
 	}
-	dev->alloc_ctx[1] = vb2_dma_contig_init_ctx(dev->mem_dev_r);
+	dev->alloc_ctx[1] = vb2_dma_contig_init_ctx(dev->mem_dev_r, 0);
 	if (IS_ERR_OR_NULL(dev->alloc_ctx[1])) {
 		ret = PTR_ERR(dev->alloc_ctx[1]);
 		goto err_mem_init_ctx_1;
diff --git a/drivers/media/video/s5p-tv/mixer_video.c b/drivers/media/video/s5p-tv/mixer_video.c
index da5b7a5..a7e3b53 100644
--- a/drivers/media/video/s5p-tv/mixer_video.c
+++ b/drivers/media/video/s5p-tv/mixer_video.c
@@ -78,7 +78,7 @@ int __devinit mxr_acquire_video(struct mxr_device *mdev,
 		goto fail;
 	}
 
-	mdev->alloc_ctx = vb2_dma_contig_init_ctx(mdev->dev);
+	mdev->alloc_ctx = vb2_dma_contig_init_ctx(mdev->dev, 0);
 	if (IS_ERR_OR_NULL(mdev->alloc_ctx)) {
 		mxr_err(mdev, "could not acquire vb2 allocator\n");
 		goto fail_v4l2_dev;
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
index 0baaf94..e085c27 100644
--- a/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/drivers/media/video/sh_mobile_ceu_camera.c
@@ -2158,7 +2158,7 @@ static int __devinit sh_mobile_ceu_probe(struct platform_device *pdev)
 	pcdev->ici.ops = &sh_mobile_ceu_host_ops;
 	pcdev->ici.capabilities = SOCAM_HOST_CAP_STRIDE;
 
-	pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+	pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev, 0);
 	if (IS_ERR(pcdev->alloc_ctx)) {
 		err = PTR_ERR(pcdev->alloc_ctx);
 		goto exit_free_clk;
diff --git a/drivers/media/video/videobuf2-dma-contig.c b/drivers/media/video/videobuf2-dma-contig.c
index 11f4a46..0729187 100644
--- a/drivers/media/video/videobuf2-dma-contig.c
+++ b/drivers/media/video/videobuf2-dma-contig.c
@@ -23,10 +23,12 @@
 
 struct vb2_dc_conf {
 	struct device		*dev;
+	unsigned int		flags;
 };
 
 struct vb2_dc_buf {
 	struct device			*dev;
+	unsigned int			flags;
 	void				*vaddr;
 	unsigned long			size;
 	dma_addr_t			dma_addr;
@@ -34,6 +36,7 @@ struct vb2_dc_buf {
 	struct sg_table			*dma_sgt;
 
 	/* MMAP related */
+	struct dma_attrs		dma_attrs;
 	struct vb2_vmarea_handler	handler;
 	atomic_t			refcount;
 	struct sg_table			*sgt_base;
@@ -98,6 +101,9 @@ static void *vb2_dc_vaddr(void *buf_priv)
 {
 	struct vb2_dc_buf *buf = buf_priv;
 
+	if (WARN_ON(~buf->flags & VB2_CREATE_VADDR))
+		return NULL;
+
 	return buf->vaddr;
 }
 
@@ -147,7 +153,8 @@ static void vb2_dc_put(void *buf_priv)
 		sg_free_table(buf->sgt_base);
 		kfree(buf->sgt_base);
 	}
-	dma_free_coherent(buf->dev, buf->size, buf->vaddr, buf->dma_addr);
+	dma_free_attrs(buf->dev, buf->size, buf->vaddr, buf->dma_addr,
+		       &buf->dma_attrs);
 	put_device(buf->dev);
 	kfree(buf);
 }
@@ -165,7 +172,14 @@ static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size)
 	/* prevent the device from release while the buffer is exported */
 	get_device(dev);
 
-	buf->vaddr = dma_alloc_coherent(dev, size, &buf->dma_addr, GFP_KERNEL);
+	/* set up alloca attributes */
+	init_dma_attrs(&buf->dma_attrs);
+	dma_set_attr(DMA_ATTR_WRITE_COMBINE, &buf->dma_attrs);
+	if (!(conf->flags & VB2_CREATE_VADDR))
+		dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &buf->dma_attrs);
+
+	buf->vaddr = dma_alloc_attrs(dev, size, &buf->dma_addr, GFP_KERNEL,
+				     &buf->dma_attrs);
 	if (!buf->vaddr) {
 		dev_err(dev, "dma_alloc_coherent of size %ld failed\n", size);
 		put_device(dev);
@@ -174,6 +188,7 @@ static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size)
 	}
 
 	buf->dev = dev;
+	buf->flags = conf->flags;
 	buf->size = size;
 
 	buf->handler.refcount = &buf->refcount;
@@ -201,9 +216,8 @@ static int vb2_dc_mmap(void *buf_priv, struct vm_area_struct *vma)
 	 */
 	vma->vm_pgoff = 0;
 
-	ret = dma_mmap_coherent(buf->dev, vma, buf->vaddr,
-		buf->dma_addr, buf->size);
-
+	ret = dma_mmap_attrs(buf->dev, vma, buf->vaddr, buf->dma_addr,
+			     buf->size, &buf->dma_attrs);
 	if (ret) {
 		pr_err("Remapping memory failed, error: %d\n", ret);
 		return ret;
@@ -345,7 +359,7 @@ static void *vb2_dc_dmabuf_ops_kmap(struct dma_buf *dbuf, unsigned long pgnum)
 {
 	struct vb2_dc_buf *buf = dbuf->priv;
 
-	return buf->vaddr + pgnum * PAGE_SIZE;
+	return buf->vaddr ? buf->vaddr + pgnum * PAGE_SIZE : NULL;
 }
 
 static void *vb2_dc_dmabuf_ops_vmap(struct dma_buf *dbuf)
@@ -385,8 +399,8 @@ static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf)
 		return ERR_PTR(-ENOMEM);
 	}
 
-	ret = dma_get_sgtable(buf->dev, sgt, buf->vaddr, buf->dma_addr,
-		buf->size);
+	ret = dma_get_sgtable_attrs(buf->dev, sgt, buf->vaddr, buf->dma_addr,
+		buf->size, &buf->dma_attrs);
 	if (ret < 0) {
 		dev_err(buf->dev, "failed to get scatterlist from DMA API\n");
 		kfree(sgt);
@@ -753,7 +767,7 @@ const struct vb2_mem_ops vb2_dma_contig_memops = {
 };
 EXPORT_SYMBOL_GPL(vb2_dma_contig_memops);
 
-void *vb2_dma_contig_init_ctx(struct device *dev)
+void *vb2_dma_contig_init_ctx(struct device *dev, unsigned int flags)
 {
 	struct vb2_dc_conf *conf;
 
@@ -762,6 +776,7 @@ void *vb2_dma_contig_init_ctx(struct device *dev)
 		return ERR_PTR(-ENOMEM);
 
 	conf->dev = dev;
+	conf->flags = flags;
 
 	return conf;
 }
diff --git a/drivers/staging/media/dt3155v4l/dt3155v4l.c b/drivers/staging/media/dt3155v4l/dt3155v4l.c
index 2e7b711..3fcf15a 100644
--- a/drivers/staging/media/dt3155v4l/dt3155v4l.c
+++ b/drivers/staging/media/dt3155v4l/dt3155v4l.c
@@ -232,7 +232,7 @@ dt3155_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
 	sizes[0] = img_width * img_height;
 	if (pd->q->alloc_ctx[0])
 		return 0;
-	ret = vb2_dma_contig_init_ctx(&pd->pdev->dev);
+	ret = vb2_dma_contig_init_ctx(&pd->pdev->dev, VB2_CREATE_VADDR);
 	if (IS_ERR(ret))
 		return PTR_ERR(ret);
 	pd->q->alloc_ctx[0] = ret;
diff --git a/include/media/videobuf2-dma-contig.h b/include/media/videobuf2-dma-contig.h
index 8197f87..8bf4b29 100644
--- a/include/media/videobuf2-dma-contig.h
+++ b/include/media/videobuf2-dma-contig.h
@@ -24,7 +24,9 @@ vb2_dma_contig_plane_dma_addr(struct vb2_buffer *vb, unsigned int plane_no)
 	return *addr;
 }
 
-void *vb2_dma_contig_init_ctx(struct device *dev);
+#define VB2_CREATE_VADDR	(1 << 0)
+
+void *vb2_dma_contig_init_ctx(struct device *dev, unsigned int flags);
 void vb2_dma_contig_cleanup_ctx(void *alloc_ctx);
 
 extern const struct vb2_mem_ops vb2_dma_contig_memops;
-- 
1.7.9.5


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

* [PATCHv8 24/26] v4l: s5p-fimc: support for dmabuf exporting
  2012-08-14 15:34 [PATCHv8 00/26] Integration of videobuf2 with DMABUF Tomasz Stanislawski
                   ` (22 preceding siblings ...)
  2012-08-14 15:34 ` [PATCHv8 23/26] v4l: vb2: add support for DMA_ATTR_NO_KERNEL_MAPPING Tomasz Stanislawski
@ 2012-08-14 15:34 ` Tomasz Stanislawski
  2012-08-14 15:34 ` [PATCHv8 25/26] v4l: s5p-tv: mixer: " Tomasz Stanislawski
  2012-08-14 15:34 ` [PATCHv8 26/26] v4l: s5p-mfc: " Tomasz Stanislawski
  25 siblings, 0 replies; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-08-14 15:34 UTC (permalink / raw)
  To: linux-media, dri-devel
  Cc: airlied, m.szyprowski, t.stanislaws, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, hverkuil, remi, subashrp,
	mchehab, g.liakhovetski, dmitriyz, s.nawrocki, k.debski

This patch enhances s5p-fimc with support for DMABUF exporting via
VIDIOC_EXPBUF ioctl.

Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 drivers/media/video/s5p-fimc/fimc-capture.c |    9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c
index 3fcaf7d..bdd2de5 100644
--- a/drivers/media/video/s5p-fimc/fimc-capture.c
+++ b/drivers/media/video/s5p-fimc/fimc-capture.c
@@ -1129,6 +1129,14 @@ static int fimc_cap_qbuf(struct file *file, void *priv,
 	return vb2_qbuf(&fimc->vid_cap.vbq, buf);
 }
 
+static int fimc_cap_expbuf(struct file *file, void *priv,
+			  struct v4l2_exportbuffer *eb)
+{
+	struct fimc_dev *fimc = video_drvdata(file);
+
+	return vb2_expbuf(&fimc->vid_cap.vbq, eb);
+}
+
 static int fimc_cap_dqbuf(struct file *file, void *priv,
 			   struct v4l2_buffer *buf)
 {
@@ -1253,6 +1261,7 @@ static const struct v4l2_ioctl_ops fimc_capture_ioctl_ops = {
 
 	.vidioc_qbuf			= fimc_cap_qbuf,
 	.vidioc_dqbuf			= fimc_cap_dqbuf,
+	.vidioc_expbuf			= fimc_cap_expbuf,
 
 	.vidioc_prepare_buf		= fimc_cap_prepare_buf,
 	.vidioc_create_bufs		= fimc_cap_create_bufs,
-- 
1.7.9.5


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

* [PATCHv8 25/26] v4l: s5p-tv: mixer: support for dmabuf exporting
  2012-08-14 15:34 [PATCHv8 00/26] Integration of videobuf2 with DMABUF Tomasz Stanislawski
                   ` (23 preceding siblings ...)
  2012-08-14 15:34 ` [PATCHv8 24/26] v4l: s5p-fimc: support for dmabuf exporting Tomasz Stanislawski
@ 2012-08-14 15:34 ` Tomasz Stanislawski
  2012-08-14 15:34 ` [PATCHv8 26/26] v4l: s5p-mfc: " Tomasz Stanislawski
  25 siblings, 0 replies; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-08-14 15:34 UTC (permalink / raw)
  To: linux-media, dri-devel
  Cc: airlied, m.szyprowski, t.stanislaws, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, hverkuil, remi, subashrp,
	mchehab, g.liakhovetski, dmitriyz, s.nawrocki, k.debski

This patch enhances s5p-tv with support for DMABUF exporting via
VIDIOC_EXPBUF ioctl.

Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 drivers/media/video/s5p-tv/mixer_video.c |   10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/media/video/s5p-tv/mixer_video.c b/drivers/media/video/s5p-tv/mixer_video.c
index a7e3b53..e5ec6bd 100644
--- a/drivers/media/video/s5p-tv/mixer_video.c
+++ b/drivers/media/video/s5p-tv/mixer_video.c
@@ -697,6 +697,15 @@ static int mxr_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
 	return vb2_dqbuf(&layer->vb_queue, p, file->f_flags & O_NONBLOCK);
 }
 
+static int mxr_expbuf(struct file *file, void *priv,
+	struct v4l2_exportbuffer *eb)
+{
+	struct mxr_layer *layer = video_drvdata(file);
+
+	mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__);
+	return vb2_expbuf(&layer->vb_queue, eb);
+}
+
 static int mxr_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
 {
 	struct mxr_layer *layer = video_drvdata(file);
@@ -724,6 +733,7 @@ static const struct v4l2_ioctl_ops mxr_ioctl_ops = {
 	.vidioc_querybuf = mxr_querybuf,
 	.vidioc_qbuf = mxr_qbuf,
 	.vidioc_dqbuf = mxr_dqbuf,
+	.vidioc_expbuf = mxr_expbuf,
 	/* Streaming control */
 	.vidioc_streamon = mxr_streamon,
 	.vidioc_streamoff = mxr_streamoff,
-- 
1.7.9.5


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

* [PATCHv8 26/26] v4l: s5p-mfc: support for dmabuf exporting
  2012-08-14 15:34 [PATCHv8 00/26] Integration of videobuf2 with DMABUF Tomasz Stanislawski
                   ` (24 preceding siblings ...)
  2012-08-14 15:34 ` [PATCHv8 25/26] v4l: s5p-tv: mixer: " Tomasz Stanislawski
@ 2012-08-14 15:34 ` Tomasz Stanislawski
  25 siblings, 0 replies; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-08-14 15:34 UTC (permalink / raw)
  To: linux-media, dri-devel
  Cc: airlied, m.szyprowski, t.stanislaws, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, hverkuil, remi, subashrp,
	mchehab, g.liakhovetski, dmitriyz, s.nawrocki, k.debski

This patch enhances s5p-mfc with support for DMABUF exporting via
VIDIOC_EXPBUF ioctl.

Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
CC: Kamil Debski <k.debski@samsung.com>
---
 drivers/media/video/s5p-mfc/s5p_mfc_dec.c |   18 ++++++++++++++++++
 drivers/media/video/s5p-mfc/s5p_mfc_enc.c |   18 ++++++++++++++++++
 2 files changed, 36 insertions(+)

diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_dec.c b/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
index c5d567f..b375209 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
@@ -570,6 +570,23 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
 	return -EINVAL;
 }
 
+/* Export DMA buffer */
+static int vidioc_expbuf(struct file *file, void *priv,
+	struct v4l2_exportbuffer *eb)
+{
+	struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+	int ret;
+
+	if (eb->mem_offset < DST_QUEUE_OFF_BASE)
+		return vb2_expbuf(&ctx->vq_src, eb);
+
+	eb->mem_offset -= DST_QUEUE_OFF_BASE;
+	ret = vb2_expbuf(&ctx->vq_dst, eb);
+	eb->mem_offset += DST_QUEUE_OFF_BASE;
+
+	return ret;
+}
+
 /* Stream on */
 static int vidioc_streamon(struct file *file, void *priv,
 			   enum v4l2_buf_type type)
@@ -745,6 +762,7 @@ static const struct v4l2_ioctl_ops s5p_mfc_dec_ioctl_ops = {
 	.vidioc_querybuf = vidioc_querybuf,
 	.vidioc_qbuf = vidioc_qbuf,
 	.vidioc_dqbuf = vidioc_dqbuf,
+	.vidioc_expbuf = vidioc_expbuf,
 	.vidioc_streamon = vidioc_streamon,
 	.vidioc_streamoff = vidioc_streamoff,
 	.vidioc_g_crop = vidioc_g_crop,
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_enc.c b/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
index aa1c244..df3da50 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
@@ -1142,6 +1142,23 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
 	return -EINVAL;
 }
 
+/* Export DMA buffer */
+static int vidioc_expbuf(struct file *file, void *priv,
+	struct v4l2_exportbuffer *eb)
+{
+	struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+	int ret;
+
+	if (eb->mem_offset < DST_QUEUE_OFF_BASE)
+		return vb2_expbuf(&ctx->vq_src, eb);
+
+	eb->mem_offset -= DST_QUEUE_OFF_BASE;
+	ret = vb2_expbuf(&ctx->vq_dst, eb);
+	eb->mem_offset += DST_QUEUE_OFF_BASE;
+
+	return ret;
+}
+
 /* Stream on */
 static int vidioc_streamon(struct file *file, void *priv,
 			   enum v4l2_buf_type type)
@@ -1487,6 +1504,7 @@ static const struct v4l2_ioctl_ops s5p_mfc_enc_ioctl_ops = {
 	.vidioc_querybuf = vidioc_querybuf,
 	.vidioc_qbuf = vidioc_qbuf,
 	.vidioc_dqbuf = vidioc_dqbuf,
+	.vidioc_expbuf = vidioc_expbuf,
 	.vidioc_streamon = vidioc_streamon,
 	.vidioc_streamoff = vidioc_streamoff,
 	.vidioc_s_parm = vidioc_s_parm,
-- 
1.7.9.5


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

* Re: [PATCHv8 06/26] v4l: vb2-dma-contig: remove reference of alloc_ctx from a buffer
  2012-08-14 15:34 ` [PATCHv8 06/26] v4l: vb2-dma-contig: remove reference of alloc_ctx from a buffer Tomasz Stanislawski
@ 2012-08-15 18:24   ` Laurent Pinchart
  0 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2012-08-15 18:24 UTC (permalink / raw)
  To: Tomasz Stanislawski
  Cc: linux-media, dri-devel, airlied, m.szyprowski, kyungmin.park,
	sumit.semwal, daeinki, daniel.vetter, robdclark, pawel,
	linaro-mm-sig, hverkuil, remi, subashrp, mchehab, g.liakhovetski,
	dmitriyz, s.nawrocki, k.debski

Hi Tomasz,

Thanks for the patch.

On Tuesday 14 August 2012 17:34:36 Tomasz Stanislawski wrote:
> This patch removes a reference to alloc_ctx from an instance of a DMA
> contiguous buffer. It helps to avoid a risk of a dangling pointer if the
> context is released while the buffer is still valid. Moreover it removes one
> dereference step while accessing a device structure.
> 
> Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>

Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> ---
>  drivers/media/video/videobuf2-dma-contig.c |   13 ++++++-------
>  1 file changed, 6 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/media/video/videobuf2-dma-contig.c
> b/drivers/media/video/videobuf2-dma-contig.c index a05784f..20c95da 100644
> --- a/drivers/media/video/videobuf2-dma-contig.c
> +++ b/drivers/media/video/videobuf2-dma-contig.c
> @@ -23,7 +23,7 @@ struct vb2_dc_conf {
>  };
> 
>  struct vb2_dc_buf {
> -	struct vb2_dc_conf		*conf;
> +	struct device			*dev;
>  	void				*vaddr;
>  	dma_addr_t			dma_addr;
>  	unsigned long			size;
> @@ -37,22 +37,21 @@ static void vb2_dc_put(void *buf_priv);
>  static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size)
>  {
>  	struct vb2_dc_conf *conf = alloc_ctx;
> +	struct device *dev = conf->dev;
>  	struct vb2_dc_buf *buf;
> 
>  	buf = kzalloc(sizeof *buf, GFP_KERNEL);
>  	if (!buf)
>  		return ERR_PTR(-ENOMEM);
> 
> -	buf->vaddr = dma_alloc_coherent(conf->dev, size, &buf->dma_addr,
> -					GFP_KERNEL);
> +	buf->vaddr = dma_alloc_coherent(dev, size, &buf->dma_addr, GFP_KERNEL);
>  	if (!buf->vaddr) {
> -		dev_err(conf->dev, "dma_alloc_coherent of size %ld failed\n",
> -			size);
> +		dev_err(dev, "dma_alloc_coherent of size %ld failed\n", size);
>  		kfree(buf);
>  		return ERR_PTR(-ENOMEM);
>  	}
> 
> -	buf->conf = conf;
> +	buf->dev = dev;
>  	buf->size = size;
> 
>  	buf->handler.refcount = &buf->refcount;
> @@ -69,7 +68,7 @@ static void vb2_dc_put(void *buf_priv)
>  	struct vb2_dc_buf *buf = buf_priv;
> 
>  	if (atomic_dec_and_test(&buf->refcount)) {
> -		dma_free_coherent(buf->conf->dev, buf->size, buf->vaddr,
> +		dma_free_coherent(buf->dev, buf->size, buf->vaddr,
>  				  buf->dma_addr);
>  		kfree(buf);
>  	}
-- 
Regards,

Laurent Pinchart


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

* Re: [PATCHv8 10/26] v4l: vb2-dma-contig: add prepare/finish to dma-contig allocator
  2012-08-14 15:34 ` [PATCHv8 10/26] v4l: vb2-dma-contig: add prepare/finish to dma-contig allocator Tomasz Stanislawski
@ 2012-08-15 18:35   ` Laurent Pinchart
  2012-08-15 18:39     ` [Linaro-mm-sig] " Laurent Pinchart
  0 siblings, 1 reply; 58+ messages in thread
From: Laurent Pinchart @ 2012-08-15 18:35 UTC (permalink / raw)
  To: Tomasz Stanislawski
  Cc: linux-media, dri-devel, airlied, m.szyprowski, kyungmin.park,
	sumit.semwal, daeinki, daniel.vetter, robdclark, pawel,
	linaro-mm-sig, hverkuil, remi, subashrp, mchehab, g.liakhovetski,
	dmitriyz, s.nawrocki, k.debski

Hi Tomasz,

Thanks for the patch.

On Tuesday 14 August 2012 17:34:40 Tomasz Stanislawski wrote:
> From: Marek Szyprowski <m.szyprowski@samsung.com>
> 
> Add prepare/finish callbacks to vb2-dma-contig allocator.
> 
> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>

As for v7,

Laurent Pinchart <laurent.pinchart@ideasonboard.com>

:-)

> ---
>  drivers/media/video/videobuf2-dma-contig.c |   24 ++++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
> 
> diff --git a/drivers/media/video/videobuf2-dma-contig.c
> b/drivers/media/video/videobuf2-dma-contig.c index 8486e06..494a824 100644
> --- a/drivers/media/video/videobuf2-dma-contig.c
> +++ b/drivers/media/video/videobuf2-dma-contig.c
> @@ -103,6 +103,28 @@ static unsigned int vb2_dc_num_users(void *buf_priv)
>  	return atomic_read(&buf->refcount);
>  }
> 
> +static void vb2_dc_prepare(void *buf_priv)
> +{
> +	struct vb2_dc_buf *buf = buf_priv;
> +	struct sg_table *sgt = buf->dma_sgt;
> +
> +	if (!sgt)
> +		return;
> +
> +	dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
> +}
> +
> +static void vb2_dc_finish(void *buf_priv)
> +{
> +	struct vb2_dc_buf *buf = buf_priv;
> +	struct sg_table *sgt = buf->dma_sgt;
> +
> +	if (!sgt)
> +		return;
> +
> +	dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
> +}
> +
>  /*********************************************/
>  /*        callbacks for MMAP buffers         */
>  /*********************************************/
> @@ -366,6 +388,8 @@ const struct vb2_mem_ops vb2_dma_contig_memops = {
>  	.mmap		= vb2_dc_mmap,
>  	.get_userptr	= vb2_dc_get_userptr,
>  	.put_userptr	= vb2_dc_put_userptr,
> +	.prepare	= vb2_dc_prepare,
> +	.finish		= vb2_dc_finish,
>  	.num_users	= vb2_dc_num_users,
>  };
>  EXPORT_SYMBOL_GPL(vb2_dma_contig_memops);

-- 
Regards,

Laurent Pinchart


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

* Re: [Linaro-mm-sig] [PATCHv8 10/26] v4l: vb2-dma-contig: add prepare/finish to dma-contig allocator
  2012-08-15 18:35   ` Laurent Pinchart
@ 2012-08-15 18:39     ` Laurent Pinchart
  0 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2012-08-15 18:39 UTC (permalink / raw)
  To: linaro-mm-sig
  Cc: Tomasz Stanislawski, k.debski, pawel, sumit.semwal, mchehab,
	robdclark, dri-devel, kyungmin.park, dmitriyz, s.nawrocki,
	airlied, remi, linux-media, g.liakhovetski

On Wednesday 15 August 2012 20:35:28 Laurent Pinchart wrote:
> On Tuesday 14 August 2012 17:34:40 Tomasz Stanislawski wrote:
> > From: Marek Szyprowski <m.szyprowski@samsung.com>
> > 
> > Add prepare/finish callbacks to vb2-dma-contig allocator.
> > 
> > Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> 
> As for v7,
> 
> Laurent Pinchart <laurent.pinchart@ideasonboard.com>

s/^/Acked-by: /

-- 
Regards,

Laurent Pinchart


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

* Re: [PATCHv8 12/26] v4l: vb2-vmalloc: add support for dmabuf importing
  2012-08-14 15:34 ` [PATCHv8 12/26] v4l: vb2-vmalloc: add support for dmabuf importing Tomasz Stanislawski
@ 2012-08-15 18:39   ` Laurent Pinchart
  0 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2012-08-15 18:39 UTC (permalink / raw)
  To: Tomasz Stanislawski
  Cc: linux-media, dri-devel, airlied, m.szyprowski, kyungmin.park,
	sumit.semwal, daeinki, daniel.vetter, robdclark, pawel,
	linaro-mm-sig, hverkuil, remi, subashrp, mchehab, g.liakhovetski,
	dmitriyz, s.nawrocki, k.debski

Hi Tomasz,

Thanks for the patch.

On Tuesday 14 August 2012 17:34:42 Tomasz Stanislawski wrote:
> This patch adds support for importing DMABUF files for
> vmalloc allocator in Videobuf2.
> 
> Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>

Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

-- 
Regards,

Laurent Pinchart


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

* Re: [PATCHv8 18/26] v4l: add buffer exporting via dmabuf
  2012-08-14 15:34 ` [PATCHv8 18/26] v4l: add buffer exporting via dmabuf Tomasz Stanislawski
@ 2012-08-15 19:08   ` Laurent Pinchart
  2012-08-22 11:41   ` Hans Verkuil
  1 sibling, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2012-08-15 19:08 UTC (permalink / raw)
  To: Tomasz Stanislawski
  Cc: linux-media, dri-devel, airlied, m.szyprowski, kyungmin.park,
	sumit.semwal, daeinki, daniel.vetter, robdclark, pawel,
	linaro-mm-sig, hverkuil, remi, subashrp, mchehab, g.liakhovetski,
	dmitriyz, s.nawrocki, k.debski

Hi Tomasz,

Thanks for the patch.

On Tuesday 14 August 2012 17:34:48 Tomasz Stanislawski wrote:
> This patch adds extension to V4L2 api. It allow to export a mmap buffer as
> file descriptor. New ioctl VIDIOC_EXPBUF is added. It takes a buffer offset
> used by mmap and return a file descriptor on success.
> 
> Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> ---
>  drivers/media/video/v4l2-compat-ioctl32.c |    1 +
>  drivers/media/video/v4l2-dev.c            |    1 +
>  drivers/media/video/v4l2-ioctl.c          |   15 +++++++++++++++
>  include/linux/videodev2.h                 |   26 ++++++++++++++++++++++++++
>  include/media/v4l2-ioctl.h                |    2 ++
>  5 files changed, 45 insertions(+)

[snip]

> b/include/linux/videodev2.h index 7f918dc..b5d058b 100644
> --- a/include/linux/videodev2.h
> +++ b/include/linux/videodev2.h
> @@ -688,6 +688,31 @@ struct v4l2_buffer {
>  #define V4L2_BUF_FLAG_NO_CACHE_INVALIDATE	0x0800
>  #define V4L2_BUF_FLAG_NO_CACHE_CLEAN		0x1000
> 
> +/**
> + * struct v4l2_exportbuffer - export of video buffer as DMABUF file
> descriptor
> + *
> + * @fd:		file descriptor associated with DMABUF (set by driver)
> + * @mem_offset:	buffer memory offset as returned by VIDIOC_QUERYBUF in
> struct
> + *		v4l2_buffer::m.offset (for single-plane formats) or
> + *		v4l2_plane::m.offset (for multi-planar formats)
> + * @flags:	flags for newly created file, currently only O_CLOEXEC is
> + *		supported, refer to manual of open syscall for more details
> + *
> + * Contains data used for exporting a video buffer as DMABUF file
> descriptor.
> + * The buffer is identified by a 'cookie' returned by VIDIOC_QUERYBUF
> + * (identical to the cookie used to mmap() the buffer to userspace). All
> + * reserved fields must be set to zero. The field reserved0 is expected to
> + * become a structure 'type' allowing an alternative layout of the
> structure
> + * content. Therefore this field should not be used for any other
> extensions.
> + */
> +struct v4l2_exportbuffer {
> +	__u32		fd;
> +	__u32		reserved0;
> +	__u32		mem_offset;
> +	__u32		flags;
> +	__u32		reserved[12];
> +};

As Hans recently pointed out, this could be layed out as

struct v4l2_exportbuffer {
	__u32		fd;	
	__u32		memory;
	union {
		__u32		mem_offset;
		unsigned long	userptr;
	} m;
	__u32		flags;
	__u32		reserved[12];
};

32-bit compatibility code would need to be added.

-- 
Regards,

Laurent Pinchart


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

* Re: [PATCHv8 21/26] v4l: vb2-dma-contig: add reference counting for a device from allocator context
  2012-08-14 15:34 ` [PATCHv8 21/26] v4l: vb2-dma-contig: add reference counting for a device from allocator context Tomasz Stanislawski
@ 2012-08-15 20:04   ` Laurent Pinchart
  2012-09-27 15:19     ` Tomasz Stanislawski
  0 siblings, 1 reply; 58+ messages in thread
From: Laurent Pinchart @ 2012-08-15 20:04 UTC (permalink / raw)
  To: Tomasz Stanislawski
  Cc: linux-media, dri-devel, airlied, m.szyprowski, kyungmin.park,
	sumit.semwal, daeinki, daniel.vetter, robdclark, pawel,
	linaro-mm-sig, hverkuil, remi, subashrp, mchehab, g.liakhovetski,
	dmitriyz, s.nawrocki, k.debski

Hi Tomasz,

Thanks for the patch.

On Tuesday 14 August 2012 17:34:51 Tomasz Stanislawski wrote:
> This patch adds taking reference to the device for MMAP buffers.
> 
> Such buffers, may be exported using DMABUF mechanism. If the driver that
> created a queue is unloaded then the queue is released, the device might be
> released too.  However, buffers cannot be released if they are referenced by
> DMABUF descriptor(s). The device pointer kept in a buffer must be valid for
> the whole buffer's lifetime. Therefore MMAP buffers should take a reference
> to the device to avoid risk of dangling pointers.

That patch looks good, but that approach won't scale if we ever need a more 
complex context that can't be copied. We can ignore that for now, but if we 
decide to support "orphan" vb2 buffers, that's an issue we need to be aware of 
as it might come back to bite us in the future.

I assume that this patch requires your dmabuf owner patch to fix the orphan 
buffer case properly.

> Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
> ---
>  drivers/media/video/videobuf2-dma-contig.c |    5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/drivers/media/video/videobuf2-dma-contig.c
> b/drivers/media/video/videobuf2-dma-contig.c index bb2b4ac8..d44766e 100644
> --- a/drivers/media/video/videobuf2-dma-contig.c
> +++ b/drivers/media/video/videobuf2-dma-contig.c
> @@ -148,6 +148,7 @@ static void vb2_dc_put(void *buf_priv)
>  		kfree(buf->sgt_base);
>  	}
>  	dma_free_coherent(buf->dev, buf->size, buf->vaddr, buf->dma_addr);
> +	put_device(buf->dev);
>  	kfree(buf);
>  }
> 
> @@ -161,9 +162,13 @@ static void *vb2_dc_alloc(void *alloc_ctx, unsigned
> long size) if (!buf)
>  		return ERR_PTR(-ENOMEM);
> 
> +	/* prevent the device from release while the buffer is exported */
> +	get_device(dev);
> +
>  	buf->vaddr = dma_alloc_coherent(dev, size, &buf->dma_addr, GFP_KERNEL);
>  	if (!buf->vaddr) {
>  		dev_err(dev, "dma_alloc_coherent of size %ld failed\n", size);
> +		put_device(dev);
>  		kfree(buf);
>  		return ERR_PTR(-ENOMEM);
>  	}
-- 
Regards,

Laurent Pinchart


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

* Re: [PATCHv8 22/26] media: vb2: fail if user ptr buffer is not correctly aligned
  2012-08-14 15:34 ` [PATCHv8 22/26] media: vb2: fail if user ptr buffer is not correctly aligned Tomasz Stanislawski
@ 2012-08-15 20:20   ` Laurent Pinchart
  0 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2012-08-15 20:20 UTC (permalink / raw)
  To: Tomasz Stanislawski
  Cc: linux-media, dri-devel, airlied, m.szyprowski, kyungmin.park,
	sumit.semwal, daeinki, daniel.vetter, robdclark, pawel,
	linaro-mm-sig, hverkuil, remi, subashrp, mchehab, g.liakhovetski,
	dmitriyz, s.nawrocki, k.debski

Hi Tomasz,

Thanks for the patch.

On Tuesday 14 August 2012 17:34:52 Tomasz Stanislawski wrote:
> From: Marek Szyprowski <m.szyprowski@samsung.com>
> 
> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> ---
>  drivers/media/video/videobuf2-dma-contig.c |   10 ++++++++++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/drivers/media/video/videobuf2-dma-contig.c
> b/drivers/media/video/videobuf2-dma-contig.c index d44766e..11f4a46 100644
> --- a/drivers/media/video/videobuf2-dma-contig.c
> +++ b/drivers/media/video/videobuf2-dma-contig.c
> @@ -498,6 +498,16 @@ static void *vb2_dc_get_userptr(void *alloc_ctx,
> unsigned long vaddr, struct vm_area_struct *vma;
>  	struct sg_table *sgt;
>  	unsigned long contig_size;
> +	unsigned long dma_align = dma_get_cache_alignment();
> +
> +	/*
> +	 * DMA transfers are not reliable to buffers which
> +	 * are not cache line aligned!
> +	 */

Are you scared of going near the 80 columns limit ? :-)

> +	if (vaddr & (dma_align - 1)) {

You could use the IS_ALIGNED macro here, but that might just be nitpicking.

> +		pr_err("userptr must be aligned to %lu bytes\n", dma_align);
> +		return ERR_PTR(-EINVAL);
> +	}

Shouldn't you also check that the size is a multiple of dma_align ?

>  	buf = kzalloc(sizeof *buf, GFP_KERNEL);
>  	if (!buf)

-- 
Regards,

Laurent Pinchart


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

* Re: [PATCHv8 23/26] v4l: vb2: add support for DMA_ATTR_NO_KERNEL_MAPPING
  2012-08-14 15:34 ` [PATCHv8 23/26] v4l: vb2: add support for DMA_ATTR_NO_KERNEL_MAPPING Tomasz Stanislawski
@ 2012-08-15 20:44   ` Laurent Pinchart
  2012-08-22 11:46   ` Hans Verkuil
  1 sibling, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2012-08-15 20:44 UTC (permalink / raw)
  To: Tomasz Stanislawski
  Cc: linux-media, dri-devel, airlied, m.szyprowski, kyungmin.park,
	sumit.semwal, daeinki, daniel.vetter, robdclark, pawel,
	linaro-mm-sig, hverkuil, remi, subashrp, mchehab, g.liakhovetski,
	dmitriyz, s.nawrocki, k.debski

Hi Tomasz,

Thanks for the patch.

On Tuesday 14 August 2012 17:34:53 Tomasz Stanislawski wrote:
> From: Marek Szyprowski <m.szyprowski@samsung.com>
> 
> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> ---
>  drivers/media/video/atmel-isi.c              |    2 +-
>  drivers/media/video/blackfin/bfin_capture.c  |    2 +-
>  drivers/media/video/marvell-ccic/mcam-core.c |    3 ++-
>  drivers/media/video/mx2_camera.c             |    2 +-
>  drivers/media/video/mx2_emmaprp.c            |    2 +-
>  drivers/media/video/mx3_camera.c             |    2 +-
>  drivers/media/video/s5p-fimc/fimc-core.c     |    2 +-
>  drivers/media/video/s5p-fimc/fimc-lite.c     |    2 +-
>  drivers/media/video/s5p-g2d/g2d.c            |    2 +-
>  drivers/media/video/s5p-jpeg/jpeg-core.c     |    2 +-
>  drivers/media/video/s5p-mfc/s5p_mfc.c        |    5 ++--
>  drivers/media/video/s5p-tv/mixer_video.c     |    2 +-
>  drivers/media/video/sh_mobile_ceu_camera.c   |    2 +-
>  drivers/media/video/videobuf2-dma-contig.c   |   33 ++++++++++++++++-------
>  drivers/staging/media/dt3155v4l/dt3155v4l.c  |    2 +-
>  include/media/videobuf2-dma-contig.h         |    4 +++-
>  16 files changed, 44 insertions(+), 25 deletions(-)

[snip]

> diff --git a/drivers/media/video/videobuf2-dma-contig.c
> b/drivers/media/video/videobuf2-dma-contig.c index 11f4a46..0729187 100644
> --- a/drivers/media/video/videobuf2-dma-contig.c
> +++ b/drivers/media/video/videobuf2-dma-contig.c
> @@ -23,10 +23,12 @@
> 
>  struct vb2_dc_conf {
>  	struct device		*dev;
> +	unsigned int		flags;
>  };
> 
>  struct vb2_dc_buf {
>  	struct device			*dev;
> +	unsigned int			flags;
>  	void				*vaddr;
>  	unsigned long			size;
>  	dma_addr_t			dma_addr;
> @@ -34,6 +36,7 @@ struct vb2_dc_buf {
>  	struct sg_table			*dma_sgt;
> 
>  	/* MMAP related */
> +	struct dma_attrs		dma_attrs;
>  	struct vb2_vmarea_handler	handler;
>  	atomic_t			refcount;
>  	struct sg_table			*sgt_base;
> @@ -98,6 +101,9 @@ static void *vb2_dc_vaddr(void *buf_priv)
>  {
>  	struct vb2_dc_buf *buf = buf_priv;
> 
> +	if (WARN_ON(~buf->flags & VB2_CREATE_VADDR))
> +		return NULL;
> +
>  	return buf->vaddr;
>  }
> 
> @@ -147,7 +153,8 @@ static void vb2_dc_put(void *buf_priv)
>  		sg_free_table(buf->sgt_base);
>  		kfree(buf->sgt_base);
>  	}
> -	dma_free_coherent(buf->dev, buf->size, buf->vaddr, buf->dma_addr);
> +	dma_free_attrs(buf->dev, buf->size, buf->vaddr, buf->dma_addr,
> +		       &buf->dma_attrs);
>  	put_device(buf->dev);
>  	kfree(buf);
>  }
> @@ -165,7 +172,14 @@ static void *vb2_dc_alloc(void *alloc_ctx, unsigned
> long size) /* prevent the device from release while the buffer is exported
> */ get_device(dev);
> 
> -	buf->vaddr = dma_alloc_coherent(dev, size, &buf->dma_addr, GFP_KERNEL);
> +	/* set up alloca attributes */
> +	init_dma_attrs(&buf->dma_attrs);
> +	dma_set_attr(DMA_ATTR_WRITE_COMBINE, &buf->dma_attrs);
> +	if (!(conf->flags & VB2_CREATE_VADDR))
> +		dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &buf->dma_attrs);
> +
> +	buf->vaddr = dma_alloc_attrs(dev, size, &buf->dma_addr, GFP_KERNEL,
> +				     &buf->dma_attrs);

What address does dma_alloc_attrs() return when the DMA_ATTR_NO_KERNEL_MAPPING 
attribute is set ?

>  	if (!buf->vaddr) {
>  		dev_err(dev, "dma_alloc_coherent of size %ld failed\n", size);
>  		put_device(dev);
> @@ -174,6 +188,7 @@ static void *vb2_dc_alloc(void *alloc_ctx, unsigned long
> size) }
> 
>  	buf->dev = dev;
> +	buf->flags = conf->flags;
>  	buf->size = size;
> 
>  	buf->handler.refcount = &buf->refcount;
> @@ -201,9 +216,8 @@ static int vb2_dc_mmap(void *buf_priv, struct
> vm_area_struct *vma) */
>  	vma->vm_pgoff = 0;
> 
> -	ret = dma_mmap_coherent(buf->dev, vma, buf->vaddr,
> -		buf->dma_addr, buf->size);
> -
> +	ret = dma_mmap_attrs(buf->dev, vma, buf->vaddr, buf->dma_addr,
> +			     buf->size, &buf->dma_attrs);
>  	if (ret) {
>  		pr_err("Remapping memory failed, error: %d\n", ret);
>  		return ret;
> @@ -345,7 +359,7 @@ static void *vb2_dc_dmabuf_ops_kmap(struct dma_buf
> *dbuf, unsigned long pgnum) {
>  	struct vb2_dc_buf *buf = dbuf->priv;
> 
> -	return buf->vaddr + pgnum * PAGE_SIZE;
> +	return buf->vaddr ? buf->vaddr + pgnum * PAGE_SIZE : NULL;

Does this mean that a V4L2 driver that doesn't need a kernel mapping will not 
be able to export buffers to devices that require such a mapping ?

>  }
> 
>  static void *vb2_dc_dmabuf_ops_vmap(struct dma_buf *dbuf)
> @@ -385,8 +399,8 @@ static struct sg_table *vb2_dc_get_base_sgt(struct
> vb2_dc_buf *buf) return ERR_PTR(-ENOMEM);
>  	}
> 
> -	ret = dma_get_sgtable(buf->dev, sgt, buf->vaddr, buf->dma_addr,
> -		buf->size);
> +	ret = dma_get_sgtable_attrs(buf->dev, sgt, buf->vaddr, buf->dma_addr,
> +		buf->size, &buf->dma_attrs);
>  	if (ret < 0) {
>  		dev_err(buf->dev, "failed to get scatterlist from DMA API\n");
>  		kfree(sgt);
> @@ -753,7 +767,7 @@ const struct vb2_mem_ops vb2_dma_contig_memops = {
>  };
>  EXPORT_SYMBOL_GPL(vb2_dma_contig_memops);
> 
> -void *vb2_dma_contig_init_ctx(struct device *dev)
> +void *vb2_dma_contig_init_ctx(struct device *dev, unsigned int flags)
>  {
>  	struct vb2_dc_conf *conf;
> 
> @@ -762,6 +776,7 @@ void *vb2_dma_contig_init_ctx(struct device *dev)
>  		return ERR_PTR(-ENOMEM);
> 
>  	conf->dev = dev;
> +	conf->flags = flags;
> 
>  	return conf;
>  }

[snip]

> diff --git a/include/media/videobuf2-dma-contig.h
> b/include/media/videobuf2-dma-contig.h index 8197f87..8bf4b29 100644
> --- a/include/media/videobuf2-dma-contig.h
> +++ b/include/media/videobuf2-dma-contig.h
> @@ -24,7 +24,9 @@ vb2_dma_contig_plane_dma_addr(struct vb2_buffer *vb,
> unsigned int plane_no) return *addr;
>  }
> 
> -void *vb2_dma_contig_init_ctx(struct device *dev);
> +#define VB2_CREATE_VADDR	(1 << 0)
> +

Would it make sense to either move the flag to a common vb2 header or to call 
it VB2_DMA_CONTIG_CREATE_VADDR ?

> +void *vb2_dma_contig_init_ctx(struct device *dev, unsigned int flags);
>  void vb2_dma_contig_cleanup_ctx(void *alloc_ctx);
> 
>  extern const struct vb2_mem_ops vb2_dma_contig_memops;

-- 
Regards,

Laurent Pinchart


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

* Re: [PATCHv8 20/26] v4l: vb2-dma-contig: add support for DMABUF exporting
  2012-08-14 15:34 ` [PATCHv8 20/26] v4l: vb2-dma-contig: add support for DMABUF exporting Tomasz Stanislawski
@ 2012-08-21 10:03   ` Laurent Pinchart
  2012-08-21 13:47     ` Tomasz Stanislawski
  0 siblings, 1 reply; 58+ messages in thread
From: Laurent Pinchart @ 2012-08-21 10:03 UTC (permalink / raw)
  To: Tomasz Stanislawski
  Cc: linux-media, dri-devel, airlied, m.szyprowski, kyungmin.park,
	sumit.semwal, daeinki, daniel.vetter, robdclark, pawel,
	linaro-mm-sig, hverkuil, remi, subashrp, mchehab, g.liakhovetski,
	dmitriyz, s.nawrocki, k.debski

Hi Tomasz,

Thanks for the patch.

Just a couple of small comments below.

On Tuesday 14 August 2012 17:34:50 Tomasz Stanislawski wrote:
> This patch adds support for exporting a dma-contig buffer using
> DMABUF interface.
> 
> Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> ---
>  drivers/media/video/videobuf2-dma-contig.c |  204 +++++++++++++++++++++++++
>  1 file changed, 204 insertions(+)
> 
> diff --git a/drivers/media/video/videobuf2-dma-contig.c
> b/drivers/media/video/videobuf2-dma-contig.c index 7fc71a0..bb2b4ac8 100644
> --- a/drivers/media/video/videobuf2-dma-contig.c
> +++ b/drivers/media/video/videobuf2-dma-contig.c

[snip]

> +static struct sg_table *vb2_dc_dmabuf_ops_map(
> +	struct dma_buf_attachment *db_attach, enum dma_data_direction dir)
> +{
> +	struct vb2_dc_attachment *attach = db_attach->priv;
> +	/* stealing dmabuf mutex to serialize map/unmap operations */

Why isn't this operation serialized by the dma-buf core itself ?

> +	struct mutex *lock = &db_attach->dmabuf->lock;
> +	struct sg_table *sgt;
> +	int ret;
> +
> +	mutex_lock(lock);
> +
> +	sgt = &attach->sgt;
> +	/* return previously mapped sg table */
> +	if (attach->dir == dir) {
> +		mutex_unlock(lock);
> +		return sgt;
> +	}
> +
> +	/* release any previous cache */
> +	if (attach->dir != DMA_NONE) {
> +		dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
> +			attach->dir);
> +		attach->dir = DMA_NONE;
> +	}
> +
> +	/* mapping to the client with new direction */
> +	ret = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, dir);
> +	if (ret <= 0) {
> +		pr_err("failed to map scatterlist\n");
> +		mutex_unlock(lock);
> +		return ERR_PTR(-EIO);
> +	}
> +
> +	attach->dir = dir;
> +
> +	mutex_unlock(lock);
> +
> +	return sgt;
> +}

[snip]

> +static int vb2_dc_dmabuf_ops_mmap(struct dma_buf *dbuf,
> +	struct vm_area_struct *vma)
> +{
> +	/* Dummy support for mmap */
> +	return -ENOTTY;

What about calling the dma-contig mmap handler here ? Is there a specific 
reason why you haven't implemented mmap support for dmabuf ?

> +}
> +
> +static struct dma_buf_ops vb2_dc_dmabuf_ops = {
> +	.attach = vb2_dc_dmabuf_ops_attach,
> +	.detach = vb2_dc_dmabuf_ops_detach,
> +	.map_dma_buf = vb2_dc_dmabuf_ops_map,
> +	.unmap_dma_buf = vb2_dc_dmabuf_ops_unmap,
> +	.kmap = vb2_dc_dmabuf_ops_kmap,
> +	.kmap_atomic = vb2_dc_dmabuf_ops_kmap,
> +	.vmap = vb2_dc_dmabuf_ops_vmap,
> +	.mmap = vb2_dc_dmabuf_ops_mmap,
> +	.release = vb2_dc_dmabuf_ops_release,
> +};
> +
> +static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf)
> +{
> +	int ret;
> +	struct sg_table *sgt;
> +
> +	sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
> +	if (!sgt) {
> +		dev_err(buf->dev, "failed to alloc sg table\n");
> +		return ERR_PTR(-ENOMEM);
> +	}
> +
> +	ret = dma_get_sgtable(buf->dev, sgt, buf->vaddr, buf->dma_addr,
> +		buf->size);
> +	if (ret < 0) {
> +		dev_err(buf->dev, "failed to get scatterlist from DMA API\n");
> +		kfree(sgt);
> +		return ERR_PTR(ret);
> +	}

As this function is only used below, where the exact value of the error code 
is ignored, what about just returning NULL on failure ? Another option is to 
return the error code in vb2_dc_get_dmabuf (not sure if that would be useful 
though).

> +
> +	return sgt;
> +}
> +
> +static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv)
> +{
> +	struct vb2_dc_buf *buf = buf_priv;
> +	struct dma_buf *dbuf;
> +	struct sg_table *sgt = buf->sgt_base;
> +
> +	if (!sgt)
> +		sgt = vb2_dc_get_base_sgt(buf);
> +	if (WARN_ON(IS_ERR(sgt)))
> +		return NULL;
> +
> +	/* cache base sgt for future use */
> +	buf->sgt_base = sgt;

You can move this assignment inside the first if, there's no need to execute 
it every time. The WARN_ON can also be moved inside the first if, as buf-
>sgt_base will either be NULL or valid. You can then get rid of the sgt 
variable initialization by testing if (!buf->sgt_base).

> +	dbuf = dma_buf_export(buf, &vb2_dc_dmabuf_ops, buf->size, 0);
> +	if (IS_ERR(dbuf))
> +		return NULL;
> +
> +	/* dmabuf keeps reference to vb2 buffer */
> +	atomic_inc(&buf->refcount);
> +
> +	return dbuf;
> +}

-- 
Regards,

Laurent Pinchart


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

* Re: [PATCHv8 20/26] v4l: vb2-dma-contig: add support for DMABUF exporting
  2012-08-21 10:03   ` Laurent Pinchart
@ 2012-08-21 13:47     ` Tomasz Stanislawski
  2012-08-21 14:07       ` Laurent Pinchart
  0 siblings, 1 reply; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-08-21 13:47 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-media, dri-devel, airlied, m.szyprowski, kyungmin.park,
	sumit.semwal, daeinki, daniel.vetter, robdclark, pawel,
	linaro-mm-sig, hverkuil, remi, subashrp, mchehab, g.liakhovetski,
	dmitriyz, s.nawrocki, k.debski

Hi Laurent,
Thank you for your comments.

On 08/21/2012 12:03 PM, Laurent Pinchart wrote:
> Hi Tomasz,
> 
> Thanks for the patch.
> 
> Just a couple of small comments below.
> 
> On Tuesday 14 August 2012 17:34:50 Tomasz Stanislawski wrote:
>> This patch adds support for exporting a dma-contig buffer using
>> DMABUF interface.
>>
>> Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
>> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
>> ---
>>  drivers/media/video/videobuf2-dma-contig.c |  204 +++++++++++++++++++++++++
>>  1 file changed, 204 insertions(+)
>>
>> diff --git a/drivers/media/video/videobuf2-dma-contig.c
>> b/drivers/media/video/videobuf2-dma-contig.c index 7fc71a0..bb2b4ac8 100644
>> --- a/drivers/media/video/videobuf2-dma-contig.c
>> +++ b/drivers/media/video/videobuf2-dma-contig.c
> 
> [snip]
> 
>> +static struct sg_table *vb2_dc_dmabuf_ops_map(
>> +	struct dma_buf_attachment *db_attach, enum dma_data_direction dir)
>> +{
>> +	struct vb2_dc_attachment *attach = db_attach->priv;
>> +	/* stealing dmabuf mutex to serialize map/unmap operations */
> 
> Why isn't this operation serialized by the dma-buf core itself ?
> 

Indeed, it is a very good question. The lock was introduced in RFCv3 of
DMABUF patches. It was dedicated to serialize attach/detach calls.
No requirements for map/unmap serialization were stated so serialization
was delegated to an exporter.

A deadlock could occur if dma_map_attachment is called from inside
of attach ops. IMO, such an operation is invalid because an attachment
list is not in a valid state while attach ops is being processed.

Do you think that stealing a lock from dma-buf internals is too hacky?
I prefer not to introduce any extra locks in dma-contig allocator
but it is not a big deal to add it.

>> +	struct mutex *lock = &db_attach->dmabuf->lock;
>> +	struct sg_table *sgt;
>> +	int ret;
>> +
>> +	mutex_lock(lock);
>> +
>> +	sgt = &attach->sgt;
>> +	/* return previously mapped sg table */
>> +	if (attach->dir == dir) {
>> +		mutex_unlock(lock);
>> +		return sgt;
>> +	}
>> +
>> +	/* release any previous cache */
>> +	if (attach->dir != DMA_NONE) {
>> +		dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
>> +			attach->dir);
>> +		attach->dir = DMA_NONE;
>> +	}
>> +
>> +	/* mapping to the client with new direction */
>> +	ret = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, dir);
>> +	if (ret <= 0) {
>> +		pr_err("failed to map scatterlist\n");
>> +		mutex_unlock(lock);
>> +		return ERR_PTR(-EIO);
>> +	}
>> +
>> +	attach->dir = dir;
>> +
>> +	mutex_unlock(lock);
>> +
>> +	return sgt;
>> +}
> 
> [snip]
> 
>> +static int vb2_dc_dmabuf_ops_mmap(struct dma_buf *dbuf,
>> +	struct vm_area_struct *vma)
>> +{
>> +	/* Dummy support for mmap */
>> +	return -ENOTTY;
> 
> What about calling the dma-contig mmap handler here ? Is there a specific 
> reason why you haven't implemented mmap support for dmabuf ?
> 

The mmap ops is mandatory in the latest DMABUF api.
I added a stub function to make DC work with DMABUF without any big effort.
Calling vb2_dc_mmap from mmap ops seams to be a simple and safe way to
handle mmap functionality.  Thank you for spotting this :)

>> +}
>> +
>> +static struct dma_buf_ops vb2_dc_dmabuf_ops = {
>> +	.attach = vb2_dc_dmabuf_ops_attach,
>> +	.detach = vb2_dc_dmabuf_ops_detach,
>> +	.map_dma_buf = vb2_dc_dmabuf_ops_map,
>> +	.unmap_dma_buf = vb2_dc_dmabuf_ops_unmap,
>> +	.kmap = vb2_dc_dmabuf_ops_kmap,
>> +	.kmap_atomic = vb2_dc_dmabuf_ops_kmap,
>> +	.vmap = vb2_dc_dmabuf_ops_vmap,
>> +	.mmap = vb2_dc_dmabuf_ops_mmap,
>> +	.release = vb2_dc_dmabuf_ops_release,
>> +};
>> +
>> +static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf)
>> +{
>> +	int ret;
>> +	struct sg_table *sgt;
>> +
>> +	sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
>> +	if (!sgt) {
>> +		dev_err(buf->dev, "failed to alloc sg table\n");
>> +		return ERR_PTR(-ENOMEM);
>> +	}
>> +
>> +	ret = dma_get_sgtable(buf->dev, sgt, buf->vaddr, buf->dma_addr,
>> +		buf->size);
>> +	if (ret < 0) {
>> +		dev_err(buf->dev, "failed to get scatterlist from DMA API\n");
>> +		kfree(sgt);
>> +		return ERR_PTR(ret);
>> +	}
> 
> As this function is only used below, where the exact value of the error code 
> is ignored, what about just returning NULL on failure ? Another option is to 
> return the error code in vb2_dc_get_dmabuf (not sure if that would be useful 
> though).
> 
>> +
>> +	return sgt;
>> +}
>> +
>> +static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv)
>> +{
>> +	struct vb2_dc_buf *buf = buf_priv;
>> +	struct dma_buf *dbuf;
>> +	struct sg_table *sgt = buf->sgt_base;
>> +
>> +	if (!sgt)
>> +		sgt = vb2_dc_get_base_sgt(buf);
>> +	if (WARN_ON(IS_ERR(sgt)))
>> +		return NULL;
>> +
>> +	/* cache base sgt for future use */
>> +	buf->sgt_base = sgt;
> 
> You can move this assignment inside the first if, there's no need to execute 
> it every time. The WARN_ON can also be moved inside the first if, as buf-
>> sgt_base will either be NULL or valid. You can then get rid of the sgt 
> variable initialization by testing if (!buf->sgt_base).

I agree. I will apply this fix in v9.

> 
>> +	dbuf = dma_buf_export(buf, &vb2_dc_dmabuf_ops, buf->size, 0);
>> +	if (IS_ERR(dbuf))
>> +		return NULL;
>> +
>> +	/* dmabuf keeps reference to vb2 buffer */
>> +	atomic_inc(&buf->refcount);
>> +
>> +	return dbuf;
>> +}
>

Regards,
Tomasz Stanislawski


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

* Re: [PATCHv8 20/26] v4l: vb2-dma-contig: add support for DMABUF exporting
  2012-08-21 13:47     ` Tomasz Stanislawski
@ 2012-08-21 14:07       ` Laurent Pinchart
  0 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2012-08-21 14:07 UTC (permalink / raw)
  To: Tomasz Stanislawski
  Cc: linux-media, dri-devel, airlied, m.szyprowski, kyungmin.park,
	sumit.semwal, daeinki, daniel.vetter, robdclark, pawel,
	linaro-mm-sig, hverkuil, remi, subashrp, mchehab, g.liakhovetski,
	dmitriyz, s.nawrocki, k.debski

Hi Tomasz,

On Tuesday 21 August 2012 15:47:13 Tomasz Stanislawski wrote:
> On 08/21/2012 12:03 PM, Laurent Pinchart wrote:
> > On Tuesday 14 August 2012 17:34:50 Tomasz Stanislawski wrote:
> >> This patch adds support for exporting a dma-contig buffer using
> >> DMABUF interface.
> >> 
> >> Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
> >> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> >> ---
> >> 
> >>  drivers/media/video/videobuf2-dma-contig.c |  204 ++++++++++++++++++++++
> >>  1 file changed, 204 insertions(+)
> >> 
> >> diff --git a/drivers/media/video/videobuf2-dma-contig.c
> >> b/drivers/media/video/videobuf2-dma-contig.c index 7fc71a0..bb2b4ac8
> >> 100644
> >> --- a/drivers/media/video/videobuf2-dma-contig.c
> >> +++ b/drivers/media/video/videobuf2-dma-contig.c
> > 
> > [snip]
> > 
> >> +static struct sg_table *vb2_dc_dmabuf_ops_map(
> >> +	struct dma_buf_attachment *db_attach, enum dma_data_direction dir)
> >> +{
> >> +	struct vb2_dc_attachment *attach = db_attach->priv;
> >> +	/* stealing dmabuf mutex to serialize map/unmap operations */
> > 
> > Why isn't this operation serialized by the dma-buf core itself ?
> 
> Indeed, it is a very good question. The lock was introduced in RFCv3 of
> DMABUF patches. It was dedicated to serialize attach/detach calls.
> No requirements for map/unmap serialization were stated so serialization
> was delegated to an exporter.
> 
> A deadlock could occur if dma_map_attachment is called from inside
> of attach ops. IMO, such an operation is invalid because an attachment
> list is not in a valid state while attach ops is being processed.
> 
> Do you think that stealing a lock from dma-buf internals is too hacky?

No, I would be OK with that, but I'd like to make sure that it won't bite us 
back later. If there's a specific reason why the lock is not taken by the 
dmabuf core around map/unmap calls, stealing the same lock might cause 
unforeseen problems. That's why I would like to understand why the core 
doesn't perform locking on its own.

> I prefer not to introduce any extra locks in dma-contig allocator

Agreed.

> but it is not a big deal to add it.
> 
> >> +	struct mutex *lock = &db_attach->dmabuf->lock;
> >> +	struct sg_table *sgt;
> >> +	int ret;
> >> +
> >> +	mutex_lock(lock);
> >> +
> >> +	sgt = &attach->sgt;
> >> +	/* return previously mapped sg table */
> >> +	if (attach->dir == dir) {
> >> +		mutex_unlock(lock);
> >> +		return sgt;
> >> +	}
> >> +
> >> +	/* release any previous cache */
> >> +	if (attach->dir != DMA_NONE) {
> >> +		dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
> >> +			attach->dir);
> >> +		attach->dir = DMA_NONE;
> >> +	}
> >> +
> >> +	/* mapping to the client with new direction */
> >> +	ret = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, dir);
> >> +	if (ret <= 0) {
> >> +		pr_err("failed to map scatterlist\n");
> >> +		mutex_unlock(lock);
> >> +		return ERR_PTR(-EIO);
> >> +	}
> >> +
> >> +	attach->dir = dir;
> >> +
> >> +	mutex_unlock(lock);
> >> +
> >> +	return sgt;
> >> +}

-- 
Regards,

Laurent Pinchart


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

* Re: [PATCHv8 01/26] v4l: Add DMABUF as a memory type
  2012-08-14 15:34 ` [PATCHv8 01/26] v4l: Add DMABUF as a memory type Tomasz Stanislawski
@ 2012-08-22 10:27   ` Hans Verkuil
  2012-08-22 12:09     ` Tomasz Stanislawski
  0 siblings, 1 reply; 58+ messages in thread
From: Hans Verkuil @ 2012-08-22 10:27 UTC (permalink / raw)
  To: Tomasz Stanislawski
  Cc: linux-media, dri-devel, airlied, m.szyprowski, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, remi, subashrp, mchehab,
	g.liakhovetski, dmitriyz, s.nawrocki, k.debski, Sumit Semwal

On Tue August 14 2012 17:34:31 Tomasz Stanislawski wrote:
> From: Sumit Semwal <sumit.semwal@ti.com>
> 
> Adds DMABUF memory type to v4l framework. Also adds the related file
> descriptor in v4l2_plane and v4l2_buffer.
> 
> Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
>    [original work in the PoC for buffer sharing]
> Signed-off-by: Sumit Semwal <sumit.semwal@ti.com>
> Signed-off-by: Sumit Semwal <sumit.semwal@linaro.org>
> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/video/v4l2-compat-ioctl32.c |   18 ++++++++++++++++++
>  drivers/media/video/v4l2-ioctl.c          |    1 +
>  include/linux/videodev2.h                 |    7 +++++++
>  3 files changed, 26 insertions(+)
> 
> diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c
> index 9ebd5c5..a2e0549 100644
> --- a/drivers/media/video/v4l2-compat-ioctl32.c
> +++ b/drivers/media/video/v4l2-compat-ioctl32.c
> @@ -304,6 +304,7 @@ struct v4l2_plane32 {
>  	union {
>  		__u32		mem_offset;
>  		compat_long_t	userptr;
> +		__u32		fd;

Shouldn't this be int?

>  	} m;
>  	__u32			data_offset;
>  	__u32			reserved[11];
> @@ -325,6 +326,7 @@ struct v4l2_buffer32 {
>  		__u32           offset;
>  		compat_long_t   userptr;
>  		compat_caddr_t  planes;
> +		__u32		fd;

Ditto.

>  	} m;
>  	__u32			length;
>  	__u32			reserved2;
> @@ -348,6 +350,9 @@ static int get_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32,
>  		up_pln = compat_ptr(p);
>  		if (put_user((unsigned long)up_pln, &up->m.userptr))
>  			return -EFAULT;
> +	} else if (memory == V4L2_MEMORY_DMABUF) {
> +		if (copy_in_user(&up->m.fd, &up32->m.fd, sizeof(int)))
> +			return -EFAULT;
>  	} else {
>  		if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset,
>  					sizeof(__u32)))
> @@ -371,6 +376,11 @@ static int put_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32,
>  		if (copy_in_user(&up32->m.mem_offset, &up->m.mem_offset,
>  					sizeof(__u32)))
>  			return -EFAULT;
> +	/* For DMABUF, driver might've set up the fd, so copy it back. */
> +	if (memory == V4L2_MEMORY_DMABUF)
> +		if (copy_in_user(&up32->m.fd, &up->m.fd,
> +					sizeof(int)))
> +			return -EFAULT;
>  
>  	return 0;
>  }
> @@ -453,6 +463,10 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user
>  			if (get_user(kp->m.offset, &up->m.offset))
>  				return -EFAULT;
>  			break;
> +		case V4L2_MEMORY_DMABUF:
> +			if (get_user(kp->m.fd, &up->m.fd))
> +				return -EFAULT;
> +			break;
>  		}
>  	}
>  
> @@ -517,6 +531,10 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user
>  			if (put_user(kp->m.offset, &up->m.offset))
>  				return -EFAULT;
>  			break;
> +		case V4L2_MEMORY_DMABUF:
> +			if (put_user(kp->m.fd, &up->m.fd))
> +				return -EFAULT;
> +			break;
>  		}
>  	}
>  
> diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
> index 6bc47fc..dffd3c9 100644
> --- a/drivers/media/video/v4l2-ioctl.c
> +++ b/drivers/media/video/v4l2-ioctl.c
> @@ -155,6 +155,7 @@ static const char *v4l2_memory_names[] = {
>  	[V4L2_MEMORY_MMAP]    = "mmap",
>  	[V4L2_MEMORY_USERPTR] = "userptr",
>  	[V4L2_MEMORY_OVERLAY] = "overlay",
> +	[V4L2_MEMORY_DMABUF] = "dmabuf",
>  };
>  
>  #define prt_names(a, arr) ((((a) >= 0) && ((a) < ARRAY_SIZE(arr))) ? \
> diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
> index 7a147c8..7f918dc 100644
> --- a/include/linux/videodev2.h
> +++ b/include/linux/videodev2.h
> @@ -186,6 +186,7 @@ enum v4l2_memory {
>  	V4L2_MEMORY_MMAP             = 1,
>  	V4L2_MEMORY_USERPTR          = 2,
>  	V4L2_MEMORY_OVERLAY          = 3,
> +	V4L2_MEMORY_DMABUF           = 4,
>  };
>  
>  /* see also http://vektor.theorem.ca/graphics/ycbcr/ */
> @@ -596,6 +597,8 @@ struct v4l2_requestbuffers {
>   *			should be passed to mmap() called on the video node)
>   * @userptr:		when memory is V4L2_MEMORY_USERPTR, a userspace pointer
>   *			pointing to this plane
> + * @fd:			when memory is V4L2_MEMORY_DMABUF, a userspace file
> + *			descriptor associated with this plane
>   * @data_offset:	offset in the plane to the start of data; usually 0,
>   *			unless there is a header in front of the data
>   *
> @@ -610,6 +613,7 @@ struct v4l2_plane {
>  	union {
>  		__u32		mem_offset;
>  		unsigned long	userptr;
> +		int		fd;
>  	} m;
>  	__u32			data_offset;
>  	__u32			reserved[11];
> @@ -634,6 +638,8 @@ struct v4l2_plane {
>   *		(or a "cookie" that should be passed to mmap() as offset)
>   * @userptr:	for non-multiplanar buffers with memory == V4L2_MEMORY_USERPTR;
>   *		a userspace pointer pointing to this buffer
> + * @fd:		for non-multiplanar buffers with memory == V4L2_MEMORY_DMABUF;
> + *		a userspace file descriptor associated with this buffer
>   * @planes:	for multiplanar buffers; userspace pointer to the array of plane
>   *		info structs for this buffer
>   * @length:	size in bytes of the buffer (NOT its payload) for single-plane
> @@ -660,6 +666,7 @@ struct v4l2_buffer {
>  		__u32           offset;
>  		unsigned long   userptr;
>  		struct v4l2_plane *planes;
> +		int		fd;
>  	} m;
>  	__u32			length;
>  	__u32			reserved2;
> 

Regards,

	Hans

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

* Re: [PATCHv8 02/26] Documentation: media: description of DMABUF importing in V4L2
  2012-08-14 15:34 ` [PATCHv8 02/26] Documentation: media: description of DMABUF importing in V4L2 Tomasz Stanislawski
@ 2012-08-22 10:47   ` Hans Verkuil
  2012-09-24 12:17     ` Tomasz Stanislawski
  0 siblings, 1 reply; 58+ messages in thread
From: Hans Verkuil @ 2012-08-22 10:47 UTC (permalink / raw)
  To: Tomasz Stanislawski
  Cc: linux-media, dri-devel, airlied, m.szyprowski, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, remi, subashrp, mchehab,
	g.liakhovetski, dmitriyz, s.nawrocki, k.debski, linux-doc

On Tue August 14 2012 17:34:32 Tomasz Stanislawski wrote:
> This patch adds description and usage examples for importing
> DMABUF file descriptor in V4L2.
> 
> Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> CC: linux-doc@vger.kernel.org
> ---
>  Documentation/DocBook/media/v4l/compat.xml         |    4 +
>  Documentation/DocBook/media/v4l/io.xml             |  180 ++++++++++++++++++++
>  .../DocBook/media/v4l/vidioc-create-bufs.xml       |    3 +-
>  Documentation/DocBook/media/v4l/vidioc-qbuf.xml    |   15 ++
>  Documentation/DocBook/media/v4l/vidioc-reqbufs.xml |   47 ++---
>  5 files changed, 226 insertions(+), 23 deletions(-)
> 
> diff --git a/Documentation/DocBook/media/v4l/compat.xml b/Documentation/DocBook/media/v4l/compat.xml
> index 98e8d08..ff45330 100644
> --- a/Documentation/DocBook/media/v4l/compat.xml
> +++ b/Documentation/DocBook/media/v4l/compat.xml
> @@ -2605,6 +2605,10 @@ ioctls.</para>
>          <listitem>
>  	  <para>Support for frequency band enumeration: &VIDIOC-ENUM-FREQ-BANDS; ioctl.</para>
>          </listitem>
> +        <listitem>
> +	  <para>Importing DMABUF file descriptors as a new IO method described
> +	  in <xref linkend="dmabuf" />.</para>
> +        </listitem>
>        </itemizedlist>
>      </section>
>  
> diff --git a/Documentation/DocBook/media/v4l/io.xml b/Documentation/DocBook/media/v4l/io.xml
> index 1885cc0..98253ee 100644
> --- a/Documentation/DocBook/media/v4l/io.xml
> +++ b/Documentation/DocBook/media/v4l/io.xml
> @@ -472,6 +472,163 @@ rest should be evident.</para>
>        </footnote></para>
>    </section>
>  
> +  <section id="dmabuf">
> +    <title>Streaming I/O (DMA buffer importing)</title>
> +
> +    <note>
> +      <title>Experimental</title>
> +      <para>This is an <link linkend="experimental"> experimental </link>
> +      interface and may change in the future.</para>
> +    </note>
> +
> +<para>The DMABUF framework provides a generic mean for sharing buffers between

s/mean/method/

> + multiple devices. Device drivers that support DMABUF can export a DMA buffer
> +to userspace as a file descriptor (known as the exporter role), import a DMA
> +buffer from userspace using a file descriptor previously exported for a
> +different or the same device (known as the importer role), or both. This
> +section describes the DMABUF importer role API in V4L2.</para>
> +
> +<para>Input and output devices support the streaming I/O method when the
> +<constant>V4L2_CAP_STREAMING</constant> flag in the
> +<structfield>capabilities</structfield> field of &v4l2-capability; returned by
> +the &VIDIOC-QUERYCAP; ioctl is set. Whether importing DMA buffers through
> +DMABUF file descriptors is supported is determined by calling the
> +&VIDIOC-REQBUFS; ioctl with the memory type set to
> +<constant>V4L2_MEMORY_DMABUF</constant>.</para>
> +
> +    <para>This I/O method is dedicated for sharing DMA buffers between V4L and
> +other APIs.  Buffers (planes) are allocated by a driver on behalf of the
> +application, and exported to the application as file descriptors using an API
> +specific to the allocator driver.  Only those file descriptor are exchanged,
> +these files and meta-information are passed in &v4l2-buffer; (or in

This sentence doesn't work well. It's unclear what is meant by 'these files'. Do
you mean 'these file descriptors'?

> +&v4l2-plane; in the multi-planar API case).  The driver must be switched into
> +DMABUF I/O mode by calling the &VIDIOC-REQBUFS; with the desired buffer type.
> +No buffers (planes) are allocated beforehand, consequently they are not indexed
> +and cannot be queried like mapped buffers with the
> +<constant>VIDIOC_QUERYBUF</constant> ioctl.</para>

I disagree with that. Userptr buffers can use QUERYBUF just fine. Even for the
userptr you still have to fill in the buffer index when calling QBUF.

So I see no reason why you couldn't use QUERYBUF in the DMABUF case. The only
difference is that the fd field is undefined (set to -1 perhaps?) if the bufffer
isn't queued.

QUERYBUF can be very useful for debugging, for example to see what the status
is of each buffer and how many are queued.

> +
> +    <example>
> +      <title>Initiating streaming I/O with DMABUF file descriptors</title>
> +
> +      <programlisting>
> +&v4l2-requestbuffers; reqbuf;
> +
> +memset (&amp;reqbuf, 0, sizeof (reqbuf));
> +reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> +reqbuf.memory = V4L2_MEMORY_DMABUF;
> +reqbuf.count = 1;
> +
> +if (ioctl (fd, &VIDIOC-REQBUFS;, &amp;reqbuf) == -1) {
> +	if (errno == EINVAL)
> +		printf ("Video capturing or DMABUF streaming is not supported\n");
> +	else
> +		perror ("VIDIOC_REQBUFS");
> +
> +	exit (EXIT_FAILURE);

Let's stick to the kernel coding style, so no ' ' before '(' in function calls.
Same for the other program examples below.

> +}
> +      </programlisting>
> +    </example>
> +
> +    <para>Buffer (plane) file descriptor is passed on the fly with the

s/Buffer/The buffer/

> +&VIDIOC-QBUF; ioctl. In case of multiplanar buffers, every plane can be

'Can be', 'should be' or 'must be'? Does it ever make sense to have the same
fd for different planes? Do we have restrictions on this in the userptr case?

> +associated with a different DMABUF descriptor. Although buffers are commonly
> +cycled, applications can pass a different DMABUF descriptor at each
> +<constant>VIDIOC_QBUF</constant> call.</para>
> +
> +    <example>
> +      <title>Queueing DMABUF using single plane API</title>
> +
> +      <programlisting>
> +int buffer_queue(int v4lfd, int index, int dmafd)
> +{
> +	&v4l2-buffer; buf;
> +
> +	memset(&amp;buf, 0, sizeof buf);
> +	buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> +	buf.memory = V4L2_MEMORY_DMABUF;
> +	buf.index = index;
> +	buf.m.fd = dmafd;
> +
> +	if (ioctl (v4lfd, &VIDIOC-QBUF;, &amp;buf) == -1) {
> +		perror ("VIDIOC_QBUF");
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +      </programlisting>
> +    </example>
> +
> +    <example>
> +      <title>Queueing DMABUF using multi plane API</title>
> +
> +      <programlisting>
> +int buffer_queue_mp(int v4lfd, int index, int dmafd[], int n_planes)
> +{
> +	&v4l2-buffer; buf;
> +	&v4l2-plane; planes[VIDEO_MAX_PLANES];
> +	int i;
> +
> +	memset(&amp;buf, 0, sizeof buf);
> +	buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
> +	buf.memory = V4L2_MEMORY_DMABUF;
> +	buf.index = index;
> +	buf.m.planes = planes;
> +	buf.length = n_planes;
> +
> +	memset(&amp;planes, 0, sizeof planes);
> +
> +	for (i = 0; i &lt; n_planes; ++i)
> +		buf.m.planes[i].m.fd = dmafd[i];
> +
> +	if (ioctl (v4lfd, &VIDIOC-QBUF;, &amp;buf) == -1) {
> +		perror ("VIDIOC_QBUF");
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +      </programlisting>
> +    </example>
> +
> +    <para>Filled or displayed buffers are dequeued with the
> +&VIDIOC-DQBUF; ioctl. The driver can unlock the buffer at any
> +time between the completion of the DMA and this ioctl. The memory is
> +also unlocked when &VIDIOC-STREAMOFF; is called, &VIDIOC-REQBUFS;, or
> +when the device is closed.</para>
> +
> +    <para>For capturing applications it is customary to enqueue a
> +number of empty buffers, to start capturing and enter the read loop.
> +Here the application waits until a filled buffer can be dequeued, and
> +re-enqueues the buffer when the data is no longer needed. Output
> +applications fill and enqueue buffers, when enough buffers are stacked
> +up output is started. In the write loop, when the application
> +runs out of free buffers it must wait until an empty buffer can be
> +dequeued and reused. Two methods exist to suspend execution of the
> +application until one or more buffers can be dequeued. By default
> +<constant>VIDIOC_DQBUF</constant> blocks when no buffer is in the
> +outgoing queue. When the <constant>O_NONBLOCK</constant> flag was
> +given to the &func-open; function, <constant>VIDIOC_DQBUF</constant>
> +returns immediately with an &EAGAIN; when no buffer is available. The
> +&func-select; or &func-poll; function are always available.</para>

s/function/functions/

> +
> +    <para>To start and stop capturing or output applications call the
> +&VIDIOC-STREAMON; and &VIDIOC-STREAMOFF; ioctls. Note that
> +<constant>VIDIOC_STREAMOFF</constant> removes all buffers from both queues and
> +unlocks all buffers as a side effect. Since there is no notion of doing
> +anything "now" on a multitasking system, if an application needs to synchronize
> +with another event it should examine the &v4l2-buffer;
> +<structfield>timestamp</structfield> of captured buffers, or set the field
> +before enqueuing buffers for output.</para>
> +
> +    <para>Drivers implementing DMABUF importing I/O must support the
> +<constant>VIDIOC_REQBUFS</constant>, <constant>VIDIOC_QBUF</constant>,
> +<constant>VIDIOC_DQBUF</constant>, <constant>VIDIOC_STREAMON</constant> and
> +<constant>VIDIOC_STREAMOFF</constant> ioctls, and the
> +<function>select()</function> and <function>poll()</function> functions.</para>
> +
> +  </section>
> +
>    <section id="async">
>      <title>Asynchronous I/O</title>
>  
> @@ -673,6 +830,14 @@ memory, set by the application. See <xref linkend="userp" /> for details.
>  	    <structname>v4l2_buffer</structname> structure.</entry>
>  	  </row>
>  	  <row>
> +	    <entry></entry>
> +	    <entry>int</entry>
> +	    <entry><structfield>fd</structfield></entry>
> +	    <entry>For the single-plane API and when
> +<structfield>memory</structfield> is <constant>V4L2_MEMORY_DMABUF</constant> this
> +is the file descriptor associated with a DMABUF buffer.</entry>
> +	  </row>
> +	  <row>
>  	    <entry>__u32</entry>
>  	    <entry><structfield>length</structfield></entry>
>  	    <entry></entry>
> @@ -746,6 +911,15 @@ should set this to 0.</entry>
>  	      </entry>
>  	  </row>
>  	  <row>
> +	    <entry></entry>
> +	    <entry>int</entry>
> +	    <entry><structfield>fd</structfield></entry>
> +	    <entry>When the memory type in the containing &v4l2-buffer; is
> +		<constant>V4L2_MEMORY_DMABUF</constant>, this is a file
> +		descriptor associated with a DMABUF buffer, similar to the
> +		<structfield>fd</structfield> field in &v4l2-buffer;.</entry>
> +	  </row>
> +	  <row>
>  	    <entry>__u32</entry>
>  	    <entry><structfield>data_offset</structfield></entry>
>  	    <entry></entry>
> @@ -973,6 +1147,12 @@ pointer</link> I/O.</entry>
>  	    <entry>3</entry>
>  	    <entry>[to do]</entry>
>  	  </row>
> +	  <row>
> +	    <entry><constant>V4L2_MEMORY_DMABUF</constant></entry>
> +	    <entry>4</entry>
> +	    <entry>The buffer is used for <link linkend="dmabuf">DMA shared
> +buffer</link> I/O.</entry>
> +	  </row>
>  	</tbody>
>        </tgroup>
>      </table>
> diff --git a/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml b/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
> index a8cda1a..1125468 100644
> --- a/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
> +++ b/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
> @@ -109,7 +109,8 @@ information.</para>
>  	    <entry>__u32</entry>
>  	    <entry><structfield>memory</structfield></entry>
>  	    <entry>Applications set this field to
> -<constant>V4L2_MEMORY_MMAP</constant> or
> +<constant>V4L2_MEMORY_MMAP</constant>,
> +<constant>V4L2_MEMORY_DMABUF</constant> or
>  <constant>V4L2_MEMORY_USERPTR</constant>. See <xref linkend="v4l2-memory"
>  /></entry>
>  	  </row>
> diff --git a/Documentation/DocBook/media/v4l/vidioc-qbuf.xml b/Documentation/DocBook/media/v4l/vidioc-qbuf.xml
> index 77ff5be..436d21c 100644
> --- a/Documentation/DocBook/media/v4l/vidioc-qbuf.xml
> +++ b/Documentation/DocBook/media/v4l/vidioc-qbuf.xml
> @@ -109,6 +109,21 @@ they cannot be swapped out to disk. Buffers remain locked until
>  dequeued, until the &VIDIOC-STREAMOFF; or &VIDIOC-REQBUFS; ioctl is
>  called, or until the device is closed.</para>
>  
> +    <para>To enqueue a <link linkend="dmabuf">DMABUF</link> buffer applications
> +set the <structfield>memory</structfield> field to
> +<constant>V4L2_MEMORY_DMABUF</constant> and the <structfield>m.fd</structfield>
> +field to a file descriptor associated with a DMABUF buffer. When the
> +multi-planar API is used <structfield>m.fd</structfield> of the passed array of

multi-planar API is used the <structfield>m.fd</structfield> fields of the passed array of

> +&v4l2-plane; have to be used instead. When <constant>VIDIOC_QBUF</constant> is
> +called with a pointer to this structure the driver sets the
> +<constant>V4L2_BUF_FLAG_QUEUED</constant> flag and clears the
> +<constant>V4L2_BUF_FLAG_MAPPED</constant> and
> +<constant>V4L2_BUF_FLAG_DONE</constant> flags in the
> +<structfield>flags</structfield> field, or it returns an error code.  This
> +ioctl locks the buffer. Buffers remain locked until dequeued, until the
> +&VIDIOC-STREAMOFF; or &VIDIOC-REQBUFS; ioctl is called, or until the device is
> +closed.</para>

You need to explain what a 'locked buffer' means.

> +
>      <para>Applications call the <constant>VIDIOC_DQBUF</constant>
>  ioctl to dequeue a filled (capturing) or displayed (output) buffer
>  from the driver's outgoing queue. They just set the
> diff --git a/Documentation/DocBook/media/v4l/vidioc-reqbufs.xml b/Documentation/DocBook/media/v4l/vidioc-reqbufs.xml
> index d7c9505..20f4323 100644
> --- a/Documentation/DocBook/media/v4l/vidioc-reqbufs.xml
> +++ b/Documentation/DocBook/media/v4l/vidioc-reqbufs.xml
> @@ -48,28 +48,30 @@
>    <refsect1>
>      <title>Description</title>
>  
> -    <para>This ioctl is used to initiate <link linkend="mmap">memory
> -mapped</link> or <link linkend="userp">user pointer</link>
> -I/O. Memory mapped buffers are located in device memory and must be
> -allocated with this ioctl before they can be mapped into the
> -application's address space. User buffers are allocated by
> -applications themselves, and this ioctl is merely used to switch the
> -driver into user pointer I/O mode and to setup some internal structures.</para>
> +<para>This ioctl is used to initiate <link linkend="mmap">memory mapped</link>,
> +<link linkend="userp">user pointer</link> or <link
> +linkend="dmabuf">DMABUF</link> based I/O.  Memory mapped buffers are located in
> +device memory and must be allocated with this ioctl before they can be mapped
> +into the application's address space. User buffers are allocated by
> +applications themselves, and this ioctl is merely used to switch the driver
> +into user pointer I/O mode and to setup some internal structures.
> +Similarly, DMABUF buffers are allocated by applications through a device
> +driver, and this ioctl only configures the driver into DMABUF I/O mode without
> +performing any direct allocation.</para>
>  
> -    <para>To allocate device buffers applications initialize all
> -fields of the <structname>v4l2_requestbuffers</structname> structure.
> -They set the <structfield>type</structfield> field to the respective
> -stream or buffer type, the <structfield>count</structfield> field to
> -the desired number of buffers, <structfield>memory</structfield>
> -must be set to the requested I/O method and the <structfield>reserved</structfield> array
> -must be zeroed. When the ioctl
> -is called with a pointer to this structure the driver will attempt to allocate
> -the requested number of buffers and it stores the actual number
> -allocated in the <structfield>count</structfield> field. It can be
> -smaller than the number requested, even zero, when the driver runs out
> -of free memory. A larger number is also possible when the driver requires
> -more buffers to function correctly. For example video output requires at least two buffers,
> -one displayed and one filled by the application.</para>
> +    <para>To allocate device buffers applications initialize all fields of the
> +<structname>v4l2_requestbuffers</structname> structure.  They set the
> +<structfield>type</structfield> field to the respective stream or buffer type,
> +the <structfield>count</structfield> field to the desired number of buffers,
> +<structfield>memory</structfield> must be set to the requested I/O method and
> +the <structfield>reserved</structfield> array must be zeroed. When the ioctl is
> +called with a pointer to this structure the driver will attempt to allocate the
> +requested number of buffers and it stores the actual number allocated in the
> +<structfield>count</structfield> field. It can be smaller than the number
> +requested, even zero, when the driver runs out of free memory. A larger number
> +is also possible when the driver requires more buffers to function correctly.
> +For example video output requires at least two buffers, one displayed and one
> +filled by the application.</para>
>      <para>When the I/O method is not supported the ioctl
>  returns an &EINVAL;.</para>
>  
> @@ -102,7 +104,8 @@ as the &v4l2-format; <structfield>type</structfield> field. See <xref
>  	    <entry>__u32</entry>
>  	    <entry><structfield>memory</structfield></entry>
>  	    <entry>Applications set this field to
> -<constant>V4L2_MEMORY_MMAP</constant> or
> +<constant>V4L2_MEMORY_MMAP</constant>,
> +<constant>V4L2_MEMORY_DMABUF</constant> or
>  <constant>V4L2_MEMORY_USERPTR</constant>. See <xref linkend="v4l2-memory"
>  />.</entry>
>  	  </row>
> 

You also have to update the VIDIOC_CREATE_BUFS ioctl documentation!

I think the VIDIOC_PREPARE_BUF ioctl documentation is OK, but you might want to
check that yourself, just in case.

Regards,

	Hans

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

* Re: [PATCHv8 13/26] v4l: vivi: support for dmabuf importing
  2012-08-14 15:34 ` [PATCHv8 13/26] v4l: vivi: " Tomasz Stanislawski
@ 2012-08-22 10:56   ` Hans Verkuil
  2012-08-22 11:03     ` Laurent Pinchart
  2012-08-22 11:47     ` Hans Verkuil
  0 siblings, 2 replies; 58+ messages in thread
From: Hans Verkuil @ 2012-08-22 10:56 UTC (permalink / raw)
  To: Tomasz Stanislawski
  Cc: linux-media, dri-devel, airlied, m.szyprowski, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, remi, subashrp, mchehab,
	g.liakhovetski, dmitriyz, s.nawrocki, k.debski

On Tue August 14 2012 17:34:43 Tomasz Stanislawski wrote:
> This patch enhances VIVI driver with a support for importing a buffer
> from DMABUF file descriptors.

Thanks for adding DMABUF support to vivi.

What would be great is if DMABUF support is also added to mem2mem_testdev.
It would make an excellent test case to take the vivi output, pass it
through mem2mem_testdev, and finally output the image using the gpu, all
using dmabuf.

It's also very useful for application developers to test dmabuf support
without requiring special hardware (other than a dmabuf-enabled gpu
driver).

Regards,

	Hans

> 
> Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> ---
>  drivers/media/video/Kconfig |    1 +
>  drivers/media/video/vivi.c  |    2 +-
>  2 files changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
> index 966954d..8fa81be 100644
> --- a/drivers/media/video/Kconfig
> +++ b/drivers/media/video/Kconfig
> @@ -653,6 +653,7 @@ config VIDEO_VIVI
>  	depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE
>  	select FONT_8x16
>  	select VIDEOBUF2_VMALLOC
> +	select DMA_SHARED_BUFFER
>  	default n
>  	---help---
>  	  Enables a virtual video driver. This device shows a color bar
> diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
> index a6351c4..37d8fd4 100644
> --- a/drivers/media/video/vivi.c
> +++ b/drivers/media/video/vivi.c
> @@ -1308,7 +1308,7 @@ static int __init vivi_create_instance(int inst)
>  	q = &dev->vb_vidq;
>  	memset(q, 0, sizeof(dev->vb_vidq));
>  	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> -	q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
> +	q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
>  	q->drv_priv = dev;
>  	q->buf_struct_size = sizeof(struct vivi_buffer);
>  	q->ops = &vivi_video_qops;
> 

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

* Re: [PATCHv8 13/26] v4l: vivi: support for dmabuf importing
  2012-08-22 10:56   ` Hans Verkuil
@ 2012-08-22 11:03     ` Laurent Pinchart
  2012-08-22 11:47     ` Hans Verkuil
  1 sibling, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2012-08-22 11:03 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: Tomasz Stanislawski, linux-media, dri-devel, airlied,
	m.szyprowski, kyungmin.park, sumit.semwal, daeinki,
	daniel.vetter, robdclark, pawel, linaro-mm-sig, remi, subashrp,
	mchehab, g.liakhovetski, dmitriyz, s.nawrocki, k.debski

Hi Hans,

On Wednesday 22 August 2012 12:56:30 Hans Verkuil wrote:
> On Tue August 14 2012 17:34:43 Tomasz Stanislawski wrote:
> > This patch enhances VIVI driver with a support for importing a buffer
> > from DMABUF file descriptors.
> 
> Thanks for adding DMABUF support to vivi.
> 
> What would be great is if DMABUF support is also added to mem2mem_testdev.
> It would make an excellent test case to take the vivi output, pass it
> through mem2mem_testdev, and finally output the image using the gpu, all
> using dmabuf.
> 
> It's also very useful for application developers to test dmabuf support
> without requiring special hardware (other than a dmabuf-enabled gpu
> driver).

One important missing feature is support for exporting GPU buffers as dmabuf 
file descriptors in the userspace APIs. I'm not sure where that would plug in 
the graphics stack, but we probably need at least a Linux-specific OpenGL 
extension for that. I've heard from Rob Clark that work was ongoing in that 
direction. I believe that  
https://wiki.linaro.org/OfficeofCTO/MemoryManagement?action=AttachFile&do=get&target=linux-
video.pdf is also related.

-- 
Regards,

Laurent Pinchart


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

* Re: [PATCHv8 17/26] Documentation: media: description of DMABUF exporting in V4L2
  2012-08-14 15:34 ` [PATCHv8 17/26] Documentation: media: description of DMABUF exporting in V4L2 Tomasz Stanislawski
@ 2012-08-22 11:23   ` Hans Verkuil
  0 siblings, 0 replies; 58+ messages in thread
From: Hans Verkuil @ 2012-08-22 11:23 UTC (permalink / raw)
  To: Tomasz Stanislawski
  Cc: linux-media, dri-devel, airlied, m.szyprowski, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, remi, subashrp, mchehab,
	g.liakhovetski, dmitriyz, s.nawrocki, k.debski, linux-doc

On Tue August 14 2012 17:34:47 Tomasz Stanislawski wrote:
> This patch adds description and usage examples for exporting
> DMABUF file descriptor in V4L2.
> 
> Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> CC: linux-doc@vger.kernel.org
> ---
>  Documentation/DocBook/media/v4l/compat.xml        |    3 +
>  Documentation/DocBook/media/v4l/io.xml            |    3 +
>  Documentation/DocBook/media/v4l/v4l2.xml          |    1 +
>  Documentation/DocBook/media/v4l/vidioc-expbuf.xml |  223 +++++++++++++++++++++
>  4 files changed, 230 insertions(+)
>  create mode 100644 Documentation/DocBook/media/v4l/vidioc-expbuf.xml
> 
> diff --git a/Documentation/DocBook/media/v4l/compat.xml b/Documentation/DocBook/media/v4l/compat.xml
> index ff45330..802c1ab 100644
> --- a/Documentation/DocBook/media/v4l/compat.xml
> +++ b/Documentation/DocBook/media/v4l/compat.xml
> @@ -2609,6 +2609,9 @@ ioctls.</para>
>  	  <para>Importing DMABUF file descriptors as a new IO method described
>  	  in <xref linkend="dmabuf" />.</para>
>          </listitem>
> +        <listitem>
> +	  <para>Exporting DMABUF files using &VIDIOC-EXPBUF; ioctl.</para>
> +        </listitem>
>        </itemizedlist>
>      </section>
>  
> diff --git a/Documentation/DocBook/media/v4l/io.xml b/Documentation/DocBook/media/v4l/io.xml
> index 98253ee..c27e59b 100644
> --- a/Documentation/DocBook/media/v4l/io.xml
> +++ b/Documentation/DocBook/media/v4l/io.xml
> @@ -488,6 +488,9 @@ buffer from userspace using a file descriptor previously exported for a
>  different or the same device (known as the importer role), or both. This
>  section describes the DMABUF importer role API in V4L2.</para>
>  
> +    <para>Refer to <link linked="vidioc-expbuf"> DMABUF exporting </link> for
> +details about exporting a V4L2 buffers as DMABUF file descriptors.</para>
> +
>  <para>Input and output devices support the streaming I/O method when the
>  <constant>V4L2_CAP_STREAMING</constant> flag in the
>  <structfield>capabilities</structfield> field of &v4l2-capability; returned by
> diff --git a/Documentation/DocBook/media/v4l/v4l2.xml b/Documentation/DocBook/media/v4l/v4l2.xml
> index 0292ed1..874c085 100644
> --- a/Documentation/DocBook/media/v4l/v4l2.xml
> +++ b/Documentation/DocBook/media/v4l/v4l2.xml
> @@ -568,6 +568,7 @@ and discussions on the V4L mailing list.</revremark>
>      &sub-overlay;
>      &sub-prepare-buf;
>      &sub-qbuf;
> +    &sub-expbuf;

This list is sorted alphabetically, so sub-expbuf should go after sub-enumstd.

>      &sub-querybuf;
>      &sub-querycap;
>      &sub-queryctrl;
> diff --git a/Documentation/DocBook/media/v4l/vidioc-expbuf.xml b/Documentation/DocBook/media/v4l/vidioc-expbuf.xml
> new file mode 100644
> index 0000000..30ebf67
> --- /dev/null
> +++ b/Documentation/DocBook/media/v4l/vidioc-expbuf.xml
> @@ -0,0 +1,223 @@
> +<refentry id="vidioc-expbuf">
> +
> +  <refmeta>
> +    <refentrytitle>ioctl VIDIOC_EXPBUF</refentrytitle>
> +    &manvol;
> +  </refmeta>
> +
> +  <refnamediv>
> +    <refname>VIDIOC_EXPBUF</refname>
> +    <refpurpose>Export a buffer as a DMABUF file descriptor.</refpurpose>
> +  </refnamediv>
> +
> +  <refsynopsisdiv>
> +    <funcsynopsis>
> +      <funcprototype>
> +	<funcdef>int <function>ioctl</function></funcdef>
> +	<paramdef>int <parameter>fd</parameter></paramdef>
> +	<paramdef>int <parameter>request</parameter></paramdef>
> +	<paramdef>struct v4l2_exportbuffer *<parameter>argp</parameter></paramdef>
> +      </funcprototype>
> +    </funcsynopsis>
> +  </refsynopsisdiv>
> +
> +  <refsect1>
> +    <title>Arguments</title>
> +
> +    <variablelist>
> +      <varlistentry>
> +	<term><parameter>fd</parameter></term>
> +	<listitem>
> +	  <para>&fd;</para>
> +	</listitem>
> +      </varlistentry>
> +      <varlistentry>
> +	<term><parameter>request</parameter></term>
> +	<listitem>
> +	  <para>VIDIOC_EXPBUF</para>
> +	</listitem>
> +      </varlistentry>
> +      <varlistentry>
> +	<term><parameter>argp</parameter></term>
> +	<listitem>
> +	  <para></para>
> +	</listitem>
> +      </varlistentry>
> +    </variablelist>
> +  </refsect1>
> +
> +  <refsect1>
> +    <title>Description</title>
> +
> +    <note>
> +      <title>Experimental</title>
> +      <para>This is an <link linkend="experimental"> experimental </link>
> +      interface and may change in the future.</para>
> +    </note>
> +
> +<para>This ioctl is an extension to the <link linkend="mmap">memory
> +mapping</link> I/O method therefore it is available only for
> +<constant>V4L2_MEMORY_MMAP</constant> buffers.  It can be used to export a
> +buffer as DMABUF file at any time after buffers have been allocated with the
> +&VIDIOC-REQBUFS; ioctl.</para>
> +
> +<para>Prior to exporting an application calls <link
> +linkend="vidioc-querybuf">VIDIOC_QUERYBUF</link> to obtain memory offsets. When
> +using the <link linkend="planar-apis">multi-planar API</link> every plane has
> +own offset.</para>
> +
> +<para>To export a buffer, the application fills &v4l2-exportbuffer;.  The
> +<structfield> mem_offset </structfield> field is set to the offset obtained
> +from <constant> VIDIOC_QUERYBUF </constant>.  Additional flags may be posted in
> +the <structfield> flags </structfield> field.  Refer to manual for open syscall

Better IMHO: 'Refer to the manual for open()'

> +for details. Currently only O_CLOEXEC is guaranteed to be supported.  All other
> +fields must be set to zero.  In a case of multi-planar API, every plane is
> +exported separately using multiple <constant> VIDIOC_EXPBUF </constant>
> +calls.</para>
> +
> +<para> After calling <constant>VIDIOC_EXPBUF</constant> the <structfield> fd
> +</structfield> field will be set by a driver.  This is a DMABUF file
> +descriptor. The application may pass it to other API. Refer to <link
> +linkend="dmabuf">DMABUF importing</link> for details about importing DMABUF
> +files into V4L2 nodes. A developer is encouraged to close a DMABUF file when it
> +is no longer used.  </para>

Some explanation of why this is recommended would be useful.

> +
> +  </refsect1>
> +  <refsect1>
> +   <section>
> +      <title>Examples</title>
> +
> +      <example>
> +	<title>Exporting a buffer.</title>
> +	<programlisting>
> +int buffer_export(int v4lfd, &v4l2-buf-type; bt, int index, int *dmafd)
> +{
> +	&v4l2-buffer; buf;
> +	&v4l2-exportbuffer; expbuf;
> +
> +	memset(&amp;buf, 0, sizeof buf);
> +	buf.type = bt;
> +	buf.memory = V4L2_MEMORY_MMAP;
> +	buf.index = index;
> +
> +	if (ioctl (v4lfd, &VIDIOC-QUERYBUF;, &amp;buf) == -1) {
> +		perror ("VIDIOC_QUERYBUF");
> +		return -1;
> +	}
> +
> +	memset(&amp;expbuf, 0, sizeof expbuf);
> +	expbuf.mem_offset = buf.m.offset;
> +	if (ioctl (v4lfd, &VIDIOC-EXPBUF;, &amp;expbuf) == -1) {
> +		perror ("VIDIOC_EXPBUF");
> +		return -1;
> +	}

Same as in the review of the previous documentation patch: use the kernel
coding style in these examples, so no space before '('.

> +
> +	*dmafd = expbuf.fd;
> +
> +	return 0;
> +}
> +        </programlisting>
> +      </example>
> +
> +      <example>
> +	<title>Exporting a buffer using multi plane API.</title>
> +	<programlisting>
> +int buffer_export_mp(int v4lfd, &v4l2-buf-type; bt, int index,
> +	int dmafd[], int n_planes)
> +{
> +	&v4l2-buffer; buf;
> +	&v4l2-plane; planes[VIDEO_MAX_PLANES];
> +	int i;
> +
> +	memset(&amp;buf, 0, sizeof buf);
> +	buf.type = bt;
> +	buf.memory = V4L2_MEMORY_MMAP;
> +	buf.index = index;
> +	buf.m.planes = planes;
> +	buf.length = n_planes;
> +	memset(&amp;planes, 0, sizeof planes);
> +
> +	if (ioctl (v4lfd, &VIDIOC-QUERYBUF;, &amp;buf) == -1) {
> +		perror ("VIDIOC_QUERYBUF");
> +		return -1;
> +	}
> +
> +	for (i = 0; i &lt; n_planes; ++i) {
> +		&v4l2-exportbuffer; expbuf;
> +
> +		memset(&amp;expbuf, 0, sizeof expbuf);
> +		expbuf.mem_offset = plane[i].m.offset;
> +		if (ioctl (v4lfd, &VIDIOC-EXPBUF;, &amp;expbuf) == -1) {
> +			perror ("VIDIOC_EXPBUF");
> +			while (i)
> +				close(dmafd[--i]);
> +			return -1;
> +		}
> +		dmafd[i] = expbuf.fd;
> +	}
> +
> +	return 0;
> +}
> +        </programlisting>
> +      </example>
> +   </section>
> +  </refsect1>
> +
> +  <refsect1>
> +    <table pgwide="1" frame="none" id="v4l2-exportbuffer">
> +      <title>struct <structname>v4l2_exportbuffer</structname></title>
> +      <tgroup cols="3">
> +	&cs-str;
> +	<tbody valign="top">
> +	  <row>
> +	    <entry>__u32</entry>
> +	    <entry><structfield>fd</structfield></entry>
> +	    <entry>The DMABUF file descriptor associated with a buffer. Set by
> +		a driver.</entry>
> +	  </row>
> +	  <row>
> +	    <entry>__u32</entry>
> +	    <entry><structfield>reserved0</structfield></entry>
> +	    <entry>Reserved field for future use. Must be set to zero.</entry>
> +	  </row>
> +	  <row>
> +	    <entry>__u32</entry>
> +	    <entry><structfield>mem_offset</structfield></entry>
> +	    <entry>Buffer memory offset as returned by <constant>
> +VIDIOC_QUERYBUF </constant> in &v4l2-buffer;<structfield> ::m.offset
> +</structfield> (for single-plane formats) or &v4l2-plane;<structfield>
> +::m.offset </structfield> (for multi-planar formats)</entry>
> +	  </row>
> +	  <row>
> +	    <entry>__u32</entry>
> +	    <entry><structfield>flags</structfield></entry>
> +	    <entry>Flags for newly created file, currently only <constant>
> +O_CLOEXEC </constant> is supported, refer to manual of open syscall for more

'to the manual of open() for more'

> +details.</entry>
> +	  </row>
> +	  <row>
> +	    <entry>__u32</entry>
> +	    <entry><structfield>reserved[12]</structfield></entry>
> +	    <entry>Reserved field for future use. Must be set to zero.</entry>
> +	  </row>
> +	</tbody>
> +      </tgroup>
> +    </table>
> +
> +  </refsect1>
> +
> +  <refsect1>
> +    &return-value;
> +    <variablelist>
> +      <varlistentry>
> +	<term><errorcode>EINVAL</errorcode></term>
> +	<listitem>
> +	  <para>A queue is not in MMAP mode or DMABUF exporting is not
> +supported or <structfield> flag </structfield> or <structfield> mem_offset

flag -> flags

> +</structfield> fields are invalid.</para>
> +	</listitem>
> +      </varlistentry>
> +    </variablelist>
> +  </refsect1>
> +
> +</refentry>
> 

Regards,

	Hans

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

* Re: [PATCHv8 18/26] v4l: add buffer exporting via dmabuf
  2012-08-14 15:34 ` [PATCHv8 18/26] v4l: add buffer exporting via dmabuf Tomasz Stanislawski
  2012-08-15 19:08   ` Laurent Pinchart
@ 2012-08-22 11:41   ` Hans Verkuil
  2012-08-22 23:39     ` Laurent Pinchart
  2012-09-25 16:30     ` Tomasz Stanislawski
  1 sibling, 2 replies; 58+ messages in thread
From: Hans Verkuil @ 2012-08-22 11:41 UTC (permalink / raw)
  To: Tomasz Stanislawski
  Cc: linux-media, dri-devel, airlied, m.szyprowski, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, remi, subashrp, mchehab,
	g.liakhovetski, dmitriyz, s.nawrocki, k.debski

On Tue August 14 2012 17:34:48 Tomasz Stanislawski wrote:
> This patch adds extension to V4L2 api. It allow to export a mmap buffer as file
> descriptor. New ioctl VIDIOC_EXPBUF is added. It takes a buffer offset used by
> mmap and return a file descriptor on success.
> 
> Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> ---
>  drivers/media/video/v4l2-compat-ioctl32.c |    1 +
>  drivers/media/video/v4l2-dev.c            |    1 +
>  drivers/media/video/v4l2-ioctl.c          |   15 +++++++++++++++
>  include/linux/videodev2.h                 |   26 ++++++++++++++++++++++++++
>  include/media/v4l2-ioctl.h                |    2 ++
>  5 files changed, 45 insertions(+)
> 
> diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c
> index a2e0549..7689c4a 100644
> --- a/drivers/media/video/v4l2-compat-ioctl32.c
> +++ b/drivers/media/video/v4l2-compat-ioctl32.c
> @@ -971,6 +971,7 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
>  	case VIDIOC_S_FBUF32:
>  	case VIDIOC_OVERLAY32:
>  	case VIDIOC_QBUF32:
> +	case VIDIOC_EXPBUF:
>  	case VIDIOC_DQBUF32:
>  	case VIDIOC_STREAMON32:
>  	case VIDIOC_STREAMOFF32:
> diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
> index 71237f5..f6e7ea5 100644
> --- a/drivers/media/video/v4l2-dev.c
> +++ b/drivers/media/video/v4l2-dev.c
> @@ -607,6 +607,7 @@ static void determine_valid_ioctls(struct video_device *vdev)
>  	SET_VALID_IOCTL(ops, VIDIOC_REQBUFS, vidioc_reqbufs);
>  	SET_VALID_IOCTL(ops, VIDIOC_QUERYBUF, vidioc_querybuf);
>  	SET_VALID_IOCTL(ops, VIDIOC_QBUF, vidioc_qbuf);
> +	SET_VALID_IOCTL(ops, VIDIOC_EXPBUF, vidioc_expbuf);
>  	SET_VALID_IOCTL(ops, VIDIOC_DQBUF, vidioc_dqbuf);
>  	SET_VALID_IOCTL(ops, VIDIOC_OVERLAY, vidioc_overlay);
>  	SET_VALID_IOCTL(ops, VIDIOC_G_FBUF, vidioc_g_fbuf);
> diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
> index dffd3c9..c4e8c7e 100644
> --- a/drivers/media/video/v4l2-ioctl.c
> +++ b/drivers/media/video/v4l2-ioctl.c
> @@ -458,6 +458,14 @@ static void v4l_print_buffer(const void *arg, bool write_only)
>  			tc->type, tc->flags, tc->frames, *(__u32 *)tc->userbits);
>  }
>  
> +static void v4l_print_exportbuffer(const void *arg, bool write_only)
> +{
> +	const struct v4l2_exportbuffer *p = arg;
> +
> +	pr_cont("fd=%d, mem_offset=%lx, flags=%lx\n",
> +		p->fd, (unsigned long)p->mem_offset, (unsigned long)p->flags);

Why the unsigned long casts?

> +}
> +
>  static void v4l_print_create_buffers(const void *arg, bool write_only)
>  {
>  	const struct v4l2_create_buffers *p = arg;
> @@ -1254,6 +1262,12 @@ static int v4l_streamoff(const struct v4l2_ioctl_ops *ops,
>  	return ops->vidioc_streamoff(file, fh, *(unsigned int *)arg);
>  }
>  
> +static int v4l_expbuf(const struct v4l2_ioctl_ops *ops,
> +				struct file *file, void *fh, void *arg)
> +{
> +	return ops->vidioc_expbuf(file, fh, arg);
> +}

Not needed...

> +
>  static int v4l_g_tuner(const struct v4l2_ioctl_ops *ops,
>  				struct file *file, void *fh, void *arg)
>  {
> @@ -1947,6 +1961,7 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = {
>  	IOCTL_INFO_STD(VIDIOC_S_FBUF, vidioc_s_fbuf, v4l_print_framebuffer, INFO_FL_PRIO),
>  	IOCTL_INFO_STD(VIDIOC_OVERLAY, vidioc_overlay, v4l_print_u32, INFO_FL_PRIO),
>  	IOCTL_INFO_FNC(VIDIOC_QBUF, v4l_qbuf, v4l_print_buffer, INFO_FL_QUEUE),
> +	IOCTL_INFO_FNC(VIDIOC_EXPBUF, v4l_expbuf, v4l_print_exportbuffer, INFO_FL_CLEAR(v4l2_exportbuffer, flags)),

...use IOCTL_INFO_STD instead.

>  	IOCTL_INFO_FNC(VIDIOC_DQBUF, v4l_dqbuf, v4l_print_buffer, INFO_FL_QUEUE),
>  	IOCTL_INFO_FNC(VIDIOC_STREAMON, v4l_streamon, v4l_print_buftype, INFO_FL_PRIO | INFO_FL_QUEUE),
>  	IOCTL_INFO_FNC(VIDIOC_STREAMOFF, v4l_streamoff, v4l_print_buftype, INFO_FL_PRIO | INFO_FL_QUEUE),
> diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
> index 7f918dc..b5d058b 100644
> --- a/include/linux/videodev2.h
> +++ b/include/linux/videodev2.h
> @@ -688,6 +688,31 @@ struct v4l2_buffer {
>  #define V4L2_BUF_FLAG_NO_CACHE_INVALIDATE	0x0800
>  #define V4L2_BUF_FLAG_NO_CACHE_CLEAN		0x1000
>  
> +/**
> + * struct v4l2_exportbuffer - export of video buffer as DMABUF file descriptor
> + *
> + * @fd:		file descriptor associated with DMABUF (set by driver)
> + * @mem_offset:	buffer memory offset as returned by VIDIOC_QUERYBUF in struct
> + *		v4l2_buffer::m.offset (for single-plane formats) or
> + *		v4l2_plane::m.offset (for multi-planar formats)
> + * @flags:	flags for newly created file, currently only O_CLOEXEC is
> + *		supported, refer to manual of open syscall for more details
> + *
> + * Contains data used for exporting a video buffer as DMABUF file descriptor.
> + * The buffer is identified by a 'cookie' returned by VIDIOC_QUERYBUF
> + * (identical to the cookie used to mmap() the buffer to userspace). All
> + * reserved fields must be set to zero. The field reserved0 is expected to
> + * become a structure 'type' allowing an alternative layout of the structure
> + * content. Therefore this field should not be used for any other extensions.
> + */
> +struct v4l2_exportbuffer {
> +	__u32		fd;
> +	__u32		reserved0;
> +	__u32		mem_offset;
> +	__u32		flags;
> +	__u32		reserved[12];
> +};

OK, I realized that we also need a type field here: you need the type field
(same as in v4l2_buffer) to know which queue the mem_offset refers to. For
M2M devices you have two queues, so you need this information.

Is there any reason not to use __u32 memory instead of __u32 reserved0?
I really dislike 'reserved0'. It's also very inconsistent with the other
buffer ioctls which all have type+memory fields.

Regarding mem_offset: I would prefer a union (possibly anonymous):

        union {
                __u32           mem_offset;
                unsigned long   reserved;
        } m;

Again, it's more consistent with the existing buffer ioctls, and it prepares
the API for future pointer values. 'reserved' in the union above could even
safely be renamed to userptr, even though userptr isn't supported at the
moment.

> +
>  /*
>   *	O V E R L A Y   P R E V I E W
>   */
> @@ -2558,6 +2583,7 @@ struct v4l2_create_buffers {
>  #define VIDIOC_S_FBUF		 _IOW('V', 11, struct v4l2_framebuffer)
>  #define VIDIOC_OVERLAY		 _IOW('V', 14, int)
>  #define VIDIOC_QBUF		_IOWR('V', 15, struct v4l2_buffer)
> +#define VIDIOC_EXPBUF		_IOWR('V', 16, struct v4l2_exportbuffer)
>  #define VIDIOC_DQBUF		_IOWR('V', 17, struct v4l2_buffer)
>  #define VIDIOC_STREAMON		 _IOW('V', 18, int)
>  #define VIDIOC_STREAMOFF	 _IOW('V', 19, int)
> diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
> index e614c9c..38fb139 100644
> --- a/include/media/v4l2-ioctl.h
> +++ b/include/media/v4l2-ioctl.h
> @@ -119,6 +119,8 @@ struct v4l2_ioctl_ops {
>  	int (*vidioc_reqbufs) (struct file *file, void *fh, struct v4l2_requestbuffers *b);
>  	int (*vidioc_querybuf)(struct file *file, void *fh, struct v4l2_buffer *b);
>  	int (*vidioc_qbuf)    (struct file *file, void *fh, struct v4l2_buffer *b);
> +	int (*vidioc_expbuf)  (struct file *file, void *fh,
> +				struct v4l2_exportbuffer *e);
>  	int (*vidioc_dqbuf)   (struct file *file, void *fh, struct v4l2_buffer *b);
>  
>  	int (*vidioc_create_bufs)(struct file *file, void *fh, struct v4l2_create_buffers *b);
> 

Regards,

	Hans

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

* Re: [PATCHv8 19/26] v4l: vb2: add buffer exporting via dmabuf
  2012-08-14 15:34 ` [PATCHv8 19/26] v4l: vb2: " Tomasz Stanislawski
@ 2012-08-22 11:43   ` Hans Verkuil
  0 siblings, 0 replies; 58+ messages in thread
From: Hans Verkuil @ 2012-08-22 11:43 UTC (permalink / raw)
  To: Tomasz Stanislawski
  Cc: linux-media, dri-devel, airlied, m.szyprowski, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, remi, subashrp, mchehab,
	g.liakhovetski, dmitriyz, s.nawrocki, k.debski

On Tue August 14 2012 17:34:49 Tomasz Stanislawski wrote:
> This patch adds extension to videobuf2-core. It allow to export a mmap buffer
> as a file descriptor.
> 
> Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/media/video/videobuf2-core.c |   67 ++++++++++++++++++++++++++++++++++
>  include/media/videobuf2-core.h       |    2 +
>  2 files changed, 69 insertions(+)
> 
> diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c
> index aed21e4..61354ec 100644
> --- a/drivers/media/video/videobuf2-core.c
> +++ b/drivers/media/video/videobuf2-core.c
> @@ -1743,6 +1743,73 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
>  }
>  
>  /**
> + * vb2_expbuf() - Export a buffer as a file descriptor
> + * @q:		videobuf2 queue
> + * @eb:		export buffer structure passed from userspace to vidioc_expbuf
> + *		handler in driver
> + *
> + * The return values from this function are intended to be directly returned
> + * from vidioc_expbuf handler in driver.
> + */
> +int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
> +{
> +	struct vb2_buffer *vb = NULL;
> +	struct vb2_plane *vb_plane;
> +	unsigned int buffer, plane;
> +	int ret;
> +	struct dma_buf *dbuf;
> +
> +	if (q->memory != V4L2_MEMORY_MMAP) {
> +		dprintk(1, "Queue is not currently set up for mmap\n");
> +		return -EINVAL;
> +	}
> +
> +	if (!q->mem_ops->get_dmabuf) {
> +		dprintk(1, "Queue does not support DMA buffer exporting\n");
> +		return -EINVAL;
> +	}
> +
> +	if (eb->flags & ~O_CLOEXEC) {
> +		dprintk(1, "Queue does support only O_CLOEXEC flag\n");
> +		return -EINVAL;
> +	}
> +
> +	/*
> +	 * Find the plane corresponding to the offset passed by userspace.
> +	 */
> +	ret = __find_plane_by_offset(q, eb->mem_offset, &buffer, &plane);
> +	if (ret) {
> +		dprintk(1, "invalid offset %u\n", eb->mem_offset);
> +		return ret;
> +	}
> +
> +	vb = q->bufs[buffer];
> +	vb_plane = &vb->planes[plane];
> +
> +	dbuf = call_memop(q, get_dmabuf, vb_plane->mem_priv);
> +	if (IS_ERR_OR_NULL(dbuf)) {
> +		dprintk(1, "Failed to export buffer %d, plane %d\n",
> +			buffer, plane);
> +		return -EINVAL;
> +	}
> +
> +	ret = dma_buf_fd(dbuf, eb->flags);
> +	if (ret < 0) {
> +		dprintk(3, "buffer %d, plane %d failed to export (%d)\n",
> +			buffer, plane, ret);
> +		dma_buf_put(dbuf);
> +		return ret;
> +	}
> +
> +	dprintk(3, "buffer %d, plane %d exported as %d descriptor\n",
> +		buffer, plane, ret);
> +	eb->fd = ret;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(vb2_expbuf);
> +
> +/**
>   * vb2_mmap() - map video buffers into application address space
>   * @q:		videobuf2 queue
>   * @vma:	vma passed to the mmap file operation handler in the driver
> diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
> index c306fec..b034424 100644
> --- a/include/media/videobuf2-core.h
> +++ b/include/media/videobuf2-core.h
> @@ -81,6 +81,7 @@ struct vb2_fileio_data;
>  struct vb2_mem_ops {
>  	void		*(*alloc)(void *alloc_ctx, unsigned long size);
>  	void		(*put)(void *buf_priv);
> +	struct dma_buf *(*get_dmabuf)(void *buf_priv);
>  
>  	void		*(*get_userptr)(void *alloc_ctx, unsigned long vaddr,
>  					unsigned long size, int write);
> @@ -363,6 +364,7 @@ int vb2_queue_init(struct vb2_queue *q);
>  void vb2_queue_release(struct vb2_queue *q);
>  
>  int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b);
> +int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb);
>  int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking);
>  
>  int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type);
> 

Please add a vb2_ioctl_expbuf helper function as well!

Regards,

	Hans

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

* Re: [PATCHv8 23/26] v4l: vb2: add support for DMA_ATTR_NO_KERNEL_MAPPING
  2012-08-14 15:34 ` [PATCHv8 23/26] v4l: vb2: add support for DMA_ATTR_NO_KERNEL_MAPPING Tomasz Stanislawski
  2012-08-15 20:44   ` Laurent Pinchart
@ 2012-08-22 11:46   ` Hans Verkuil
  1 sibling, 0 replies; 58+ messages in thread
From: Hans Verkuil @ 2012-08-22 11:46 UTC (permalink / raw)
  To: Tomasz Stanislawski
  Cc: linux-media, dri-devel, airlied, m.szyprowski, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, remi, subashrp, mchehab,
	g.liakhovetski, dmitriyz, s.nawrocki, k.debski

On Tue August 14 2012 17:34:53 Tomasz Stanislawski wrote:
> From: Marek Szyprowski <m.szyprowski@samsung.com>

Please add some more information in the commit message. I've no idea what's
going on here or why :-)

Regards,

	Hans

> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> ---
>  drivers/media/video/atmel-isi.c              |    2 +-
>  drivers/media/video/blackfin/bfin_capture.c  |    2 +-
>  drivers/media/video/marvell-ccic/mcam-core.c |    3 ++-
>  drivers/media/video/mx2_camera.c             |    2 +-
>  drivers/media/video/mx2_emmaprp.c            |    2 +-
>  drivers/media/video/mx3_camera.c             |    2 +-
>  drivers/media/video/s5p-fimc/fimc-core.c     |    2 +-
>  drivers/media/video/s5p-fimc/fimc-lite.c     |    2 +-
>  drivers/media/video/s5p-g2d/g2d.c            |    2 +-
>  drivers/media/video/s5p-jpeg/jpeg-core.c     |    2 +-
>  drivers/media/video/s5p-mfc/s5p_mfc.c        |    5 ++--
>  drivers/media/video/s5p-tv/mixer_video.c     |    2 +-
>  drivers/media/video/sh_mobile_ceu_camera.c   |    2 +-
>  drivers/media/video/videobuf2-dma-contig.c   |   33 +++++++++++++++++++-------
>  drivers/staging/media/dt3155v4l/dt3155v4l.c  |    2 +-
>  include/media/videobuf2-dma-contig.h         |    4 +++-
>  16 files changed, 44 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/media/video/atmel-isi.c b/drivers/media/video/atmel-isi.c
> index 6274a91..9fb5283 100644
> --- a/drivers/media/video/atmel-isi.c
> +++ b/drivers/media/video/atmel-isi.c
> @@ -1000,7 +1000,7 @@ static int __devinit atmel_isi_probe(struct platform_device *pdev)
>  		list_add(&isi->dma_desc[i].list, &isi->dma_desc_head);
>  	}
>  
> -	isi->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
> +	isi->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev, 0);
>  	if (IS_ERR(isi->alloc_ctx)) {
>  		ret = PTR_ERR(isi->alloc_ctx);
>  		goto err_alloc_ctx;
> diff --git a/drivers/media/video/blackfin/bfin_capture.c b/drivers/media/video/blackfin/bfin_capture.c
> index 1677623..7e90b65 100644
> --- a/drivers/media/video/blackfin/bfin_capture.c
> +++ b/drivers/media/video/blackfin/bfin_capture.c
> @@ -893,7 +893,7 @@ static int __devinit bcap_probe(struct platform_device *pdev)
>  	}
>  	bcap_dev->ppi->priv = bcap_dev;
>  
> -	bcap_dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
> +	bcap_dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev, 0);
>  	if (IS_ERR(bcap_dev->alloc_ctx)) {
>  		ret = PTR_ERR(bcap_dev->alloc_ctx);
>  		goto err_free_ppi;
> diff --git a/drivers/media/video/marvell-ccic/mcam-core.c b/drivers/media/video/marvell-ccic/mcam-core.c
> index ce2b7b4..10d4db5 100644
> --- a/drivers/media/video/marvell-ccic/mcam-core.c
> +++ b/drivers/media/video/marvell-ccic/mcam-core.c
> @@ -1111,7 +1111,8 @@ static int mcam_setup_vb2(struct mcam_camera *cam)
>  #ifdef MCAM_MODE_DMA_CONTIG
>  		vq->ops = &mcam_vb2_ops;
>  		vq->mem_ops = &vb2_dma_contig_memops;
> -		cam->vb_alloc_ctx = vb2_dma_contig_init_ctx(cam->dev);
> +		cam->vb_alloc_ctx = vb2_dma_contig_init_ctx(cam->dev,
> +			VB2_CREATE_VADDR);
>  		vq->io_modes = VB2_MMAP | VB2_USERPTR;
>  		cam->dma_setup = mcam_ctlr_dma_contig;
>  		cam->frame_complete = mcam_dma_contig_done;
> diff --git a/drivers/media/video/mx2_camera.c b/drivers/media/video/mx2_camera.c
> index 637bde8..5c30302 100644
> --- a/drivers/media/video/mx2_camera.c
> +++ b/drivers/media/video/mx2_camera.c
> @@ -1766,7 +1766,7 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)
>  	if (cpu_is_mx25())
>  		pcdev->soc_host.capabilities = SOCAM_HOST_CAP_STRIDE;
>  
> -	pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
> +	pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev, 0);
>  	if (IS_ERR(pcdev->alloc_ctx)) {
>  		err = PTR_ERR(pcdev->alloc_ctx);
>  		goto eallocctx;
> diff --git a/drivers/media/video/mx2_emmaprp.c b/drivers/media/video/mx2_emmaprp.c
> index 2810015..23c6c42 100644
> --- a/drivers/media/video/mx2_emmaprp.c
> +++ b/drivers/media/video/mx2_emmaprp.c
> @@ -962,7 +962,7 @@ static int emmaprp_probe(struct platform_device *pdev)
>  			     0, MEM2MEM_NAME, pcdev) < 0)
>  		goto rel_vdev;
>  
> -	pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
> +	pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev, 0);
>  	if (IS_ERR(pcdev->alloc_ctx)) {
>  		v4l2_err(&pcdev->v4l2_dev, "Failed to alloc vb2 context\n");
>  		ret = PTR_ERR(pcdev->alloc_ctx);
> diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c
> index f13643d..882026f 100644
> --- a/drivers/media/video/mx3_camera.c
> +++ b/drivers/media/video/mx3_camera.c
> @@ -1227,7 +1227,7 @@ static int __devinit mx3_camera_probe(struct platform_device *pdev)
>  	soc_host->v4l2_dev.dev	= &pdev->dev;
>  	soc_host->nr		= pdev->id;
>  
> -	mx3_cam->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
> +	mx3_cam->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev, 0);
>  	if (IS_ERR(mx3_cam->alloc_ctx)) {
>  		err = PTR_ERR(mx3_cam->alloc_ctx);
>  		goto eallocctx;
> diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c
> index 1a44540..e1747f2 100644
> --- a/drivers/media/video/s5p-fimc/fimc-core.c
> +++ b/drivers/media/video/s5p-fimc/fimc-core.c
> @@ -929,7 +929,7 @@ static int fimc_probe(struct platform_device *pdev)
>  	if (ret < 0)
>  		goto err_sd;
>  	/* Initialize contiguous memory allocator */
> -	fimc->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
> +	fimc->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev, 0);
>  	if (IS_ERR(fimc->alloc_ctx)) {
>  		ret = PTR_ERR(fimc->alloc_ctx);
>  		goto err_pm;
> diff --git a/drivers/media/video/s5p-fimc/fimc-lite.c b/drivers/media/video/s5p-fimc/fimc-lite.c
> index c5b57e8..ccc70a0 100644
> --- a/drivers/media/video/s5p-fimc/fimc-lite.c
> +++ b/drivers/media/video/s5p-fimc/fimc-lite.c
> @@ -1459,7 +1459,7 @@ static int __devinit fimc_lite_probe(struct platform_device *pdev)
>  	if (ret < 0)
>  		goto err_sd;
>  
> -	fimc->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
> +	fimc->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev, 0);
>  	if (IS_ERR(fimc->alloc_ctx)) {
>  		ret = PTR_ERR(fimc->alloc_ctx);
>  		goto err_pm;
> diff --git a/drivers/media/video/s5p-g2d/g2d.c b/drivers/media/video/s5p-g2d/g2d.c
> index 0edc2df..ad7837f 100644
> --- a/drivers/media/video/s5p-g2d/g2d.c
> +++ b/drivers/media/video/s5p-g2d/g2d.c
> @@ -756,7 +756,7 @@ static int g2d_probe(struct platform_device *pdev)
>  		goto put_clk_gate;
>  	}
>  
> -	dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
> +	dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev, 0);
>  	if (IS_ERR(dev->alloc_ctx)) {
>  		ret = PTR_ERR(dev->alloc_ctx);
>  		goto unprep_clk_gate;
> diff --git a/drivers/media/video/s5p-jpeg/jpeg-core.c b/drivers/media/video/s5p-jpeg/jpeg-core.c
> index be04d58..900059e 100644
> --- a/drivers/media/video/s5p-jpeg/jpeg-core.c
> +++ b/drivers/media/video/s5p-jpeg/jpeg-core.c
> @@ -1372,7 +1372,7 @@ static int s5p_jpeg_probe(struct platform_device *pdev)
>  		goto device_register_rollback;
>  	}
>  
> -	jpeg->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
> +	jpeg->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev, VB2_CREATE_VADDR);
>  	if (IS_ERR(jpeg->alloc_ctx)) {
>  		v4l2_err(&jpeg->v4l2_dev, "Failed to init memory allocator\n");
>  		ret = PTR_ERR(jpeg->alloc_ctx);
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc.c b/drivers/media/video/s5p-mfc/s5p_mfc.c
> index e3e616d..9056a10 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc.c
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc.c
> @@ -1018,12 +1018,13 @@ static int s5p_mfc_probe(struct platform_device *pdev)
>  		goto err_res;
>  	}
>  
> -	dev->alloc_ctx[0] = vb2_dma_contig_init_ctx(dev->mem_dev_l);
> +	dev->alloc_ctx[0] = vb2_dma_contig_init_ctx(dev->mem_dev_l,
> +		VB2_CREATE_VADDR);
>  	if (IS_ERR_OR_NULL(dev->alloc_ctx[0])) {
>  		ret = PTR_ERR(dev->alloc_ctx[0]);
>  		goto err_res;
>  	}
> -	dev->alloc_ctx[1] = vb2_dma_contig_init_ctx(dev->mem_dev_r);
> +	dev->alloc_ctx[1] = vb2_dma_contig_init_ctx(dev->mem_dev_r, 0);
>  	if (IS_ERR_OR_NULL(dev->alloc_ctx[1])) {
>  		ret = PTR_ERR(dev->alloc_ctx[1]);
>  		goto err_mem_init_ctx_1;
> diff --git a/drivers/media/video/s5p-tv/mixer_video.c b/drivers/media/video/s5p-tv/mixer_video.c
> index da5b7a5..a7e3b53 100644
> --- a/drivers/media/video/s5p-tv/mixer_video.c
> +++ b/drivers/media/video/s5p-tv/mixer_video.c
> @@ -78,7 +78,7 @@ int __devinit mxr_acquire_video(struct mxr_device *mdev,
>  		goto fail;
>  	}
>  
> -	mdev->alloc_ctx = vb2_dma_contig_init_ctx(mdev->dev);
> +	mdev->alloc_ctx = vb2_dma_contig_init_ctx(mdev->dev, 0);
>  	if (IS_ERR_OR_NULL(mdev->alloc_ctx)) {
>  		mxr_err(mdev, "could not acquire vb2 allocator\n");
>  		goto fail_v4l2_dev;
> diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
> index 0baaf94..e085c27 100644
> --- a/drivers/media/video/sh_mobile_ceu_camera.c
> +++ b/drivers/media/video/sh_mobile_ceu_camera.c
> @@ -2158,7 +2158,7 @@ static int __devinit sh_mobile_ceu_probe(struct platform_device *pdev)
>  	pcdev->ici.ops = &sh_mobile_ceu_host_ops;
>  	pcdev->ici.capabilities = SOCAM_HOST_CAP_STRIDE;
>  
> -	pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
> +	pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev, 0);
>  	if (IS_ERR(pcdev->alloc_ctx)) {
>  		err = PTR_ERR(pcdev->alloc_ctx);
>  		goto exit_free_clk;
> diff --git a/drivers/media/video/videobuf2-dma-contig.c b/drivers/media/video/videobuf2-dma-contig.c
> index 11f4a46..0729187 100644
> --- a/drivers/media/video/videobuf2-dma-contig.c
> +++ b/drivers/media/video/videobuf2-dma-contig.c
> @@ -23,10 +23,12 @@
>  
>  struct vb2_dc_conf {
>  	struct device		*dev;
> +	unsigned int		flags;
>  };
>  
>  struct vb2_dc_buf {
>  	struct device			*dev;
> +	unsigned int			flags;
>  	void				*vaddr;
>  	unsigned long			size;
>  	dma_addr_t			dma_addr;
> @@ -34,6 +36,7 @@ struct vb2_dc_buf {
>  	struct sg_table			*dma_sgt;
>  
>  	/* MMAP related */
> +	struct dma_attrs		dma_attrs;
>  	struct vb2_vmarea_handler	handler;
>  	atomic_t			refcount;
>  	struct sg_table			*sgt_base;
> @@ -98,6 +101,9 @@ static void *vb2_dc_vaddr(void *buf_priv)
>  {
>  	struct vb2_dc_buf *buf = buf_priv;
>  
> +	if (WARN_ON(~buf->flags & VB2_CREATE_VADDR))
> +		return NULL;
> +
>  	return buf->vaddr;
>  }
>  
> @@ -147,7 +153,8 @@ static void vb2_dc_put(void *buf_priv)
>  		sg_free_table(buf->sgt_base);
>  		kfree(buf->sgt_base);
>  	}
> -	dma_free_coherent(buf->dev, buf->size, buf->vaddr, buf->dma_addr);
> +	dma_free_attrs(buf->dev, buf->size, buf->vaddr, buf->dma_addr,
> +		       &buf->dma_attrs);
>  	put_device(buf->dev);
>  	kfree(buf);
>  }
> @@ -165,7 +172,14 @@ static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size)
>  	/* prevent the device from release while the buffer is exported */
>  	get_device(dev);
>  
> -	buf->vaddr = dma_alloc_coherent(dev, size, &buf->dma_addr, GFP_KERNEL);
> +	/* set up alloca attributes */
> +	init_dma_attrs(&buf->dma_attrs);
> +	dma_set_attr(DMA_ATTR_WRITE_COMBINE, &buf->dma_attrs);
> +	if (!(conf->flags & VB2_CREATE_VADDR))
> +		dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &buf->dma_attrs);
> +
> +	buf->vaddr = dma_alloc_attrs(dev, size, &buf->dma_addr, GFP_KERNEL,
> +				     &buf->dma_attrs);
>  	if (!buf->vaddr) {
>  		dev_err(dev, "dma_alloc_coherent of size %ld failed\n", size);
>  		put_device(dev);
> @@ -174,6 +188,7 @@ static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size)
>  	}
>  
>  	buf->dev = dev;
> +	buf->flags = conf->flags;
>  	buf->size = size;
>  
>  	buf->handler.refcount = &buf->refcount;
> @@ -201,9 +216,8 @@ static int vb2_dc_mmap(void *buf_priv, struct vm_area_struct *vma)
>  	 */
>  	vma->vm_pgoff = 0;
>  
> -	ret = dma_mmap_coherent(buf->dev, vma, buf->vaddr,
> -		buf->dma_addr, buf->size);
> -
> +	ret = dma_mmap_attrs(buf->dev, vma, buf->vaddr, buf->dma_addr,
> +			     buf->size, &buf->dma_attrs);
>  	if (ret) {
>  		pr_err("Remapping memory failed, error: %d\n", ret);
>  		return ret;
> @@ -345,7 +359,7 @@ static void *vb2_dc_dmabuf_ops_kmap(struct dma_buf *dbuf, unsigned long pgnum)
>  {
>  	struct vb2_dc_buf *buf = dbuf->priv;
>  
> -	return buf->vaddr + pgnum * PAGE_SIZE;
> +	return buf->vaddr ? buf->vaddr + pgnum * PAGE_SIZE : NULL;
>  }
>  
>  static void *vb2_dc_dmabuf_ops_vmap(struct dma_buf *dbuf)
> @@ -385,8 +399,8 @@ static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf)
>  		return ERR_PTR(-ENOMEM);
>  	}
>  
> -	ret = dma_get_sgtable(buf->dev, sgt, buf->vaddr, buf->dma_addr,
> -		buf->size);
> +	ret = dma_get_sgtable_attrs(buf->dev, sgt, buf->vaddr, buf->dma_addr,
> +		buf->size, &buf->dma_attrs);
>  	if (ret < 0) {
>  		dev_err(buf->dev, "failed to get scatterlist from DMA API\n");
>  		kfree(sgt);
> @@ -753,7 +767,7 @@ const struct vb2_mem_ops vb2_dma_contig_memops = {
>  };
>  EXPORT_SYMBOL_GPL(vb2_dma_contig_memops);
>  
> -void *vb2_dma_contig_init_ctx(struct device *dev)
> +void *vb2_dma_contig_init_ctx(struct device *dev, unsigned int flags)
>  {
>  	struct vb2_dc_conf *conf;
>  
> @@ -762,6 +776,7 @@ void *vb2_dma_contig_init_ctx(struct device *dev)
>  		return ERR_PTR(-ENOMEM);
>  
>  	conf->dev = dev;
> +	conf->flags = flags;
>  
>  	return conf;
>  }
> diff --git a/drivers/staging/media/dt3155v4l/dt3155v4l.c b/drivers/staging/media/dt3155v4l/dt3155v4l.c
> index 2e7b711..3fcf15a 100644
> --- a/drivers/staging/media/dt3155v4l/dt3155v4l.c
> +++ b/drivers/staging/media/dt3155v4l/dt3155v4l.c
> @@ -232,7 +232,7 @@ dt3155_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
>  	sizes[0] = img_width * img_height;
>  	if (pd->q->alloc_ctx[0])
>  		return 0;
> -	ret = vb2_dma_contig_init_ctx(&pd->pdev->dev);
> +	ret = vb2_dma_contig_init_ctx(&pd->pdev->dev, VB2_CREATE_VADDR);
>  	if (IS_ERR(ret))
>  		return PTR_ERR(ret);
>  	pd->q->alloc_ctx[0] = ret;
> diff --git a/include/media/videobuf2-dma-contig.h b/include/media/videobuf2-dma-contig.h
> index 8197f87..8bf4b29 100644
> --- a/include/media/videobuf2-dma-contig.h
> +++ b/include/media/videobuf2-dma-contig.h
> @@ -24,7 +24,9 @@ vb2_dma_contig_plane_dma_addr(struct vb2_buffer *vb, unsigned int plane_no)
>  	return *addr;
>  }
>  
> -void *vb2_dma_contig_init_ctx(struct device *dev);
> +#define VB2_CREATE_VADDR	(1 << 0)
> +
> +void *vb2_dma_contig_init_ctx(struct device *dev, unsigned int flags);
>  void vb2_dma_contig_cleanup_ctx(void *alloc_ctx);
>  
>  extern const struct vb2_mem_ops vb2_dma_contig_memops;
> 

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

* Re: [PATCHv8 13/26] v4l: vivi: support for dmabuf importing
  2012-08-22 10:56   ` Hans Verkuil
  2012-08-22 11:03     ` Laurent Pinchart
@ 2012-08-22 11:47     ` Hans Verkuil
  2012-09-25 14:41       ` Tomasz Stanislawski
  1 sibling, 1 reply; 58+ messages in thread
From: Hans Verkuil @ 2012-08-22 11:47 UTC (permalink / raw)
  To: Tomasz Stanislawski
  Cc: linux-media, dri-devel, airlied, m.szyprowski, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, remi, subashrp, mchehab,
	g.liakhovetski, dmitriyz, s.nawrocki, k.debski

On Wed August 22 2012 12:56:30 Hans Verkuil wrote:
> On Tue August 14 2012 17:34:43 Tomasz Stanislawski wrote:
> > This patch enhances VIVI driver with a support for importing a buffer
> > from DMABUF file descriptors.
> 
> Thanks for adding DMABUF support to vivi.
> 
> What would be great is if DMABUF support is also added to mem2mem_testdev.
> It would make an excellent test case to take the vivi output, pass it
> through mem2mem_testdev, and finally output the image using the gpu, all
> using dmabuf.
> 
> It's also very useful for application developers to test dmabuf support
> without requiring special hardware (other than a dmabuf-enabled gpu
> driver).

Adding VIDIOC_EXPBUF support to vivi and mem2mem_testdev would be
welcome as well for the same reasons.

Regards,

	Hans

> 
> Regards,
> 
> 	Hans
> 
> > 
> > Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
> > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> > ---
> >  drivers/media/video/Kconfig |    1 +
> >  drivers/media/video/vivi.c  |    2 +-
> >  2 files changed, 2 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
> > index 966954d..8fa81be 100644
> > --- a/drivers/media/video/Kconfig
> > +++ b/drivers/media/video/Kconfig
> > @@ -653,6 +653,7 @@ config VIDEO_VIVI
> >  	depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE
> >  	select FONT_8x16
> >  	select VIDEOBUF2_VMALLOC
> > +	select DMA_SHARED_BUFFER
> >  	default n
> >  	---help---
> >  	  Enables a virtual video driver. This device shows a color bar
> > diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
> > index a6351c4..37d8fd4 100644
> > --- a/drivers/media/video/vivi.c
> > +++ b/drivers/media/video/vivi.c
> > @@ -1308,7 +1308,7 @@ static int __init vivi_create_instance(int inst)
> >  	q = &dev->vb_vidq;
> >  	memset(q, 0, sizeof(dev->vb_vidq));
> >  	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> > -	q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
> > +	q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
> >  	q->drv_priv = dev;
> >  	q->buf_struct_size = sizeof(struct vivi_buffer);
> >  	q->ops = &vivi_video_qops;
> > 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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

* Re: [PATCHv8 01/26] v4l: Add DMABUF as a memory type
  2012-08-22 10:27   ` Hans Verkuil
@ 2012-08-22 12:09     ` Tomasz Stanislawski
  2012-08-22 12:21       ` Hans Verkuil
  0 siblings, 1 reply; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-08-22 12:09 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: linux-media, dri-devel, airlied, m.szyprowski, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, remi, subashrp, mchehab,
	g.liakhovetski, dmitriyz, s.nawrocki, k.debski, Sumit Semwal

Hi Hans,
Thank your for the review.
Please refer to the comments below.

On 08/22/2012 12:27 PM, Hans Verkuil wrote:
> On Tue August 14 2012 17:34:31 Tomasz Stanislawski wrote:
>> From: Sumit Semwal <sumit.semwal@ti.com>
>>
>> Adds DMABUF memory type to v4l framework. Also adds the related file
>> descriptor in v4l2_plane and v4l2_buffer.
>>
>> Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
>>    [original work in the PoC for buffer sharing]
>> Signed-off-by: Sumit Semwal <sumit.semwal@ti.com>
>> Signed-off-by: Sumit Semwal <sumit.semwal@linaro.org>
>> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>> ---
>>  drivers/media/video/v4l2-compat-ioctl32.c |   18 ++++++++++++++++++
>>  drivers/media/video/v4l2-ioctl.c          |    1 +
>>  include/linux/videodev2.h                 |    7 +++++++
>>  3 files changed, 26 insertions(+)
>>
>> diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c
>> index 9ebd5c5..a2e0549 100644
>> --- a/drivers/media/video/v4l2-compat-ioctl32.c
>> +++ b/drivers/media/video/v4l2-compat-ioctl32.c
>> @@ -304,6 +304,7 @@ struct v4l2_plane32 {
>>  	union {
>>  		__u32		mem_offset;
>>  		compat_long_t	userptr;
>> +		__u32		fd;
> 
> Shouldn't this be int?
> 

Notice that this field should be consistent with fd field used in
'struct v4l2_exportbuffer'. Therefore I prefer to use fixed-size types.
One could use __s32 here but notice that file descriptors are defined
as small, nonnegative integers according to POSIX spec. The type __u32
suits well for this purpose. The negative values returned by open
syscall are used only to indicate failures.

On the other hand, using __s32 may help to avoid compiler warning while
building userspace apps due to 'signed-vs-unsigned comparisons'.

However, I do not have any strong opinion about 'int vs __u32' issue :).
Do you think that using __s32 for both QUERYBUF and EXPBUF is a good
compromise?

>>  	} m;
>>  	__u32			data_offset;
>>  	__u32			reserved[11];
>> @@ -325,6 +326,7 @@ struct v4l2_buffer32 {
>>  		__u32           offset;
>>  		compat_long_t   userptr;
>>  		compat_caddr_t  planes;
>> +		__u32		fd;
> 
> Ditto.
> 
>>  	} m;
>>  	__u32			length;
>>  	__u32			reserved2;

> Regards,
> 
> 	Hans
> 

Regards,

	Tomasz

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

* Re: [PATCHv8 01/26] v4l: Add DMABUF as a memory type
  2012-08-22 12:09     ` Tomasz Stanislawski
@ 2012-08-22 12:21       ` Hans Verkuil
  0 siblings, 0 replies; 58+ messages in thread
From: Hans Verkuil @ 2012-08-22 12:21 UTC (permalink / raw)
  To: Tomasz Stanislawski
  Cc: linux-media, dri-devel, airlied, m.szyprowski, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, remi, subashrp, mchehab,
	g.liakhovetski, dmitriyz, s.nawrocki, k.debski, Sumit Semwal

On Wed August 22 2012 14:09:18 Tomasz Stanislawski wrote:
> Hi Hans,
> Thank your for the review.
> Please refer to the comments below.
> 
> On 08/22/2012 12:27 PM, Hans Verkuil wrote:
> > On Tue August 14 2012 17:34:31 Tomasz Stanislawski wrote:
> >> From: Sumit Semwal <sumit.semwal@ti.com>
> >>
> >> Adds DMABUF memory type to v4l framework. Also adds the related file
> >> descriptor in v4l2_plane and v4l2_buffer.
> >>
> >> Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
> >>    [original work in the PoC for buffer sharing]
> >> Signed-off-by: Sumit Semwal <sumit.semwal@ti.com>
> >> Signed-off-by: Sumit Semwal <sumit.semwal@linaro.org>
> >> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> >> ---
> >>  drivers/media/video/v4l2-compat-ioctl32.c |   18 ++++++++++++++++++
> >>  drivers/media/video/v4l2-ioctl.c          |    1 +
> >>  include/linux/videodev2.h                 |    7 +++++++
> >>  3 files changed, 26 insertions(+)
> >>
> >> diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c
> >> index 9ebd5c5..a2e0549 100644
> >> --- a/drivers/media/video/v4l2-compat-ioctl32.c
> >> +++ b/drivers/media/video/v4l2-compat-ioctl32.c
> >> @@ -304,6 +304,7 @@ struct v4l2_plane32 {
> >>  	union {
> >>  		__u32		mem_offset;
> >>  		compat_long_t	userptr;
> >> +		__u32		fd;
> > 
> > Shouldn't this be int?
> > 
> 
> Notice that this field should be consistent with fd field used in
> 'struct v4l2_exportbuffer'. Therefore I prefer to use fixed-size types.
> One could use __s32 here but notice that file descriptors are defined
> as small, nonnegative integers according to POSIX spec. The type __u32
> suits well for this purpose. The negative values returned by open
> syscall are used only to indicate failures.
> 
> On the other hand, using __s32 may help to avoid compiler warning while
> building userspace apps due to 'signed-vs-unsigned comparisons'.
> 
> However, I do not have any strong opinion about 'int vs __u32' issue :).
> Do you think that using __s32 for both QUERYBUF and EXPBUF is a good
> compromise?

The type of a fd is highly variable in the kernel. Just try this for fun:

	grep [^a-z]fd[^a-z] -rsI include/linux/

'int' or 'unsigned int' are by far the most common types.

But in structs I did see a few __s32 types, so I think __s32 is a decent
type to use. Just make sure it is __s32 everywhere. Right now __u32 and
int are both used.

Regards,

	Hans

> 
> >>  	} m;
> >>  	__u32			data_offset;
> >>  	__u32			reserved[11];
> >> @@ -325,6 +326,7 @@ struct v4l2_buffer32 {
> >>  		__u32           offset;
> >>  		compat_long_t   userptr;
> >>  		compat_caddr_t  planes;
> >> +		__u32		fd;
> > 
> > Ditto.
> > 
> >>  	} m;
> >>  	__u32			length;
> >>  	__u32			reserved2;
> 
> > Regards,
> > 
> > 	Hans
> > 
> 
> Regards,
> 
> 	Tomasz
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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

* Re: [PATCHv8 18/26] v4l: add buffer exporting via dmabuf
  2012-08-22 11:41   ` Hans Verkuil
@ 2012-08-22 23:39     ` Laurent Pinchart
  2012-08-23  6:50       ` Hans Verkuil
  2012-09-25 16:30     ` Tomasz Stanislawski
  1 sibling, 1 reply; 58+ messages in thread
From: Laurent Pinchart @ 2012-08-22 23:39 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: Tomasz Stanislawski, linux-media, dri-devel, airlied,
	m.szyprowski, kyungmin.park, sumit.semwal, daeinki,
	daniel.vetter, robdclark, pawel, linaro-mm-sig, remi, subashrp,
	mchehab, g.liakhovetski, dmitriyz, s.nawrocki, k.debski

Hi Hans,

On Wednesday 22 August 2012 13:41:05 Hans Verkuil wrote:
> On Tue August 14 2012 17:34:48 Tomasz Stanislawski wrote:
> > This patch adds extension to V4L2 api. It allow to export a mmap buffer as
> > file descriptor. New ioctl VIDIOC_EXPBUF is added. It takes a buffer
> > offset used by mmap and return a file descriptor on success.
> > 
> > Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
> > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>

[snip]

> > diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
> > index 7f918dc..b5d058b 100644
> > --- a/include/linux/videodev2.h
> > +++ b/include/linux/videodev2.h
> > @@ -688,6 +688,31 @@ struct v4l2_buffer {
> > 
> >  #define V4L2_BUF_FLAG_NO_CACHE_INVALIDATE	0x0800
> >  #define V4L2_BUF_FLAG_NO_CACHE_CLEAN		0x1000
> > 
> > +/**
> > + * struct v4l2_exportbuffer - export of video buffer as DMABUF file
> > descriptor + *
> > + * @fd:		file descriptor associated with DMABUF (set by driver)
> > + * @mem_offset:	buffer memory offset as returned by VIDIOC_QUERYBUF in
> > struct + *		v4l2_buffer::m.offset (for single-plane formats) or
> > + *		v4l2_plane::m.offset (for multi-planar formats)
> > + * @flags:	flags for newly created file, currently only O_CLOEXEC is
> > + *		supported, refer to manual of open syscall for more details
> > + *
> > + * Contains data used for exporting a video buffer as DMABUF file
> > descriptor. + * The buffer is identified by a 'cookie' returned by
> > VIDIOC_QUERYBUF + * (identical to the cookie used to mmap() the buffer to
> > userspace). All + * reserved fields must be set to zero. The field
> > reserved0 is expected to + * become a structure 'type' allowing an
> > alternative layout of the structure + * content. Therefore this field
> > should not be used for any other extensions. + */
> > +struct v4l2_exportbuffer {
> > +	__u32		fd;
> > +	__u32		reserved0;
> > +	__u32		mem_offset;
> > +	__u32		flags;
> > +	__u32		reserved[12];
> > +};
> 
> OK, I realized that we also need a type field here: you need the type field
> (same as in v4l2_buffer) to know which queue the mem_offset refers to. For
> M2M devices you have two queues, so you need this information.
> 
> Is there any reason not to use __u32 memory instead of __u32 reserved0?
> I really dislike 'reserved0'. It's also very inconsistent with the other
> buffer ioctls which all have type+memory fields.

I'm concerned that we might need to export buffers in the future based on 
something else than the memory type. That's probably an irrational fear 
though.

> Regarding mem_offset: I would prefer a union (possibly anonymous):
> 
>         union {
>                 __u32           mem_offset;
>                 unsigned long   reserved;
>         } m;
> 
> Again, it's more consistent with the existing buffer ioctls, and it prepares
> the API for future pointer values. 'reserved' in the union above could even
> safely be renamed to userptr, even though userptr isn't supported at the
> moment.

Once again I would really want to see compeling use cases before we export a 
userptr buffer as a dmabuf object. As Mauro previously stated, userptr for 
buffer sharing was a hack in the first place (although a pretty successful one 
so far).

-- 
Regards,

Laurent Pinchart


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

* Re: [PATCHv8 18/26] v4l: add buffer exporting via dmabuf
  2012-08-22 23:39     ` Laurent Pinchart
@ 2012-08-23  6:50       ` Hans Verkuil
  0 siblings, 0 replies; 58+ messages in thread
From: Hans Verkuil @ 2012-08-23  6:50 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Tomasz Stanislawski, linux-media, dri-devel, airlied,
	m.szyprowski, kyungmin.park, sumit.semwal, daeinki,
	daniel.vetter, robdclark, pawel, linaro-mm-sig, remi, subashrp,
	mchehab, g.liakhovetski, dmitriyz, s.nawrocki, k.debski

On Thu August 23 2012 01:39:34 Laurent Pinchart wrote:
> Hi Hans,
> 
> On Wednesday 22 August 2012 13:41:05 Hans Verkuil wrote:
> > On Tue August 14 2012 17:34:48 Tomasz Stanislawski wrote:
> > > This patch adds extension to V4L2 api. It allow to export a mmap buffer as
> > > file descriptor. New ioctl VIDIOC_EXPBUF is added. It takes a buffer
> > > offset used by mmap and return a file descriptor on success.
> > > 
> > > Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
> > > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> 
> [snip]
> 
> > > diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
> > > index 7f918dc..b5d058b 100644
> > > --- a/include/linux/videodev2.h
> > > +++ b/include/linux/videodev2.h
> > > @@ -688,6 +688,31 @@ struct v4l2_buffer {
> > > 
> > >  #define V4L2_BUF_FLAG_NO_CACHE_INVALIDATE	0x0800
> > >  #define V4L2_BUF_FLAG_NO_CACHE_CLEAN		0x1000
> > > 
> > > +/**
> > > + * struct v4l2_exportbuffer - export of video buffer as DMABUF file
> > > descriptor + *
> > > + * @fd:		file descriptor associated with DMABUF (set by driver)
> > > + * @mem_offset:	buffer memory offset as returned by VIDIOC_QUERYBUF in
> > > struct + *		v4l2_buffer::m.offset (for single-plane formats) or
> > > + *		v4l2_plane::m.offset (for multi-planar formats)
> > > + * @flags:	flags for newly created file, currently only O_CLOEXEC is
> > > + *		supported, refer to manual of open syscall for more details
> > > + *
> > > + * Contains data used for exporting a video buffer as DMABUF file
> > > descriptor. + * The buffer is identified by a 'cookie' returned by
> > > VIDIOC_QUERYBUF + * (identical to the cookie used to mmap() the buffer to
> > > userspace). All + * reserved fields must be set to zero. The field
> > > reserved0 is expected to + * become a structure 'type' allowing an
> > > alternative layout of the structure + * content. Therefore this field
> > > should not be used for any other extensions. + */
> > > +struct v4l2_exportbuffer {
> > > +	__u32		fd;
> > > +	__u32		reserved0;
> > > +	__u32		mem_offset;
> > > +	__u32		flags;
> > > +	__u32		reserved[12];
> > > +};
> > 
> > OK, I realized that we also need a type field here: you need the type field
> > (same as in v4l2_buffer) to know which queue the mem_offset refers to. For
> > M2M devices you have two queues, so you need this information.
> > 
> > Is there any reason not to use __u32 memory instead of __u32 reserved0?
> > I really dislike 'reserved0'. It's also very inconsistent with the other
> > buffer ioctls which all have type+memory fields.
> 
> I'm concerned that we might need to export buffers in the future based on 
> something else than the memory type. That's probably an irrational fear 
> though.

We're exporting buffers from the V4L2 core. The only method of creating such
buffers is through REQBUFS/CREATE_BUFS, both of which use the memory field.
Even if we need something else in the future, then there is nothing preventing
us from extending the memory enum.

> > Regarding mem_offset: I would prefer a union (possibly anonymous):
> > 
> >         union {
> >                 __u32           mem_offset;
> >                 unsigned long   reserved;
> >         } m;
> > 
> > Again, it's more consistent with the existing buffer ioctls, and it prepares
> > the API for future pointer values. 'reserved' in the union above could even
> > safely be renamed to userptr, even though userptr isn't supported at the
> > moment.
> 
> Once again I would really want to see compeling use cases before we export a 
> userptr buffer as a dmabuf object. As Mauro previously stated, userptr for 
> buffer sharing was a hack in the first place (although a pretty successful one 
> so far).

I don't want to export a userptr, I want to make sure we *can* export a
pointer-sized thing in the future. Which is why in my proposal above I'm
calling it reserved and not userptr.

Regards,

	Hans

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

* Re: [PATCHv8 02/26] Documentation: media: description of DMABUF importing in V4L2
  2012-08-22 10:47   ` Hans Verkuil
@ 2012-09-24 12:17     ` Tomasz Stanislawski
  2012-09-25 10:48       ` Hans Verkuil
  0 siblings, 1 reply; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-09-24 12:17 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: linux-media, dri-devel, airlied, m.szyprowski, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, remi, subashrp, mchehab,
	g.liakhovetski, dmitriyz, s.nawrocki, k.debski, linux-doc

Hi Hans,
Thank you for review.

On 08/22/2012 12:47 PM, Hans Verkuil wrote:
> On Tue August 14 2012 17:34:32 Tomasz Stanislawski wrote:
>> This patch adds description and usage examples for importing
>> DMABUF file descriptor in V4L2.
>>
>> Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
>> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
>> CC: linux-doc@vger.kernel.org
>> ---
>>  Documentation/DocBook/media/v4l/compat.xml         |    4 +
>>  Documentation/DocBook/media/v4l/io.xml             |  180 ++++++++++++++++++++
>>  .../DocBook/media/v4l/vidioc-create-bufs.xml       |    3 +-
>>  Documentation/DocBook/media/v4l/vidioc-qbuf.xml    |   15 ++
>>  Documentation/DocBook/media/v4l/vidioc-reqbufs.xml |   47 ++---
>>  5 files changed, 226 insertions(+), 23 deletions(-)
>>

[snip]

>> +&v4l2-plane; in the multi-planar API case).  The driver must be switched into
>> +DMABUF I/O mode by calling the &VIDIOC-REQBUFS; with the desired buffer type.
>> +No buffers (planes) are allocated beforehand, consequently they are not indexed
>> +and cannot be queried like mapped buffers with the
>> +<constant>VIDIOC_QUERYBUF</constant> ioctl.</para>
> 
> I disagree with that. Userptr buffers can use QUERYBUF just fine. Even for the
> userptr you still have to fill in the buffer index when calling QBUF.
> 
> So I see no reason why you couldn't use QUERYBUF in the DMABUF case. The only
> difference is that the fd field is undefined (set to -1 perhaps?) if the bufffer
> isn't queued.
> 
> QUERYBUF can be very useful for debugging, for example to see what the status
> is of each buffer and how many are queued.
> 

Ok. I agree that QUERYBUF can be useful for debugging. The value of fd field
should be the last value passed using QBUF. It would simplify streaming
because an application would not have to keep the file descriptor around.

>> +
>> +    <example>
>> +      <title>Initiating streaming I/O with DMABUF file descriptors</title>
>> +
>> +      <programlisting>
>> +&v4l2-requestbuffers; reqbuf;
>> +
>> +memset (&amp;reqbuf, 0, sizeof (reqbuf));
>> +reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
>> +reqbuf.memory = V4L2_MEMORY_DMABUF;
>> +reqbuf.count = 1;
>> +
>> +if (ioctl (fd, &VIDIOC-REQBUFS;, &amp;reqbuf) == -1) {
>> +	if (errno == EINVAL)
>> +		printf ("Video capturing or DMABUF streaming is not supported\n");
>> +	else
>> +		perror ("VIDIOC_REQBUFS");
>> +
>> +	exit (EXIT_FAILURE);
> 
> Let's stick to the kernel coding style, so no ' ' before '(' in function calls.
> Same for the other program examples below.
> 

The ' ' before function was used for userptr and mmap usage examples.
These examples should be fixed too.

>> +}
>> +      </programlisting>
>> +    </example>
>> +
>> +    <para>Buffer (plane) file descriptor is passed on the fly with the
> 
> s/Buffer/The buffer/
> 
>> +&VIDIOC-QBUF; ioctl. In case of multiplanar buffers, every plane can be
> 
> 'Can be', 'should be' or 'must be'? Does it ever make sense to have the same
> fd for different planes? Do we have restrictions on this in the userptr case?
> 

I think that we should keep to 'can be'. I see no good reason to
prevent the same dmabuf to be used for different planes.
Allowing reusing of dmabufs with assistance of data_offset field
would allow to pass a 2-planar YUV420 from V4L2-single-plane API
to a driver with V4L2-multi-plane API.

[snip]

>> diff --git a/Documentation/DocBook/media/v4l/vidioc-qbuf.xml b/Documentation/DocBook/media/v4l/vidioc-qbuf.xml
>> index 77ff5be..436d21c 100644
>> --- a/Documentation/DocBook/media/v4l/vidioc-qbuf.xml
>> +++ b/Documentation/DocBook/media/v4l/vidioc-qbuf.xml
>> @@ -109,6 +109,21 @@ they cannot be swapped out to disk. Buffers remain locked until
>>  dequeued, until the &VIDIOC-STREAMOFF; or &VIDIOC-REQBUFS; ioctl is
>>  called, or until the device is closed.</para>
>>  
>> +    <para>To enqueue a <link linkend="dmabuf">DMABUF</link> buffer applications
>> +set the <structfield>memory</structfield> field to
>> +<constant>V4L2_MEMORY_DMABUF</constant> and the <structfield>m.fd</structfield>
>> +field to a file descriptor associated with a DMABUF buffer. When the
>> +multi-planar API is used <structfield>m.fd</structfield> of the passed array of
> 
> multi-planar API is used the <structfield>m.fd</structfield> fields of the passed array of
> 
>> +&v4l2-plane; have to be used instead. When <constant>VIDIOC_QBUF</constant> is
>> +called with a pointer to this structure the driver sets the
>> +<constant>V4L2_BUF_FLAG_QUEUED</constant> flag and clears the
>> +<constant>V4L2_BUF_FLAG_MAPPED</constant> and
>> +<constant>V4L2_BUF_FLAG_DONE</constant> flags in the
>> +<structfield>flags</structfield> field, or it returns an error code.  This
>> +ioctl locks the buffer. Buffers remain locked until dequeued, until the
>> +&VIDIOC-STREAMOFF; or &VIDIOC-REQBUFS; ioctl is called, or until the device is
>> +closed.</para>
> 
> You need to explain what a 'locked buffer' means.

I propose following definition:
"Locking a buffer means passing it to a driver for an access by hardware.
"If an application accesses (reads/writes) a locked buffer then the result
is undefined."

What is your opinion about proposed definition?

> 
>> +
>>      <para>Applications call the <constant>VIDIOC_DQBUF</constant>
>>  ioctl to dequeue a filled (capturing) or displayed (output) buffer
>>  from the driver's outgoing queue. They just set the
>> diff --git a/Documentation/DocBook/media/v4l/vidioc-reqbufs.xml b/Documentation/DocBook/media/v4l/vidioc-reqbufs.xml
>> index d7c9505..20f4323 100644
>> --- a/Documentation/DocBook/media/v4l/vidioc-reqbufs.xml
>> +++ b/Documentation/DocBook/media/v4l/vidioc-reqbufs.xml
>> @@ -48,28 +48,30 @@
>>    <refsect1>
>>      <title>Description</title>
>>  
>> -    <para>This ioctl is used to initiate <link linkend="mmap">memory
>> -mapped</link> or <link linkend="userp">user pointer</link>
>> -I/O. Memory mapped buffers are located in device memory and must be
>> -allocated with this ioctl before they can be mapped into the
>> -application's address space. User buffers are allocated by
>> -applications themselves, and this ioctl is merely used to switch the
>> -driver into user pointer I/O mode and to setup some internal structures.</para>
>> +<para>This ioctl is used to initiate <link linkend="mmap">memory mapped</link>,
>> +<link linkend="userp">user pointer</link> or <link
>> +linkend="dmabuf">DMABUF</link> based I/O.  Memory mapped buffers are located in
>> +device memory and must be allocated with this ioctl before they can be mapped
>> +into the application's address space. User buffers are allocated by
>> +applications themselves, and this ioctl is merely used to switch the driver
>> +into user pointer I/O mode and to setup some internal structures.
>> +Similarly, DMABUF buffers are allocated by applications through a device
>> +driver, and this ioctl only configures the driver into DMABUF I/O mode without
>> +performing any direct allocation.</para>
>>  
>> -    <para>To allocate device buffers applications initialize all
>> -fields of the <structname>v4l2_requestbuffers</structname> structure.
>> -They set the <structfield>type</structfield> field to the respective
>> -stream or buffer type, the <structfield>count</structfield> field to
>> -the desired number of buffers, <structfield>memory</structfield>
>> -must be set to the requested I/O method and the <structfield>reserved</structfield> array
>> -must be zeroed. When the ioctl
>> -is called with a pointer to this structure the driver will attempt to allocate
>> -the requested number of buffers and it stores the actual number
>> -allocated in the <structfield>count</structfield> field. It can be
>> -smaller than the number requested, even zero, when the driver runs out
>> -of free memory. A larger number is also possible when the driver requires
>> -more buffers to function correctly. For example video output requires at least two buffers,
>> -one displayed and one filled by the application.</para>
>> +    <para>To allocate device buffers applications initialize all fields of the
>> +<structname>v4l2_requestbuffers</structname> structure.  They set the
>> +<structfield>type</structfield> field to the respective stream or buffer type,
>> +the <structfield>count</structfield> field to the desired number of buffers,
>> +<structfield>memory</structfield> must be set to the requested I/O method and
>> +the <structfield>reserved</structfield> array must be zeroed. When the ioctl is
>> +called with a pointer to this structure the driver will attempt to allocate the
>> +requested number of buffers and it stores the actual number allocated in the
>> +<structfield>count</structfield> field. It can be smaller than the number
>> +requested, even zero, when the driver runs out of free memory. A larger number
>> +is also possible when the driver requires more buffers to function correctly.
>> +For example video output requires at least two buffers, one displayed and one
>> +filled by the application.</para>
>>      <para>When the I/O method is not supported the ioctl
>>  returns an &EINVAL;.</para>
>>  
>> @@ -102,7 +104,8 @@ as the &v4l2-format; <structfield>type</structfield> field. See <xref
>>  	    <entry>__u32</entry>
>>  	    <entry><structfield>memory</structfield></entry>
>>  	    <entry>Applications set this field to
>> -<constant>V4L2_MEMORY_MMAP</constant> or
>> +<constant>V4L2_MEMORY_MMAP</constant>,
>> +<constant>V4L2_MEMORY_DMABUF</constant> or
>>  <constant>V4L2_MEMORY_USERPTR</constant>. See <xref linkend="v4l2-memory"
>>  />.</entry>
>>  	  </row>
>>
> 
> You also have to update the VIDIOC_CREATE_BUFS ioctl documentation!
> 
> I think the VIDIOC_PREPARE_BUF ioctl documentation is OK, but you might want to
> check that yourself, just in case.
> 

Ok.
Regards,
Tomasz Stanislawski

> Regards,
> 
> 	Hans
> 


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

* Re: [PATCHv8 02/26] Documentation: media: description of DMABUF importing in V4L2
  2012-09-24 12:17     ` Tomasz Stanislawski
@ 2012-09-25 10:48       ` Hans Verkuil
  0 siblings, 0 replies; 58+ messages in thread
From: Hans Verkuil @ 2012-09-25 10:48 UTC (permalink / raw)
  To: Tomasz Stanislawski
  Cc: linux-media, dri-devel, airlied, m.szyprowski, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, remi, subashrp, mchehab,
	g.liakhovetski, dmitriyz, s.nawrocki, k.debski, linux-doc

On Mon 24 September 2012 14:17:00 Tomasz Stanislawski wrote:
> Hi Hans,
> Thank you for review.
> 
> On 08/22/2012 12:47 PM, Hans Verkuil wrote:
> > On Tue August 14 2012 17:34:32 Tomasz Stanislawski wrote:
> >> This patch adds description and usage examples for importing
> >> DMABUF file descriptor in V4L2.
> >>
> >> Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
> >> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> >> CC: linux-doc@vger.kernel.org
> >> ---
> >>  Documentation/DocBook/media/v4l/compat.xml         |    4 +
> >>  Documentation/DocBook/media/v4l/io.xml             |  180 ++++++++++++++++++++
> >>  .../DocBook/media/v4l/vidioc-create-bufs.xml       |    3 +-
> >>  Documentation/DocBook/media/v4l/vidioc-qbuf.xml    |   15 ++
> >>  Documentation/DocBook/media/v4l/vidioc-reqbufs.xml |   47 ++---
> >>  5 files changed, 226 insertions(+), 23 deletions(-)
> >>
> 
> [snip]
> 
> >> +&v4l2-plane; in the multi-planar API case).  The driver must be switched into
> >> +DMABUF I/O mode by calling the &VIDIOC-REQBUFS; with the desired buffer type.
> >> +No buffers (planes) are allocated beforehand, consequently they are not indexed
> >> +and cannot be queried like mapped buffers with the
> >> +<constant>VIDIOC_QUERYBUF</constant> ioctl.</para>
> > 
> > I disagree with that. Userptr buffers can use QUERYBUF just fine. Even for the
> > userptr you still have to fill in the buffer index when calling QBUF.
> > 
> > So I see no reason why you couldn't use QUERYBUF in the DMABUF case. The only
> > difference is that the fd field is undefined (set to -1 perhaps?) if the bufffer
> > isn't queued.
> > 
> > QUERYBUF can be very useful for debugging, for example to see what the status
> > is of each buffer and how many are queued.
> > 
> 
> Ok. I agree that QUERYBUF can be useful for debugging. The value of fd field
> should be the last value passed using QBUF. It would simplify streaming
> because an application would not have to keep the file descriptor around.

If a buffer isn't queued, then fd really is undefined. I don't see any advantage
of remembering the last value used there (and after a REQBUFS there isn't a 'last
value' anyway).

> >> +
> >> +    <example>
> >> +      <title>Initiating streaming I/O with DMABUF file descriptors</title>
> >> +
> >> +      <programlisting>
> >> +&v4l2-requestbuffers; reqbuf;
> >> +
> >> +memset (&amp;reqbuf, 0, sizeof (reqbuf));
> >> +reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> >> +reqbuf.memory = V4L2_MEMORY_DMABUF;
> >> +reqbuf.count = 1;
> >> +
> >> +if (ioctl (fd, &VIDIOC-REQBUFS;, &amp;reqbuf) == -1) {
> >> +	if (errno == EINVAL)
> >> +		printf ("Video capturing or DMABUF streaming is not supported\n");
> >> +	else
> >> +		perror ("VIDIOC_REQBUFS");
> >> +
> >> +	exit (EXIT_FAILURE);
> > 
> > Let's stick to the kernel coding style, so no ' ' before '(' in function calls.
> > Same for the other program examples below.
> > 
> 
> The ' ' before function was used for userptr and mmap usage examples.
> These examples should be fixed too.
> 
> >> +}
> >> +      </programlisting>
> >> +    </example>
> >> +
> >> +    <para>Buffer (plane) file descriptor is passed on the fly with the
> > 
> > s/Buffer/The buffer/
> > 
> >> +&VIDIOC-QBUF; ioctl. In case of multiplanar buffers, every plane can be
> > 
> > 'Can be', 'should be' or 'must be'? Does it ever make sense to have the same
> > fd for different planes? Do we have restrictions on this in the userptr case?
> > 
> 
> I think that we should keep to 'can be'. I see no good reason to
> prevent the same dmabuf to be used for different planes.
> Allowing reusing of dmabufs with assistance of data_offset field
> would allow to pass a 2-planar YUV420 from V4L2-single-plane API
> to a driver with V4L2-multi-plane API.

That's true.

> 
> [snip]
> 
> >> diff --git a/Documentation/DocBook/media/v4l/vidioc-qbuf.xml b/Documentation/DocBook/media/v4l/vidioc-qbuf.xml
> >> index 77ff5be..436d21c 100644
> >> --- a/Documentation/DocBook/media/v4l/vidioc-qbuf.xml
> >> +++ b/Documentation/DocBook/media/v4l/vidioc-qbuf.xml
> >> @@ -109,6 +109,21 @@ they cannot be swapped out to disk. Buffers remain locked until
> >>  dequeued, until the &VIDIOC-STREAMOFF; or &VIDIOC-REQBUFS; ioctl is
> >>  called, or until the device is closed.</para>
> >>  
> >> +    <para>To enqueue a <link linkend="dmabuf">DMABUF</link> buffer applications
> >> +set the <structfield>memory</structfield> field to
> >> +<constant>V4L2_MEMORY_DMABUF</constant> and the <structfield>m.fd</structfield>
> >> +field to a file descriptor associated with a DMABUF buffer. When the
> >> +multi-planar API is used <structfield>m.fd</structfield> of the passed array of
> > 
> > multi-planar API is used the <structfield>m.fd</structfield> fields of the passed array of
> > 
> >> +&v4l2-plane; have to be used instead. When <constant>VIDIOC_QBUF</constant> is
> >> +called with a pointer to this structure the driver sets the
> >> +<constant>V4L2_BUF_FLAG_QUEUED</constant> flag and clears the
> >> +<constant>V4L2_BUF_FLAG_MAPPED</constant> and
> >> +<constant>V4L2_BUF_FLAG_DONE</constant> flags in the

What does it do to the PREPARED flag I wonder?

> >> +<structfield>flags</structfield> field, or it returns an error code.  This
> >> +ioctl locks the buffer. Buffers remain locked until dequeued, until the
> >> +&VIDIOC-STREAMOFF; or &VIDIOC-REQBUFS; ioctl is called, or until the device is
> >> +closed.</para>
> > 
> > You need to explain what a 'locked buffer' means.
> 
> I propose following definition:
> "Locking a buffer means passing it to a driver for an access by hardware.
> "If an application accesses (reads/writes) a locked buffer then the result
> is undefined."
> 
> What is your opinion about proposed definition?

Sounds good.

> 
> > 
> >> +
> >>      <para>Applications call the <constant>VIDIOC_DQBUF</constant>
> >>  ioctl to dequeue a filled (capturing) or displayed (output) buffer
> >>  from the driver's outgoing queue. They just set the
> >> diff --git a/Documentation/DocBook/media/v4l/vidioc-reqbufs.xml b/Documentation/DocBook/media/v4l/vidioc-reqbufs.xml
> >> index d7c9505..20f4323 100644
> >> --- a/Documentation/DocBook/media/v4l/vidioc-reqbufs.xml
> >> +++ b/Documentation/DocBook/media/v4l/vidioc-reqbufs.xml
> >> @@ -48,28 +48,30 @@
> >>    <refsect1>
> >>      <title>Description</title>
> >>  
> >> -    <para>This ioctl is used to initiate <link linkend="mmap">memory
> >> -mapped</link> or <link linkend="userp">user pointer</link>
> >> -I/O. Memory mapped buffers are located in device memory and must be
> >> -allocated with this ioctl before they can be mapped into the
> >> -application's address space. User buffers are allocated by
> >> -applications themselves, and this ioctl is merely used to switch the
> >> -driver into user pointer I/O mode and to setup some internal structures.</para>
> >> +<para>This ioctl is used to initiate <link linkend="mmap">memory mapped</link>,
> >> +<link linkend="userp">user pointer</link> or <link
> >> +linkend="dmabuf">DMABUF</link> based I/O.  Memory mapped buffers are located in
> >> +device memory and must be allocated with this ioctl before they can be mapped
> >> +into the application's address space. User buffers are allocated by
> >> +applications themselves, and this ioctl is merely used to switch the driver
> >> +into user pointer I/O mode and to setup some internal structures.
> >> +Similarly, DMABUF buffers are allocated by applications through a device
> >> +driver, and this ioctl only configures the driver into DMABUF I/O mode without
> >> +performing any direct allocation.</para>
> >>  
> >> -    <para>To allocate device buffers applications initialize all
> >> -fields of the <structname>v4l2_requestbuffers</structname> structure.
> >> -They set the <structfield>type</structfield> field to the respective
> >> -stream or buffer type, the <structfield>count</structfield> field to
> >> -the desired number of buffers, <structfield>memory</structfield>
> >> -must be set to the requested I/O method and the <structfield>reserved</structfield> array
> >> -must be zeroed. When the ioctl
> >> -is called with a pointer to this structure the driver will attempt to allocate
> >> -the requested number of buffers and it stores the actual number
> >> -allocated in the <structfield>count</structfield> field. It can be
> >> -smaller than the number requested, even zero, when the driver runs out
> >> -of free memory. A larger number is also possible when the driver requires
> >> -more buffers to function correctly. For example video output requires at least two buffers,
> >> -one displayed and one filled by the application.</para>
> >> +    <para>To allocate device buffers applications initialize all fields of the
> >> +<structname>v4l2_requestbuffers</structname> structure.  They set the
> >> +<structfield>type</structfield> field to the respective stream or buffer type,
> >> +the <structfield>count</structfield> field to the desired number of buffers,
> >> +<structfield>memory</structfield> must be set to the requested I/O method and
> >> +the <structfield>reserved</structfield> array must be zeroed. When the ioctl is
> >> +called with a pointer to this structure the driver will attempt to allocate the
> >> +requested number of buffers and it stores the actual number allocated in the
> >> +<structfield>count</structfield> field. It can be smaller than the number
> >> +requested, even zero, when the driver runs out of free memory. A larger number
> >> +is also possible when the driver requires more buffers to function correctly.
> >> +For example video output requires at least two buffers, one displayed and one
> >> +filled by the application.</para>
> >>      <para>When the I/O method is not supported the ioctl
> >>  returns an &EINVAL;.</para>
> >>  
> >> @@ -102,7 +104,8 @@ as the &v4l2-format; <structfield>type</structfield> field. See <xref
> >>  	    <entry>__u32</entry>
> >>  	    <entry><structfield>memory</structfield></entry>
> >>  	    <entry>Applications set this field to
> >> -<constant>V4L2_MEMORY_MMAP</constant> or
> >> +<constant>V4L2_MEMORY_MMAP</constant>,
> >> +<constant>V4L2_MEMORY_DMABUF</constant> or
> >>  <constant>V4L2_MEMORY_USERPTR</constant>. See <xref linkend="v4l2-memory"
> >>  />.</entry>
> >>  	  </row>
> >>
> > 
> > You also have to update the VIDIOC_CREATE_BUFS ioctl documentation!
> > 
> > I think the VIDIOC_PREPARE_BUF ioctl documentation is OK, but you might want to
> > check that yourself, just in case.
> > 
> 
> Ok.
> Regards,
> Tomasz Stanislawski
> 
> > Regards,
> > 
> > 	Hans
> > 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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

* Re: [PATCHv8 13/26] v4l: vivi: support for dmabuf importing
  2012-08-22 11:47     ` Hans Verkuil
@ 2012-09-25 14:41       ` Tomasz Stanislawski
  0 siblings, 0 replies; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-09-25 14:41 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: linux-media, dri-devel, airlied, m.szyprowski, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, remi, subashrp, mchehab,
	g.liakhovetski, dmitriyz, s.nawrocki, k.debski

On 08/22/2012 01:47 PM, Hans Verkuil wrote:
> On Wed August 22 2012 12:56:30 Hans Verkuil wrote:
>> On Tue August 14 2012 17:34:43 Tomasz Stanislawski wrote:
>>> This patch enhances VIVI driver with a support for importing a buffer
>>> from DMABUF file descriptors.
>>
>> Thanks for adding DMABUF support to vivi.
>>
>> What would be great is if DMABUF support is also added to mem2mem_testdev.
>> It would make an excellent test case to take the vivi output, pass it
>> through mem2mem_testdev, and finally output the image using the gpu, all
>> using dmabuf.
>>
>> It's also very useful for application developers to test dmabuf support
>> without requiring special hardware (other than a dmabuf-enabled gpu
>> driver).
> 
> Adding VIDIOC_EXPBUF support to vivi and mem2mem_testdev would be
> welcome as well for the same reasons.
> 
> Regards,
> 
> 	Hans
> 

Hi Hans,

Adding DMABUF exporting to vmalloc is not easy as it seams.
Exporting introduces a new level of complexity and code bloat to a framework.
I mean support for:
- NULL devices as DMABUF exporters
- vmalloc to sglist conversions
- calling dma_map_sg for importers
- cache management

I admit that most of the work should be delegated to dmabuf framework.
I propose to postpone support for dmabuf exporting in vmalloc until
vb2-dmabuf gets merged.

Regards,
Tomasz Stanislawski


>>
>> Regards,
>>
>> 	Hans
>>
>>>
>>> Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
>>> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
>>> ---
>>>  drivers/media/video/Kconfig |    1 +
>>>  drivers/media/video/vivi.c  |    2 +-
>>>  2 files changed, 2 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
>>> index 966954d..8fa81be 100644
>>> --- a/drivers/media/video/Kconfig
>>> +++ b/drivers/media/video/Kconfig
>>> @@ -653,6 +653,7 @@ config VIDEO_VIVI
>>>  	depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE
>>>  	select FONT_8x16
>>>  	select VIDEOBUF2_VMALLOC
>>> +	select DMA_SHARED_BUFFER
>>>  	default n
>>>  	---help---
>>>  	  Enables a virtual video driver. This device shows a color bar
>>> diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
>>> index a6351c4..37d8fd4 100644
>>> --- a/drivers/media/video/vivi.c
>>> +++ b/drivers/media/video/vivi.c
>>> @@ -1308,7 +1308,7 @@ static int __init vivi_create_instance(int inst)
>>>  	q = &dev->vb_vidq;
>>>  	memset(q, 0, sizeof(dev->vb_vidq));
>>>  	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
>>> -	q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
>>> +	q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
>>>  	q->drv_priv = dev;
>>>  	q->buf_struct_size = sizeof(struct vivi_buffer);
>>>  	q->ops = &vivi_video_qops;
>>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-media" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>


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

* Re: [PATCHv8 18/26] v4l: add buffer exporting via dmabuf
  2012-08-22 11:41   ` Hans Verkuil
  2012-08-22 23:39     ` Laurent Pinchart
@ 2012-09-25 16:30     ` Tomasz Stanislawski
  2012-09-26  6:39       ` Hans Verkuil
  1 sibling, 1 reply; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-09-25 16:30 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: linux-media, dri-devel, airlied, m.szyprowski, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, remi, subashrp, mchehab,
	g.liakhovetski, dmitriyz, s.nawrocki, k.debski

Hi Hans,
Thank you for review.
Please refer to the comments below.

On 08/22/2012 01:41 PM, Hans Verkuil wrote:
> On Tue August 14 2012 17:34:48 Tomasz Stanislawski wrote:
>> This patch adds extension to V4L2 api. It allow to export a mmap buffer as file
>> descriptor. New ioctl VIDIOC_EXPBUF is added. It takes a buffer offset used by
>> mmap and return a file descriptor on success.
>>
>> Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
>> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
>> ---
>>  drivers/media/video/v4l2-compat-ioctl32.c |    1 +
>>  drivers/media/video/v4l2-dev.c            |    1 +
>>  drivers/media/video/v4l2-ioctl.c          |   15 +++++++++++++++
>>  include/linux/videodev2.h                 |   26 ++++++++++++++++++++++++++
>>  include/media/v4l2-ioctl.h                |    2 ++
>>  5 files changed, 45 insertions(+)
>>

[snip]

>> diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
>> index dffd3c9..c4e8c7e 100644
>> --- a/drivers/media/video/v4l2-ioctl.c
>> +++ b/drivers/media/video/v4l2-ioctl.c
>> @@ -458,6 +458,14 @@ static void v4l_print_buffer(const void *arg, bool write_only)
>>  			tc->type, tc->flags, tc->frames, *(__u32 *)tc->userbits);
>>  }
>>  
>> +static void v4l_print_exportbuffer(const void *arg, bool write_only)
>> +{
>> +	const struct v4l2_exportbuffer *p = arg;
>> +
>> +	pr_cont("fd=%d, mem_offset=%lx, flags=%lx\n",
>> +		p->fd, (unsigned long)p->mem_offset, (unsigned long)p->flags);
> 
> Why the unsigned long casts?
> 

It is needed to avoid compiler warnings on machines where "%lx" is not
compatible with u32.

>> +}
>> +
>>  static void v4l_print_create_buffers(const void *arg, bool write_only)
>>  {
>>  	const struct v4l2_create_buffers *p = arg;

[snip]

>> diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
>> index 7f918dc..b5d058b 100644
>> --- a/include/linux/videodev2.h
>> +++ b/include/linux/videodev2.h
>> @@ -688,6 +688,31 @@ struct v4l2_buffer {
>>  #define V4L2_BUF_FLAG_NO_CACHE_INVALIDATE	0x0800
>>  #define V4L2_BUF_FLAG_NO_CACHE_CLEAN		0x1000
>>  
>> +/**
>> + * struct v4l2_exportbuffer - export of video buffer as DMABUF file descriptor
>> + *
>> + * @fd:		file descriptor associated with DMABUF (set by driver)
>> + * @mem_offset:	buffer memory offset as returned by VIDIOC_QUERYBUF in struct
>> + *		v4l2_buffer::m.offset (for single-plane formats) or
>> + *		v4l2_plane::m.offset (for multi-planar formats)
>> + * @flags:	flags for newly created file, currently only O_CLOEXEC is
>> + *		supported, refer to manual of open syscall for more details
>> + *
>> + * Contains data used for exporting a video buffer as DMABUF file descriptor.
>> + * The buffer is identified by a 'cookie' returned by VIDIOC_QUERYBUF
>> + * (identical to the cookie used to mmap() the buffer to userspace). All
>> + * reserved fields must be set to zero. The field reserved0 is expected to
>> + * become a structure 'type' allowing an alternative layout of the structure
>> + * content. Therefore this field should not be used for any other extensions.
>> + */
>> +struct v4l2_exportbuffer {
>> +	__u32		fd;
>> +	__u32		reserved0;
>> +	__u32		mem_offset;
>> +	__u32		flags;
>> +	__u32		reserved[12];
>> +};
> 
> OK, I realized that we also need a type field here: you need the type field
> (same as in v4l2_buffer) to know which queue the mem_offset refers to. For
> M2M devices you have two queues, so you need this information.

I do not agree with you. The mmap() does not need buffer_type.
So VIDIOC_EXPBUF should not need the field either.
Please refer to patch "[PATCHv8 26/26] v4l: s5p-mfc: support for dmabuf exporting"
for example how to deal without buffer_type.

> 
> Is there any reason not to use __u32 memory instead of __u32 reserved0?
> I really dislike 'reserved0'. It's also very inconsistent with the other
> buffer ioctls which all have type+memory fields.

The type is not needed for exporting if mem_offset is available like in mmap() case.
The memory is not needed because exporting is available only for MMAP buffers.

I see two ways to describe a buffer for exporting:
a) by mem_offset
b) by (buffer_type, index, plane_index) tuple

For know I prefer to implement only method (a) to avoid
"single vs. multi plane" madness. Moreover it guarantees
that only MMAP buffers are exported.

The second method assisted by VIDIOC_PREPARE_BUF will allow
userptr-to-dmabuf conversion or dmabuf reexporting.

> 
> Regarding mem_offset: I would prefer a union (possibly anonymous):

I prefer not to add anonymous unions (though I like them) because
the unions are not compatible with multiple C standards including C89.

> 
>         union {
>                 __u32           mem_offset;
>                 unsigned long   reserved;
>         } m;
> 
> Again, it's more consistent with the existing buffer ioctls, and it prepares
> the API for future pointer values. 'reserved' in the union above could even
> safely be renamed to userptr, even though userptr isn't supported at the
> moment.
> 

There is no guarantee that DMABUF could ever be created from user pointer.
IMO, there is little need for support for such a feature.
I prefer not to add any fields that to not immediately map to DMABUF
functionalities. Let's keep the structures simple for now.

Moreover I prefer not to add 'unsigned long' as union member because
the size of the union would be different on 32 and 64 bit machines.

The API is marked as experimental so it can change significantly.

Regards,
Tomasz Stanislawski


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

* Re: [PATCHv8 18/26] v4l: add buffer exporting via dmabuf
  2012-09-25 16:30     ` Tomasz Stanislawski
@ 2012-09-26  6:39       ` Hans Verkuil
  2012-09-26  9:55         ` Tomasz Stanislawski
  0 siblings, 1 reply; 58+ messages in thread
From: Hans Verkuil @ 2012-09-26  6:39 UTC (permalink / raw)
  To: Tomasz Stanislawski
  Cc: linux-media, dri-devel, airlied, m.szyprowski, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, remi, subashrp, mchehab,
	g.liakhovetski, dmitriyz, s.nawrocki, k.debski

On Tue September 25 2012 18:30:43 Tomasz Stanislawski wrote:
> Hi Hans,
> Thank you for review.
> Please refer to the comments below.
> 
> On 08/22/2012 01:41 PM, Hans Verkuil wrote:
> > On Tue August 14 2012 17:34:48 Tomasz Stanislawski wrote:
> >> This patch adds extension to V4L2 api. It allow to export a mmap buffer as file
> >> descriptor. New ioctl VIDIOC_EXPBUF is added. It takes a buffer offset used by
> >> mmap and return a file descriptor on success.
> >>
> >> Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
> >> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> >> ---
> >>  drivers/media/video/v4l2-compat-ioctl32.c |    1 +
> >>  drivers/media/video/v4l2-dev.c            |    1 +
> >>  drivers/media/video/v4l2-ioctl.c          |   15 +++++++++++++++
> >>  include/linux/videodev2.h                 |   26 ++++++++++++++++++++++++++
> >>  include/media/v4l2-ioctl.h                |    2 ++
> >>  5 files changed, 45 insertions(+)
> >>
> 
> [snip]
> 
> >> diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
> >> index dffd3c9..c4e8c7e 100644
> >> --- a/drivers/media/video/v4l2-ioctl.c
> >> +++ b/drivers/media/video/v4l2-ioctl.c
> >> @@ -458,6 +458,14 @@ static void v4l_print_buffer(const void *arg, bool write_only)
> >>  			tc->type, tc->flags, tc->frames, *(__u32 *)tc->userbits);
> >>  }
> >>  
> >> +static void v4l_print_exportbuffer(const void *arg, bool write_only)
> >> +{
> >> +	const struct v4l2_exportbuffer *p = arg;
> >> +
> >> +	pr_cont("fd=%d, mem_offset=%lx, flags=%lx\n",
> >> +		p->fd, (unsigned long)p->mem_offset, (unsigned long)p->flags);
> > 
> > Why the unsigned long casts?
> > 
> 
> It is needed to avoid compiler warnings on machines where "%lx" is not
> compatible with u32.

Why not use %x instead of %lx?

> >> +}
> >> +
> >>  static void v4l_print_create_buffers(const void *arg, bool write_only)
> >>  {
> >>  	const struct v4l2_create_buffers *p = arg;
> 
> [snip]
> 
> >> diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
> >> index 7f918dc..b5d058b 100644
> >> --- a/include/linux/videodev2.h
> >> +++ b/include/linux/videodev2.h
> >> @@ -688,6 +688,31 @@ struct v4l2_buffer {
> >>  #define V4L2_BUF_FLAG_NO_CACHE_INVALIDATE	0x0800
> >>  #define V4L2_BUF_FLAG_NO_CACHE_CLEAN		0x1000
> >>  
> >> +/**
> >> + * struct v4l2_exportbuffer - export of video buffer as DMABUF file descriptor
> >> + *
> >> + * @fd:		file descriptor associated with DMABUF (set by driver)
> >> + * @mem_offset:	buffer memory offset as returned by VIDIOC_QUERYBUF in struct
> >> + *		v4l2_buffer::m.offset (for single-plane formats) or
> >> + *		v4l2_plane::m.offset (for multi-planar formats)
> >> + * @flags:	flags for newly created file, currently only O_CLOEXEC is
> >> + *		supported, refer to manual of open syscall for more details
> >> + *
> >> + * Contains data used for exporting a video buffer as DMABUF file descriptor.
> >> + * The buffer is identified by a 'cookie' returned by VIDIOC_QUERYBUF
> >> + * (identical to the cookie used to mmap() the buffer to userspace). All
> >> + * reserved fields must be set to zero. The field reserved0 is expected to
> >> + * become a structure 'type' allowing an alternative layout of the structure
> >> + * content. Therefore this field should not be used for any other extensions.
> >> + */
> >> +struct v4l2_exportbuffer {
> >> +	__u32		fd;
> >> +	__u32		reserved0;
> >> +	__u32		mem_offset;
> >> +	__u32		flags;
> >> +	__u32		reserved[12];
> >> +};
> > 
> > OK, I realized that we also need a type field here: you need the type field
> > (same as in v4l2_buffer) to know which queue the mem_offset refers to. For
> > M2M devices you have two queues, so you need this information.
> 
> I do not agree with you. The mmap() does not need buffer_type.
> So VIDIOC_EXPBUF should not need the field either.
> Please refer to patch "[PATCHv8 26/26] v4l: s5p-mfc: support for dmabuf exporting"
> for example how to deal without buffer_type.
> 
> > 
> > Is there any reason not to use __u32 memory instead of __u32 reserved0?
> > I really dislike 'reserved0'. It's also very inconsistent with the other
> > buffer ioctls which all have type+memory fields.
> 
> The type is not needed for exporting if mem_offset is available like in mmap() case.
> The memory is not needed because exporting is available only for MMAP buffers.

Today, yes. Perhaps not in the future. mem_offset uniquely identifies a buffer,
but only in the MMAP case. That happens to be the only one we support at the
moment, but in the future we might want to support others as well.

> I see two ways to describe a buffer for exporting:
> a) by mem_offset
> b) by (buffer_type, index, plane_index) tuple

Actually a (buffer_type, index, plane_index, memory) tuple.

> 
> For know I prefer to implement only method (a) to avoid
> "single vs. multi plane" madness. Moreover it guarantees
> that only MMAP buffers are exported.

You see that as an advantage, I see that as a disadvantage. Because b is more
future-proof than a. And while you need to provide more information, you do
have that information available anyway in struct v4l2_buffer. It's the same
information we use in any of the other streaming I/O ioctls, and I really
like that consistency.

> The second method assisted by VIDIOC_PREPARE_BUF will allow
> userptr-to-dmabuf conversion or dmabuf reexporting.
> 
> > 
> > Regarding mem_offset: I would prefer a union (possibly anonymous):
> 
> I prefer not to add anonymous unions (though I like them) because
> the unions are not compatible with multiple C standards including C89.
> 
> > 
> >         union {
> >                 __u32           mem_offset;
> >                 unsigned long   reserved;
> >         } m;
> > 
> > Again, it's more consistent with the existing buffer ioctls, and it prepares
> > the API for future pointer values. 'reserved' in the union above could even
> > safely be renamed to userptr, even though userptr isn't supported at the
> > moment.
> > 
> 
> There is no guarantee that DMABUF could ever be created from user pointer.

There is no guarantee that it could never be created from a user pointer either.
Or some other newer memory type that doesn't exist yet.

> IMO, there is little need for support for such a feature.
> I prefer not to add any fields that to not immediately map to DMABUF
> functionalities. Let's keep the structures simple for now.
> 
> Moreover I prefer not to add 'unsigned long' as union member because
> the size of the union would be different on 32 and 64 bit machines.

Well, that's the point. sizeof(unsigned long) == sizeof(void *)
You could also write 'void *reserved;', as long as we can stick a pointer
in there.

> The API is marked as experimental so it can change significantly.

If we ever add new memory types or userptr dmabuf support, then that's
most likely a long time in the future. By that time the experimental status
of the API is surely revoked. So we need to do this right the first time.
One reason the V4L2 API has scaled so well for the most part is due to the
fact that the original designers were very conscious of the fact that the API
should be as future proof as possible. We should follow that.

So instead of thinking of this ioctl as "exporting an mmaped buffer", think
of it as "exporting a buffer". The first will work today, the second will
work in the future as well.

Regards,

	Hans

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

* Re: [PATCHv8 18/26] v4l: add buffer exporting via dmabuf
  2012-09-26  6:39       ` Hans Verkuil
@ 2012-09-26  9:55         ` Tomasz Stanislawski
  0 siblings, 0 replies; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-09-26  9:55 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: linux-media, dri-devel, airlied, m.szyprowski, kyungmin.park,
	laurent.pinchart, sumit.semwal, daeinki, daniel.vetter,
	robdclark, pawel, linaro-mm-sig, remi, subashrp, mchehab,
	g.liakhovetski, dmitriyz, s.nawrocki, k.debski

Hi Hans,
Thank your for your comments.

On 09/26/2012 08:39 AM, Hans Verkuil wrote:
> On Tue September 25 2012 18:30:43 Tomasz Stanislawski wrote:
>> Hi Hans,
>> Thank you for review.
>> Please refer to the comments below.
>>
>> On 08/22/2012 01:41 PM, Hans Verkuil wrote:
>>> On Tue August 14 2012 17:34:48 Tomasz Stanislawski wrote:
>>>> This patch adds extension to V4L2 api. It allow to export a mmap buffer as file
>>>> descriptor. New ioctl VIDIOC_EXPBUF is added. It takes a buffer offset used by
>>>> mmap and return a file descriptor on success.
>>>>
>>>> Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
>>>> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
>>>> ---
>>>>  drivers/media/video/v4l2-compat-ioctl32.c |    1 +
>>>>  drivers/media/video/v4l2-dev.c            |    1 +
>>>>  drivers/media/video/v4l2-ioctl.c          |   15 +++++++++++++++
>>>>  include/linux/videodev2.h                 |   26 ++++++++++++++++++++++++++
>>>>  include/media/v4l2-ioctl.h                |    2 ++
>>>>  5 files changed, 45 insertions(+)
>>>>
>>
>> [snip]
>>
>>>> diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
>>>> index dffd3c9..c4e8c7e 100644
>>>> --- a/drivers/media/video/v4l2-ioctl.c
>>>> +++ b/drivers/media/video/v4l2-ioctl.c
>>>> @@ -458,6 +458,14 @@ static void v4l_print_buffer(const void *arg, bool write_only)
>>>>  			tc->type, tc->flags, tc->frames, *(__u32 *)tc->userbits);
>>>>  }
>>>>  
>>>> +static void v4l_print_exportbuffer(const void *arg, bool write_only)
>>>> +{
>>>> +	const struct v4l2_exportbuffer *p = arg;
>>>> +
>>>> +	pr_cont("fd=%d, mem_offset=%lx, flags=%lx\n",
>>>> +		p->fd, (unsigned long)p->mem_offset, (unsigned long)p->flags);
>>>
>>> Why the unsigned long casts?
>>>
>>
>> It is needed to avoid compiler warnings on machines where "%lx" is not
>> compatible with u32.
> 
> Why not use %x instead of %lx?
> 

Ok. '%x' or '%08x' should be compatible with u32.
Hopefully, no one is using V4L2 on 16-bit machines :).

>>>> +}
>>>> +
>>>>  static void v4l_print_create_buffers(const void *arg, bool write_only)
>>>>  {
>>>>  	const struct v4l2_create_buffers *p = arg;
>>
>> [snip]
>>
>>>> diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
>>>> index 7f918dc..b5d058b 100644
>>>> --- a/include/linux/videodev2.h
>>>> +++ b/include/linux/videodev2.h
>>>> @@ -688,6 +688,31 @@ struct v4l2_buffer {
>>>>  #define V4L2_BUF_FLAG_NO_CACHE_INVALIDATE	0x0800
>>>>  #define V4L2_BUF_FLAG_NO_CACHE_CLEAN		0x1000
>>>>  
>>>> +/**
>>>> + * struct v4l2_exportbuffer - export of video buffer as DMABUF file descriptor
>>>> + *
>>>> + * @fd:		file descriptor associated with DMABUF (set by driver)
>>>> + * @mem_offset:	buffer memory offset as returned by VIDIOC_QUERYBUF in struct
>>>> + *		v4l2_buffer::m.offset (for single-plane formats) or
>>>> + *		v4l2_plane::m.offset (for multi-planar formats)
>>>> + * @flags:	flags for newly created file, currently only O_CLOEXEC is
>>>> + *		supported, refer to manual of open syscall for more details
>>>> + *
>>>> + * Contains data used for exporting a video buffer as DMABUF file descriptor.
>>>> + * The buffer is identified by a 'cookie' returned by VIDIOC_QUERYBUF
>>>> + * (identical to the cookie used to mmap() the buffer to userspace). All
>>>> + * reserved fields must be set to zero. The field reserved0 is expected to
>>>> + * become a structure 'type' allowing an alternative layout of the structure
>>>> + * content. Therefore this field should not be used for any other extensions.
>>>> + */
>>>> +struct v4l2_exportbuffer {
>>>> +	__u32		fd;
>>>> +	__u32		reserved0;
>>>> +	__u32		mem_offset;
>>>> +	__u32		flags;
>>>> +	__u32		reserved[12];
>>>> +};
>>>
>>> OK, I realized that we also need a type field here: you need the type field
>>> (same as in v4l2_buffer) to know which queue the mem_offset refers to. For
>>> M2M devices you have two queues, so you need this information.
>>
>> I do not agree with you. The mmap() does not need buffer_type.
>> So VIDIOC_EXPBUF should not need the field either.
>> Please refer to patch "[PATCHv8 26/26] v4l: s5p-mfc: support for dmabuf exporting"
>> for example how to deal without buffer_type.
>>
>>>
>>> Is there any reason not to use __u32 memory instead of __u32 reserved0?
>>> I really dislike 'reserved0'. It's also very inconsistent with the other
>>> buffer ioctls which all have type+memory fields.
>>
>> The type is not needed for exporting if mem_offset is available like in mmap() case.
>> The memory is not needed because exporting is available only for MMAP buffers.
> 
> Today, yes. Perhaps not in the future. mem_offset uniquely identifies a buffer,
> but only in the MMAP case. That happens to be the only one we support at the
> moment, but in the future we might want to support others as well.
> 
>> I see two ways to describe a buffer for exporting:
>> a) by mem_offset
>> b) by (buffer_type, index, plane_index) tuple
> 
> Actually a (buffer_type, index, plane_index, memory) tuple.
> 

Why the memory goes into the tuple?
Is it possible that the queue can work in two modes at the same time?
Is it possible that userptr and mmap buffers both with index 0 can coexist
at the same queue?

IMO, currently the memory is  a parameter of a V4L queue, not buffer's.
In time, the field may become a buffer parameter if VIDIOC_CREATE_BUFS
would permit a creation of buffers with different memory modes.
Anyway, the memory would become only a parameter of a buffer.
Similar to 'length' or 'sequence' or etc.
As I understand, the memory field is used for v4l2_buffer only to
inform which members of 'union m' should be copied to/from the userspace
by V4L middle layer operation between ioctl() and a driver.

>>
>> For know I prefer to implement only method (a) to avoid
>> "single vs. multi plane" madness. Moreover it guarantees
>> that only MMAP buffers are exported.
> 
> You see that as an advantage, I see that as a disadvantage. Because b is more
> future-proof than a. And while you need to provide more information, you do
> have that information available anyway in struct v4l2_buffer. It's the same
> information we use in any of the other streaming I/O ioctls, and I really
> like that consistency.
> 

I agree that proposition (b) is more future-proof.
Bad news is that implementing it implies significant changes to vb2-dmabuf code
and documentation. It will postpone v9 which is already late.
However, it is better to sacrifice some time on doing things right.
I will start modifications now.

Does the structure layout suit you?

struct v4l2_exportbuffer {
	s32	fd;
	u32	reserved0; /* place for export-mode if some fields below become a union */
	u32	type; /* enum v4l2_buf_type */
	u32	index;
	u32	plane;
	u32	reserved[10];
	u32	flags;
};


>> The second method assisted by VIDIOC_PREPARE_BUF will allow
>> userptr-to-dmabuf conversion or dmabuf reexporting.
>>
>>>
>>> Regarding mem_offset: I would prefer a union (possibly anonymous):
>>
>> I prefer not to add anonymous unions (though I like them) because
>> the unions are not compatible with multiple C standards including C89.
>>
>>>
>>>         union {
>>>                 __u32           mem_offset;
>>>                 unsigned long   reserved;
>>>         } m;
>>>
>>> Again, it's more consistent with the existing buffer ioctls, and it prepares
>>> the API for future pointer values. 'reserved' in the union above could even
>>> safely be renamed to userptr, even though userptr isn't supported at the
>>> moment.
>>>
>>
>> There is no guarantee that DMABUF could ever be created from user pointer.
> 
> There is no guarantee that it could never be created from a user pointer either.
> Or some other newer memory type that doesn't exist yet.
> 
>> IMO, there is little need for support for such a feature.
>> I prefer not to add any fields that to not immediately map to DMABUF
>> functionalities. Let's keep the structures simple for now.
>>
>> Moreover I prefer not to add 'unsigned long' as union member because
>> the size of the union would be different on 32 and 64 bit machines.
> 
> Well, that's the point. sizeof(unsigned long) == sizeof(void *)
> You could also write 'void *reserved;', as long as we can stick a pointer
> in there.
> 

The problem is that the size of void* varies on different architectures.
The u64 can always store void*, it has a fixed size and should be
sufficient for at least 50 years :).

>> The API is marked as experimental so it can change significantly.
> 
> If we ever add new memory types or userptr dmabuf support, then that's
> most likely a long time in the future. By that time the experimental status
> of the API is surely revoked. So we need to do this right the first time.
> One reason the V4L2 API has scaled so well for the most part is due to the
> fact that the original designers were very conscious of the fact that the API
> should be as future proof as possible. We should follow that.
> 
> So instead of thinking of this ioctl as "exporting an mmaped buffer", think
> of it as "exporting a buffer". The first will work today, the second will
> work in the future as well.
> 
> Regards,
> 
> 	Hans
> 

Regards,
Tomasz Stanislawski


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

* Re: [PATCHv8 21/26] v4l: vb2-dma-contig: add reference counting for a device from allocator context
  2012-08-15 20:04   ` Laurent Pinchart
@ 2012-09-27 15:19     ` Tomasz Stanislawski
  0 siblings, 0 replies; 58+ messages in thread
From: Tomasz Stanislawski @ 2012-09-27 15:19 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-media, dri-devel, airlied, m.szyprowski, kyungmin.park,
	sumit.semwal, daeinki, daniel.vetter, robdclark, pawel,
	linaro-mm-sig, hverkuil, remi, subashrp, mchehab, g.liakhovetski,
	dmitriyz, s.nawrocki, k.debski

Hi Laurent,

On 08/15/2012 10:04 PM, Laurent Pinchart wrote:
> Hi Tomasz,
> 
> Thanks for the patch.
> 
> On Tuesday 14 August 2012 17:34:51 Tomasz Stanislawski wrote:
>> This patch adds taking reference to the device for MMAP buffers.
>>
>> Such buffers, may be exported using DMABUF mechanism. If the driver that
>> created a queue is unloaded then the queue is released, the device might be
>> released too.  However, buffers cannot be released if they are referenced by
>> DMABUF descriptor(s). The device pointer kept in a buffer must be valid for
>> the whole buffer's lifetime. Therefore MMAP buffers should take a reference
>> to the device to avoid risk of dangling pointers.
> 
> That patch looks good, but that approach won't scale if we ever need a more 
> complex context that can't be copied. We can ignore that for now, but if we 
> decide to support "orphan" vb2 buffers, that's an issue we need to be aware of 
> as it might come back to bite us in the future.
> 

Good news is that vb2-dma-contig knows the structure of the context.
Therefore it will always be able to implement a proper 'copy constructor'.
One could always add reference counting for contexts but I consider it
little over-engineering.

> I assume that this patch requires your dmabuf owner patch to fix the orphan 
> buffer case properly.
> 

The 'dmabuf owner' patch is not required for this patchset.
It will only protect 'videobuf2-dma-contig' module from being
unloaded while its dmabuf is in use.

Regards,
Tomasz Stanislawski

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

end of thread, other threads:[~2012-09-27 15:19 UTC | newest]

Thread overview: 58+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-08-14 15:34 [PATCHv8 00/26] Integration of videobuf2 with DMABUF Tomasz Stanislawski
2012-08-14 15:34 ` [PATCHv8 01/26] v4l: Add DMABUF as a memory type Tomasz Stanislawski
2012-08-22 10:27   ` Hans Verkuil
2012-08-22 12:09     ` Tomasz Stanislawski
2012-08-22 12:21       ` Hans Verkuil
2012-08-14 15:34 ` [PATCHv8 02/26] Documentation: media: description of DMABUF importing in V4L2 Tomasz Stanislawski
2012-08-22 10:47   ` Hans Verkuil
2012-09-24 12:17     ` Tomasz Stanislawski
2012-09-25 10:48       ` Hans Verkuil
2012-08-14 15:34 ` [PATCHv8 03/26] v4l: vb2: add support for shared buffer (dma_buf) Tomasz Stanislawski
2012-08-14 15:34 ` [PATCHv8 04/26] v4l: vb: remove warnings about MEMORY_DMABUF Tomasz Stanislawski
2012-08-14 15:34 ` [PATCHv8 05/26] v4l: vb2-dma-contig: Shorten vb2_dma_contig prefix to vb2_dc Tomasz Stanislawski
2012-08-14 15:34 ` [PATCHv8 06/26] v4l: vb2-dma-contig: remove reference of alloc_ctx from a buffer Tomasz Stanislawski
2012-08-15 18:24   ` Laurent Pinchart
2012-08-14 15:34 ` [PATCHv8 07/26] v4l: vb2-dma-contig: Reorder functions Tomasz Stanislawski
2012-08-14 15:34 ` [PATCHv8 08/26] v4l: vb2-dma-contig: add support for scatterlist in userptr mode Tomasz Stanislawski
2012-08-14 15:34 ` [PATCHv8 09/26] v4l: vb2: add prepare/finish callbacks to allocators Tomasz Stanislawski
2012-08-14 15:34 ` [PATCHv8 10/26] v4l: vb2-dma-contig: add prepare/finish to dma-contig allocator Tomasz Stanislawski
2012-08-15 18:35   ` Laurent Pinchart
2012-08-15 18:39     ` [Linaro-mm-sig] " Laurent Pinchart
2012-08-14 15:34 ` [PATCHv8 11/26] v4l: vb2-dma-contig: add support for dma_buf importing Tomasz Stanislawski
2012-08-14 15:34 ` [PATCHv8 12/26] v4l: vb2-vmalloc: add support for dmabuf importing Tomasz Stanislawski
2012-08-15 18:39   ` Laurent Pinchart
2012-08-14 15:34 ` [PATCHv8 13/26] v4l: vivi: " Tomasz Stanislawski
2012-08-22 10:56   ` Hans Verkuil
2012-08-22 11:03     ` Laurent Pinchart
2012-08-22 11:47     ` Hans Verkuil
2012-09-25 14:41       ` Tomasz Stanislawski
2012-08-14 15:34 ` [PATCHv8 14/26] v4l: s5p-tv: mixer: " Tomasz Stanislawski
2012-08-14 15:34 ` [PATCHv8 15/26] v4l: s5p-fimc: " Tomasz Stanislawski
2012-08-14 15:34 ` [PATCHv8 16/26] v4l: vb2-dma-contig: let mmap method to use dma_mmap_coherent call Tomasz Stanislawski
2012-08-14 15:34 ` [PATCHv8 17/26] Documentation: media: description of DMABUF exporting in V4L2 Tomasz Stanislawski
2012-08-22 11:23   ` Hans Verkuil
2012-08-14 15:34 ` [PATCHv8 18/26] v4l: add buffer exporting via dmabuf Tomasz Stanislawski
2012-08-15 19:08   ` Laurent Pinchart
2012-08-22 11:41   ` Hans Verkuil
2012-08-22 23:39     ` Laurent Pinchart
2012-08-23  6:50       ` Hans Verkuil
2012-09-25 16:30     ` Tomasz Stanislawski
2012-09-26  6:39       ` Hans Verkuil
2012-09-26  9:55         ` Tomasz Stanislawski
2012-08-14 15:34 ` [PATCHv8 19/26] v4l: vb2: " Tomasz Stanislawski
2012-08-22 11:43   ` Hans Verkuil
2012-08-14 15:34 ` [PATCHv8 20/26] v4l: vb2-dma-contig: add support for DMABUF exporting Tomasz Stanislawski
2012-08-21 10:03   ` Laurent Pinchart
2012-08-21 13:47     ` Tomasz Stanislawski
2012-08-21 14:07       ` Laurent Pinchart
2012-08-14 15:34 ` [PATCHv8 21/26] v4l: vb2-dma-contig: add reference counting for a device from allocator context Tomasz Stanislawski
2012-08-15 20:04   ` Laurent Pinchart
2012-09-27 15:19     ` Tomasz Stanislawski
2012-08-14 15:34 ` [PATCHv8 22/26] media: vb2: fail if user ptr buffer is not correctly aligned Tomasz Stanislawski
2012-08-15 20:20   ` Laurent Pinchart
2012-08-14 15:34 ` [PATCHv8 23/26] v4l: vb2: add support for DMA_ATTR_NO_KERNEL_MAPPING Tomasz Stanislawski
2012-08-15 20:44   ` Laurent Pinchart
2012-08-22 11:46   ` Hans Verkuil
2012-08-14 15:34 ` [PATCHv8 24/26] v4l: s5p-fimc: support for dmabuf exporting Tomasz Stanislawski
2012-08-14 15:34 ` [PATCHv8 25/26] v4l: s5p-tv: mixer: " Tomasz Stanislawski
2012-08-14 15:34 ` [PATCHv8 26/26] v4l: s5p-mfc: " Tomasz Stanislawski

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.