linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFCv6 PATCH 00/16] vb2: improve dma-sg, expbuf
@ 2014-11-10 12:49 Hans Verkuil
  2014-11-10 12:49 ` [RFCv6 PATCH 01/16] videobuf2-core.h: improve documentation Hans Verkuil
                   ` (15 more replies)
  0 siblings, 16 replies; 29+ messages in thread
From: Hans Verkuil @ 2014-11-10 12:49 UTC (permalink / raw)
  To: linux-media; +Cc: m.szyprowski, pawel

Changes since v5:
- Moved 'replace write by dma_dir' to the beginning of the patch series.
- Split off the 'add dma_dir to alloc()' as a separate patch.
- Address all Pawel's review comments.

The patch series adds an allocation context to dma-sg and uses that to move
dma_(un)map_sg into the vb2 framework, which is where it belongs.

Some drivers needs to fixup the buffers before giving it back to userspace
(or before handing it over to the kernel). Document that this can be done
in buf_prepare and buf_finish.

The last 5 patches make this more strict by requiring all cpu access to
be bracketed by calls to vb2_plane_begin/end_cpu_access() which replaces
the old vb2_plane_vaddr() call.

Note: two drivers still use the vb2_plane_vaddr() call: coda and
exynos4-is/fimc-capture.c. For both drivers I will need some help since
I am not sure where to put the begin/end calls. Patch 15 removes
the vb2_plane_vaddr call, so obviously those two drivers won't compile
after that.

DMABUF export support is added to dma-sg and vmalloc, so now all memory
models support DMABUF importing and exporting.

I am inclined to make a pull request for patches 1-11 if there are no
new comments. The issues that patches 12-16 address are separate from
the patches 1-11 and this is only an issue when using dmabuf with
drivers that need cpu access.

Reviews are very welcome.

Regards,

	Hans


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

* [RFCv6 PATCH 01/16] videobuf2-core.h: improve documentation
  2014-11-10 12:49 [RFCv6 PATCH 00/16] vb2: improve dma-sg, expbuf Hans Verkuil
@ 2014-11-10 12:49 ` Hans Verkuil
  2014-11-10 12:49 ` [RFCv6 PATCH 02/16] vb2: replace 'write' by 'dma_dir' Hans Verkuil
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 29+ messages in thread
From: Hans Verkuil @ 2014-11-10 12:49 UTC (permalink / raw)
  To: linux-media; +Cc: m.szyprowski, pawel, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Document that drivers can access/modify the buffer contents in buf_prepare
and buf_finish. That was not clearly stated before.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 include/media/videobuf2-core.h | 32 +++++++++++++++++---------------
 1 file changed, 17 insertions(+), 15 deletions(-)

diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 6ef2d01..70ace7c 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -270,22 +270,24 @@ struct vb2_buffer {
  *			queue setup from completing successfully; optional.
  * @buf_prepare:	called every time the buffer is queued from userspace
  *			and from the VIDIOC_PREPARE_BUF ioctl; drivers may
- *			perform any initialization required before each hardware
- *			operation in this callback; drivers that support
- *			VIDIOC_CREATE_BUFS must also validate the buffer size;
- *			if an error is returned, the buffer will not be queued
- *			in driver; optional.
+ *			perform any initialization required before each
+ *			hardware operation in this callback; drivers can
+ *			access/modify the buffer here as it is still synced for
+ *			the CPU; drivers that support VIDIOC_CREATE_BUFS must
+ *			also validate the buffer size; if an error is returned,
+ *			the buffer will not be queued in driver; optional.
  * @buf_finish:		called before every dequeue of the buffer back to
- *			userspace; drivers may perform any operations required
- *			before userspace accesses the buffer; optional. The
- *			buffer state can be one of the following: DONE and
- *			ERROR occur while streaming is in progress, and the
- *			PREPARED state occurs when the queue has been canceled
- *			and all pending buffers are being returned to their
- *			default DEQUEUED state. Typically you only have to do
- *			something if the state is VB2_BUF_STATE_DONE, since in
- *			all other cases the buffer contents will be ignored
- *			anyway.
+ *			userspace; the buffer is synced for the CPU, so drivers
+ *			can access/modify the buffer contents; drivers may
+ *			perform any operations required before userspace
+ *			accesses the buffer; optional. The buffer state can be
+ *			one of the following: DONE and ERROR occur while
+ *			streaming is in progress, and the PREPARED state occurs
+ *			when the queue has been canceled and all pending
+ *			buffers are being returned to their default DEQUEUED
+ *			state. Typically you only have to do something if the
+ *			state is VB2_BUF_STATE_DONE, since in all other cases
+ *			the buffer contents will be ignored anyway.
  * @buf_cleanup:	called once before the buffer is freed; drivers may
  *			perform any additional cleanup; optional.
  * @start_streaming:	called once to enter 'streaming' state; the driver may
-- 
2.1.1


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

* [RFCv6 PATCH 02/16] vb2: replace 'write' by 'dma_dir'
  2014-11-10 12:49 [RFCv6 PATCH 00/16] vb2: improve dma-sg, expbuf Hans Verkuil
  2014-11-10 12:49 ` [RFCv6 PATCH 01/16] videobuf2-core.h: improve documentation Hans Verkuil
@ 2014-11-10 12:49 ` Hans Verkuil
  2014-11-16 12:34   ` Pawel Osciak
  2014-11-10 12:49 ` [RFCv6 PATCH 03/16] vb2: add dma_dir to the alloc memop Hans Verkuil
                   ` (13 subsequent siblings)
  15 siblings, 1 reply; 29+ messages in thread
From: Hans Verkuil @ 2014-11-10 12:49 UTC (permalink / raw)
  To: linux-media; +Cc: m.szyprowski, pawel, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

The 'write' argument is very ambiguous. I first assumed that if it is 1,
then we're doing video output but instead it meant the reverse.

Since it is used to setup the dma_dir value anyway it is now replaced by
the correct dma_dir value which is unambiguous.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/v4l2-core/videobuf2-core.c       | 10 ++++---
 drivers/media/v4l2-core/videobuf2-dma-contig.c | 40 ++++++++++++++------------
 drivers/media/v4l2-core/videobuf2-dma-sg.c     | 13 +++++----
 drivers/media/v4l2-core/videobuf2-vmalloc.c    | 16 ++++++-----
 include/media/videobuf2-core.h                 |  6 ++--
 5 files changed, 47 insertions(+), 38 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index f2e43de..573f6fb 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -1358,7 +1358,8 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 	void *mem_priv;
 	unsigned int plane;
 	int ret;
-	int write = !V4L2_TYPE_IS_OUTPUT(q->type);
+	enum dma_data_direction dma_dir =
+		V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
 	bool reacquired = vb->planes[0].mem_priv == NULL;
 
 	memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1400,7 +1401,7 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 		/* Acquire each plane's memory */
 		mem_priv = call_ptr_memop(vb, get_userptr, q->alloc_ctx[plane],
 				      planes[plane].m.userptr,
-				      planes[plane].length, write);
+				      planes[plane].length, dma_dir);
 		if (IS_ERR_OR_NULL(mem_priv)) {
 			dprintk(1, "failed acquiring userspace "
 						"memory for plane %d\n", plane);
@@ -1461,7 +1462,8 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 	void *mem_priv;
 	unsigned int plane;
 	int ret;
-	int write = !V4L2_TYPE_IS_OUTPUT(q->type);
+	enum dma_data_direction dma_dir =
+		V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
 	bool reacquired = vb->planes[0].mem_priv == NULL;
 
 	memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1509,7 +1511,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 
 		/* Acquire each plane's memory */
 		mem_priv = call_ptr_memop(vb, attach_dmabuf, q->alloc_ctx[plane],
-			dbuf, planes[plane].length, write);
+			dbuf, planes[plane].length, dma_dir);
 		if (IS_ERR(mem_priv)) {
 			dprintk(1, "failed to attach dmabuf\n");
 			ret = PTR_ERR(mem_priv);
diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index 4a02ade..2bdffd3 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -229,7 +229,7 @@ static int vb2_dc_mmap(void *buf_priv, struct vm_area_struct *vma)
 
 struct vb2_dc_attachment {
 	struct sg_table sgt;
-	enum dma_data_direction dir;
+	enum dma_data_direction dma_dir;
 };
 
 static int vb2_dc_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev,
@@ -264,7 +264,7 @@ static int vb2_dc_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev,
 		wr = sg_next(wr);
 	}
 
-	attach->dir = DMA_NONE;
+	attach->dma_dir = DMA_NONE;
 	dbuf_attach->priv = attach;
 
 	return 0;
@@ -282,16 +282,16 @@ static void vb2_dc_dmabuf_ops_detach(struct dma_buf *dbuf,
 	sgt = &attach->sgt;
 
 	/* release the scatterlist cache */
-	if (attach->dir != DMA_NONE)
+	if (attach->dma_dir != DMA_NONE)
 		dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
-			attach->dir);
+			attach->dma_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 dma_buf_attachment *db_attach, enum dma_data_direction dma_dir)
 {
 	struct vb2_dc_attachment *attach = db_attach->priv;
 	/* stealing dmabuf mutex to serialize map/unmap operations */
@@ -303,27 +303,27 @@ static struct sg_table *vb2_dc_dmabuf_ops_map(
 
 	sgt = &attach->sgt;
 	/* return previously mapped sg table */
-	if (attach->dir == dir) {
+	if (attach->dma_dir == dma_dir) {
 		mutex_unlock(lock);
 		return sgt;
 	}
 
 	/* release any previous cache */
-	if (attach->dir != DMA_NONE) {
+	if (attach->dma_dir != DMA_NONE) {
 		dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
-			attach->dir);
-		attach->dir = DMA_NONE;
+			attach->dma_dir);
+		attach->dma_dir = DMA_NONE;
 	}
 
 	/* mapping to the client with new direction */
-	ret = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, dir);
+	ret = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, dma_dir);
 	if (ret <= 0) {
 		pr_err("failed to map scatterlist\n");
 		mutex_unlock(lock);
 		return ERR_PTR(-EIO);
 	}
 
-	attach->dir = dir;
+	attach->dma_dir = dma_dir;
 
 	mutex_unlock(lock);
 
@@ -331,7 +331,7 @@ static struct sg_table *vb2_dc_dmabuf_ops_map(
 }
 
 static void vb2_dc_dmabuf_ops_unmap(struct dma_buf_attachment *db_attach,
-	struct sg_table *sgt, enum dma_data_direction dir)
+	struct sg_table *sgt, enum dma_data_direction dma_dir)
 {
 	/* nothing to be done here */
 }
@@ -460,7 +460,8 @@ static int vb2_dc_get_user_pfn(unsigned long start, int n_pages,
 }
 
 static int vb2_dc_get_user_pages(unsigned long start, struct page **pages,
-	int n_pages, struct vm_area_struct *vma, int write)
+	int n_pages, struct vm_area_struct *vma,
+	enum dma_data_direction dma_dir)
 {
 	if (vma_is_io(vma)) {
 		unsigned int i;
@@ -482,7 +483,7 @@ static int vb2_dc_get_user_pages(unsigned long start, struct page **pages,
 		int n;
 
 		n = get_user_pages(current, current->mm, start & PAGE_MASK,
-			n_pages, write, 1, pages, NULL);
+			n_pages, dma_dir == DMA_FROM_DEVICE, 1, pages, NULL);
 		/* negative error means that no page was pinned */
 		n = max(n, 0);
 		if (n != n_pages) {
@@ -551,7 +552,7 @@ static inline dma_addr_t vb2_dc_pfn_to_dma(struct device *dev, unsigned long pfn
 #endif
 
 static void *vb2_dc_get_userptr(void *alloc_ctx, unsigned long vaddr,
-	unsigned long size, int write)
+	unsigned long size, enum dma_data_direction dma_dir)
 {
 	struct vb2_dc_conf *conf = alloc_ctx;
 	struct vb2_dc_buf *buf;
@@ -582,7 +583,7 @@ static void *vb2_dc_get_userptr(void *alloc_ctx, unsigned long vaddr,
 		return ERR_PTR(-ENOMEM);
 
 	buf->dev = conf->dev;
-	buf->dma_dir = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+	buf->dma_dir = dma_dir;
 
 	start = vaddr & PAGE_MASK;
 	offset = vaddr & ~PAGE_MASK;
@@ -618,7 +619,8 @@ static void *vb2_dc_get_userptr(void *alloc_ctx, unsigned long vaddr,
 	}
 
 	/* extract page list from userspace mapping */
-	ret = vb2_dc_get_user_pages(start, pages, n_pages, vma, write);
+	ret = vb2_dc_get_user_pages(start, pages, n_pages, vma,
+				    dma_dir == DMA_FROM_DEVICE);
 	if (ret) {
 		unsigned long pfn;
 		if (vb2_dc_get_user_pfn(start, n_pages, vma, &pfn) == 0) {
@@ -782,7 +784,7 @@ static void vb2_dc_detach_dmabuf(void *mem_priv)
 }
 
 static void *vb2_dc_attach_dmabuf(void *alloc_ctx, struct dma_buf *dbuf,
-	unsigned long size, int write)
+	unsigned long size, enum dma_data_direction dma_dir)
 {
 	struct vb2_dc_conf *conf = alloc_ctx;
 	struct vb2_dc_buf *buf;
@@ -804,7 +806,7 @@ static void *vb2_dc_attach_dmabuf(void *alloc_ctx, struct dma_buf *dbuf,
 		return dba;
 	}
 
-	buf->dma_dir = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+	buf->dma_dir = dma_dir;
 	buf->size = size;
 	buf->db_attach = dba;
 
diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index 9b163a4..6b54a14 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -33,8 +33,8 @@ module_param(debug, int, 0644);
 struct vb2_dma_sg_buf {
 	void				*vaddr;
 	struct page			**pages;
-	int				write;
 	int				offset;
+	enum dma_data_direction		dma_dir;
 	struct sg_table			sg_table;
 	size_t				size;
 	unsigned int			num_pages;
@@ -97,7 +97,7 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_fla
 		return NULL;
 
 	buf->vaddr = NULL;
-	buf->write = 0;
+	buf->dma_dir = DMA_NONE;
 	buf->offset = 0;
 	buf->size = size;
 	/* size is already page aligned */
@@ -162,7 +162,8 @@ static inline int vma_is_io(struct vm_area_struct *vma)
 }
 
 static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
-				    unsigned long size, int write)
+				    unsigned long size,
+				    enum dma_data_direction dma_dir)
 {
 	struct vb2_dma_sg_buf *buf;
 	unsigned long first, last;
@@ -174,7 +175,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
 		return NULL;
 
 	buf->vaddr = NULL;
-	buf->write = write;
+	buf->dma_dir = dma_dir;
 	buf->offset = vaddr & ~PAGE_MASK;
 	buf->size = size;
 
@@ -221,7 +222,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
 		num_pages_from_user = get_user_pages(current, current->mm,
 					     vaddr & PAGE_MASK,
 					     buf->num_pages,
-					     write,
+					     buf->dma_dir == DMA_FROM_DEVICE,
 					     1, /* force */
 					     buf->pages,
 					     NULL);
@@ -265,7 +266,7 @@ static void vb2_dma_sg_put_userptr(void *buf_priv)
 		vm_unmap_ram(buf->vaddr, buf->num_pages);
 	sg_free_table(&buf->sg_table);
 	while (--i >= 0) {
-		if (buf->write)
+		if (buf->dma_dir == DMA_FROM_DEVICE)
 			set_page_dirty_lock(buf->pages[i]);
 		if (!vma_is_io(buf->vma))
 			put_page(buf->pages[i]);
diff --git a/drivers/media/v4l2-core/videobuf2-vmalloc.c b/drivers/media/v4l2-core/videobuf2-vmalloc.c
index 313d977..fc1eb45 100644
--- a/drivers/media/v4l2-core/videobuf2-vmalloc.c
+++ b/drivers/media/v4l2-core/videobuf2-vmalloc.c
@@ -25,7 +25,7 @@ struct vb2_vmalloc_buf {
 	void				*vaddr;
 	struct page			**pages;
 	struct vm_area_struct		*vma;
-	int				write;
+	enum dma_data_direction		dma_dir;
 	unsigned long			size;
 	unsigned int			n_pages;
 	atomic_t			refcount;
@@ -70,7 +70,8 @@ static void vb2_vmalloc_put(void *buf_priv)
 }
 
 static void *vb2_vmalloc_get_userptr(void *alloc_ctx, unsigned long vaddr,
-				     unsigned long size, int write)
+				     unsigned long size,
+				     enum dma_data_direction dma_dir)
 {
 	struct vb2_vmalloc_buf *buf;
 	unsigned long first, last;
@@ -82,7 +83,7 @@ static void *vb2_vmalloc_get_userptr(void *alloc_ctx, unsigned long vaddr,
 	if (!buf)
 		return NULL;
 
-	buf->write = write;
+	buf->dma_dir = dma_dir;
 	offset = vaddr & ~PAGE_MASK;
 	buf->size = size;
 
@@ -107,7 +108,8 @@ static void *vb2_vmalloc_get_userptr(void *alloc_ctx, unsigned long vaddr,
 		/* current->mm->mmap_sem is taken by videobuf2 core */
 		n_pages = get_user_pages(current, current->mm,
 					 vaddr & PAGE_MASK, buf->n_pages,
-					 write, 1, /* force */
+					 dma_dir == DMA_FROM_DEVICE,
+					 1, /* force */
 					 buf->pages, NULL);
 		if (n_pages != buf->n_pages)
 			goto fail_get_user_pages;
@@ -144,7 +146,7 @@ static void vb2_vmalloc_put_userptr(void *buf_priv)
 		if (vaddr)
 			vm_unmap_ram((void *)vaddr, buf->n_pages);
 		for (i = 0; i < buf->n_pages; ++i) {
-			if (buf->write)
+			if (buf->dma_dir == DMA_FROM_DEVICE)
 				set_page_dirty_lock(buf->pages[i]);
 			put_page(buf->pages[i]);
 		}
@@ -240,7 +242,7 @@ static void vb2_vmalloc_detach_dmabuf(void *mem_priv)
 }
 
 static void *vb2_vmalloc_attach_dmabuf(void *alloc_ctx, struct dma_buf *dbuf,
-	unsigned long size, int write)
+	unsigned long size, enum dma_data_direction dma_dir)
 {
 	struct vb2_vmalloc_buf *buf;
 
@@ -252,7 +254,7 @@ static void *vb2_vmalloc_attach_dmabuf(void *alloc_ctx, struct dma_buf *dbuf,
 		return ERR_PTR(-ENOMEM);
 
 	buf->dbuf = dbuf;
-	buf->write = write;
+	buf->dma_dir = dma_dir;
 	buf->size = size;
 
 	return buf;
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 70ace7c..d607871 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -87,14 +87,16 @@ struct vb2_mem_ops {
 	struct dma_buf *(*get_dmabuf)(void *buf_priv, unsigned long flags);
 
 	void		*(*get_userptr)(void *alloc_ctx, unsigned long vaddr,
-					unsigned long size, int write);
+					unsigned long size,
+					enum dma_data_direction dma_dir);
 	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);
+					  unsigned long size,
+					  enum dma_data_direction dma_dir);
 	void		(*detach_dmabuf)(void *buf_priv);
 	int		(*map_dmabuf)(void *buf_priv);
 	void		(*unmap_dmabuf)(void *buf_priv);
-- 
2.1.1


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

* [RFCv6 PATCH 03/16] vb2: add dma_dir to the alloc memop.
  2014-11-10 12:49 [RFCv6 PATCH 00/16] vb2: improve dma-sg, expbuf Hans Verkuil
  2014-11-10 12:49 ` [RFCv6 PATCH 01/16] videobuf2-core.h: improve documentation Hans Verkuil
  2014-11-10 12:49 ` [RFCv6 PATCH 02/16] vb2: replace 'write' by 'dma_dir' Hans Verkuil
@ 2014-11-10 12:49 ` Hans Verkuil
  2014-11-16 12:47   ` Pawel Osciak
  2014-11-10 12:49 ` [RFCv6 PATCH 04/16] vb2-dma-sg: add allocation context to dma-sg Hans Verkuil
                   ` (12 subsequent siblings)
  15 siblings, 1 reply; 29+ messages in thread
From: Hans Verkuil @ 2014-11-10 12:49 UTC (permalink / raw)
  To: linux-media; +Cc: m.szyprowski, pawel, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

This is needed for the next patch where the dma-sg alloc memop needs
to know the dma_dir.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/v4l2-core/videobuf2-core.c       | 4 +++-
 drivers/media/v4l2-core/videobuf2-dma-contig.c | 4 +++-
 drivers/media/v4l2-core/videobuf2-dma-sg.c     | 5 +++--
 drivers/media/v4l2-core/videobuf2-vmalloc.c    | 4 +++-
 include/media/videobuf2-core.h                 | 4 +++-
 5 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index 573f6fb..7aed8f2 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -189,6 +189,8 @@ static void __vb2_queue_cancel(struct vb2_queue *q);
 static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 {
 	struct vb2_queue *q = vb->vb2_queue;
+	enum dma_data_direction dma_dir =
+		V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
 	void *mem_priv;
 	int plane;
 
@@ -200,7 +202,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 		unsigned long size = PAGE_ALIGN(q->plane_sizes[plane]);
 
 		mem_priv = call_ptr_memop(vb, alloc, q->alloc_ctx[plane],
-				      size, q->gfp_flags);
+				      size, dma_dir, q->gfp_flags);
 		if (IS_ERR_OR_NULL(mem_priv))
 			goto free;
 
diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index 2bdffd3..c4305bf 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -155,7 +155,8 @@ static void vb2_dc_put(void *buf_priv)
 	kfree(buf);
 }
 
-static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_flags)
+static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size,
+			  enum dma_data_direction dma_dir, gfp_t gfp_flags)
 {
 	struct vb2_dc_conf *conf = alloc_ctx;
 	struct device *dev = conf->dev;
@@ -176,6 +177,7 @@ static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_flags)
 	/* Prevent the device from being released while the buffer is used */
 	buf->dev = get_device(dev);
 	buf->size = size;
+	buf->dma_dir = dma_dir;
 
 	buf->handler.refcount = &buf->refcount;
 	buf->handler.put = vb2_dc_put;
diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index 6b54a14..2529b83 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -86,7 +86,8 @@ static int vb2_dma_sg_alloc_compacted(struct vb2_dma_sg_buf *buf,
 	return 0;
 }
 
-static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_flags)
+static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size,
+			      enum dma_data_direction dma_dir, gfp_t gfp_flags)
 {
 	struct vb2_dma_sg_buf *buf;
 	int ret;
@@ -97,7 +98,7 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_fla
 		return NULL;
 
 	buf->vaddr = NULL;
-	buf->dma_dir = DMA_NONE;
+	buf->dma_dir = dma_dir;
 	buf->offset = 0;
 	buf->size = size;
 	/* size is already page aligned */
diff --git a/drivers/media/v4l2-core/videobuf2-vmalloc.c b/drivers/media/v4l2-core/videobuf2-vmalloc.c
index fc1eb45..bba2460 100644
--- a/drivers/media/v4l2-core/videobuf2-vmalloc.c
+++ b/drivers/media/v4l2-core/videobuf2-vmalloc.c
@@ -35,7 +35,8 @@ struct vb2_vmalloc_buf {
 
 static void vb2_vmalloc_put(void *buf_priv);
 
-static void *vb2_vmalloc_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_flags)
+static void *vb2_vmalloc_alloc(void *alloc_ctx, unsigned long size,
+			       enum dma_data_direction dma_dir, gfp_t gfp_flags)
 {
 	struct vb2_vmalloc_buf *buf;
 
@@ -45,6 +46,7 @@ static void *vb2_vmalloc_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_fl
 
 	buf->size = size;
 	buf->vaddr = vmalloc_user(buf->size);
+	buf->dma_dir = dma_dir;
 	buf->handler.refcount = &buf->refcount;
 	buf->handler.put = vb2_vmalloc_put;
 	buf->handler.arg = buf;
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index d607871..bd2cec2 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -82,7 +82,9 @@ struct vb2_threadio_data;
  *				  unmap_dmabuf.
  */
 struct vb2_mem_ops {
-	void		*(*alloc)(void *alloc_ctx, unsigned long size, gfp_t gfp_flags);
+	void		*(*alloc)(void *alloc_ctx, unsigned long size,
+				  enum dma_data_direction dma_dir,
+				  gfp_t gfp_flags);
 	void		(*put)(void *buf_priv);
 	struct dma_buf *(*get_dmabuf)(void *buf_priv, unsigned long flags);
 
-- 
2.1.1


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

* [RFCv6 PATCH 04/16] vb2-dma-sg: add allocation context to dma-sg
  2014-11-10 12:49 [RFCv6 PATCH 00/16] vb2: improve dma-sg, expbuf Hans Verkuil
                   ` (2 preceding siblings ...)
  2014-11-10 12:49 ` [RFCv6 PATCH 03/16] vb2: add dma_dir to the alloc memop Hans Verkuil
@ 2014-11-10 12:49 ` Hans Verkuil
  2014-11-16 13:13   ` Pawel Osciak
  2014-11-10 12:49 ` [RFCv6 PATCH 05/16] vb2-dma-sg: move dma_(un)map_sg here Hans Verkuil
                   ` (11 subsequent siblings)
  15 siblings, 1 reply; 29+ messages in thread
From: Hans Verkuil @ 2014-11-10 12:49 UTC (permalink / raw)
  To: linux-media; +Cc: m.szyprowski, pawel, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Require that dma-sg also uses an allocation context. This is in preparation
for adding prepare/finish memops to sync the memory between DMA and CPU.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/pci/cx23885/cx23885-417.c         |  1 +
 drivers/media/pci/cx23885/cx23885-core.c        | 10 ++++++-
 drivers/media/pci/cx23885/cx23885-dvb.c         |  1 +
 drivers/media/pci/cx23885/cx23885-vbi.c         |  1 +
 drivers/media/pci/cx23885/cx23885-video.c       |  1 +
 drivers/media/pci/cx23885/cx23885.h             |  1 +
 drivers/media/pci/saa7134/saa7134-core.c        | 18 +++++++++----
 drivers/media/pci/saa7134/saa7134-ts.c          |  1 +
 drivers/media/pci/saa7134/saa7134-vbi.c         |  1 +
 drivers/media/pci/saa7134/saa7134-video.c       |  1 +
 drivers/media/pci/saa7134/saa7134.h             |  1 +
 drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c  | 10 +++++++
 drivers/media/pci/solo6x10/solo6x10.h           |  1 +
 drivers/media/pci/tw68/tw68-core.c              | 15 ++++++++---
 drivers/media/pci/tw68/tw68-video.c             |  1 +
 drivers/media/pci/tw68/tw68.h                   |  1 +
 drivers/media/platform/marvell-ccic/mcam-core.c | 13 ++++++++-
 drivers/media/platform/marvell-ccic/mcam-core.h |  1 +
 drivers/media/v4l2-core/videobuf2-dma-sg.c      | 36 +++++++++++++++++++++++++
 include/media/videobuf2-dma-sg.h                |  3 +++
 20 files changed, 108 insertions(+), 10 deletions(-)

diff --git a/drivers/media/pci/cx23885/cx23885-417.c b/drivers/media/pci/cx23885/cx23885-417.c
index 3948db3..d72a3ec 100644
--- a/drivers/media/pci/cx23885/cx23885-417.c
+++ b/drivers/media/pci/cx23885/cx23885-417.c
@@ -1148,6 +1148,7 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
 	dev->ts1.ts_packet_count = mpeglines;
 	*num_planes = 1;
 	sizes[0] = mpeglinesize * mpeglines;
+	alloc_ctxs[0] = dev->alloc_ctx;
 	*num_buffers = mpegbufs;
 	return 0;
 }
diff --git a/drivers/media/pci/cx23885/cx23885-core.c b/drivers/media/pci/cx23885/cx23885-core.c
index 331edda..d452b5c 100644
--- a/drivers/media/pci/cx23885/cx23885-core.c
+++ b/drivers/media/pci/cx23885/cx23885-core.c
@@ -1997,9 +1997,14 @@ static int cx23885_initdev(struct pci_dev *pci_dev,
 	if (!pci_dma_supported(pci_dev, 0xffffffff)) {
 		printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
 		err = -EIO;
-		goto fail_irq;
+		goto fail_context;
 	}
 
+	dev->alloc_ctx = vb2_dma_sg_init_ctx(&pci_dev->dev);
+	if (IS_ERR(dev->alloc_ctx)) {
+		err = PTR_ERR(dev->alloc_ctx);
+		goto fail_context;
+	}
 	err = request_irq(pci_dev->irq, cx23885_irq,
 			  IRQF_SHARED, dev->name, dev);
 	if (err < 0) {
@@ -2028,6 +2033,8 @@ static int cx23885_initdev(struct pci_dev *pci_dev,
 	return 0;
 
 fail_irq:
+	vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
+fail_context:
 	cx23885_dev_unregister(dev);
 fail_ctrl:
 	v4l2_ctrl_handler_free(hdl);
@@ -2053,6 +2060,7 @@ static void cx23885_finidev(struct pci_dev *pci_dev)
 	free_irq(pci_dev->irq, dev);
 
 	cx23885_dev_unregister(dev);
+	vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
 	v4l2_ctrl_handler_free(&dev->ctrl_handler);
 	v4l2_device_unregister(v4l2_dev);
 	kfree(dev);
diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c
index 9da5cf3..e63759e 100644
--- a/drivers/media/pci/cx23885/cx23885-dvb.c
+++ b/drivers/media/pci/cx23885/cx23885-dvb.c
@@ -102,6 +102,7 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
 	port->ts_packet_count = 32;
 	*num_planes = 1;
 	sizes[0] = port->ts_packet_size * port->ts_packet_count;
+	alloc_ctxs[0] = port->dev->alloc_ctx;
 	*num_buffers = 32;
 	return 0;
 }
diff --git a/drivers/media/pci/cx23885/cx23885-vbi.c b/drivers/media/pci/cx23885/cx23885-vbi.c
index a7c6ef8..1d339a6 100644
--- a/drivers/media/pci/cx23885/cx23885-vbi.c
+++ b/drivers/media/pci/cx23885/cx23885-vbi.c
@@ -132,6 +132,7 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
 		lines = VBI_NTSC_LINE_COUNT;
 	*num_planes = 1;
 	sizes[0] = lines * VBI_LINE_LENGTH * 2;
+	alloc_ctxs[0] = dev->alloc_ctx;
 	return 0;
 }
 
diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c
index 682a4f9..1b04ab3 100644
--- a/drivers/media/pci/cx23885/cx23885-video.c
+++ b/drivers/media/pci/cx23885/cx23885-video.c
@@ -323,6 +323,7 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
 
 	*num_planes = 1;
 	sizes[0] = (dev->fmt->depth * dev->width * dev->height) >> 3;
+	alloc_ctxs[0] = dev->alloc_ctx;
 	return 0;
 }
 
diff --git a/drivers/media/pci/cx23885/cx23885.h b/drivers/media/pci/cx23885/cx23885.h
index 7eee2ea..fa43d1b 100644
--- a/drivers/media/pci/cx23885/cx23885.h
+++ b/drivers/media/pci/cx23885/cx23885.h
@@ -422,6 +422,7 @@ struct cx23885_dev {
 	struct vb2_queue           vb2_vidq;
 	struct cx23885_dmaqueue    vbiq;
 	struct vb2_queue           vb2_vbiq;
+	void			   *alloc_ctx;
 
 	spinlock_t                 slock;
 
diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c
index 236ed72..a349e96 100644
--- a/drivers/media/pci/saa7134/saa7134-core.c
+++ b/drivers/media/pci/saa7134/saa7134-core.c
@@ -1001,13 +1001,18 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
 	saa7134_board_init1(dev);
 	saa7134_hwinit1(dev);
 
+	dev->alloc_ctx = vb2_dma_sg_init_ctx(&pci_dev->dev);
+	if (IS_ERR(dev->alloc_ctx)) {
+		err = PTR_ERR(dev->alloc_ctx);
+		goto fail3;
+	}
 	/* get irq */
 	err = request_irq(pci_dev->irq, saa7134_irq,
 			  IRQF_SHARED, dev->name, dev);
 	if (err < 0) {
 		printk(KERN_ERR "%s: can't get IRQ %d\n",
 		       dev->name,pci_dev->irq);
-		goto fail3;
+		goto fail4;
 	}
 
 	/* wait a bit, register i2c bus */
@@ -1065,7 +1070,7 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
 	if (err < 0) {
 		printk(KERN_INFO "%s: can't register video device\n",
 		       dev->name);
-		goto fail4;
+		goto fail5;
 	}
 	printk(KERN_INFO "%s: registered device %s [v4l2]\n",
 	       dev->name, video_device_node_name(dev->video_dev));
@@ -1078,7 +1083,7 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
 	err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI,
 				    vbi_nr[dev->nr]);
 	if (err < 0)
-		goto fail4;
+		goto fail5;
 	printk(KERN_INFO "%s: registered device %s\n",
 	       dev->name, video_device_node_name(dev->vbi_dev));
 
@@ -1089,7 +1094,7 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
 		err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO,
 					    radio_nr[dev->nr]);
 		if (err < 0)
-			goto fail4;
+			goto fail5;
 		printk(KERN_INFO "%s: registered device %s\n",
 		       dev->name, video_device_node_name(dev->radio_dev));
 	}
@@ -1103,10 +1108,12 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
 	request_submodules(dev);
 	return 0;
 
- fail4:
+ fail5:
 	saa7134_unregister_video(dev);
 	saa7134_i2c_unregister(dev);
 	free_irq(pci_dev->irq, dev);
+ fail4:
+	vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
  fail3:
 	saa7134_hwfini(dev);
 	iounmap(dev->lmmio);
@@ -1173,6 +1180,7 @@ static void saa7134_finidev(struct pci_dev *pci_dev)
 
 	/* release resources */
 	free_irq(pci_dev->irq, dev);
+	vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
 	iounmap(dev->lmmio);
 	release_mem_region(pci_resource_start(pci_dev,0),
 			   pci_resource_len(pci_dev,0));
diff --git a/drivers/media/pci/saa7134/saa7134-ts.c b/drivers/media/pci/saa7134/saa7134-ts.c
index bd25323..8eff4a7 100644
--- a/drivers/media/pci/saa7134/saa7134-ts.c
+++ b/drivers/media/pci/saa7134/saa7134-ts.c
@@ -142,6 +142,7 @@ int saa7134_ts_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
 		*nbuffers = 3;
 	*nplanes = 1;
 	sizes[0] = size;
+	alloc_ctxs[0] = dev->alloc_ctx;
 	return 0;
 }
 EXPORT_SYMBOL_GPL(saa7134_ts_queue_setup);
diff --git a/drivers/media/pci/saa7134/saa7134-vbi.c b/drivers/media/pci/saa7134/saa7134-vbi.c
index 4f0b101..e2cc684 100644
--- a/drivers/media/pci/saa7134/saa7134-vbi.c
+++ b/drivers/media/pci/saa7134/saa7134-vbi.c
@@ -156,6 +156,7 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
 	*nbuffers = saa7134_buffer_count(size, *nbuffers);
 	*nplanes = 1;
 	sizes[0] = size;
+	alloc_ctxs[0] = dev->alloc_ctx;
 	return 0;
 }
 
diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c
index fc4a427..ba02995 100644
--- a/drivers/media/pci/saa7134/saa7134-video.c
+++ b/drivers/media/pci/saa7134/saa7134-video.c
@@ -932,6 +932,7 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
 	*nbuffers = saa7134_buffer_count(size, *nbuffers);
 	*nplanes = 1;
 	sizes[0] = size;
+	alloc_ctxs[0] = dev->alloc_ctx;
 	return 0;
 }
 
diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h
index 1a82dd0..c644c7d 100644
--- a/drivers/media/pci/saa7134/saa7134.h
+++ b/drivers/media/pci/saa7134/saa7134.h
@@ -588,6 +588,7 @@ struct saa7134_dev {
 
 
 	/* video+ts+vbi capture */
+	void			   *alloc_ctx;
 	struct saa7134_dmaqueue    video_q;
 	struct vb2_queue           video_vbq;
 	struct saa7134_dmaqueue    vbi_q;
diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
index 28023f9..4f79b68 100644
--- a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
+++ b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
@@ -720,7 +720,10 @@ static int solo_enc_queue_setup(struct vb2_queue *q,
 				unsigned int *num_planes, unsigned int sizes[],
 				void *alloc_ctxs[])
 {
+	struct solo_enc_dev *solo_enc = vb2_get_drv_priv(q);
+
 	sizes[0] = FRAME_BUF_SIZE;
+	alloc_ctxs[0] = solo_enc->alloc_ctx;
 	*num_planes = 1;
 
 	if (*num_buffers < MIN_VID_BUFFERS)
@@ -1263,6 +1266,11 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev,
 		return ERR_PTR(-ENOMEM);
 
 	hdl = &solo_enc->hdl;
+	solo_enc->alloc_ctx = vb2_dma_sg_init_ctx(&solo_dev->pdev->dev);
+	if (IS_ERR(solo_enc->alloc_ctx)) {
+		ret = PTR_ERR(solo_enc->alloc_ctx);
+		goto hdl_free;
+	}
 	v4l2_ctrl_handler_init(hdl, 10);
 	v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
 			V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
@@ -1366,6 +1374,7 @@ pci_free:
 			solo_enc->desc_items, solo_enc->desc_dma);
 hdl_free:
 	v4l2_ctrl_handler_free(hdl);
+	vb2_dma_sg_cleanup_ctx(solo_enc->alloc_ctx);
 	kfree(solo_enc);
 	return ERR_PTR(ret);
 }
@@ -1377,6 +1386,7 @@ static void solo_enc_free(struct solo_enc_dev *solo_enc)
 
 	video_unregister_device(solo_enc->vfd);
 	v4l2_ctrl_handler_free(&solo_enc->hdl);
+	vb2_dma_sg_cleanup_ctx(solo_enc->alloc_ctx);
 	kfree(solo_enc);
 }
 
diff --git a/drivers/media/pci/solo6x10/solo6x10.h b/drivers/media/pci/solo6x10/solo6x10.h
index 72017b7..bd8edfa 100644
--- a/drivers/media/pci/solo6x10/solo6x10.h
+++ b/drivers/media/pci/solo6x10/solo6x10.h
@@ -180,6 +180,7 @@ struct solo_enc_dev {
 	u32			sequence;
 	struct vb2_queue	vidq;
 	struct list_head	vidq_active;
+	void			*alloc_ctx;
 	int			desc_count;
 	int			desc_nelts;
 	struct solo_p2m_desc	*desc_items;
diff --git a/drivers/media/pci/tw68/tw68-core.c b/drivers/media/pci/tw68/tw68-core.c
index 63f0b64..c135165 100644
--- a/drivers/media/pci/tw68/tw68-core.c
+++ b/drivers/media/pci/tw68/tw68-core.c
@@ -304,13 +304,19 @@ static int tw68_initdev(struct pci_dev *pci_dev,
 	/* Then do any initialisation wanted before interrupts are on */
 	tw68_hw_init1(dev);
 
+	dev->alloc_ctx = vb2_dma_sg_init_ctx(&pci_dev->dev);
+	if (IS_ERR(dev->alloc_ctx)) {
+		err = PTR_ERR(dev->alloc_ctx);
+		goto fail3;
+	}
+
 	/* get irq */
 	err = devm_request_irq(&pci_dev->dev, pci_dev->irq, tw68_irq,
 			  IRQF_SHARED, dev->name, dev);
 	if (err < 0) {
 		pr_err("%s: can't get IRQ %d\n",
 		       dev->name, pci_dev->irq);
-		goto fail3;
+		goto fail4;
 	}
 
 	/*
@@ -324,7 +330,7 @@ static int tw68_initdev(struct pci_dev *pci_dev,
 	if (err < 0) {
 		pr_err("%s: can't register video device\n",
 		       dev->name);
-		goto fail4;
+		goto fail5;
 	}
 	tw_setl(TW68_INTMASK, dev->pci_irqmask);
 
@@ -333,8 +339,10 @@ static int tw68_initdev(struct pci_dev *pci_dev,
 
 	return 0;
 
-fail4:
+fail5:
 	video_unregister_device(&dev->vdev);
+fail4:
+	vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
 fail3:
 	iounmap(dev->lmmio);
 fail2:
@@ -358,6 +366,7 @@ static void tw68_finidev(struct pci_dev *pci_dev)
 	/* unregister */
 	video_unregister_device(&dev->vdev);
 	v4l2_ctrl_handler_free(&dev->hdl);
+	vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
 
 	/* release resources */
 	iounmap(dev->lmmio);
diff --git a/drivers/media/pci/tw68/tw68-video.c b/drivers/media/pci/tw68/tw68-video.c
index 5c94ac7..50dcce6 100644
--- a/drivers/media/pci/tw68/tw68-video.c
+++ b/drivers/media/pci/tw68/tw68-video.c
@@ -384,6 +384,7 @@ static int tw68_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
 	unsigned tot_bufs = q->num_buffers + *num_buffers;
 
 	sizes[0] = (dev->fmt->depth * dev->width * dev->height) >> 3;
+	alloc_ctxs[0] = dev->alloc_ctx;
 	/*
 	 * We allow create_bufs, but only if the sizeimage is the same as the
 	 * current sizeimage. The tw68_buffer_count calculation becomes quite
diff --git a/drivers/media/pci/tw68/tw68.h b/drivers/media/pci/tw68/tw68.h
index 2c8abe2..7a7501b 100644
--- a/drivers/media/pci/tw68/tw68.h
+++ b/drivers/media/pci/tw68/tw68.h
@@ -181,6 +181,7 @@ struct tw68_dev {
 	unsigned		field;
 	struct vb2_queue	vidq;
 	struct list_head	active;
+	void			*alloc_ctx;
 
 	/* various v4l controls */
 	const struct tw68_tvnorm *tvnorm;	/* video */
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
index 7a86c77..7398b3f 100644
--- a/drivers/media/platform/marvell-ccic/mcam-core.c
+++ b/drivers/media/platform/marvell-ccic/mcam-core.c
@@ -1080,6 +1080,8 @@ static int mcam_vb_queue_setup(struct vb2_queue *vq,
 		*nbufs = minbufs;
 	if (cam->buffer_mode == B_DMA_contig)
 		alloc_ctxs[0] = cam->vb_alloc_ctx;
+	else if (cam->buffer_mode == B_DMA_sg)
+		alloc_ctxs[0] = cam->vb_alloc_ctx_sg;
 	return 0;
 }
 
@@ -1287,10 +1289,12 @@ static int mcam_setup_vb2(struct mcam_camera *cam)
 		vq->ops = &mcam_vb2_ops;
 		vq->mem_ops = &vb2_dma_contig_memops;
 		vq->buf_struct_size = sizeof(struct mcam_vb_buffer);
-		cam->vb_alloc_ctx = vb2_dma_contig_init_ctx(cam->dev);
 		vq->io_modes = VB2_MMAP | VB2_USERPTR;
 		cam->dma_setup = mcam_ctlr_dma_contig;
 		cam->frame_complete = mcam_dma_contig_done;
+		cam->vb_alloc_ctx = vb2_dma_contig_init_ctx(cam->dev);
+		if (IS_ERR(cam->vb_alloc_ctx))
+			return PTR_ERR(cam->vb_alloc_ctx);
 #endif
 		break;
 	case B_DMA_sg:
@@ -1301,6 +1305,9 @@ static int mcam_setup_vb2(struct mcam_camera *cam)
 		vq->io_modes = VB2_MMAP | VB2_USERPTR;
 		cam->dma_setup = mcam_ctlr_dma_sg;
 		cam->frame_complete = mcam_dma_sg_done;
+		cam->vb_alloc_ctx_sg = vb2_dma_sg_init_ctx(cam->dev);
+		if (IS_ERR(cam->vb_alloc_ctx_sg))
+			return PTR_ERR(cam->vb_alloc_ctx_sg);
 #endif
 		break;
 	case B_vmalloc:
@@ -1326,6 +1333,10 @@ static void mcam_cleanup_vb2(struct mcam_camera *cam)
 	if (cam->buffer_mode == B_DMA_contig)
 		vb2_dma_contig_cleanup_ctx(cam->vb_alloc_ctx);
 #endif
+#ifdef MCAM_MODE_DMA_SG
+	if (cam->buffer_mode == B_DMA_sg)
+		vb2_dma_sg_cleanup_ctx(cam->vb_alloc_ctx_sg);
+#endif
 }
 
 
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h
index e0e628c..7b8c201 100644
--- a/drivers/media/platform/marvell-ccic/mcam-core.h
+++ b/drivers/media/platform/marvell-ccic/mcam-core.h
@@ -176,6 +176,7 @@ struct mcam_camera {
 	/* DMA buffers - DMA modes */
 	struct mcam_vb_buffer *vb_bufs[MAX_DMA_BUFS];
 	struct vb2_alloc_ctx *vb_alloc_ctx;
+	struct vb2_alloc_ctx *vb_alloc_ctx_sg;
 
 	/* Mode-specific ops, set at open time */
 	void (*dma_setup)(struct mcam_camera *cam);
diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index 2529b83..72c89d0 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -30,7 +30,12 @@ module_param(debug, int, 0644);
 			printk(KERN_DEBUG "vb2-dma-sg: " fmt, ## arg);	\
 	} while (0)
 
+struct vb2_dma_sg_conf {
+	struct device		*dev;
+};
+
 struct vb2_dma_sg_buf {
+	struct device			*dev;
 	void				*vaddr;
 	struct page			**pages;
 	int				offset;
@@ -89,10 +94,13 @@ static int vb2_dma_sg_alloc_compacted(struct vb2_dma_sg_buf *buf,
 static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size,
 			      enum dma_data_direction dma_dir, gfp_t gfp_flags)
 {
+	struct vb2_dma_sg_conf *conf = alloc_ctx;
 	struct vb2_dma_sg_buf *buf;
 	int ret;
 	int num_pages;
 
+	if (WARN_ON(alloc_ctx == NULL))
+		return NULL;
 	buf = kzalloc(sizeof *buf, GFP_KERNEL);
 	if (!buf)
 		return NULL;
@@ -118,6 +126,8 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size,
 	if (ret)
 		goto fail_table_alloc;
 
+	/* Prevent the device from being released while the buffer is used */
+	buf->dev = get_device(conf->dev);
 	buf->handler.refcount = &buf->refcount;
 	buf->handler.put = vb2_dma_sg_put;
 	buf->handler.arg = buf;
@@ -153,6 +163,7 @@ static void vb2_dma_sg_put(void *buf_priv)
 		while (--i >= 0)
 			__free_page(buf->pages[i]);
 		kfree(buf->pages);
+		put_device(buf->dev);
 		kfree(buf);
 	}
 }
@@ -166,6 +177,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
 				    unsigned long size,
 				    enum dma_data_direction dma_dir)
 {
+	struct vb2_dma_sg_conf *conf = alloc_ctx;
 	struct vb2_dma_sg_buf *buf;
 	unsigned long first, last;
 	int num_pages_from_user;
@@ -235,6 +247,8 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
 			buf->num_pages, buf->offset, size, 0))
 		goto userptr_fail_alloc_table_from_pages;
 
+	/* Prevent the device from being released while the buffer is used */
+	buf->dev = get_device(conf->dev);
 	return buf;
 
 userptr_fail_alloc_table_from_pages:
@@ -274,6 +288,7 @@ static void vb2_dma_sg_put_userptr(void *buf_priv)
 	}
 	kfree(buf->pages);
 	vb2_put_vma(buf->vma);
+	put_device(buf->dev);
 	kfree(buf);
 }
 
@@ -356,6 +371,27 @@ const struct vb2_mem_ops vb2_dma_sg_memops = {
 };
 EXPORT_SYMBOL_GPL(vb2_dma_sg_memops);
 
+void *vb2_dma_sg_init_ctx(struct device *dev)
+{
+	struct vb2_dma_sg_conf *conf;
+
+	conf = kzalloc(sizeof(*conf), GFP_KERNEL);
+	if (!conf)
+		return ERR_PTR(-ENOMEM);
+
+	conf->dev = dev;
+
+	return conf;
+}
+EXPORT_SYMBOL_GPL(vb2_dma_sg_init_ctx);
+
+void vb2_dma_sg_cleanup_ctx(void *alloc_ctx)
+{
+	if (!IS_ERR_OR_NULL(alloc_ctx))
+		kfree(alloc_ctx);
+}
+EXPORT_SYMBOL_GPL(vb2_dma_sg_cleanup_ctx);
+
 MODULE_DESCRIPTION("dma scatter/gather memory handling routines for videobuf2");
 MODULE_AUTHOR("Andrzej Pietrasiewicz");
 MODULE_LICENSE("GPL");
diff --git a/include/media/videobuf2-dma-sg.h b/include/media/videobuf2-dma-sg.h
index 7b89852..14ce306 100644
--- a/include/media/videobuf2-dma-sg.h
+++ b/include/media/videobuf2-dma-sg.h
@@ -21,6 +21,9 @@ static inline struct sg_table *vb2_dma_sg_plane_desc(
 	return (struct sg_table *)vb2_plane_cookie(vb, plane_no);
 }
 
+void *vb2_dma_sg_init_ctx(struct device *dev);
+void vb2_dma_sg_cleanup_ctx(void *alloc_ctx);
+
 extern const struct vb2_mem_ops vb2_dma_sg_memops;
 
 #endif
-- 
2.1.1


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

* [RFCv6 PATCH 05/16] vb2-dma-sg: move dma_(un)map_sg here
  2014-11-10 12:49 [RFCv6 PATCH 00/16] vb2: improve dma-sg, expbuf Hans Verkuil
                   ` (3 preceding siblings ...)
  2014-11-10 12:49 ` [RFCv6 PATCH 04/16] vb2-dma-sg: add allocation context to dma-sg Hans Verkuil
@ 2014-11-10 12:49 ` Hans Verkuil
  2014-11-10 12:49 ` [RFCv6 PATCH 06/16] vb2-dma-sg: add dmabuf import support Hans Verkuil
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 29+ messages in thread
From: Hans Verkuil @ 2014-11-10 12:49 UTC (permalink / raw)
  To: linux-media; +Cc: m.szyprowski, pawel, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

This moves dma_(un)map_sg to the get_userptr/put_userptr and alloc/put
memops of videobuf2-dma-sg.c and adds dma_sync_sg_for_device/cpu to the
prepare/finish memops.

Now that vb2-dma-sg will sync the buffers for you in the prepare/finish
memops we can drop that from the drivers that use dma-sg.

For the solo6x10 driver that was a bit more involved because it needs to
copy JPEG or MPEG headers to the buffer before returning it to userspace,
and that cannot be done in the old place since the buffer there is still
setup for DMA access, not for CPU access. However, the buf_finish
op is the ideal place to do this. By the time buf_finish is called
the buffer is available for CPU access, so copying to the buffer is fine.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Pawel Osciak <pawel@osciak.com>
---
 drivers/media/pci/cx23885/cx23885-417.c         |  3 --
 drivers/media/pci/cx23885/cx23885-core.c        |  5 ---
 drivers/media/pci/cx23885/cx23885-dvb.c         |  3 --
 drivers/media/pci/cx23885/cx23885-vbi.c         |  9 -----
 drivers/media/pci/cx23885/cx23885-video.c       |  9 -----
 drivers/media/pci/saa7134/saa7134-empress.c     |  1 -
 drivers/media/pci/saa7134/saa7134-ts.c          | 16 --------
 drivers/media/pci/saa7134/saa7134-vbi.c         | 15 --------
 drivers/media/pci/saa7134/saa7134-video.c       | 15 --------
 drivers/media/pci/saa7134/saa7134.h             |  1 -
 drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c  | 50 +++++++++++--------------
 drivers/media/pci/tw68/tw68-video.c             |  8 ----
 drivers/media/platform/marvell-ccic/mcam-core.c | 18 +--------
 drivers/media/v4l2-core/videobuf2-dma-sg.c      | 40 ++++++++++++++++++++
 14 files changed, 63 insertions(+), 130 deletions(-)

diff --git a/drivers/media/pci/cx23885/cx23885-417.c b/drivers/media/pci/cx23885/cx23885-417.c
index d72a3ec..e4901a5 100644
--- a/drivers/media/pci/cx23885/cx23885-417.c
+++ b/drivers/media/pci/cx23885/cx23885-417.c
@@ -1167,11 +1167,8 @@ static void buffer_finish(struct vb2_buffer *vb)
 	struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
 	struct cx23885_buffer *buf = container_of(vb,
 		struct cx23885_buffer, vb);
-	struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
 
 	cx23885_free_buffer(dev, buf);
-
-	dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
 }
 
 static void buffer_queue(struct vb2_buffer *vb)
diff --git a/drivers/media/pci/cx23885/cx23885-core.c b/drivers/media/pci/cx23885/cx23885-core.c
index d452b5c..d07b04a 100644
--- a/drivers/media/pci/cx23885/cx23885-core.c
+++ b/drivers/media/pci/cx23885/cx23885-core.c
@@ -1453,17 +1453,12 @@ int cx23885_buf_prepare(struct cx23885_buffer *buf, struct cx23885_tsport *port)
 	struct cx23885_dev *dev = port->dev;
 	int size = port->ts_packet_size * port->ts_packet_count;
 	struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb, 0);
-	int rc;
 
 	dprintk(1, "%s: %p\n", __func__, buf);
 	if (vb2_plane_size(&buf->vb, 0) < size)
 		return -EINVAL;
 	vb2_set_plane_payload(&buf->vb, 0, size);
 
-	rc = dma_map_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
-	if (!rc)
-		return -EIO;
-
 	cx23885_risc_databuffer(dev->pci, &buf->risc,
 				sgt->sgl,
 				port->ts_packet_size, port->ts_packet_count, 0);
diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c
index e63759e..79239b1 100644
--- a/drivers/media/pci/cx23885/cx23885-dvb.c
+++ b/drivers/media/pci/cx23885/cx23885-dvb.c
@@ -123,11 +123,8 @@ static void buffer_finish(struct vb2_buffer *vb)
 	struct cx23885_dev *dev = port->dev;
 	struct cx23885_buffer *buf = container_of(vb,
 		struct cx23885_buffer, vb);
-	struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
 
 	cx23885_free_buffer(dev, buf);
-
-	dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
 }
 
 static void buffer_queue(struct vb2_buffer *vb)
diff --git a/drivers/media/pci/cx23885/cx23885-vbi.c b/drivers/media/pci/cx23885/cx23885-vbi.c
index 1d339a6..d362d38 100644
--- a/drivers/media/pci/cx23885/cx23885-vbi.c
+++ b/drivers/media/pci/cx23885/cx23885-vbi.c
@@ -143,7 +143,6 @@ static int buffer_prepare(struct vb2_buffer *vb)
 		struct cx23885_buffer, vb);
 	struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
 	unsigned lines = VBI_PAL_LINE_COUNT;
-	int ret;
 
 	if (dev->tvnorm & V4L2_STD_525_60)
 		lines = VBI_NTSC_LINE_COUNT;
@@ -152,10 +151,6 @@ static int buffer_prepare(struct vb2_buffer *vb)
 		return -EINVAL;
 	vb2_set_plane_payload(vb, 0, lines * VBI_LINE_LENGTH * 2);
 
-	ret = dma_map_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
-	if (!ret)
-		return -EIO;
-
 	cx23885_risc_vbibuffer(dev->pci, &buf->risc,
 			 sgt->sgl,
 			 0, VBI_LINE_LENGTH * lines,
@@ -166,14 +161,10 @@ static int buffer_prepare(struct vb2_buffer *vb)
 
 static void buffer_finish(struct vb2_buffer *vb)
 {
-	struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
 	struct cx23885_buffer *buf = container_of(vb,
 		struct cx23885_buffer, vb);
-	struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
 
 	cx23885_free_buffer(vb->vb2_queue->drv_priv, buf);
-
-	dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
 }
 
 /*
diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c
index 1b04ab3..6f4fcd9 100644
--- a/drivers/media/pci/cx23885/cx23885-video.c
+++ b/drivers/media/pci/cx23885/cx23885-video.c
@@ -335,7 +335,6 @@ static int buffer_prepare(struct vb2_buffer *vb)
 	u32 line0_offset, line1_offset;
 	struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
 	int field_tff;
-	int ret;
 
 	buf->bpl = (dev->width * dev->fmt->depth) >> 3;
 
@@ -343,10 +342,6 @@ static int buffer_prepare(struct vb2_buffer *vb)
 		return -EINVAL;
 	vb2_set_plane_payload(vb, 0, dev->height * buf->bpl);
 
-	ret = dma_map_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
-	if (!ret)
-		return -EIO;
-
 	switch (dev->field) {
 	case V4L2_FIELD_TOP:
 		cx23885_risc_buffer(dev->pci, &buf->risc,
@@ -414,14 +409,10 @@ static int buffer_prepare(struct vb2_buffer *vb)
 
 static void buffer_finish(struct vb2_buffer *vb)
 {
-	struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
 	struct cx23885_buffer *buf = container_of(vb,
 		struct cx23885_buffer, vb);
-	struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
 
 	cx23885_free_buffer(vb->vb2_queue->drv_priv, buf);
-
-	dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
 }
 
 /*
diff --git a/drivers/media/pci/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c
index e4ea85f..b1cfd0e 100644
--- a/drivers/media/pci/saa7134/saa7134-empress.c
+++ b/drivers/media/pci/saa7134/saa7134-empress.c
@@ -96,7 +96,6 @@ static struct vb2_ops saa7134_empress_qops = {
 	.queue_setup	= saa7134_ts_queue_setup,
 	.buf_init	= saa7134_ts_buffer_init,
 	.buf_prepare	= saa7134_ts_buffer_prepare,
-	.buf_finish	= saa7134_ts_buffer_finish,
 	.buf_queue	= saa7134_vb2_buffer_queue,
 	.wait_prepare	= vb2_ops_wait_prepare,
 	.wait_finish	= vb2_ops_wait_finish,
diff --git a/drivers/media/pci/saa7134/saa7134-ts.c b/drivers/media/pci/saa7134/saa7134-ts.c
index 8eff4a7..2709b83 100644
--- a/drivers/media/pci/saa7134/saa7134-ts.c
+++ b/drivers/media/pci/saa7134/saa7134-ts.c
@@ -94,7 +94,6 @@ int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2)
 	struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
 	struct sg_table *dma = vb2_dma_sg_plane_desc(vb2, 0);
 	unsigned int lines, llength, size;
-	int ret;
 
 	dprintk("buffer_prepare [%p]\n", buf);
 
@@ -108,25 +107,11 @@ int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2)
 	vb2_set_plane_payload(vb2, 0, size);
 	vb2->v4l2_buf.field = dev->field;
 
-	ret = dma_map_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
-	if (!ret)
-		return -EIO;
 	return saa7134_pgtable_build(dev->pci, &dmaq->pt, dma->sgl, dma->nents,
 				    saa7134_buffer_startpage(buf));
 }
 EXPORT_SYMBOL_GPL(saa7134_ts_buffer_prepare);
 
-void saa7134_ts_buffer_finish(struct vb2_buffer *vb2)
-{
-	struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
-	struct saa7134_dev *dev = dmaq->dev;
-	struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
-	struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
-
-	dma_unmap_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
-}
-EXPORT_SYMBOL_GPL(saa7134_ts_buffer_finish);
-
 int saa7134_ts_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
 			   unsigned int *nbuffers, unsigned int *nplanes,
 			   unsigned int sizes[], void *alloc_ctxs[])
@@ -188,7 +173,6 @@ struct vb2_ops saa7134_ts_qops = {
 	.queue_setup	= saa7134_ts_queue_setup,
 	.buf_init	= saa7134_ts_buffer_init,
 	.buf_prepare	= saa7134_ts_buffer_prepare,
-	.buf_finish	= saa7134_ts_buffer_finish,
 	.buf_queue	= saa7134_vb2_buffer_queue,
 	.wait_prepare	= vb2_ops_wait_prepare,
 	.wait_finish	= vb2_ops_wait_finish,
diff --git a/drivers/media/pci/saa7134/saa7134-vbi.c b/drivers/media/pci/saa7134/saa7134-vbi.c
index e2cc684..5306e54 100644
--- a/drivers/media/pci/saa7134/saa7134-vbi.c
+++ b/drivers/media/pci/saa7134/saa7134-vbi.c
@@ -120,7 +120,6 @@ static int buffer_prepare(struct vb2_buffer *vb2)
 	struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
 	struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
 	unsigned int size;
-	int ret;
 
 	if (dma->sgl->offset) {
 		pr_err("The buffer is not page-aligned\n");
@@ -132,9 +131,6 @@ static int buffer_prepare(struct vb2_buffer *vb2)
 
 	vb2_set_plane_payload(vb2, 0, size);
 
-	ret = dma_map_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
-	if (!ret)
-		return -EIO;
 	return saa7134_pgtable_build(dev->pci, &dmaq->pt, dma->sgl, dma->nents,
 				    saa7134_buffer_startpage(buf));
 }
@@ -170,21 +166,10 @@ static int buffer_init(struct vb2_buffer *vb2)
 	return 0;
 }
 
-static void buffer_finish(struct vb2_buffer *vb2)
-{
-	struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
-	struct saa7134_dev *dev = dmaq->dev;
-	struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
-	struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
-
-	dma_unmap_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
-}
-
 struct vb2_ops saa7134_vbi_qops = {
 	.queue_setup	= queue_setup,
 	.buf_init	= buffer_init,
 	.buf_prepare	= buffer_prepare,
-	.buf_finish	= buffer_finish,
 	.buf_queue	= saa7134_vb2_buffer_queue,
 	.wait_prepare	= vb2_ops_wait_prepare,
 	.wait_finish	= vb2_ops_wait_finish,
diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c
index ba02995..701b52f 100644
--- a/drivers/media/pci/saa7134/saa7134-video.c
+++ b/drivers/media/pci/saa7134/saa7134-video.c
@@ -883,7 +883,6 @@ static int buffer_prepare(struct vb2_buffer *vb2)
 	struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
 	struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
 	unsigned int size;
-	int ret;
 
 	if (dma->sgl->offset) {
 		pr_err("The buffer is not page-aligned\n");
@@ -896,23 +895,10 @@ static int buffer_prepare(struct vb2_buffer *vb2)
 	vb2_set_plane_payload(vb2, 0, size);
 	vb2->v4l2_buf.field = dev->field;
 
-	ret = dma_map_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
-	if (!ret)
-		return -EIO;
 	return saa7134_pgtable_build(dev->pci, &dmaq->pt, dma->sgl, dma->nents,
 				    saa7134_buffer_startpage(buf));
 }
 
-static void buffer_finish(struct vb2_buffer *vb2)
-{
-	struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
-	struct saa7134_dev *dev = dmaq->dev;
-	struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
-	struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
-
-	dma_unmap_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
-}
-
 static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
 			   unsigned int *nbuffers, unsigned int *nplanes,
 			   unsigned int sizes[], void *alloc_ctxs[])
@@ -1005,7 +991,6 @@ static struct vb2_ops vb2_qops = {
 	.queue_setup	= queue_setup,
 	.buf_init	= buffer_init,
 	.buf_prepare	= buffer_prepare,
-	.buf_finish	= buffer_finish,
 	.buf_queue	= saa7134_vb2_buffer_queue,
 	.wait_prepare	= vb2_ops_wait_prepare,
 	.wait_finish	= vb2_ops_wait_finish,
diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h
index c644c7d..8bf0553 100644
--- a/drivers/media/pci/saa7134/saa7134.h
+++ b/drivers/media/pci/saa7134/saa7134.h
@@ -815,7 +815,6 @@ void saa7134_video_fini(struct saa7134_dev *dev);
 
 int saa7134_ts_buffer_init(struct vb2_buffer *vb2);
 int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2);
-void saa7134_ts_buffer_finish(struct vb2_buffer *vb2);
 int saa7134_ts_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
 			   unsigned int *nbuffers, unsigned int *nplanes,
 			   unsigned int sizes[], void *alloc_ctxs[]);
diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
index 4f79b68..fb6270c 100644
--- a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
+++ b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
@@ -463,7 +463,6 @@ static int solo_fill_jpeg(struct solo_enc_dev *solo_enc,
 	struct solo_dev *solo_dev = solo_enc->solo_dev;
 	struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0);
 	int frame_size;
-	int ret;
 
 	vb->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
 
@@ -473,22 +472,10 @@ static int solo_fill_jpeg(struct solo_enc_dev *solo_enc,
 	frame_size = ALIGN(vop_jpeg_size(vh) + solo_enc->jpeg_len, DMA_ALIGN);
 	vb2_set_plane_payload(vb, 0, vop_jpeg_size(vh) + solo_enc->jpeg_len);
 
-	/* may discard all previous data in vbuf->sgl */
-	if (!dma_map_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
-			DMA_FROM_DEVICE))
-		return -ENOMEM;
-	ret = solo_send_desc(solo_enc, solo_enc->jpeg_len, vbuf,
+	return solo_send_desc(solo_enc, solo_enc->jpeg_len, vbuf,
 			     vop_jpeg_offset(vh) - SOLO_JPEG_EXT_ADDR(solo_dev),
 			     frame_size, SOLO_JPEG_EXT_ADDR(solo_dev),
 			     SOLO_JPEG_EXT_SIZE(solo_dev));
-	dma_unmap_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
-			DMA_FROM_DEVICE);
-
-	/* add the header only after dma_unmap_sg() */
-	sg_copy_from_buffer(vbuf->sgl, vbuf->nents,
-			    solo_enc->jpeg_header, solo_enc->jpeg_len);
-
-	return ret;
 }
 
 static int solo_fill_mpeg(struct solo_enc_dev *solo_enc,
@@ -498,7 +485,6 @@ static int solo_fill_mpeg(struct solo_enc_dev *solo_enc,
 	struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0);
 	int frame_off, frame_size;
 	int skip = 0;
-	int ret;
 
 	if (vb2_plane_size(vb, 0) < vop_mpeg_size(vh))
 		return -EIO;
@@ -521,21 +507,9 @@ static int solo_fill_mpeg(struct solo_enc_dev *solo_enc,
 		sizeof(*vh)) % SOLO_MP4E_EXT_SIZE(solo_dev);
 	frame_size = ALIGN(vop_mpeg_size(vh) + skip, DMA_ALIGN);
 
-	/* may discard all previous data in vbuf->sgl */
-	if (!dma_map_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
-			DMA_FROM_DEVICE))
-		return -ENOMEM;
-	ret = solo_send_desc(solo_enc, skip, vbuf, frame_off, frame_size,
+	return solo_send_desc(solo_enc, skip, vbuf, frame_off, frame_size,
 			SOLO_MP4E_EXT_ADDR(solo_dev),
 			SOLO_MP4E_EXT_SIZE(solo_dev));
-	dma_unmap_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
-			DMA_FROM_DEVICE);
-
-	/* add the header only after dma_unmap_sg() */
-	if (!vop_type(vh))
-		sg_copy_from_buffer(vbuf->sgl, vbuf->nents,
-				    solo_enc->vop, solo_enc->vop_len);
-	return ret;
 }
 
 static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc,
@@ -790,9 +764,29 @@ static void solo_enc_stop_streaming(struct vb2_queue *q)
 	solo_ring_stop(solo_enc->solo_dev);
 }
 
+static void solo_enc_buf_finish(struct vb2_buffer *vb)
+{
+	struct solo_enc_dev *solo_enc = vb2_get_drv_priv(vb->vb2_queue);
+	struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0);
+
+	switch (solo_enc->fmt) {
+	case V4L2_PIX_FMT_MPEG4:
+	case V4L2_PIX_FMT_H264:
+		if (vb->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME)
+			sg_copy_from_buffer(vbuf->sgl, vbuf->nents,
+					solo_enc->vop, solo_enc->vop_len);
+		break;
+	default: /* V4L2_PIX_FMT_MJPEG */
+		sg_copy_from_buffer(vbuf->sgl, vbuf->nents,
+				solo_enc->jpeg_header, solo_enc->jpeg_len);
+		break;
+	}
+}
+
 static struct vb2_ops solo_enc_video_qops = {
 	.queue_setup	= solo_enc_queue_setup,
 	.buf_queue	= solo_enc_buf_queue,
+	.buf_finish	= solo_enc_buf_finish,
 	.start_streaming = solo_enc_start_streaming,
 	.stop_streaming = solo_enc_stop_streaming,
 	.wait_prepare	= vb2_ops_wait_prepare,
diff --git a/drivers/media/pci/tw68/tw68-video.c b/drivers/media/pci/tw68/tw68-video.c
index 50dcce6..8355e55 100644
--- a/drivers/media/pci/tw68/tw68-video.c
+++ b/drivers/media/pci/tw68/tw68-video.c
@@ -462,17 +462,12 @@ static int tw68_buf_prepare(struct vb2_buffer *vb)
 	struct tw68_buf *buf = container_of(vb, struct tw68_buf, vb);
 	struct sg_table *dma = vb2_dma_sg_plane_desc(vb, 0);
 	unsigned size, bpl;
-	int rc;
 
 	size = (dev->width * dev->height * dev->fmt->depth) >> 3;
 	if (vb2_plane_size(vb, 0) < size)
 		return -EINVAL;
 	vb2_set_plane_payload(vb, 0, size);
 
-	rc = dma_map_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
-	if (!rc)
-		return -EIO;
-
 	bpl = (dev->width * dev->fmt->depth) >> 3;
 	switch (dev->field) {
 	case V4L2_FIELD_TOP:
@@ -506,11 +501,8 @@ static void tw68_buf_finish(struct vb2_buffer *vb)
 {
 	struct vb2_queue *vq = vb->vb2_queue;
 	struct tw68_dev *dev = vb2_get_drv_priv(vq);
-	struct sg_table *dma = vb2_dma_sg_plane_desc(vb, 0);
 	struct tw68_buf *buf = container_of(vb, struct tw68_buf, vb);
 
-	dma_unmap_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
-
 	pci_free_consistent(dev->pci, buf->size, buf->cpu, buf->dma);
 }
 
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
index 7398b3f..daaff51 100644
--- a/drivers/media/platform/marvell-ccic/mcam-core.c
+++ b/drivers/media/platform/marvell-ccic/mcam-core.c
@@ -1221,17 +1221,12 @@ static int mcam_vb_sg_buf_init(struct vb2_buffer *vb)
 static int mcam_vb_sg_buf_prepare(struct vb2_buffer *vb)
 {
 	struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
-	struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
 	struct sg_table *sg_table = vb2_dma_sg_plane_desc(vb, 0);
 	struct mcam_dma_desc *desc = mvb->dma_desc;
 	struct scatterlist *sg;
 	int i;
 
-	mvb->dma_desc_nent = dma_map_sg(cam->dev, sg_table->sgl,
-			sg_table->nents, DMA_FROM_DEVICE);
-	if (mvb->dma_desc_nent <= 0)
-		return -EIO;  /* Not sure what's right here */
-	for_each_sg(sg_table->sgl, sg, mvb->dma_desc_nent, i) {
+	for_each_sg(sg_table->sgl, sg, sg_table->nents, i) {
 		desc->dma_addr = sg_dma_address(sg);
 		desc->segment_len = sg_dma_len(sg);
 		desc++;
@@ -1239,16 +1234,6 @@ static int mcam_vb_sg_buf_prepare(struct vb2_buffer *vb)
 	return 0;
 }
 
-static void mcam_vb_sg_buf_finish(struct vb2_buffer *vb)
-{
-	struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
-	struct sg_table *sg_table = vb2_dma_sg_plane_desc(vb, 0);
-
-	if (sg_table)
-		dma_unmap_sg(cam->dev, sg_table->sgl,
-				sg_table->nents, DMA_FROM_DEVICE);
-}
-
 static void mcam_vb_sg_buf_cleanup(struct vb2_buffer *vb)
 {
 	struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
@@ -1265,7 +1250,6 @@ static const struct vb2_ops mcam_vb2_sg_ops = {
 	.buf_init		= mcam_vb_sg_buf_init,
 	.buf_prepare		= mcam_vb_sg_buf_prepare,
 	.buf_queue		= mcam_vb_buf_queue,
-	.buf_finish		= mcam_vb_sg_buf_finish,
 	.buf_cleanup		= mcam_vb_sg_buf_cleanup,
 	.start_streaming	= mcam_vb_start_streaming,
 	.stop_streaming		= mcam_vb_stop_streaming,
diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index 72c89d0..bda3293 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -96,6 +96,7 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size,
 {
 	struct vb2_dma_sg_conf *conf = alloc_ctx;
 	struct vb2_dma_sg_buf *buf;
+	struct sg_table *sgt;
 	int ret;
 	int num_pages;
 
@@ -128,6 +129,12 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size,
 
 	/* Prevent the device from being released while the buffer is used */
 	buf->dev = get_device(conf->dev);
+
+	sgt = &buf->sg_table;
+	if (dma_map_sg(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir) == 0)
+		goto fail_map;
+	dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
+
 	buf->handler.refcount = &buf->refcount;
 	buf->handler.put = vb2_dma_sg_put;
 	buf->handler.arg = buf;
@@ -138,6 +145,9 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size,
 		__func__, buf->num_pages);
 	return buf;
 
+fail_map:
+	put_device(buf->dev);
+	sg_free_table(buf->dma_sgt);
 fail_table_alloc:
 	num_pages = buf->num_pages;
 	while (num_pages--)
@@ -152,11 +162,13 @@ fail_pages_array_alloc:
 static void vb2_dma_sg_put(void *buf_priv)
 {
 	struct vb2_dma_sg_buf *buf = buf_priv;
+	struct sg_table *sgt = &buf->sg_table;
 	int i = buf->num_pages;
 
 	if (atomic_dec_and_test(&buf->refcount)) {
 		dprintk(1, "%s: Freeing buffer of %d pages\n", __func__,
 			buf->num_pages);
+		dma_unmap_sg(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
 		if (buf->vaddr)
 			vm_unmap_ram(buf->vaddr, buf->num_pages);
 		sg_free_table(&buf->sg_table);
@@ -168,6 +180,22 @@ static void vb2_dma_sg_put(void *buf_priv)
 	}
 }
 
+static void vb2_dma_sg_prepare(void *buf_priv)
+{
+	struct vb2_dma_sg_buf *buf = buf_priv;
+	struct sg_table *sgt = &buf->sg_table;
+
+	dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
+}
+
+static void vb2_dma_sg_finish(void *buf_priv)
+{
+	struct vb2_dma_sg_buf *buf = buf_priv;
+	struct sg_table *sgt = &buf->sg_table;
+
+	dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
+}
+
 static inline int vma_is_io(struct vm_area_struct *vma)
 {
 	return !!(vma->vm_flags & (VM_IO | VM_PFNMAP));
@@ -182,6 +210,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
 	unsigned long first, last;
 	int num_pages_from_user;
 	struct vm_area_struct *vma;
+	struct sg_table *sgt;
 
 	buf = kzalloc(sizeof *buf, GFP_KERNEL);
 	if (!buf)
@@ -249,8 +278,15 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
 
 	/* Prevent the device from being released while the buffer is used */
 	buf->dev = get_device(conf->dev);
+
+	sgt = &buf->sg_table;
+	if (dma_map_sg(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir) == 0)
+		goto userptr_fail_map;
+	dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
 	return buf;
 
+userptr_fail_map:
+	sg_free_table(&buf->sg_table);
 userptr_fail_alloc_table_from_pages:
 userptr_fail_get_user_pages:
 	dprintk(1, "get_user_pages requested/got: %d/%d]\n",
@@ -273,10 +309,12 @@ userptr_fail_alloc_pages:
 static void vb2_dma_sg_put_userptr(void *buf_priv)
 {
 	struct vb2_dma_sg_buf *buf = buf_priv;
+	struct sg_table *sgt = &buf->sg_table;
 	int i = buf->num_pages;
 
 	dprintk(1, "%s: Releasing userspace buffer of %d pages\n",
 	       __func__, buf->num_pages);
+	dma_unmap_sg(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
 	if (buf->vaddr)
 		vm_unmap_ram(buf->vaddr, buf->num_pages);
 	sg_free_table(&buf->sg_table);
@@ -364,6 +402,8 @@ const struct vb2_mem_ops vb2_dma_sg_memops = {
 	.put		= vb2_dma_sg_put,
 	.get_userptr	= vb2_dma_sg_get_userptr,
 	.put_userptr	= vb2_dma_sg_put_userptr,
+	.prepare	= vb2_dma_sg_prepare,
+	.finish		= vb2_dma_sg_finish,
 	.vaddr		= vb2_dma_sg_vaddr,
 	.mmap		= vb2_dma_sg_mmap,
 	.num_users	= vb2_dma_sg_num_users,
-- 
2.1.1


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

* [RFCv6 PATCH 06/16] vb2-dma-sg: add dmabuf import support
  2014-11-10 12:49 [RFCv6 PATCH 00/16] vb2: improve dma-sg, expbuf Hans Verkuil
                   ` (4 preceding siblings ...)
  2014-11-10 12:49 ` [RFCv6 PATCH 05/16] vb2-dma-sg: move dma_(un)map_sg here Hans Verkuil
@ 2014-11-10 12:49 ` Hans Verkuil
  2014-11-16 13:29   ` Pawel Osciak
  2014-11-10 12:49 ` [RFCv6 PATCH 07/16] vb2-dma-sg: add support for dmabuf exports Hans Verkuil
                   ` (9 subsequent siblings)
  15 siblings, 1 reply; 29+ messages in thread
From: Hans Verkuil @ 2014-11-10 12:49 UTC (permalink / raw)
  To: linux-media; +Cc: m.szyprowski, pawel, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Add support for importing dmabuf to videobuf2-dma-sg.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/v4l2-core/videobuf2-dma-sg.c | 149 ++++++++++++++++++++++++++---
 1 file changed, 136 insertions(+), 13 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index bda3293..85e2e09 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -41,11 +41,19 @@ struct vb2_dma_sg_buf {
 	int				offset;
 	enum dma_data_direction		dma_dir;
 	struct sg_table			sg_table;
+	/*
+	 * This will point to sg_table when used with the MMAP or USERPTR
+	 * memory model, and to the dma_buf sglist when used with the
+	 * DMABUF memory model.
+	 */
+	struct sg_table			*dma_sgt;
 	size_t				size;
 	unsigned int			num_pages;
 	atomic_t			refcount;
 	struct vb2_vmarea_handler	handler;
 	struct vm_area_struct		*vma;
+
+	struct dma_buf_attachment	*db_attach;
 };
 
 static void vb2_dma_sg_put(void *buf_priv);
@@ -112,6 +120,7 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size,
 	buf->size = size;
 	/* size is already page aligned */
 	buf->num_pages = size >> PAGE_SHIFT;
+	buf->dma_sgt = &buf->sg_table;
 
 	buf->pages = kzalloc(buf->num_pages * sizeof(struct page *),
 			     GFP_KERNEL);
@@ -122,7 +131,7 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size,
 	if (ret)
 		goto fail_pages_alloc;
 
-	ret = sg_alloc_table_from_pages(&buf->sg_table, buf->pages,
+	ret = sg_alloc_table_from_pages(buf->dma_sgt, buf->pages,
 			buf->num_pages, 0, size, GFP_KERNEL);
 	if (ret)
 		goto fail_table_alloc;
@@ -171,7 +180,7 @@ static void vb2_dma_sg_put(void *buf_priv)
 		dma_unmap_sg(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
 		if (buf->vaddr)
 			vm_unmap_ram(buf->vaddr, buf->num_pages);
-		sg_free_table(&buf->sg_table);
+		sg_free_table(buf->dma_sgt);
 		while (--i >= 0)
 			__free_page(buf->pages[i]);
 		kfree(buf->pages);
@@ -183,7 +192,11 @@ static void vb2_dma_sg_put(void *buf_priv)
 static void vb2_dma_sg_prepare(void *buf_priv)
 {
 	struct vb2_dma_sg_buf *buf = buf_priv;
-	struct sg_table *sgt = &buf->sg_table;
+	struct sg_table *sgt = buf->dma_sgt;
+
+	/* DMABUF exporter will flush the cache for us */
+	if (buf->db_attach)
+		return;
 
 	dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
 }
@@ -191,7 +204,11 @@ static void vb2_dma_sg_prepare(void *buf_priv)
 static void vb2_dma_sg_finish(void *buf_priv)
 {
 	struct vb2_dma_sg_buf *buf = buf_priv;
-	struct sg_table *sgt = &buf->sg_table;
+	struct sg_table *sgt = buf->dma_sgt;
+
+	/* DMABUF exporter will flush the cache for us */
+	if (buf->db_attach)
+		return;
 
 	dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
 }
@@ -220,6 +237,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
 	buf->dma_dir = dma_dir;
 	buf->offset = vaddr & ~PAGE_MASK;
 	buf->size = size;
+	buf->dma_sgt = &buf->sg_table;
 
 	first = (vaddr           & PAGE_MASK) >> PAGE_SHIFT;
 	last  = ((vaddr + size - 1) & PAGE_MASK) >> PAGE_SHIFT;
@@ -272,7 +290,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
 	if (num_pages_from_user != buf->num_pages)
 		goto userptr_fail_get_user_pages;
 
-	if (sg_alloc_table_from_pages(&buf->sg_table, buf->pages,
+	if (sg_alloc_table_from_pages(buf->dma_sgt, buf->pages,
 			buf->num_pages, buf->offset, size, 0))
 		goto userptr_fail_alloc_table_from_pages;
 
@@ -317,7 +335,7 @@ static void vb2_dma_sg_put_userptr(void *buf_priv)
 	dma_unmap_sg(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
 	if (buf->vaddr)
 		vm_unmap_ram(buf->vaddr, buf->num_pages);
-	sg_free_table(&buf->sg_table);
+	sg_free_table(buf->dma_sgt);
 	while (--i >= 0) {
 		if (buf->dma_dir == DMA_FROM_DEVICE)
 			set_page_dirty_lock(buf->pages[i]);
@@ -336,14 +354,16 @@ static void *vb2_dma_sg_vaddr(void *buf_priv)
 
 	BUG_ON(!buf);
 
-	if (!buf->vaddr)
-		buf->vaddr = vm_map_ram(buf->pages,
-					buf->num_pages,
-					-1,
-					PAGE_KERNEL);
+	if (!buf->vaddr) {
+		if (buf->db_attach)
+			buf->vaddr = dma_buf_vmap(buf->db_attach->dmabuf);
+		else
+			buf->vaddr = vm_map_ram(buf->pages,
+					buf->num_pages, -1, PAGE_KERNEL);
+	}
 
 	/* add offset in case userptr is not page-aligned */
-	return buf->vaddr + buf->offset;
+	return buf->vaddr ? buf->vaddr + buf->offset : NULL;
 }
 
 static unsigned int vb2_dma_sg_num_users(void *buf_priv)
@@ -390,11 +410,110 @@ static int vb2_dma_sg_mmap(void *buf_priv, struct vm_area_struct *vma)
 	return 0;
 }
 
+/*********************************************/
+/*       callbacks for DMABUF buffers        */
+/*********************************************/
+
+static int vb2_dma_sg_map_dmabuf(void *mem_priv)
+{
+	struct vb2_dma_sg_buf *buf = mem_priv;
+	struct sg_table *sgt;
+
+	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(sgt)) {
+		pr_err("Error getting dmabuf scatterlist\n");
+		return -EINVAL;
+	}
+
+	buf->dma_sgt = sgt;
+	buf->vaddr = NULL;
+
+	return 0;
+}
+
+static void vb2_dma_sg_unmap_dmabuf(void *mem_priv)
+{
+	struct vb2_dma_sg_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;
+	}
+
+	if (buf->vaddr) {
+		dma_buf_vunmap(buf->db_attach->dmabuf, buf->vaddr);
+		buf->vaddr = NULL;
+	}
+	dma_buf_unmap_attachment(buf->db_attach, sgt, buf->dma_dir);
+
+	buf->dma_sgt = NULL;
+}
+
+static void vb2_dma_sg_detach_dmabuf(void *mem_priv)
+{
+	struct vb2_dma_sg_buf *buf = mem_priv;
+
+	/* if vb2 works correctly you should never detach mapped buffer */
+	if (WARN_ON(buf->dma_sgt))
+		vb2_dma_sg_unmap_dmabuf(buf);
+
+	/* detach this attachment */
+	dma_buf_detach(buf->db_attach->dmabuf, buf->db_attach);
+	kfree(buf);
+}
+
+static void *vb2_dma_sg_attach_dmabuf(void *alloc_ctx, struct dma_buf *dbuf,
+	unsigned long size, enum dma_data_direction dma_dir)
+{
+	struct vb2_dma_sg_conf *conf = alloc_ctx;
+	struct vb2_dma_sg_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 = dma_dir;
+	buf->size = size;
+	buf->db_attach = dba;
+
+	return buf;
+}
+
 static void *vb2_dma_sg_cookie(void *buf_priv)
 {
 	struct vb2_dma_sg_buf *buf = buf_priv;
 
-	return &buf->sg_table;
+	return buf->dma_sgt;
 }
 
 const struct vb2_mem_ops vb2_dma_sg_memops = {
@@ -407,6 +526,10 @@ const struct vb2_mem_ops vb2_dma_sg_memops = {
 	.vaddr		= vb2_dma_sg_vaddr,
 	.mmap		= vb2_dma_sg_mmap,
 	.num_users	= vb2_dma_sg_num_users,
+	.map_dmabuf	= vb2_dma_sg_map_dmabuf,
+	.unmap_dmabuf	= vb2_dma_sg_unmap_dmabuf,
+	.attach_dmabuf	= vb2_dma_sg_attach_dmabuf,
+	.detach_dmabuf	= vb2_dma_sg_detach_dmabuf,
 	.cookie		= vb2_dma_sg_cookie,
 };
 EXPORT_SYMBOL_GPL(vb2_dma_sg_memops);
-- 
2.1.1


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

* [RFCv6 PATCH 07/16] vb2-dma-sg: add support for dmabuf exports
  2014-11-10 12:49 [RFCv6 PATCH 00/16] vb2: improve dma-sg, expbuf Hans Verkuil
                   ` (5 preceding siblings ...)
  2014-11-10 12:49 ` [RFCv6 PATCH 06/16] vb2-dma-sg: add dmabuf import support Hans Verkuil
@ 2014-11-10 12:49 ` Hans Verkuil
  2014-11-16 13:35   ` Pawel Osciak
  2014-11-10 12:49 ` [RFCv6 PATCH 08/16] vb2-vmalloc: " Hans Verkuil
                   ` (8 subsequent siblings)
  15 siblings, 1 reply; 29+ messages in thread
From: Hans Verkuil @ 2014-11-10 12:49 UTC (permalink / raw)
  To: linux-media; +Cc: m.szyprowski, pawel, Hans Verkuil

From: Hans Verkuil <hansverk@cisco.com>

Add DMABUF export support to vb2-dma-sg.

Signed-off-by: Hans Verkuil <hansverk@cisco.com>
---
 drivers/media/v4l2-core/videobuf2-dma-sg.c | 170 +++++++++++++++++++++++++++++
 1 file changed, 170 insertions(+)

diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index 85e2e09..0f7d293 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -411,6 +411,175 @@ static int vb2_dma_sg_mmap(void *buf_priv, struct vm_area_struct *vma)
 }
 
 /*********************************************/
+/*         DMABUF ops for exporters          */
+/*********************************************/
+
+struct vb2_dma_sg_attachment {
+	struct sg_table sgt;
+	enum dma_data_direction dma_dir;
+};
+
+static int vb2_dma_sg_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev,
+	struct dma_buf_attachment *dbuf_attach)
+{
+	struct vb2_dma_sg_attachment *attach;
+	unsigned int i;
+	struct scatterlist *rd, *wr;
+	struct sg_table *sgt;
+	struct vb2_dma_sg_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->dma_sgt->orig_nents, GFP_KERNEL);
+	if (ret) {
+		kfree(attach);
+		return -ENOMEM;
+	}
+
+	rd = buf->dma_sgt->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->dma_dir = DMA_NONE;
+	dbuf_attach->priv = attach;
+
+	return 0;
+}
+
+static void vb2_dma_sg_dmabuf_ops_detach(struct dma_buf *dbuf,
+	struct dma_buf_attachment *db_attach)
+{
+	struct vb2_dma_sg_attachment *attach = db_attach->priv;
+	struct sg_table *sgt;
+
+	if (!attach)
+		return;
+
+	sgt = &attach->sgt;
+
+	/* release the scatterlist cache */
+	if (attach->dma_dir != DMA_NONE)
+		dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
+			attach->dma_dir);
+	sg_free_table(sgt);
+	kfree(attach);
+	db_attach->priv = NULL;
+}
+
+static struct sg_table *vb2_dma_sg_dmabuf_ops_map(
+	struct dma_buf_attachment *db_attach, enum dma_data_direction dma_dir)
+{
+	struct vb2_dma_sg_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->dma_dir == dma_dir) {
+		mutex_unlock(lock);
+		return sgt;
+	}
+
+	/* release any previous cache */
+	if (attach->dma_dir != DMA_NONE) {
+		dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
+			attach->dma_dir);
+		attach->dma_dir = DMA_NONE;
+	}
+
+	/* mapping to the client with new direction */
+	ret = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, dma_dir);
+	if (ret <= 0) {
+		pr_err("failed to map scatterlist\n");
+		mutex_unlock(lock);
+		return ERR_PTR(-EIO);
+	}
+
+	attach->dma_dir = dma_dir;
+
+	mutex_unlock(lock);
+
+	return sgt;
+}
+
+static void vb2_dma_sg_dmabuf_ops_unmap(struct dma_buf_attachment *db_attach,
+	struct sg_table *sgt, enum dma_data_direction dma_dir)
+{
+	/* nothing to be done here */
+}
+
+static void vb2_dma_sg_dmabuf_ops_release(struct dma_buf *dbuf)
+{
+	/* drop reference obtained in vb2_dma_sg_get_dmabuf */
+	vb2_dma_sg_put(dbuf->priv);
+}
+
+static void *vb2_dma_sg_dmabuf_ops_kmap(struct dma_buf *dbuf, unsigned long pgnum)
+{
+	struct vb2_dma_sg_buf *buf = dbuf->priv;
+
+	return buf->vaddr ? buf->vaddr + pgnum * PAGE_SIZE : NULL;
+}
+
+static void *vb2_dma_sg_dmabuf_ops_vmap(struct dma_buf *dbuf)
+{
+	struct vb2_dma_sg_buf *buf = dbuf->priv;
+
+	return vb2_dma_sg_vaddr(buf);
+}
+
+static int vb2_dma_sg_dmabuf_ops_mmap(struct dma_buf *dbuf,
+	struct vm_area_struct *vma)
+{
+	return vb2_dma_sg_mmap(dbuf->priv, vma);
+}
+
+static struct dma_buf_ops vb2_dma_sg_dmabuf_ops = {
+	.attach = vb2_dma_sg_dmabuf_ops_attach,
+	.detach = vb2_dma_sg_dmabuf_ops_detach,
+	.map_dma_buf = vb2_dma_sg_dmabuf_ops_map,
+	.unmap_dma_buf = vb2_dma_sg_dmabuf_ops_unmap,
+	.kmap = vb2_dma_sg_dmabuf_ops_kmap,
+	.kmap_atomic = vb2_dma_sg_dmabuf_ops_kmap,
+	.vmap = vb2_dma_sg_dmabuf_ops_vmap,
+	.mmap = vb2_dma_sg_dmabuf_ops_mmap,
+	.release = vb2_dma_sg_dmabuf_ops_release,
+};
+
+static struct dma_buf *vb2_dma_sg_get_dmabuf(void *buf_priv, unsigned long flags)
+{
+	struct vb2_dma_sg_buf *buf = buf_priv;
+	struct dma_buf *dbuf;
+
+	if (WARN_ON(!buf->dma_sgt))
+		return NULL;
+
+	dbuf = dma_buf_export(buf, &vb2_dma_sg_dmabuf_ops, buf->size, flags, NULL);
+	if (IS_ERR(dbuf))
+		return NULL;
+
+	/* dmabuf keeps reference to vb2 buffer */
+	atomic_inc(&buf->refcount);
+
+	return dbuf;
+}
+
+/*********************************************/
 /*       callbacks for DMABUF buffers        */
 /*********************************************/
 
@@ -526,6 +695,7 @@ const struct vb2_mem_ops vb2_dma_sg_memops = {
 	.vaddr		= vb2_dma_sg_vaddr,
 	.mmap		= vb2_dma_sg_mmap,
 	.num_users	= vb2_dma_sg_num_users,
+	.get_dmabuf	= vb2_dma_sg_get_dmabuf,
 	.map_dmabuf	= vb2_dma_sg_map_dmabuf,
 	.unmap_dmabuf	= vb2_dma_sg_unmap_dmabuf,
 	.attach_dmabuf	= vb2_dma_sg_attach_dmabuf,
-- 
2.1.1


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

* [RFCv6 PATCH 08/16] vb2-vmalloc: add support for dmabuf exports
  2014-11-10 12:49 [RFCv6 PATCH 00/16] vb2: improve dma-sg, expbuf Hans Verkuil
                   ` (6 preceding siblings ...)
  2014-11-10 12:49 ` [RFCv6 PATCH 07/16] vb2-dma-sg: add support for dmabuf exports Hans Verkuil
@ 2014-11-10 12:49 ` Hans Verkuil
  2014-11-18  9:34   ` Pawel Osciak
  2014-11-10 12:49 ` [RFCv6 PATCH 09/16] vivid: enable vb2_expbuf support Hans Verkuil
                   ` (7 subsequent siblings)
  15 siblings, 1 reply; 29+ messages in thread
From: Hans Verkuil @ 2014-11-10 12:49 UTC (permalink / raw)
  To: linux-media; +Cc: m.szyprowski, pawel, Hans Verkuil

From: Hans Verkuil <hansverk@cisco.com>

Add support for DMABUF exporting to the vb2-vmalloc implementation.

All memory models now have support for both importing and exporting of DMABUFs.

Signed-off-by: Hans Verkuil <hansverk@cisco.com>
---
 drivers/media/v4l2-core/videobuf2-vmalloc.c | 174 ++++++++++++++++++++++++++++
 1 file changed, 174 insertions(+)

diff --git a/drivers/media/v4l2-core/videobuf2-vmalloc.c b/drivers/media/v4l2-core/videobuf2-vmalloc.c
index bba2460..dfbb6d5 100644
--- a/drivers/media/v4l2-core/videobuf2-vmalloc.c
+++ b/drivers/media/v4l2-core/videobuf2-vmalloc.c
@@ -31,6 +31,9 @@ struct vb2_vmalloc_buf {
 	atomic_t			refcount;
 	struct vb2_vmarea_handler	handler;
 	struct dma_buf			*dbuf;
+
+	/* DMABUF related */
+	struct dma_buf_attachment	*db_attach;
 };
 
 static void vb2_vmalloc_put(void *buf_priv);
@@ -213,6 +216,176 @@ static int vb2_vmalloc_mmap(void *buf_priv, struct vm_area_struct *vma)
 }
 
 /*********************************************/
+/*         DMABUF ops for exporters          */
+/*********************************************/
+
+struct vb2_vmalloc_attachment {
+	struct sg_table sgt;
+	enum dma_data_direction dma_dir;
+};
+
+static int vb2_vmalloc_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev,
+	struct dma_buf_attachment *dbuf_attach)
+{
+	struct vb2_vmalloc_attachment *attach;
+	struct vb2_vmalloc_buf *buf = dbuf->priv;
+	int num_pages = PAGE_ALIGN(buf->size) / PAGE_SIZE;
+	struct sg_table *sgt;
+	struct scatterlist *sg;
+	void *vaddr = buf->vaddr;
+	int ret;
+	int i;
+
+	attach = kzalloc(sizeof(*attach), GFP_KERNEL);
+	if (!attach)
+		return -ENOMEM;
+
+	sgt = &attach->sgt;
+	ret = sg_alloc_table(sgt, num_pages, GFP_KERNEL);
+	if (ret) {
+		kfree(attach);
+		return ret;
+	}
+	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+		struct page *page = vmalloc_to_page(vaddr);
+
+		if (!page) {
+			sg_free_table(sgt);
+			kfree(attach);
+			return -ENOMEM;
+		}
+		sg_set_page(sg, page, PAGE_SIZE, 0);
+		vaddr += PAGE_SIZE;
+	}
+
+	attach->dma_dir = DMA_NONE;
+	dbuf_attach->priv = attach;
+	return 0;
+}
+
+static void vb2_vmalloc_dmabuf_ops_detach(struct dma_buf *dbuf,
+	struct dma_buf_attachment *db_attach)
+{
+	struct vb2_vmalloc_attachment *attach = db_attach->priv;
+	struct sg_table *sgt;
+
+	if (!attach)
+		return;
+
+	sgt = &attach->sgt;
+
+	/* release the scatterlist cache */
+	if (attach->dma_dir != DMA_NONE)
+		dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
+			attach->dma_dir);
+	sg_free_table(sgt);
+	kfree(attach);
+	db_attach->priv = NULL;
+}
+
+static struct sg_table *vb2_vmalloc_dmabuf_ops_map(
+	struct dma_buf_attachment *db_attach, enum dma_data_direction dma_dir)
+{
+	struct vb2_vmalloc_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->dma_dir == dma_dir) {
+		mutex_unlock(lock);
+		return sgt;
+	}
+
+	/* release any previous cache */
+	if (attach->dma_dir != DMA_NONE) {
+		dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
+			attach->dma_dir);
+		attach->dma_dir = DMA_NONE;
+	}
+
+	/* mapping to the client with new direction */
+	ret = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, dma_dir);
+	if (ret <= 0) {
+		pr_err("failed to map scatterlist\n");
+		mutex_unlock(lock);
+		return ERR_PTR(-EIO);
+	}
+
+	attach->dma_dir = dma_dir;
+
+	mutex_unlock(lock);
+
+	return sgt;
+}
+
+static void vb2_vmalloc_dmabuf_ops_unmap(struct dma_buf_attachment *db_attach,
+	struct sg_table *sgt, enum dma_data_direction dma_dir)
+{
+	/* nothing to be done here */
+}
+
+static void vb2_vmalloc_dmabuf_ops_release(struct dma_buf *dbuf)
+{
+	/* drop reference obtained in vb2_vmalloc_get_dmabuf */
+	vb2_vmalloc_put(dbuf->priv);
+}
+
+static void *vb2_vmalloc_dmabuf_ops_kmap(struct dma_buf *dbuf, unsigned long pgnum)
+{
+	struct vb2_vmalloc_buf *buf = dbuf->priv;
+
+	return buf->vaddr + pgnum * PAGE_SIZE;
+}
+
+static void *vb2_vmalloc_dmabuf_ops_vmap(struct dma_buf *dbuf)
+{
+	struct vb2_vmalloc_buf *buf = dbuf->priv;
+
+	return buf->vaddr;
+}
+
+static int vb2_vmalloc_dmabuf_ops_mmap(struct dma_buf *dbuf,
+	struct vm_area_struct *vma)
+{
+	return vb2_vmalloc_mmap(dbuf->priv, vma);
+}
+
+static struct dma_buf_ops vb2_vmalloc_dmabuf_ops = {
+	.attach = vb2_vmalloc_dmabuf_ops_attach,
+	.detach = vb2_vmalloc_dmabuf_ops_detach,
+	.map_dma_buf = vb2_vmalloc_dmabuf_ops_map,
+	.unmap_dma_buf = vb2_vmalloc_dmabuf_ops_unmap,
+	.kmap = vb2_vmalloc_dmabuf_ops_kmap,
+	.kmap_atomic = vb2_vmalloc_dmabuf_ops_kmap,
+	.vmap = vb2_vmalloc_dmabuf_ops_vmap,
+	.mmap = vb2_vmalloc_dmabuf_ops_mmap,
+	.release = vb2_vmalloc_dmabuf_ops_release,
+};
+
+static struct dma_buf *vb2_vmalloc_get_dmabuf(void *buf_priv, unsigned long flags)
+{
+	struct vb2_vmalloc_buf *buf = buf_priv;
+	struct dma_buf *dbuf;
+
+	if (WARN_ON(!buf->vaddr))
+		return NULL;
+
+	dbuf = dma_buf_export(buf, &vb2_vmalloc_dmabuf_ops, buf->size, flags, NULL);
+	if (IS_ERR(dbuf))
+		return NULL;
+
+	/* dmabuf keeps reference to vb2 buffer */
+	atomic_inc(&buf->refcount);
+
+	return dbuf;
+}
+
+/*********************************************/
 /*       callbacks for DMABUF buffers        */
 /*********************************************/
 
@@ -268,6 +441,7 @@ const struct vb2_mem_ops vb2_vmalloc_memops = {
 	.put		= vb2_vmalloc_put,
 	.get_userptr	= vb2_vmalloc_get_userptr,
 	.put_userptr	= vb2_vmalloc_put_userptr,
+	.get_dmabuf	= vb2_vmalloc_get_dmabuf,
 	.map_dmabuf	= vb2_vmalloc_map_dmabuf,
 	.unmap_dmabuf	= vb2_vmalloc_unmap_dmabuf,
 	.attach_dmabuf	= vb2_vmalloc_attach_dmabuf,
-- 
2.1.1


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

* [RFCv6 PATCH 09/16] vivid: enable vb2_expbuf support.
  2014-11-10 12:49 [RFCv6 PATCH 00/16] vb2: improve dma-sg, expbuf Hans Verkuil
                   ` (7 preceding siblings ...)
  2014-11-10 12:49 ` [RFCv6 PATCH 08/16] vb2-vmalloc: " Hans Verkuil
@ 2014-11-10 12:49 ` Hans Verkuil
  2014-11-18  9:38   ` Pawel Osciak
  2014-11-10 12:49 ` [RFCv6 PATCH 10/16] vim2m: support expbuf Hans Verkuil
                   ` (6 subsequent siblings)
  15 siblings, 1 reply; 29+ messages in thread
From: Hans Verkuil @ 2014-11-10 12:49 UTC (permalink / raw)
  To: linux-media; +Cc: m.szyprowski, pawel, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Now that vb2 supports DMABUF export for dma-sg and vmalloc memory
modes, we can enable the vb2_expbuf support in vivid.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vivid/vivid-core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c
index 2c61a62..7de8d9d 100644
--- a/drivers/media/platform/vivid/vivid-core.c
+++ b/drivers/media/platform/vivid/vivid-core.c
@@ -588,7 +588,7 @@ static const struct v4l2_ioctl_ops vivid_ioctl_ops = {
 	.vidioc_querybuf		= vb2_ioctl_querybuf,
 	.vidioc_qbuf			= vb2_ioctl_qbuf,
 	.vidioc_dqbuf			= vb2_ioctl_dqbuf,
-/* Not yet	.vidioc_expbuf		= vb2_ioctl_expbuf,*/
+	.vidioc_expbuf			= vb2_ioctl_expbuf,
 	.vidioc_streamon		= vb2_ioctl_streamon,
 	.vidioc_streamoff		= vb2_ioctl_streamoff,
 
-- 
2.1.1


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

* [RFCv6 PATCH 10/16] vim2m: support expbuf
  2014-11-10 12:49 [RFCv6 PATCH 00/16] vb2: improve dma-sg, expbuf Hans Verkuil
                   ` (8 preceding siblings ...)
  2014-11-10 12:49 ` [RFCv6 PATCH 09/16] vivid: enable vb2_expbuf support Hans Verkuil
@ 2014-11-10 12:49 ` Hans Verkuil
  2014-11-18  9:40   ` Pawel Osciak
  2014-11-10 12:49 ` [RFCv6 PATCH 11/16] vb2: use dma_map_sg_attrs to prevent unnecessary sync Hans Verkuil
                   ` (5 subsequent siblings)
  15 siblings, 1 reply; 29+ messages in thread
From: Hans Verkuil @ 2014-11-10 12:49 UTC (permalink / raw)
  To: linux-media; +Cc: m.szyprowski, pawel, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/platform/vim2m.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c
index 87af47a..1105c11 100644
--- a/drivers/media/platform/vim2m.c
+++ b/drivers/media/platform/vim2m.c
@@ -697,6 +697,7 @@ static const struct v4l2_ioctl_ops vim2m_ioctl_ops = {
 	.vidioc_querybuf	= v4l2_m2m_ioctl_querybuf,
 	.vidioc_qbuf		= v4l2_m2m_ioctl_qbuf,
 	.vidioc_dqbuf		= v4l2_m2m_ioctl_dqbuf,
+	.vidioc_expbuf		= v4l2_m2m_ioctl_expbuf,
 
 	.vidioc_streamon	= v4l2_m2m_ioctl_streamon,
 	.vidioc_streamoff	= v4l2_m2m_ioctl_streamoff,
-- 
2.1.1


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

* [RFCv6 PATCH 11/16] vb2: use dma_map_sg_attrs to prevent unnecessary sync
  2014-11-10 12:49 [RFCv6 PATCH 00/16] vb2: improve dma-sg, expbuf Hans Verkuil
                   ` (9 preceding siblings ...)
  2014-11-10 12:49 ` [RFCv6 PATCH 10/16] vim2m: support expbuf Hans Verkuil
@ 2014-11-10 12:49 ` Hans Verkuil
  2014-11-18  9:55   ` Pawel Osciak
  2014-11-10 12:49 ` [RFCv6 PATCH 12/16] vb2: add begin/end_cpu_access functions Hans Verkuil
                   ` (4 subsequent siblings)
  15 siblings, 1 reply; 29+ messages in thread
From: Hans Verkuil @ 2014-11-10 12:49 UTC (permalink / raw)
  To: linux-media; +Cc: m.szyprowski, pawel, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

By default dma_map_sg syncs the mapped buffer to the device. But
buf_prepare expects a buffer syncs for the cpu and the buffer
will be synced to the device in the prepare memop.

The reverse is true for dma_unmap_sg, buf_finish and the finish
memop.

To prevent unnecessary syncs we ask dma_(un)map_sg to skip the
sync.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/v4l2-core/videobuf2-dma-contig.c | 29 +++++++++++++++++-----
 drivers/media/v4l2-core/videobuf2-dma-sg.c     | 33 +++++++++++++++++++++-----
 2 files changed, 50 insertions(+), 12 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index c4305bf..27f5926 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -317,8 +317,9 @@ static struct sg_table *vb2_dc_dmabuf_ops_map(
 		attach->dma_dir = DMA_NONE;
 	}
 
-	/* mapping to the client with new direction */
-	ret = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, dma_dir);
+	/* Mapping to the client with new direction */
+	ret = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
+			 dma_dir);
 	if (ret <= 0) {
 		pr_err("failed to map scatterlist\n");
 		mutex_unlock(lock);
@@ -511,7 +512,15 @@ static void vb2_dc_put_userptr(void *buf_priv)
 	struct sg_table *sgt = buf->dma_sgt;
 
 	if (sgt) {
-		dma_unmap_sg(buf->dev, sgt->sgl, sgt->orig_nents, buf->dma_dir);
+		DEFINE_DMA_ATTRS(attrs);
+
+		dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
+		/*
+		 * No need to sync to CPU, it's already synced to the CPU
+		 * since the finish() memop will have been called before this.
+		 */
+		dma_unmap_sg_attrs(buf->dev, sgt->sgl, sgt->orig_nents,
+				   buf->dma_dir, &attrs);
 		if (!vma_is_io(buf->vma))
 			vb2_dc_sgt_foreach_page(sgt, vb2_dc_put_dirty_page);
 
@@ -568,6 +577,9 @@ static void *vb2_dc_get_userptr(void *alloc_ctx, unsigned long vaddr,
 	struct sg_table *sgt;
 	unsigned long contig_size;
 	unsigned long dma_align = dma_get_cache_alignment();
+	DEFINE_DMA_ATTRS(attrs);
+
+	dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
 
 	/* Only cache aligned DMA transfers are reliable */
 	if (!IS_ALIGNED(vaddr | size, dma_align)) {
@@ -654,8 +666,12 @@ static void *vb2_dc_get_userptr(void *alloc_ctx, unsigned long vaddr,
 	kfree(pages);
 	pages = NULL;
 
-	sgt->nents = dma_map_sg(buf->dev, sgt->sgl, sgt->orig_nents,
-		buf->dma_dir);
+	/*
+	 * No need to sync to the device, this will happen later when the
+	 * prepare() memop is called.
+	 */
+	sgt->nents = dma_map_sg_attrs(buf->dev, sgt->sgl, sgt->orig_nents,
+				      buf->dma_dir, &attrs);
 	if (sgt->nents <= 0) {
 		pr_err("failed to map scatterlist\n");
 		ret = -EIO;
@@ -677,7 +693,8 @@ static void *vb2_dc_get_userptr(void *alloc_ctx, unsigned long vaddr,
 	return buf;
 
 fail_map_sg:
-	dma_unmap_sg(buf->dev, sgt->sgl, sgt->orig_nents, buf->dma_dir);
+	dma_unmap_sg_attrs(buf->dev, sgt->sgl, sgt->orig_nents,
+			   buf->dma_dir, &attrs);
 
 fail_sgt_init:
 	if (!vma_is_io(buf->vma))
diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index 0f7d293..a692c3e 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -107,6 +107,9 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size,
 	struct sg_table *sgt;
 	int ret;
 	int num_pages;
+	DEFINE_DMA_ATTRS(attrs);
+
+	dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
 
 	if (WARN_ON(alloc_ctx == NULL))
 		return NULL;
@@ -140,9 +143,13 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size,
 	buf->dev = get_device(conf->dev);
 
 	sgt = &buf->sg_table;
-	if (dma_map_sg(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir) == 0)
+	/*
+	 * No need to sync to the device, this will happen later when the
+	 * prepare() memop is called.
+	 */
+	if (dma_map_sg_attrs(buf->dev, sgt->sgl, sgt->nents,
+			     buf->dma_dir, &attrs) == 0)
 		goto fail_map;
-	dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
 
 	buf->handler.refcount = &buf->refcount;
 	buf->handler.put = vb2_dma_sg_put;
@@ -175,9 +182,13 @@ static void vb2_dma_sg_put(void *buf_priv)
 	int i = buf->num_pages;
 
 	if (atomic_dec_and_test(&buf->refcount)) {
+		DEFINE_DMA_ATTRS(attrs);
+
+		dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
 		dprintk(1, "%s: Freeing buffer of %d pages\n", __func__,
 			buf->num_pages);
-		dma_unmap_sg(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
+		dma_unmap_sg_attrs(buf->dev, sgt->sgl, sgt->nents,
+				   buf->dma_dir, &attrs);
 		if (buf->vaddr)
 			vm_unmap_ram(buf->vaddr, buf->num_pages);
 		sg_free_table(buf->dma_sgt);
@@ -228,6 +239,9 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
 	int num_pages_from_user;
 	struct vm_area_struct *vma;
 	struct sg_table *sgt;
+	DEFINE_DMA_ATTRS(attrs);
+
+	dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
 
 	buf = kzalloc(sizeof *buf, GFP_KERNEL);
 	if (!buf)
@@ -298,9 +312,13 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
 	buf->dev = get_device(conf->dev);
 
 	sgt = &buf->sg_table;
-	if (dma_map_sg(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir) == 0)
+	/*
+	 * No need to sync to the device, this will happen later when the
+	 * prepare() memop is called.
+	 */
+	if (dma_map_sg_attrs(buf->dev, sgt->sgl, sgt->nents,
+			     buf->dma_dir, &attrs) == 0)
 		goto userptr_fail_map;
-	dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
 	return buf;
 
 userptr_fail_map:
@@ -329,10 +347,13 @@ static void vb2_dma_sg_put_userptr(void *buf_priv)
 	struct vb2_dma_sg_buf *buf = buf_priv;
 	struct sg_table *sgt = &buf->sg_table;
 	int i = buf->num_pages;
+	DEFINE_DMA_ATTRS(attrs);
+
+	dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
 
 	dprintk(1, "%s: Releasing userspace buffer of %d pages\n",
 	       __func__, buf->num_pages);
-	dma_unmap_sg(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
+	dma_unmap_sg_attrs(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir, &attrs);
 	if (buf->vaddr)
 		vm_unmap_ram(buf->vaddr, buf->num_pages);
 	sg_free_table(buf->dma_sgt);
-- 
2.1.1


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

* [RFCv6 PATCH 12/16] vb2: add begin/end_cpu_access functions
  2014-11-10 12:49 [RFCv6 PATCH 00/16] vb2: improve dma-sg, expbuf Hans Verkuil
                   ` (10 preceding siblings ...)
  2014-11-10 12:49 ` [RFCv6 PATCH 11/16] vb2: use dma_map_sg_attrs to prevent unnecessary sync Hans Verkuil
@ 2014-11-10 12:49 ` Hans Verkuil
  2014-11-10 12:49 ` [RFCv6 PATCH 13/16] videobuf2-dvb.c: convert to vb2_plane_begin_cpu_access() Hans Verkuil
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 29+ messages in thread
From: Hans Verkuil @ 2014-11-10 12:49 UTC (permalink / raw)
  To: linux-media; +Cc: m.szyprowski, pawel, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

The existing vb2_plane_vaddr function is not enough when dealing with
dmabuf. For dmabuf you need to be explicit when the cpu needs access to
the buffer and when that can be stopped.

So add vb2_plane_begin/end_cpu_access as a vaddr replacement. The old
vb2_plane_vaddr function is kept around for a bit so drivers can be
converted in a separate patch.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/v4l2-core/videobuf2-core.c       | 65 ++++++++++++++++++-----
 drivers/media/v4l2-core/videobuf2-dma-contig.c | 56 ++++++++++++++++++++
 drivers/media/v4l2-core/videobuf2-dma-sg.c     | 73 +++++++++++++++++++++++++-
 drivers/media/v4l2-core/videobuf2-vmalloc.c    | 39 +++++++++++++-
 include/media/videobuf2-core.h                 | 16 ++++--
 5 files changed, 229 insertions(+), 20 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index 7aed8f2..036b947 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -501,6 +501,7 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
 				  vb->cnt_mem_get_userptr != vb->cnt_mem_put_userptr ||
 				  vb->cnt_mem_attach_dmabuf != vb->cnt_mem_detach_dmabuf ||
 				  vb->cnt_mem_map_dmabuf != vb->cnt_mem_unmap_dmabuf ||
+				  vb->cnt_mem_begin_cpu_access != vb->cnt_mem_end_cpu_access ||
 				  vb->cnt_buf_queue != vb->cnt_buf_done ||
 				  vb->cnt_buf_prepare != vb->cnt_buf_finish ||
 				  vb->cnt_buf_init != vb->cnt_buf_cleanup;
@@ -522,10 +523,11 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
 			pr_info("vb2:     attach_dmabuf: %u detach_dmabuf: %u map_dmabuf: %u unmap_dmabuf: %u\n",
 				vb->cnt_mem_attach_dmabuf, vb->cnt_mem_detach_dmabuf,
 				vb->cnt_mem_map_dmabuf, vb->cnt_mem_unmap_dmabuf);
-			pr_info("vb2:     get_dmabuf: %u num_users: %u vaddr: %u cookie: %u\n",
+			pr_info("vb2:     begin_cpu_access: %u end_cpu_access: %u\n",
+				vb->cnt_mem_begin_cpu_access, vb->cnt_mem_end_cpu_access);
+			pr_info("vb2:     get_dmabuf: %u num_users: %u cookie: %u\n",
 				vb->cnt_mem_get_dmabuf,
 				vb->cnt_mem_num_users,
-				vb->cnt_mem_vaddr,
 				vb->cnt_mem_cookie);
 		}
 	}
@@ -791,7 +793,8 @@ 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)
+	    !q->mem_ops->unmap_dmabuf || !q->mem_ops->begin_cpu_access ||
+	    !q->mem_ops->end_cpu_access)
 		return -EINVAL;
 
 	return 0;
@@ -1113,24 +1116,48 @@ int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
 EXPORT_SYMBOL_GPL(vb2_create_bufs);
 
 /**
- * vb2_plane_vaddr() - Return a kernel virtual address of a given plane
+ * vb2_plane_begin_cpu_access() - Return a kernel virtual address of a given plane
  * @vb:		vb2_buffer to which the plane in question belongs to
  * @plane_no:	plane number for which the address is to be returned
  *
- * This function returns a kernel virtual address of a given plane if
- * such a mapping exist, NULL otherwise.
+ * This function returns a kernel virtual address of a given plane synced for
+ * cpu access if such a mapping exist, NULL otherwise.
  */
-void *vb2_plane_vaddr(struct vb2_buffer *vb, unsigned int plane_no)
+void *vb2_plane_begin_cpu_access(struct vb2_buffer *vb, unsigned int plane_no)
 {
 	if (plane_no > vb->num_planes || !vb->planes[plane_no].mem_priv)
 		return NULL;
 
-	return call_ptr_memop(vb, vaddr, vb->planes[plane_no].mem_priv);
+	return call_ptr_memop(vb, begin_cpu_access, vb->planes[plane_no].mem_priv);
+}
+EXPORT_SYMBOL_GPL(vb2_plane_begin_cpu_access);
 
+/* Keep this for backwards compatibility. Will be removed soon. */
+void *vb2_plane_vaddr(struct vb2_buffer *vb, unsigned int plane_no)
+{
+	return vb2_plane_begin_cpu_access(vb, plane_no);
 }
 EXPORT_SYMBOL_GPL(vb2_plane_vaddr);
 
 /**
+ * vb2_plane_end_cpu_access() - Return a kernel virtual address of a given plane
+ * @vb:		vb2_buffer to which the plane in question belongs to
+ * @plane_no:	plane number for which the address is to be returned
+ *
+ * This function ends the cpu access of the mapping earlier returned by
+ * @vb2_plane_begin_cpu_access.
+ */
+void vb2_plane_end_cpu_access(struct vb2_buffer *vb, unsigned int plane_no)
+{
+	if (plane_no > vb->num_planes || !vb->planes[plane_no].mem_priv)
+		return;
+
+	call_void_memop(vb, end_cpu_access, vb->planes[plane_no].mem_priv);
+
+}
+EXPORT_SYMBOL_GPL(vb2_plane_end_cpu_access);
+
+/**
  * vb2_plane_cookie() - Return allocator specific cookie for the given plane
  * @vb:		vb2_buffer to which the plane in question belongs to
  * @plane_no:	plane number for which the cookie is to be returned
@@ -1558,7 +1585,8 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 		}
 	}
 
-	ret = call_vb_qop(vb, buf_prepare, vb);
+	if (!ret)
+		ret = call_vb_qop(vb, buf_prepare, vb);
 	if (ret) {
 		dprintk(1, "buffer preparation failed\n");
 		call_void_vb_qop(vb, buf_cleanup, vb);
@@ -2537,8 +2565,16 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
 
 	vb = q->bufs[buffer];
 
-	vaddr = vb2_plane_vaddr(vb, plane);
-	return vaddr ? (unsigned long)vaddr : -EINVAL;
+	/*
+	 * vb2_get_unmapped_area is used only with V4L2_MEMORY_MMAP. For
+	 * that memory model the vb2_plane_end_cpu_access() call is always
+	 * a NOP. The only reason it is called here is to keep the begin/end
+	 * calls balanced.
+	 */
+	vaddr = vb2_plane_begin_cpu_access(vb, plane);
+	if (vaddr)
+		vb2_plane_end_cpu_access(vb, plane);
+	return vaddr ? (unsigned long)vaddr : -ENOMEM;
 }
 EXPORT_SYMBOL_GPL(vb2_get_unmapped_area);
 #endif
@@ -2784,7 +2820,7 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
 	/*
 	 * Check if device supports mapping buffers to kernel virtual space.
 	 */
-	if (!q->mem_ops->vaddr)
+	if (!q->mem_ops->begin_cpu_access)
 		return -EBUSY;
 
 	/*
@@ -2832,7 +2868,7 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
 	 * Get kernel address of each buffer.
 	 */
 	for (i = 0; i < q->num_buffers; i++) {
-		fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
+		fileio->bufs[i].vaddr = vb2_plane_begin_cpu_access(q->bufs[i], 0);
 		if (fileio->bufs[i].vaddr == NULL) {
 			ret = -EINVAL;
 			goto err_reqbufs;
@@ -2900,9 +2936,12 @@ err_kfree:
 static int __vb2_cleanup_fileio(struct vb2_queue *q)
 {
 	struct vb2_fileio_data *fileio = q->fileio;
+	int i;
 
 	if (fileio) {
 		vb2_internal_streamoff(q, q->type);
+		for (i = 0; i < q->num_buffers; i++)
+			vb2_plane_end_cpu_access(q->bufs[i], 0);
 		q->fileio = NULL;
 		fileio->req.count = 0;
 		vb2_reqbufs(q, &fileio->req);
diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index 27f5926..58a4bf2 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -348,17 +348,37 @@ static void vb2_dc_dmabuf_ops_release(struct dma_buf *dbuf)
 static void *vb2_dc_dmabuf_ops_kmap(struct dma_buf *dbuf, unsigned long pgnum)
 {
 	struct vb2_dc_buf *buf = dbuf->priv;
+	struct sg_table *sgt = buf->sgt_base;
 
+	dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
 	return buf->vaddr + pgnum * PAGE_SIZE;
 }
 
 static void *vb2_dc_dmabuf_ops_vmap(struct dma_buf *dbuf)
 {
 	struct vb2_dc_buf *buf = dbuf->priv;
+	struct sg_table *sgt = buf->sgt_base;
 
+	dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
 	return buf->vaddr;
 }
 
+static void vb2_dc_dmabuf_ops_kunmap(struct dma_buf *dbuf, unsigned long pgnum, void *vaddr)
+{
+	struct vb2_dc_buf *buf = dbuf->priv;
+	struct sg_table *sgt = buf->sgt_base;
+
+	dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
+}
+
+static void vb2_dc_dmabuf_ops_vunmap(struct dma_buf *dbuf, void *vaddr)
+{
+	struct vb2_dc_buf *buf = dbuf->priv;
+	struct sg_table *sgt = buf->sgt_base;
+
+	dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
+}
+
 static int vb2_dc_dmabuf_ops_mmap(struct dma_buf *dbuf,
 	struct vm_area_struct *vma)
 {
@@ -372,7 +392,10 @@ static struct dma_buf_ops vb2_dc_dmabuf_ops = {
 	.unmap_dma_buf = vb2_dc_dmabuf_ops_unmap,
 	.kmap = vb2_dc_dmabuf_ops_kmap,
 	.kmap_atomic = vb2_dc_dmabuf_ops_kmap,
+	.kunmap = vb2_dc_dmabuf_ops_kunmap,
+	.kunmap_atomic = vb2_dc_dmabuf_ops_kunmap,
 	.vmap = vb2_dc_dmabuf_ops_vmap,
+	.vunmap = vb2_dc_dmabuf_ops_vunmap,
 	.mmap = vb2_dc_dmabuf_ops_mmap,
 	.release = vb2_dc_dmabuf_ops_release,
 };
@@ -832,6 +855,37 @@ static void *vb2_dc_attach_dmabuf(void *alloc_ctx, struct dma_buf *dbuf,
 	return buf;
 }
 
+static void *vb2_dc_begin_cpu_access(void *mem_priv)
+{
+	struct vb2_dc_buf *buf = mem_priv;
+	int ret;
+
+	if (buf->db_attach) {
+		ret = dma_buf_begin_cpu_access(buf->db_attach->dmabuf,
+				0, buf->size, buf->dma_dir);
+		if (ret)
+			return NULL;
+		buf->vaddr = dma_buf_vmap(buf->db_attach->dmabuf);
+		if (buf->vaddr == NULL)
+			dma_buf_end_cpu_access(buf->db_attach->dmabuf,
+					0, buf->size, buf->dma_dir);
+	}
+
+	return buf->vaddr;
+}
+
+static void vb2_dc_end_cpu_access(void *mem_priv)
+{
+	struct vb2_dc_buf *buf = mem_priv;
+
+	if (!buf->db_attach)
+		return;
+	dma_buf_vunmap(buf->db_attach->dmabuf, buf->vaddr);
+	buf->vaddr = NULL;
+	dma_buf_end_cpu_access(buf->db_attach->dmabuf,
+			0, buf->size, buf->dma_dir);
+}
+
 /*********************************************/
 /*       DMA CONTIG exported functions       */
 /*********************************************/
@@ -851,6 +905,8 @@ const struct vb2_mem_ops vb2_dma_contig_memops = {
 	.unmap_dmabuf	= vb2_dc_unmap_dmabuf,
 	.attach_dmabuf	= vb2_dc_attach_dmabuf,
 	.detach_dmabuf	= vb2_dc_detach_dmabuf,
+	.begin_cpu_access = vb2_dc_begin_cpu_access,
+	.end_cpu_access = vb2_dc_end_cpu_access,
 	.num_users	= vb2_dc_num_users,
 };
 EXPORT_SYMBOL_GPL(vb2_dma_contig_memops);
diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index a692c3e..0148bd8 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -550,18 +550,51 @@ static void vb2_dma_sg_dmabuf_ops_release(struct dma_buf *dbuf)
 	vb2_dma_sg_put(dbuf->priv);
 }
 
+static int vb2_dma_sg_dmabuf_begin_cpu_access(struct dma_buf *dbuf,
+		size_t start, size_t len, enum dma_data_direction dma_dir)
+{
+	struct vb2_dma_sg_buf *buf = dbuf->priv;
+
+	vb2_dma_sg_vaddr(buf);
+	return 0;
+}
+
 static void *vb2_dma_sg_dmabuf_ops_kmap(struct dma_buf *dbuf, unsigned long pgnum)
 {
 	struct vb2_dma_sg_buf *buf = dbuf->priv;
+	struct sg_table *sgt = buf->dma_sgt;
 
-	return buf->vaddr ? buf->vaddr + pgnum * PAGE_SIZE : NULL;
+	if (WARN_ON(!buf->vaddr))
+		return NULL;
+	dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
+	return buf->vaddr + pgnum * PAGE_SIZE;
 }
 
 static void *vb2_dma_sg_dmabuf_ops_vmap(struct dma_buf *dbuf)
 {
 	struct vb2_dma_sg_buf *buf = dbuf->priv;
+	struct sg_table *sgt = buf->dma_sgt;
 
-	return vb2_dma_sg_vaddr(buf);
+	if (WARN_ON(!buf->vaddr))
+		return NULL;
+	dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
+	return buf->vaddr;
+}
+
+static void vb2_dma_sg_dmabuf_ops_kunmap(struct dma_buf *dbuf, unsigned long pgnum, void *vaddr)
+{
+	struct vb2_dma_sg_buf *buf = dbuf->priv;
+	struct sg_table *sgt = buf->dma_sgt;
+
+	dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
+}
+
+static void vb2_dma_sg_dmabuf_ops_vunmap(struct dma_buf *dbuf, void *vaddr)
+{
+	struct vb2_dma_sg_buf *buf = dbuf->priv;
+	struct sg_table *sgt = buf->dma_sgt;
+
+	dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
 }
 
 static int vb2_dma_sg_dmabuf_ops_mmap(struct dma_buf *dbuf,
@@ -575,9 +608,13 @@ static struct dma_buf_ops vb2_dma_sg_dmabuf_ops = {
 	.detach = vb2_dma_sg_dmabuf_ops_detach,
 	.map_dma_buf = vb2_dma_sg_dmabuf_ops_map,
 	.unmap_dma_buf = vb2_dma_sg_dmabuf_ops_unmap,
+	.begin_cpu_access = vb2_dma_sg_dmabuf_begin_cpu_access,
 	.kmap = vb2_dma_sg_dmabuf_ops_kmap,
 	.kmap_atomic = vb2_dma_sg_dmabuf_ops_kmap,
+	.kunmap = vb2_dma_sg_dmabuf_ops_kunmap,
+	.kunmap_atomic = vb2_dma_sg_dmabuf_ops_kunmap,
 	.vmap = vb2_dma_sg_dmabuf_ops_vmap,
+	.vunmap = vb2_dma_sg_dmabuf_ops_vunmap,
 	.mmap = vb2_dma_sg_dmabuf_ops_mmap,
 	.release = vb2_dma_sg_dmabuf_ops_release,
 };
@@ -699,6 +736,36 @@ static void *vb2_dma_sg_attach_dmabuf(void *alloc_ctx, struct dma_buf *dbuf,
 	return buf;
 }
 
+static void *vb2_dma_sg_begin_cpu_access(void *mem_priv)
+{
+	struct vb2_dma_sg_buf *buf = mem_priv;
+	int ret;
+
+	if (!buf->db_attach)
+		return vb2_dma_sg_vaddr(buf);
+
+	ret = dma_buf_begin_cpu_access(buf->db_attach->dmabuf,
+			0, buf->size, buf->dma_dir);
+	if (ret)
+		return NULL;
+	buf->vaddr = dma_buf_vmap(buf->db_attach->dmabuf);
+	if (buf->vaddr == NULL)
+		dma_buf_end_cpu_access(buf->db_attach->dmabuf,
+				0, buf->size, buf->dma_dir);
+	return buf->vaddr;
+}
+
+static void vb2_dma_sg_end_cpu_access(void *mem_priv)
+{
+	struct vb2_dma_sg_buf *buf = mem_priv;
+
+	if (!buf->db_attach)
+		return;
+	dma_buf_vunmap(buf->db_attach->dmabuf, buf->vaddr);
+	dma_buf_end_cpu_access(buf->db_attach->dmabuf,
+			0, buf->size, buf->dma_dir);
+}
+
 static void *vb2_dma_sg_cookie(void *buf_priv)
 {
 	struct vb2_dma_sg_buf *buf = buf_priv;
@@ -721,6 +788,8 @@ const struct vb2_mem_ops vb2_dma_sg_memops = {
 	.unmap_dmabuf	= vb2_dma_sg_unmap_dmabuf,
 	.attach_dmabuf	= vb2_dma_sg_attach_dmabuf,
 	.detach_dmabuf	= vb2_dma_sg_detach_dmabuf,
+	.begin_cpu_access = vb2_dma_sg_begin_cpu_access,
+	.end_cpu_access = vb2_dma_sg_end_cpu_access,
 	.cookie		= vb2_dma_sg_cookie,
 };
 EXPORT_SYMBOL_GPL(vb2_dma_sg_memops);
diff --git a/drivers/media/v4l2-core/videobuf2-vmalloc.c b/drivers/media/v4l2-core/videobuf2-vmalloc.c
index dfbb6d5..875a1b0 100644
--- a/drivers/media/v4l2-core/videobuf2-vmalloc.c
+++ b/drivers/media/v4l2-core/videobuf2-vmalloc.c
@@ -338,15 +338,16 @@ static void vb2_vmalloc_dmabuf_ops_release(struct dma_buf *dbuf)
 static void *vb2_vmalloc_dmabuf_ops_kmap(struct dma_buf *dbuf, unsigned long pgnum)
 {
 	struct vb2_vmalloc_buf *buf = dbuf->priv;
+	void *vaddr = vb2_vmalloc_vaddr(buf);
 
-	return buf->vaddr + pgnum * PAGE_SIZE;
+	return vaddr ? vaddr + pgnum * PAGE_SIZE : NULL;
 }
 
 static void *vb2_vmalloc_dmabuf_ops_vmap(struct dma_buf *dbuf)
 {
 	struct vb2_vmalloc_buf *buf = dbuf->priv;
 
-	return buf->vaddr;
+	return vb2_vmalloc_vaddr(buf);
 }
 
 static int vb2_vmalloc_dmabuf_ops_mmap(struct dma_buf *dbuf,
@@ -435,6 +436,38 @@ static void *vb2_vmalloc_attach_dmabuf(void *alloc_ctx, struct dma_buf *dbuf,
 	return buf;
 }
 
+static void *vb2_vmalloc_begin_cpu_access(void *mem_priv)
+{
+	struct vb2_vmalloc_buf *buf = mem_priv;
+	int ret;
+
+	if (!buf->db_attach)
+		return vb2_vmalloc_vaddr(buf);
+
+	ret = dma_buf_begin_cpu_access(buf->db_attach->dmabuf,
+			0, buf->size, buf->dma_dir);
+	if (ret)
+		return NULL;
+	buf->vaddr = dma_buf_vmap(buf->db_attach->dmabuf);
+	if (buf->vaddr == NULL)
+		dma_buf_end_cpu_access(buf->db_attach->dmabuf,
+				0, buf->size, buf->dma_dir);
+
+	return buf->vaddr;
+}
+
+static void vb2_vmalloc_end_cpu_access(void *mem_priv)
+{
+	struct vb2_vmalloc_buf *buf = mem_priv;
+
+	if (!buf->db_attach)
+		return;
+	dma_buf_vunmap(buf->db_attach->dmabuf, buf->vaddr);
+	buf->vaddr = NULL;
+	dma_buf_end_cpu_access(buf->db_attach->dmabuf,
+			0, buf->size, buf->dma_dir);
+}
+
 
 const struct vb2_mem_ops vb2_vmalloc_memops = {
 	.alloc		= vb2_vmalloc_alloc,
@@ -447,6 +480,8 @@ const struct vb2_mem_ops vb2_vmalloc_memops = {
 	.attach_dmabuf	= vb2_vmalloc_attach_dmabuf,
 	.detach_dmabuf	= vb2_vmalloc_detach_dmabuf,
 	.vaddr		= vb2_vmalloc_vaddr,
+	.begin_cpu_access = vb2_vmalloc_begin_cpu_access,
+	.end_cpu_access = vb2_vmalloc_end_cpu_access,
 	.mmap		= vb2_vmalloc_mmap,
 	.num_users	= vb2_vmalloc_num_users,
 };
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index bd2cec2..a22d17e 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -64,8 +64,11 @@ struct vb2_threadio_data;
  * @finish:	called every time the buffer is passed back from the driver
  *		to the userspace, also optional.
  * @vaddr:	return a kernel virtual address to a given memory buffer
+ * @begin_cpu_access: return a kernel virtual address to a given memory buffer
  *		associated with the passed private structure or NULL if no
- *		such mapping exists.
+ *		such mapping exists. This memory buffer can be written by the
+ *		cpu.
+ * @end_cpu_access: call this when you are done writing to the memory buffer.
  * @cookie:	return allocator specific cookie for a given memory buffer
  *		associated with the passed private structure or NULL if not
  *		available.
@@ -77,9 +80,10 @@ struct vb2_threadio_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 read/write access types: alloc, put, num_users, vaddr,
+ *			begin_cpu_access, end_cpu_access.
  * Required ops for DMABUF types: attach_dmabuf, detach_dmabuf, map_dmabuf,
- *				  unmap_dmabuf.
+ *			unmap_dmabuf, begin_cpu_access, end_cpu_access.
  */
 struct vb2_mem_ops {
 	void		*(*alloc)(void *alloc_ctx, unsigned long size,
@@ -102,6 +106,8 @@ struct vb2_mem_ops {
 	void		(*detach_dmabuf)(void *buf_priv);
 	int		(*map_dmabuf)(void *buf_priv);
 	void		(*unmap_dmabuf)(void *buf_priv);
+	void		*(*begin_cpu_access)(void *buf_priv);
+	void		(*end_cpu_access)(void *buf_priv);
 
 	void		*(*vaddr)(void *buf_priv);
 	void		*(*cookie)(void *buf_priv);
@@ -226,6 +232,8 @@ struct vb2_buffer {
 	u32		cnt_mem_map_dmabuf;
 	u32		cnt_mem_unmap_dmabuf;
 	u32		cnt_mem_vaddr;
+	u32		cnt_mem_begin_cpu_access;
+	u32		cnt_mem_end_cpu_access;
 	u32		cnt_mem_cookie;
 	u32		cnt_mem_num_users;
 	u32		cnt_mem_mmap;
@@ -447,6 +455,8 @@ struct vb2_queue {
 };
 
 void *vb2_plane_vaddr(struct vb2_buffer *vb, unsigned int plane_no);
+void *vb2_plane_begin_cpu_access(struct vb2_buffer *vb, unsigned int plane_no);
+void vb2_plane_end_cpu_access(struct vb2_buffer *vb, unsigned int plane_no);
 void *vb2_plane_cookie(struct vb2_buffer *vb, unsigned int plane_no);
 
 void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state);
-- 
2.1.1


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

* [RFCv6 PATCH 13/16] videobuf2-dvb.c: convert to vb2_plane_begin_cpu_access()
  2014-11-10 12:49 [RFCv6 PATCH 00/16] vb2: improve dma-sg, expbuf Hans Verkuil
                   ` (11 preceding siblings ...)
  2014-11-10 12:49 ` [RFCv6 PATCH 12/16] vb2: add begin/end_cpu_access functions Hans Verkuil
@ 2014-11-10 12:49 ` Hans Verkuil
  2014-11-10 12:49 ` [RFCv6 PATCH 14/16] v4l: convert vb2_plane_vaddr to vb2_plane_begin_cpu_access Hans Verkuil
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 29+ messages in thread
From: Hans Verkuil @ 2014-11-10 12:49 UTC (permalink / raw)
  To: linux-media; +Cc: m.szyprowski, pawel, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/v4l2-core/videobuf2-dvb.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-dvb.c b/drivers/media/v4l2-core/videobuf2-dvb.c
index d092698..d954bb8 100644
--- a/drivers/media/v4l2-core/videobuf2-dvb.c
+++ b/drivers/media/v4l2-core/videobuf2-dvb.c
@@ -30,9 +30,12 @@ MODULE_LICENSE("GPL");
 static int dvb_fnc(struct vb2_buffer *vb, void *priv)
 {
 	struct vb2_dvb *dvb = priv;
+	void *p = vb2_plane_begin_cpu_access(vb, 0);
 
-	dvb_dmx_swfilter(&dvb->demux, vb2_plane_vaddr(vb, 0),
-				      vb2_get_plane_payload(vb, 0));
+	if (p == NULL)
+		return -ENOMEM;
+	dvb_dmx_swfilter(&dvb->demux, p, vb2_get_plane_payload(vb, 0));
+	vb2_plane_end_cpu_access(vb, 0);
 	return 0;
 }
 
-- 
2.1.1


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

* [RFCv6 PATCH 14/16] v4l: convert vb2_plane_vaddr to vb2_plane_begin_cpu_access
  2014-11-10 12:49 [RFCv6 PATCH 00/16] vb2: improve dma-sg, expbuf Hans Verkuil
                   ` (12 preceding siblings ...)
  2014-11-10 12:49 ` [RFCv6 PATCH 13/16] videobuf2-dvb.c: convert to vb2_plane_begin_cpu_access() Hans Verkuil
@ 2014-11-10 12:49 ` Hans Verkuil
  2014-11-10 12:49 ` [RFCv6 PATCH 15/16] vb2: drop the unused vb2_plane_vaddr function Hans Verkuil
  2014-11-10 12:49 ` [RFCv6 PATCH 16/16] vb2: update the buf_prepare/finish documentation Hans Verkuil
  15 siblings, 0 replies; 29+ messages in thread
From: Hans Verkuil @ 2014-11-10 12:49 UTC (permalink / raw)
  To: linux-media; +Cc: m.szyprowski, pawel, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/dvb-frontends/rtl2832_sdr.c          | 16 ++++++--
 drivers/media/parport/bw-qcam.c                    |  5 ++-
 drivers/media/pci/solo6x10/solo6x10-v4l2.c         |  6 ++-
 drivers/media/platform/marvell-ccic/mcam-core.c    | 26 ++++++++++++-
 drivers/media/platform/s5p-jpeg/jpeg-core.c        | 17 +++++---
 drivers/media/platform/soc_camera/mx2_camera.c     | 24 +++++++-----
 drivers/media/platform/soc_camera/mx3_camera.c     | 10 ++++-
 drivers/media/platform/soc_camera/rcar_vin.c       |  4 +-
 .../platform/soc_camera/sh_mobile_ceu_camera.c     | 14 +++++--
 drivers/media/platform/vim2m.c                     | 22 ++++++++---
 drivers/media/platform/vivid/vivid-kthread-cap.c   | 13 +++++--
 drivers/media/platform/vivid/vivid-sdr-cap.c       |  3 +-
 drivers/media/platform/vivid/vivid-vbi-cap.c       |  6 ++-
 drivers/media/platform/vivid/vivid-vbi-out.c       |  3 +-
 drivers/media/usb/airspy/airspy.c                  | 21 ++++++++--
 drivers/media/usb/em28xx/em28xx-vbi.c              | 13 +++++--
 drivers/media/usb/em28xx/em28xx-video.c            | 12 ++++--
 drivers/media/usb/go7007/go7007-driver.c           |  7 +---
 drivers/media/usb/go7007/go7007-priv.h             |  1 +
 drivers/media/usb/go7007/go7007-v4l2.c             |  6 ++-
 drivers/media/usb/hackrf/hackrf.c                  | 21 ++++++++--
 drivers/media/usb/msi2500/msi2500.c                | 22 +++++++++--
 drivers/media/usb/pwc/pwc-if.c                     |  5 ++-
 drivers/media/usb/pwc/pwc-uncompress.c             |  2 +-
 drivers/media/usb/pwc/pwc.h                        |  1 +
 drivers/media/usb/s2255/s2255drv.c                 | 12 +++++-
 drivers/media/usb/stk1160/stk1160-v4l.c            | 45 ++++++++++++++--------
 drivers/media/usb/stk1160/stk1160-video.c          |  1 +
 drivers/media/usb/usbtv/usbtv-video.c              | 19 +++++++--
 drivers/media/usb/usbtv/usbtv.h                    |  1 +
 drivers/media/usb/uvc/uvc_queue.c                  |  5 ++-
 drivers/staging/media/davinci_vpfe/vpfe_video.c    |  5 +--
 drivers/usb/gadget/function/uvc_queue.c            | 10 ++++-
 33 files changed, 280 insertions(+), 98 deletions(-)

diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c b/drivers/media/dvb-frontends/rtl2832_sdr.c
index 7bf98cf..9e1fafd 100644
--- a/drivers/media/dvb-frontends/rtl2832_sdr.c
+++ b/drivers/media/dvb-frontends/rtl2832_sdr.c
@@ -105,6 +105,7 @@ static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats);
 struct rtl2832_sdr_frame_buf {
 	struct vb2_buffer vb;   /* common v4l buffer stuff -- must be first */
 	struct list_head list;
+	void *vaddr;
 };
 
 struct rtl2832_sdr_state {
@@ -415,7 +416,6 @@ static void rtl2832_sdr_urb_complete(struct urb *urb)
 	}
 
 	if (likely(urb->actual_length > 0)) {
-		void *ptr;
 		unsigned int len;
 		/* get free framebuffer */
 		fbuf = rtl2832_sdr_get_next_fill_buf(s);
@@ -428,8 +428,7 @@ static void rtl2832_sdr_urb_complete(struct urb *urb)
 		}
 
 		/* fill framebuffer */
-		ptr = vb2_plane_vaddr(&fbuf->vb, 0);
-		len = rtl2832_sdr_convert_stream(s, ptr, urb->transfer_buffer,
+		len = rtl2832_sdr_convert_stream(s, fbuf->vaddr, urb->transfer_buffer,
 				urb->actual_length);
 		vb2_set_plane_payload(&fbuf->vb, 0, len);
 		v4l2_get_timestamp(&fbuf->vb.v4l2_buf.timestamp);
@@ -644,12 +643,20 @@ static int rtl2832_sdr_queue_setup(struct vb2_queue *vq,
 static int rtl2832_sdr_buf_prepare(struct vb2_buffer *vb)
 {
 	struct rtl2832_sdr_state *s = vb2_get_drv_priv(vb->vb2_queue);
+	struct rtl2832_sdr_frame_buf *buf =
+			container_of(vb, struct rtl2832_sdr_frame_buf, vb);
 
 	/* Don't allow queing new buffers after device disconnection */
 	if (!s->udev)
 		return -ENODEV;
 
-	return 0;
+	buf->vaddr = vb2_plane_begin_cpu_access(vb, 0);
+	return buf->vaddr ? 0 : -ENOMEM;
+}
+
+static void rtl2832_sdr_buf_finish(struct vb2_buffer *vb)
+{
+	vb2_plane_end_cpu_access(vb, 0);
 }
 
 static void rtl2832_sdr_buf_queue(struct vb2_buffer *vb)
@@ -1073,6 +1080,7 @@ static void rtl2832_sdr_stop_streaming(struct vb2_queue *vq)
 static struct vb2_ops rtl2832_sdr_vb2_ops = {
 	.queue_setup            = rtl2832_sdr_queue_setup,
 	.buf_prepare            = rtl2832_sdr_buf_prepare,
+	.buf_finish             = rtl2832_sdr_buf_finish,
 	.buf_queue              = rtl2832_sdr_buf_queue,
 	.start_streaming        = rtl2832_sdr_start_streaming,
 	.stop_streaming         = rtl2832_sdr_stop_streaming,
diff --git a/drivers/media/parport/bw-qcam.c b/drivers/media/parport/bw-qcam.c
index 67b9da1..7d4fa3a 100644
--- a/drivers/media/parport/bw-qcam.c
+++ b/drivers/media/parport/bw-qcam.c
@@ -670,11 +670,11 @@ static void buffer_queue(struct vb2_buffer *vb)
 static void buffer_finish(struct vb2_buffer *vb)
 {
 	struct qcam *qcam = vb2_get_drv_priv(vb->vb2_queue);
-	void *vbuf = vb2_plane_vaddr(vb, 0);
+	void *vbuf = vb2_plane_begin_cpu_access(vb, 0);
 	int size = vb->vb2_queue->plane_sizes[0];
 	int len;
 
-	if (!vb2_is_streaming(vb->vb2_queue))
+	if (vbuf == NULL || !vb2_is_streaming(vb->vb2_queue))
 		return;
 
 	mutex_lock(&qcam->lock);
@@ -694,6 +694,7 @@ static void buffer_finish(struct vb2_buffer *vb)
 	if (len != size)
 		vb->state = VB2_BUF_STATE_ERROR;
 	vb2_set_plane_payload(vb, 0, len);
+	vb2_plane_end_cpu_access(vb, 0);
 }
 
 static struct vb2_ops qcam_video_qops = {
diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2.c b/drivers/media/pci/solo6x10/solo6x10-v4l2.c
index 63ae8a6..0c5e159 100644
--- a/drivers/media/pci/solo6x10/solo6x10-v4l2.c
+++ b/drivers/media/pci/solo6x10/solo6x10-v4l2.c
@@ -201,13 +201,17 @@ static void solo_fillbuf(struct solo_dev *solo_dev,
 		goto finish_buf;
 
 	if (erase_off(solo_dev)) {
-		void *p = vb2_plane_vaddr(vb, 0);
+		void *p = vb2_plane_begin_cpu_access(vb, 0);
 		int image_size = solo_image_size(solo_dev);
 
+		if (p == NULL)
+			goto finish_buf;
+
 		for (i = 0; i < image_size; i += 2) {
 			((u8 *)p)[i] = 0x80;
 			((u8 *)p)[i + 1] = 0x00;
 		}
+		vb2_plane_end_cpu_access(vb, 0);
 		error = 0;
 	} else {
 		fdma_addr = SOLO_DISP_EXT_ADDR + (solo_dev->old_write *
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
index daaff51..a491ee3 100644
--- a/drivers/media/platform/marvell-ccic/mcam-core.c
+++ b/drivers/media/platform/marvell-ccic/mcam-core.c
@@ -223,6 +223,9 @@ struct mcam_vb_buffer {
 	dma_addr_t dma_desc_pa;		/* Descriptor physical address */
 	int dma_desc_nent;		/* Number of mapped descriptors */
 	struct yuv_pointer_t yuv_p;
+#ifdef MCAM_MODE_VMALLOC
+	void *vaddr;
+#endif
 };
 
 static inline struct mcam_vb_buffer *vb_to_mvb(struct vb2_buffer *vb)
@@ -457,7 +460,7 @@ static void mcam_frame_tasklet(unsigned long data)
 		 * Drop the lock during the big copy.  This *should* be safe...
 		 */
 		spin_unlock_irqrestore(&cam->dev_lock, flags);
-		memcpy(vb2_plane_vaddr(&buf->vb_buf, 0), cam->dma_bufs[bufno],
+		memcpy(buf->vaddr, cam->dma_bufs[bufno],
 				cam->pix_format.sizeimage);
 		mcam_buffer_done(cam, bufno, &buf->vb_buf);
 		spin_lock_irqsave(&cam->dev_lock, flags);
@@ -1103,6 +1106,25 @@ static void mcam_vb_buf_queue(struct vb2_buffer *vb)
 		mcam_read_setup(cam);
 }
 
+static int mcam_vb_buf_prepare(struct vb2_buffer *vb)
+{
+#ifdef MCAM_MODE_VMALLOC
+	struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
+
+	mvb->vaddr = vb2_plane_begin_cpu_access(vb, 0);
+	return mvb->vaddr ? 0 : -ENOMEM;
+#else
+	return 0;
+#endif
+}
+
+static void mcam_vb_buf_finish(struct vb2_buffer *vb)
+{
+#ifdef MCAM_MODE_VMALLOC
+	vb2_plane_end_cpu_access(vb, 0);
+#endif
+}
+
 
 /*
  * vb2 uses these to release the mutex when waiting in dqbuf.  I'm
@@ -1190,6 +1212,8 @@ static void mcam_vb_stop_streaming(struct vb2_queue *vq)
 static const struct vb2_ops mcam_vb2_ops = {
 	.queue_setup		= mcam_vb_queue_setup,
 	.buf_queue		= mcam_vb_buf_queue,
+	.buf_prepare		= mcam_vb_buf_prepare,
+	.buf_finish		= mcam_vb_buf_finish,
 	.start_streaming	= mcam_vb_start_streaming,
 	.stop_streaming		= mcam_vb_stop_streaming,
 	.wait_prepare		= mcam_vb_wait_prepare,
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c
index 6fcc7f0..dae4e32 100644
--- a/drivers/media/platform/s5p-jpeg/jpeg-core.c
+++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c
@@ -2165,11 +2165,18 @@ static void s5p_jpeg_buf_queue(struct vb2_buffer *vb)
 	if (ctx->mode == S5P_JPEG_DECODE &&
 	    vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
 		struct s5p_jpeg_q_data tmp, *q_data;
-		ctx->hdr_parsed = s5p_jpeg_parse_hdr(&tmp,
-		     (unsigned long)vb2_plane_vaddr(vb, 0),
-		     min((unsigned long)ctx->out_q.size,
-			 vb2_get_plane_payload(vb, 0)), ctx);
-		if (!ctx->hdr_parsed) {
+		void *vaddr = vb2_plane_begin_cpu_access(vb, 0);
+
+		if (vaddr) {
+			tmp.w = tmp.h = 0;
+			ctx->hdr_parsed = s5p_jpeg_parse_hdr(&tmp,
+					(unsigned long)vaddr,
+					min((unsigned long)ctx->out_q.size,
+						vb2_get_plane_payload(vb, 0)),
+					ctx);
+			vb2_plane_end_cpu_access(vb, 0);
+		}
+		if (!vaddr || !ctx->hdr_parsed) {
 			vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
 			return;
 		}
diff --git a/drivers/media/platform/soc_camera/mx2_camera.c b/drivers/media/platform/soc_camera/mx2_camera.c
index 2347612a..1b3635b 100644
--- a/drivers/media/platform/soc_camera/mx2_camera.c
+++ b/drivers/media/platform/soc_camera/mx2_camera.c
@@ -505,21 +505,26 @@ static int mx2_videobuf_prepare(struct vb2_buffer *vb)
 	struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
 	int ret = 0;
 
-	dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
-		vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
+	dev_dbg(icd->parent, "%s (vb=0x%p) %lu\n", __func__,
+		vb, vb2_get_plane_payload(vb, 0));
 
 #ifdef DEBUG
 	/*
 	 * This can be useful if you want to see if we actually fill
 	 * the buffer with something
 	 */
-	memset((void *)vb2_plane_vaddr(vb, 0),
-	       0xaa, vb2_get_plane_payload(vb, 0));
+	{
+		void *vaddr = vb2_plane_begin_cpu_access(vb, 0);
+
+		if (vaddr) {
+			memset(vaddr, 0xaa, vb2_get_plane_payload(vb, 0));
+			vb2_plane_end_cpu_access(vb, 0);
+		}
+	}
 #endif
 
 	vb2_set_plane_payload(vb, 0, icd->sizeimage);
-	if (vb2_plane_vaddr(vb, 0) &&
-	    vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) {
+	if (vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) {
 		ret = -EINVAL;
 		goto out;
 	}
@@ -539,8 +544,8 @@ static void mx2_videobuf_queue(struct vb2_buffer *vb)
 	struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb);
 	unsigned long flags;
 
-	dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
-		vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
+	dev_dbg(icd->parent, "%s (vb=0x%p) %lu\n", __func__,
+		vb, vb2_get_plane_payload(vb, 0));
 
 	spin_lock_irqsave(&pcdev->lock, flags);
 
@@ -1330,8 +1335,7 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev,
 			}
 		}
 #endif
-		dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%p %lu\n", __func__, vb,
-				vb2_plane_vaddr(vb, 0),
+		dev_dbg(pcdev->dev, "%s (vb=0x%p) %lu\n", __func__, vb,
 				vb2_get_plane_payload(vb, 0));
 
 		list_del_init(&buf->internal.queue);
diff --git a/drivers/media/platform/soc_camera/mx3_camera.c b/drivers/media/platform/soc_camera/mx3_camera.c
index 7696a87..2fb395f 100644
--- a/drivers/media/platform/soc_camera/mx3_camera.c
+++ b/drivers/media/platform/soc_camera/mx3_camera.c
@@ -323,8 +323,14 @@ static void mx3_videobuf_queue(struct vb2_buffer *vb)
 
 #ifdef DEBUG
 	/* helps to see what DMA actually has written */
-	if (vb2_plane_vaddr(vb, 0))
-		memset(vb2_plane_vaddr(vb, 0), 0xaa, vb2_get_plane_payload(vb, 0));
+	{
+		void *vaddr = vb2_plane_begin_cpu_access(vb, 0);
+
+		if (vaddr) {
+			memset(vaddr, 0xaa, vb2_get_plane_payload(vb, 0));
+			vb2_plane_end_cpu_access(vb, 0);
+		}
+	}
 #endif
 
 	spin_lock_irq(&mx3_cam->lock);
diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c
index 20defcb..debec8f 100644
--- a/drivers/media/platform/soc_camera/rcar_vin.c
+++ b/drivers/media/platform/soc_camera/rcar_vin.c
@@ -428,8 +428,8 @@ static void rcar_vin_videobuf_queue(struct vb2_buffer *vb)
 
 	vb2_set_plane_payload(vb, 0, size);
 
-	dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
-		vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
+	dev_dbg(icd->parent, "%s (vb=0x%p) %lu\n", __func__,
+		vb, vb2_get_plane_payload(vb, 0));
 
 	spin_lock_irq(&priv->lock);
 
diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
index 20ad4a5..26031b2 100644
--- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
+++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
@@ -395,16 +395,22 @@ static void sh_mobile_ceu_videobuf_queue(struct vb2_buffer *vb)
 
 	vb2_set_plane_payload(vb, 0, size);
 
-	dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
-		vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
+	dev_dbg(icd->parent, "%s (vb=0x%p) %lu\n", __func__,
+		vb, vb2_get_plane_payload(vb, 0));
 
 #ifdef DEBUG
 	/*
 	 * This can be useful if you want to see if we actually fill
 	 * the buffer with something
 	 */
-	if (vb2_plane_vaddr(vb, 0))
-		memset(vb2_plane_vaddr(vb, 0), 0xaa, vb2_get_plane_payload(vb, 0));
+	{
+		void *vaddr = vb2_plane_begin_cpu_access(vb, 0);
+
+		if (vaddr) {
+			memset(vaddr, 0xaa, vb2_get_plane_payload(vb, 0));
+			vb2_plane_end_cpu_access(vb, 0);
+		}
+	}
 #endif
 
 	spin_lock_irq(&pcdev->lock);
diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c
index 1105c11..926d434 100644
--- a/drivers/media/platform/vim2m.c
+++ b/drivers/media/platform/vim2m.c
@@ -205,10 +205,11 @@ static int device_process(struct vim2m_ctx *ctx,
 {
 	struct vim2m_dev *dev = ctx->dev;
 	struct vim2m_q_data *q_data;
-	u8 *p_in, *p_out;
+	u8 *p_in, *p_out = NULL;
 	int x, y, t, w;
 	int tile_w, bytes_left;
 	int width, height, bytesperline;
+	int err = 0;
 
 	q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
 
@@ -216,17 +217,20 @@ static int device_process(struct vim2m_ctx *ctx,
 	height	= q_data->height;
 	bytesperline	= (q_data->width * q_data->fmt->depth) >> 3;
 
-	p_in = vb2_plane_vaddr(in_vb, 0);
-	p_out = vb2_plane_vaddr(out_vb, 0);
+	p_in = vb2_plane_begin_cpu_access(in_vb, 0);
+	if (p_in)
+		p_out = vb2_plane_begin_cpu_access(out_vb, 0);
 	if (!p_in || !p_out) {
 		v4l2_err(&dev->v4l2_dev,
 			 "Acquiring kernel pointers to buffers failed\n");
-		return -EFAULT;
+		err = -EFAULT;
+		goto fail;
 	}
 
 	if (vb2_plane_size(in_vb, 0) > vb2_plane_size(out_vb, 0)) {
 		v4l2_err(&dev->v4l2_dev, "Output buffer is too small\n");
-		return -EINVAL;
+		err = -EINVAL;
+		goto fail;
 	}
 
 	tile_w = (width * (q_data[V4L2_M2M_DST].fmt->depth >> 3))
@@ -330,7 +334,13 @@ static int device_process(struct vim2m_ctx *ctx,
 		}
 	}
 
-	return 0;
+fail:
+	if (p_in)
+		vb2_plane_end_cpu_access(in_vb, 0);
+	if (p_out)
+		vb2_plane_end_cpu_access(out_vb, 0);
+
+	return err;
 }
 
 static void schedule_irq(struct vim2m_dev *dev, int msec_timeout)
diff --git a/drivers/media/platform/vivid/vivid-kthread-cap.c b/drivers/media/platform/vivid/vivid-kthread-cap.c
index 39a67cf..dbb6ceb 100644
--- a/drivers/media/platform/vivid/vivid-kthread-cap.c
+++ b/drivers/media/platform/vivid/vivid-kthread-cap.c
@@ -269,7 +269,7 @@ static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf,
 
 	vid_cap_buf->vb.v4l2_buf.field = vid_out_buf->vb.v4l2_buf.field;
 
-	voutbuf = vb2_plane_vaddr(&vid_out_buf->vb, p) +
+	voutbuf = vb2_plane_begin_cpu_access(&vid_out_buf->vb, p) +
 				  vid_out_buf->vb.v4l2_planes[p].data_offset;
 	voutbuf += dev->loop_vid_out.left * pixsize + dev->loop_vid_out.top * stride_out;
 	vcapbuf += dev->compose_cap.left * pixsize + dev->compose_cap.top * stride_cap;
@@ -281,6 +281,7 @@ static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf,
 		 */
 		for (y = 0; y < hmax; y++, vcapbuf += stride_cap)
 			memcpy(vcapbuf, tpg->black_line[p], img_width * pixsize);
+		vb2_plane_end_cpu_access(&vid_out_buf->vb, p);
 		return 0;
 	}
 
@@ -386,6 +387,7 @@ update_vid_out_y:
 		}
 	}
 
+	vb2_plane_end_cpu_access(&vid_out_buf->vb, p);
 	if (!blank)
 		return 0;
 	for (; y < img_height; y++, vcapbuf += stride_cap)
@@ -442,7 +444,7 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
 	vivid_precalc_copy_rects(dev);
 
 	for (p = 0; p < tpg_g_planes(&dev->tpg); p++) {
-		void *vbuf = vb2_plane_vaddr(&buf->vb, p);
+		void *vbuf = vb2_plane_begin_cpu_access(&buf->vb, p);
 
 		/*
 		 * The first plane of a multiplanar format has a non-zero
@@ -457,6 +459,7 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
 		tpg_calc_text_basep(&dev->tpg, basep, p, vbuf);
 		if (!is_loop || vivid_copy_buffer(dev, p, vbuf, buf))
 			tpg_fillbuffer(&dev->tpg, vivid_get_std_cap(dev), p, vbuf);
+		vb2_plane_end_cpu_access(&buf->vb, p);
 	}
 	dev->must_blank[buf->vb.v4l2_buf.index] = false;
 
@@ -577,7 +580,7 @@ static void vivid_overlay(struct vivid_dev *dev, struct vivid_buffer *buf)
 	struct tpg_data *tpg = &dev->tpg;
 	unsigned pixsize = tpg_g_twopixelsize(tpg, 0) / 2;
 	void *vbase = dev->fb_vbase_cap;
-	void *vbuf = vb2_plane_vaddr(&buf->vb, 0);
+	void *vbuf;
 	unsigned img_width = dev->compose_cap.width;
 	unsigned img_height = dev->compose_cap.height;
 	unsigned stride = tpg->bytesperline[0];
@@ -590,7 +593,6 @@ static void vivid_overlay(struct vivid_dev *dev, struct vivid_buffer *buf)
 	    dev->overlay_cap_field != buf->vb.v4l2_buf.field)
 		return;
 
-	vbuf += dev->compose_cap.left * pixsize + dev->compose_cap.top * stride;
 	x = dev->overlay_cap_left;
 	w = img_width;
 	if (x < 0) {
@@ -604,6 +606,8 @@ static void vivid_overlay(struct vivid_dev *dev, struct vivid_buffer *buf)
 	}
 	if (w <= 0)
 		return;
+	vbuf = vb2_plane_begin_cpu_access(&buf->vb, 0);
+	vbuf += dev->compose_cap.left * pixsize + dev->compose_cap.top * stride;
 	if (dev->overlay_cap_top >= 0)
 		vbase += dev->overlay_cap_top * dev->fb_cap.fmt.bytesperline;
 	for (y = dev->overlay_cap_top;
@@ -629,6 +633,7 @@ static void vivid_overlay(struct vivid_dev *dev, struct vivid_buffer *buf)
 		}
 		vbase += dev->fb_cap.fmt.bytesperline;
 	}
+	vb2_plane_end_cpu_access(&buf->vb, 0);
 }
 
 static void vivid_thread_vid_cap_tick(struct vivid_dev *dev, int dropped_bufs)
diff --git a/drivers/media/platform/vivid/vivid-sdr-cap.c b/drivers/media/platform/vivid/vivid-sdr-cap.c
index 8c5d661..a2747d2 100644
--- a/drivers/media/platform/vivid/vivid-sdr-cap.c
+++ b/drivers/media/platform/vivid/vivid-sdr-cap.c
@@ -453,7 +453,7 @@ static inline s32 fixp_sin(unsigned int x)
 
 void vivid_sdr_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf)
 {
-	u8 *vbuf = vb2_plane_vaddr(&buf->vb, 0);
+	u8 *vbuf = vb2_plane_begin_cpu_access(&buf->vb, 0);
 	unsigned long i;
 	unsigned long plane_size = vb2_plane_size(&buf->vb, 0);
 	int fixp_src_phase_step, fixp_i, fixp_q;
@@ -496,4 +496,5 @@ void vivid_sdr_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf)
 		*vbuf++ = DIV_ROUND_CLOSEST(fixp_i, FIXP_FRAC * 10);
 		*vbuf++ = DIV_ROUND_CLOSEST(fixp_q, FIXP_FRAC * 10);
 	}
+	vb2_plane_end_cpu_access(&buf->vb, 0);
 }
diff --git a/drivers/media/platform/vivid/vivid-vbi-cap.c b/drivers/media/platform/vivid/vivid-vbi-cap.c
index 2166d0b..73d3746 100644
--- a/drivers/media/platform/vivid/vivid-vbi-cap.c
+++ b/drivers/media/platform/vivid/vivid-vbi-cap.c
@@ -94,7 +94,7 @@ static void vivid_g_fmt_vbi_cap(struct vivid_dev *dev, struct v4l2_vbi_format *v
 void vivid_raw_vbi_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf)
 {
 	struct v4l2_vbi_format vbi;
-	u8 *vbuf = vb2_plane_vaddr(&buf->vb, 0);
+	u8 *vbuf = vb2_plane_begin_cpu_access(&buf->vb, 0);
 
 	vivid_g_fmt_vbi_cap(dev, &vbi);
 	buf->vb.v4l2_buf.sequence = dev->vbi_cap_seq_count;
@@ -107,6 +107,7 @@ void vivid_raw_vbi_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf)
 
 	if (!VIVID_INVALID_SIGNAL(dev->std_signal_mode))
 		vivid_vbi_gen_raw(&dev->vbi_gen, &vbi, vbuf);
+	vb2_plane_end_cpu_access(&buf->vb, 0);
 
 	v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
 	buf->vb.v4l2_buf.timestamp.tv_sec += dev->time_wrap_offset;
@@ -115,7 +116,7 @@ void vivid_raw_vbi_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf)
 
 void vivid_sliced_vbi_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf)
 {
-	struct v4l2_sliced_vbi_data *vbuf = vb2_plane_vaddr(&buf->vb, 0);
+	struct v4l2_sliced_vbi_data *vbuf = vb2_plane_begin_cpu_access(&buf->vb, 0);
 
 	buf->vb.v4l2_buf.sequence = dev->vbi_cap_seq_count;
 	if (dev->field_cap == V4L2_FIELD_ALTERNATE)
@@ -130,6 +131,7 @@ void vivid_sliced_vbi_cap_process(struct vivid_dev *dev, struct vivid_buffer *bu
 		for (i = 0; i < 25; i++)
 			vbuf[i] = dev->vbi_gen.data[i];
 	}
+	vb2_plane_end_cpu_access(&buf->vb, 0);
 
 	v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
 	buf->vb.v4l2_buf.timestamp.tv_sec += dev->time_wrap_offset;
diff --git a/drivers/media/platform/vivid/vivid-vbi-out.c b/drivers/media/platform/vivid/vivid-vbi-out.c
index 9d00a07..406c0fd 100644
--- a/drivers/media/platform/vivid/vivid-vbi-out.c
+++ b/drivers/media/platform/vivid/vivid-vbi-out.c
@@ -219,7 +219,7 @@ int vidioc_s_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format
 
 void vivid_sliced_vbi_out_process(struct vivid_dev *dev, struct vivid_buffer *buf)
 {
-	struct v4l2_sliced_vbi_data *vbi = vb2_plane_vaddr(&buf->vb, 0);
+	struct v4l2_sliced_vbi_data *vbi = vb2_plane_begin_cpu_access(&buf->vb, 0);
 	unsigned elems = vb2_get_plane_payload(&buf->vb, 0) / sizeof(*vbi);
 
 	dev->vbi_out_have_cc[0] = false;
@@ -245,4 +245,5 @@ void vivid_sliced_vbi_out_process(struct vivid_dev *dev, struct vivid_buffer *bu
 		}
 		vbi++;
 	}
+	vb2_plane_end_cpu_access(&buf->vb, 0);
 }
diff --git a/drivers/media/usb/airspy/airspy.c b/drivers/media/usb/airspy/airspy.c
index 4069234..594a1d6 100644
--- a/drivers/media/usb/airspy/airspy.c
+++ b/drivers/media/usb/airspy/airspy.c
@@ -99,6 +99,7 @@ static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats);
 struct airspy_frame_buf {
 	struct vb2_buffer vb;   /* common v4l buffer stuff -- must be first */
 	struct list_head list;
+	void *vaddr;
 };
 
 struct airspy {
@@ -297,7 +298,6 @@ static void airspy_urb_complete(struct urb *urb)
 	}
 
 	if (likely(urb->actual_length > 0)) {
-		void *ptr;
 		unsigned int len;
 		/* get free framebuffer */
 		fbuf = airspy_get_next_fill_buf(s);
@@ -310,8 +310,7 @@ static void airspy_urb_complete(struct urb *urb)
 		}
 
 		/* fill framebuffer */
-		ptr = vb2_plane_vaddr(&fbuf->vb, 0);
-		len = airspy_convert_stream(s, ptr, urb->transfer_buffer,
+		len = airspy_convert_stream(s, fbuf->vaddr, urb->transfer_buffer,
 				urb->actual_length);
 		vb2_set_plane_payload(&fbuf->vb, 0, len);
 		v4l2_get_timestamp(&fbuf->vb.v4l2_buf.timestamp);
@@ -521,6 +520,20 @@ static void airspy_buf_queue(struct vb2_buffer *vb)
 	spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
 }
 
+static int airspy_buf_prepare(struct vb2_buffer *vb)
+{
+	struct airspy_frame_buf *buf =
+			container_of(vb, struct airspy_frame_buf, vb);
+
+	buf->vaddr = vb2_plane_begin_cpu_access(vb, 0);
+	return buf->vaddr ? 0 : -ENOMEM;
+}
+
+static void airspy_buf_finish(struct vb2_buffer *vb)
+{
+	vb2_plane_end_cpu_access(vb, 0);
+}
+
 static int airspy_start_streaming(struct vb2_queue *vq, unsigned int count)
 {
 	struct airspy *s = vb2_get_drv_priv(vq);
@@ -606,6 +619,8 @@ static void airspy_stop_streaming(struct vb2_queue *vq)
 static struct vb2_ops airspy_vb2_ops = {
 	.queue_setup            = airspy_queue_setup,
 	.buf_queue              = airspy_buf_queue,
+	.buf_prepare            = airspy_buf_prepare,
+	.buf_finish             = airspy_buf_finish,
 	.start_streaming        = airspy_start_streaming,
 	.stop_streaming         = airspy_stop_streaming,
 	.wait_prepare           = vb2_ops_wait_prepare,
diff --git a/drivers/media/usb/em28xx/em28xx-vbi.c b/drivers/media/usb/em28xx/em28xx-vbi.c
index 34ee1e0..014ed97 100644
--- a/drivers/media/usb/em28xx/em28xx-vbi.c
+++ b/drivers/media/usb/em28xx/em28xx-vbi.c
@@ -72,8 +72,15 @@ static int vbi_buffer_prepare(struct vb2_buffer *vb)
 		return -EINVAL;
 	}
 	vb2_set_plane_payload(&buf->vb, 0, size);
+	buf->length = size;
+	buf->mem = vb2_plane_begin_cpu_access(vb, 0);
 
-	return 0;
+	return buf->mem ? 0 : -ENOMEM;
+}
+
+static void vbi_buffer_finish(struct vb2_buffer *vb)
+{
+	vb2_plane_end_cpu_access(vb, 0);
 }
 
 static void
@@ -84,9 +91,6 @@ vbi_buffer_queue(struct vb2_buffer *vb)
 	struct em28xx_dmaqueue *vbiq = &dev->vbiq;
 	unsigned long flags = 0;
 
-	buf->mem = vb2_plane_vaddr(vb, 0);
-	buf->length = vb2_plane_size(vb, 0);
-
 	spin_lock_irqsave(&dev->slock, flags);
 	list_add_tail(&buf->list, &vbiq->active);
 	spin_unlock_irqrestore(&dev->slock, flags);
@@ -96,6 +100,7 @@ vbi_buffer_queue(struct vb2_buffer *vb)
 struct vb2_ops em28xx_vbi_qops = {
 	.queue_setup    = vbi_queue_setup,
 	.buf_prepare    = vbi_buffer_prepare,
+	.buf_finish     = vbi_buffer_finish,
 	.buf_queue      = vbi_buffer_queue,
 	.start_streaming = em28xx_start_analog_streaming,
 	.stop_streaming = em28xx_stop_vbi_streaming,
diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
index 03d5ece..0e287b0 100644
--- a/drivers/media/usb/em28xx/em28xx-video.c
+++ b/drivers/media/usb/em28xx/em28xx-video.c
@@ -918,8 +918,15 @@ buffer_prepare(struct vb2_buffer *vb)
 		return -EINVAL;
 	}
 	vb2_set_plane_payload(&buf->vb, 0, size);
+	buf->length = size;
+	buf->mem = vb2_plane_begin_cpu_access(vb, 0);
 
-	return 0;
+	return buf->mem ? 0 : -ENOMEM;
+}
+
+static void buffer_finish(struct vb2_buffer *vb)
+{
+	vb2_plane_end_cpu_access(vb, 0);
 }
 
 int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count)
@@ -1049,8 +1056,6 @@ buffer_queue(struct vb2_buffer *vb)
 	unsigned long flags = 0;
 
 	em28xx_videodbg("%s\n", __func__);
-	buf->mem = vb2_plane_vaddr(vb, 0);
-	buf->length = vb2_plane_size(vb, 0);
 
 	spin_lock_irqsave(&dev->slock, flags);
 	list_add_tail(&buf->list, &vidq->active);
@@ -1060,6 +1065,7 @@ buffer_queue(struct vb2_buffer *vb)
 static struct vb2_ops em28xx_video_qops = {
 	.queue_setup    = queue_setup,
 	.buf_prepare    = buffer_prepare,
+	.buf_finish     = buffer_finish,
 	.buf_queue      = buffer_queue,
 	.start_streaming = em28xx_start_analog_streaming,
 	.stop_streaming = em28xx_stop_streaming,
diff --git a/drivers/media/usb/go7007/go7007-driver.c b/drivers/media/usb/go7007/go7007-driver.c
index 95cffb7..e5a37ed 100644
--- a/drivers/media/usb/go7007/go7007-driver.c
+++ b/drivers/media/usb/go7007/go7007-driver.c
@@ -386,11 +386,8 @@ start_error:
  */
 static inline void store_byte(struct go7007_buffer *vb, u8 byte)
 {
-	if (vb && vb->vb.v4l2_planes[0].bytesused < GO7007_BUF_SIZE) {
-		u8 *ptr = vb2_plane_vaddr(&vb->vb, 0);
-
-		ptr[vb->vb.v4l2_planes[0].bytesused++] = byte;
-	}
+	if (vb && vb->vb.v4l2_planes[0].bytesused < GO7007_BUF_SIZE)
+		vb->vaddr[vb->vb.v4l2_planes[0].bytesused++] = byte;
 }
 
 static void go7007_set_motion_regions(struct go7007 *go, struct go7007_buffer *vb,
diff --git a/drivers/media/usb/go7007/go7007-priv.h b/drivers/media/usb/go7007/go7007-priv.h
index 2251c3f..73571f2 100644
--- a/drivers/media/usb/go7007/go7007-priv.h
+++ b/drivers/media/usb/go7007/go7007-priv.h
@@ -140,6 +140,7 @@ struct go7007_buffer {
 	struct list_head list;
 	unsigned int frame_offset;
 	u32 modet_active;
+	u8 *vaddr;
 };
 
 #define GO7007_RATIO_1_1	0
diff --git a/drivers/media/usb/go7007/go7007-v4l2.c b/drivers/media/usb/go7007/go7007-v4l2.c
index ec799b4..ad9b877 100644
--- a/drivers/media/usb/go7007/go7007-v4l2.c
+++ b/drivers/media/usb/go7007/go7007-v4l2.c
@@ -52,7 +52,7 @@ static bool valid_pixelformat(u32 pixelformat)
 
 static u32 get_frame_type_flag(struct go7007_buffer *vb, int format)
 {
-	u8 *ptr = vb2_plane_vaddr(&vb->vb, 0);
+	u8 *ptr = vb->vaddr;
 
 	switch (format) {
 	case V4L2_PIX_FMT_MJPEG:
@@ -401,7 +401,8 @@ static int go7007_buf_prepare(struct vb2_buffer *vb)
 	go7007_vb->modet_active = 0;
 	go7007_vb->frame_offset = 0;
 	vb->v4l2_planes[0].bytesused = 0;
-	return 0;
+	go7007_vb->vaddr = vb2_plane_begin_cpu_access(vb, 0);
+	return go7007_vb->vaddr ? 0 : -ENOMEM;
 }
 
 static void go7007_buf_finish(struct vb2_buffer *vb)
@@ -413,6 +414,7 @@ static void go7007_buf_finish(struct vb2_buffer *vb)
 	u32 frame_type_flag = get_frame_type_flag(go7007_vb, go->format);
 	struct v4l2_buffer *buf = &vb->v4l2_buf;
 
+	vb2_plane_end_cpu_access(vb, 0);
 	buf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_BFRAME |
 			V4L2_BUF_FLAG_PFRAME);
 	buf->flags |= frame_type_flag;
diff --git a/drivers/media/usb/hackrf/hackrf.c b/drivers/media/usb/hackrf/hackrf.c
index fd1fa41..70ea8b3 100644
--- a/drivers/media/usb/hackrf/hackrf.c
+++ b/drivers/media/usb/hackrf/hackrf.c
@@ -87,6 +87,7 @@ static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats);
 struct hackrf_frame_buf {
 	struct vb2_buffer vb;   /* common v4l buffer stuff -- must be first */
 	struct list_head list;
+	void *vaddr;
 };
 
 struct hackrf_dev {
@@ -274,7 +275,6 @@ static void hackrf_urb_complete(struct urb *urb)
 	}
 
 	if (likely(urb->actual_length > 0)) {
-		void *ptr;
 		unsigned int len;
 		/* get free framebuffer */
 		fbuf = hackrf_get_next_fill_buf(dev);
@@ -287,8 +287,7 @@ static void hackrf_urb_complete(struct urb *urb)
 		}
 
 		/* fill framebuffer */
-		ptr = vb2_plane_vaddr(&fbuf->vb, 0);
-		len = hackrf_convert_stream(dev, ptr, urb->transfer_buffer,
+		len = hackrf_convert_stream(dev, fbuf->vaddr, urb->transfer_buffer,
 				urb->actual_length);
 		vb2_set_plane_payload(&fbuf->vb, 0, len);
 		v4l2_get_timestamp(&fbuf->vb.v4l2_buf.timestamp);
@@ -493,6 +492,20 @@ static void hackrf_buf_queue(struct vb2_buffer *vb)
 	spin_unlock_irqrestore(&dev->queued_bufs_lock, flags);
 }
 
+static int hackrf_buf_prepare(struct vb2_buffer *vb)
+{
+	struct hackrf_frame_buf *buf =
+			container_of(vb, struct hackrf_frame_buf, vb);
+
+	buf->vaddr = vb2_plane_begin_cpu_access(vb, 0);
+	return buf->vaddr ? 0 : -ENOMEM;
+}
+
+static void hackrf_buf_finish(struct vb2_buffer *vb)
+{
+	vb2_plane_end_cpu_access(vb, 0);
+}
+
 static int hackrf_start_streaming(struct vb2_queue *vq, unsigned int count)
 {
 	struct hackrf_dev *dev = vb2_get_drv_priv(vq);
@@ -574,6 +587,8 @@ static void hackrf_stop_streaming(struct vb2_queue *vq)
 static struct vb2_ops hackrf_vb2_ops = {
 	.queue_setup            = hackrf_queue_setup,
 	.buf_queue              = hackrf_buf_queue,
+	.buf_prepare            = hackrf_buf_prepare,
+	.buf_finish             = hackrf_buf_finish,
 	.start_streaming        = hackrf_start_streaming,
 	.stop_streaming         = hackrf_stop_streaming,
 	.wait_prepare           = vb2_ops_wait_prepare,
diff --git a/drivers/media/usb/msi2500/msi2500.c b/drivers/media/usb/msi2500/msi2500.c
index efc761c..09b624a 100644
--- a/drivers/media/usb/msi2500/msi2500.c
+++ b/drivers/media/usb/msi2500/msi2500.c
@@ -117,6 +117,7 @@ static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats);
 struct msi2500_frame_buf {
 	struct vb2_buffer vb;   /* common v4l buffer stuff -- must be first */
 	struct list_head list;
+	void *vaddr;
 };
 
 struct msi2500_state {
@@ -403,8 +404,6 @@ static void msi2500_isoc_handler(struct urb *urb)
 
 	/* Compact data */
 	for (i = 0; i < urb->number_of_packets; i++) {
-		void *ptr;
-
 		/* Check frame error */
 		fstatus = urb->iso_frame_desc[i].status;
 		if (unlikely(fstatus)) {
@@ -432,8 +431,7 @@ static void msi2500_isoc_handler(struct urb *urb)
 		}
 
 		/* fill framebuffer */
-		ptr = vb2_plane_vaddr(&fbuf->vb, 0);
-		flen = msi2500_convert_stream(s, ptr, iso_buf, flen);
+		flen = msi2500_convert_stream(s, fbuf->vaddr, iso_buf, flen);
 		vb2_set_plane_payload(&fbuf->vb, 0, flen);
 		vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
 	}
@@ -647,6 +645,20 @@ static void msi2500_buf_queue(struct vb2_buffer *vb)
 	spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
 }
 
+static int msi2500_buf_prepare(struct vb2_buffer *vb)
+{
+	struct msi2500_frame_buf *buf =
+			container_of(vb, struct msi2500_frame_buf, vb);
+
+	buf->vaddr = vb2_plane_begin_cpu_access(vb, 0);
+	return buf->vaddr ? 0 : -ENOMEM;
+}
+
+static void msi2500_buf_finish(struct vb2_buffer *vb)
+{
+	vb2_plane_end_cpu_access(vb, 0);
+}
+
 #define CMD_WREG               0x41
 #define CMD_START_STREAMING    0x43
 #define CMD_STOP_STREAMING     0x45
@@ -879,6 +891,8 @@ static void msi2500_stop_streaming(struct vb2_queue *vq)
 static struct vb2_ops msi2500_vb2_ops = {
 	.queue_setup            = msi2500_queue_setup,
 	.buf_queue              = msi2500_buf_queue,
+	.buf_prepare            = msi2500_buf_prepare,
+	.buf_finish             = msi2500_buf_finish,
 	.start_streaming        = msi2500_start_streaming,
 	.stop_streaming         = msi2500_stop_streaming,
 	.wait_prepare           = vb2_ops_wait_prepare,
diff --git a/drivers/media/usb/pwc/pwc-if.c b/drivers/media/usb/pwc/pwc-if.c
index 15b754d..6cde648 100644
--- a/drivers/media/usb/pwc/pwc-if.c
+++ b/drivers/media/usb/pwc/pwc-if.c
@@ -606,12 +606,14 @@ static int buffer_init(struct vb2_buffer *vb)
 static int buffer_prepare(struct vb2_buffer *vb)
 {
 	struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue);
+	struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
 
 	/* Don't allow queing new buffers after device disconnection */
 	if (!pdev->udev)
 		return -ENODEV;
 
-	return 0;
+	buf->vaddr = vb2_plane_begin_cpu_access(vb, 0);
+	return buf->vaddr ? 0 : -ENOMEM;
 }
 
 static void buffer_finish(struct vb2_buffer *vb)
@@ -628,6 +630,7 @@ static void buffer_finish(struct vb2_buffer *vb)
 		 */
 		pwc_decompress(pdev, buf);
 	}
+	vb2_plane_end_cpu_access(vb, 0);
 }
 
 static void buffer_cleanup(struct vb2_buffer *vb)
diff --git a/drivers/media/usb/pwc/pwc-uncompress.c b/drivers/media/usb/pwc/pwc-uncompress.c
index b65903f..de43a4d 100644
--- a/drivers/media/usb/pwc/pwc-uncompress.c
+++ b/drivers/media/usb/pwc/pwc-uncompress.c
@@ -40,7 +40,7 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf)
 	u16 *src;
 	u16 *dsty, *dstu, *dstv;
 
-	image = vb2_plane_vaddr(&fbuf->vb, 0);
+	image = fbuf->vaddr;
 
 	yuv = fbuf->data + pdev->frame_header_size;  /* Skip header */
 
diff --git a/drivers/media/usb/pwc/pwc.h b/drivers/media/usb/pwc/pwc.h
index 81b017a..3a90ab2 100644
--- a/drivers/media/usb/pwc/pwc.h
+++ b/drivers/media/usb/pwc/pwc.h
@@ -213,6 +213,7 @@ struct pwc_frame_buf
 	struct vb2_buffer vb;	/* common v4l buffer stuff -- must be first */
 	struct list_head list;
 	void *data;
+	void *vaddr;
 	int filled;		/* number of bytes filled */
 };
 
diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c
index ccc0009..ea3e07f 100644
--- a/drivers/media/usb/s2255/s2255drv.c
+++ b/drivers/media/usb/s2255/s2255drv.c
@@ -295,6 +295,7 @@ struct s2255_buffer {
 	/* common v4l buffer stuff -- must be first */
 	struct vb2_buffer vb;
 	struct list_head list;
+	void *vaddr;
 };
 
 
@@ -609,7 +610,7 @@ static void s2255_fillbuff(struct s2255_vc *vc,
 {
 	int pos = 0;
 	const char *tmpbuf;
-	char *vbuf = vb2_plane_vaddr(&buf->vb, 0);
+	char *vbuf = buf->vaddr;
 	unsigned long last_frame;
 	struct s2255_dev *dev = vc->dev;
 
@@ -699,7 +700,13 @@ static int buffer_prepare(struct vb2_buffer *vb)
 	}
 
 	vb2_set_plane_payload(&buf->vb, 0, size);
-	return 0;
+	buf->vaddr = vb2_plane_begin_cpu_access(vb, 0);
+	return buf->vaddr ? 0 : -ENOMEM;
+}
+
+static void buffer_finish(struct vb2_buffer *vb)
+{
+	vb2_plane_end_cpu_access(vb, 0);
 }
 
 static void buffer_queue(struct vb2_buffer *vb)
@@ -719,6 +726,7 @@ static void stop_streaming(struct vb2_queue *vq);
 static struct vb2_ops s2255_video_qops = {
 	.queue_setup = queue_setup,
 	.buf_prepare = buffer_prepare,
+	.buf_finish = buffer_finish,
 	.buf_queue = buffer_queue,
 	.start_streaming = start_streaming,
 	.stop_streaming = stop_streaming,
diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c
index 2330543..55f501e 100644
--- a/drivers/media/usb/stk1160/stk1160-v4l.c
+++ b/drivers/media/usb/stk1160/stk1160-v4l.c
@@ -542,6 +542,32 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *v4l_fmt,
 	return 0;
 }
 
+static int buffer_prepare(struct vb2_buffer *vb)
+{
+	struct stk1160 *dev = vb2_get_drv_priv(vb->vb2_queue);
+	struct stk1160_buffer *buf =
+		container_of(vb, struct stk1160_buffer, vb);
+
+	buf->length = vb2_plane_size(vb, 0);
+	buf->bytesused = 0;
+	buf->pos = 0;
+
+	/*
+	 * If buffer length is less from expected then we return
+	 * the buffer to userspace directly.
+	 */
+	if (buf->length < dev->width * dev->height * 2)
+		return -EINVAL;
+
+	buf->mem = vb2_plane_begin_cpu_access(vb, 0);
+	return buf->mem ? 0 : -ENOMEM;
+}
+
+static void buffer_finish(struct vb2_buffer *vb)
+{
+	vb2_plane_end_cpu_access(vb, 0);
+}
+
 static void buffer_queue(struct vb2_buffer *vb)
 {
 	unsigned long flags;
@@ -557,21 +583,7 @@ static void buffer_queue(struct vb2_buffer *vb)
 		 */
 		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
 	} else {
-
-		buf->mem = vb2_plane_vaddr(vb, 0);
-		buf->length = vb2_plane_size(vb, 0);
-		buf->bytesused = 0;
-		buf->pos = 0;
-
-		/*
-		 * If buffer length is less from expected then we return
-		 * the buffer to userspace directly.
-		 */
-		if (buf->length < dev->width * dev->height * 2)
-			vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
-		else
-			list_add_tail(&buf->list, &dev->avail_bufs);
-
+		list_add_tail(&buf->list, &dev->avail_bufs);
 	}
 	spin_unlock_irqrestore(&dev->buf_lock, flags);
 }
@@ -592,6 +604,8 @@ static void stop_streaming(struct vb2_queue *vq)
 static struct vb2_ops stk1160_video_qops = {
 	.queue_setup		= queue_setup,
 	.buf_queue		= buffer_queue,
+	.buf_prepare		= buffer_prepare,
+	.buf_finish		= buffer_finish,
 	.start_streaming	= start_streaming,
 	.stop_streaming		= stop_streaming,
 	.wait_prepare		= vb2_ops_wait_prepare,
@@ -620,6 +634,7 @@ void stk1160_clear_queue(struct stk1160 *dev)
 		buf = list_first_entry(&dev->avail_bufs,
 			struct stk1160_buffer, list);
 		list_del(&buf->list);
+		vb2_plane_end_cpu_access(&buf->vb, 0);
 		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
 		stk1160_info("buffer [%p/%d] aborted\n",
 				buf, buf->vb.v4l2_buf.index);
diff --git a/drivers/media/usb/stk1160/stk1160-video.c b/drivers/media/usb/stk1160/stk1160-video.c
index 39f1aae..da5c08f 100644
--- a/drivers/media/usb/stk1160/stk1160-video.c
+++ b/drivers/media/usb/stk1160/stk1160-video.c
@@ -104,6 +104,7 @@ void stk1160_buffer_done(struct stk1160 *dev)
 	v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
 
 	vb2_set_plane_payload(&buf->vb, 0, buf->bytesused);
+	vb2_plane_end_cpu_access(&buf->vb, 0);
 	vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
 
 	dev->isoc_ctl.buf = NULL;
diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c
index 9d3525f..d69e730 100644
--- a/drivers/media/usb/usbtv/usbtv-video.c
+++ b/drivers/media/usb/usbtv/usbtv-video.c
@@ -275,7 +275,6 @@ static void usbtv_chunk_to_vbuf(u32 *frame, __be32 *src, int chunk_no, int odd)
 static void usbtv_image_chunk(struct usbtv *usbtv, __be32 *chunk)
 {
 	int frame_id, odd, chunk_no;
-	u32 *frame;
 	struct usbtv_buf *buf;
 	unsigned long flags;
 
@@ -306,10 +305,9 @@ static void usbtv_image_chunk(struct usbtv *usbtv, __be32 *chunk)
 
 	/* First available buffer. */
 	buf = list_first_entry(&usbtv->bufs, struct usbtv_buf, list);
-	frame = vb2_plane_vaddr(&buf->vb, 0);
 
 	/* Copy the chunk data. */
-	usbtv_chunk_to_vbuf(frame, &chunk[1], chunk_no, odd);
+	usbtv_chunk_to_vbuf(buf->vaddr, &chunk[1], chunk_no, odd);
 	usbtv->chunks_done++;
 
 	/* Last chunk in a frame, signalling an end */
@@ -628,6 +626,19 @@ static void usbtv_buf_queue(struct vb2_buffer *vb)
 	spin_unlock_irqrestore(&usbtv->buflock, flags);
 }
 
+static int usbtv_buf_prepare(struct vb2_buffer *vb)
+{
+	struct usbtv_buf *buf = container_of(vb, struct usbtv_buf, vb);
+
+	buf->vaddr = vb2_plane_begin_cpu_access(vb, 0);
+	return buf->vaddr ? 0 : -ENOMEM;
+}
+
+static void usbtv_buf_finish(struct vb2_buffer *vb)
+{
+	vb2_plane_end_cpu_access(vb, 0);
+}
+
 static int usbtv_start_streaming(struct vb2_queue *vq, unsigned int count)
 {
 	struct usbtv *usbtv = vb2_get_drv_priv(vq);
@@ -649,6 +660,8 @@ static void usbtv_stop_streaming(struct vb2_queue *vq)
 static struct vb2_ops usbtv_vb2_ops = {
 	.queue_setup = usbtv_queue_setup,
 	.buf_queue = usbtv_buf_queue,
+	.buf_prepare = usbtv_buf_prepare,
+	.buf_finish = usbtv_buf_finish,
 	.start_streaming = usbtv_start_streaming,
 	.stop_streaming = usbtv_stop_streaming,
 };
diff --git a/drivers/media/usb/usbtv/usbtv.h b/drivers/media/usb/usbtv/usbtv.h
index 9681195..751ddea 100644
--- a/drivers/media/usb/usbtv/usbtv.h
+++ b/drivers/media/usb/usbtv/usbtv.h
@@ -63,6 +63,7 @@ struct usbtv_norm_params {
 struct usbtv_buf {
 	struct vb2_buffer vb;
 	struct list_head list;
+	void *vaddr;
 };
 
 /* Per-device structure. */
diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c
index 6e92d20..664c0c6 100644
--- a/drivers/media/usb/uvc/uvc_queue.c
+++ b/drivers/media/usb/uvc/uvc_queue.c
@@ -76,14 +76,14 @@ static int uvc_buffer_prepare(struct vb2_buffer *vb)
 
 	buf->state = UVC_BUF_STATE_QUEUED;
 	buf->error = 0;
-	buf->mem = vb2_plane_vaddr(vb, 0);
+	buf->mem = vb2_plane_begin_cpu_access(vb, 0);
 	buf->length = vb2_plane_size(vb, 0);
 	if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
 		buf->bytesused = 0;
 	else
 		buf->bytesused = vb2_get_plane_payload(vb, 0);
 
-	return 0;
+	return buf->mem ? 0 : -ENOMEM;
 }
 
 static void uvc_buffer_queue(struct vb2_buffer *vb)
@@ -115,6 +115,7 @@ static void uvc_buffer_finish(struct vb2_buffer *vb)
 
 	if (vb->state == VB2_BUF_STATE_DONE)
 		uvc_video_clock_update(stream, &vb->v4l2_buf, buf);
+	vb2_plane_end_cpu_access(vb, 0);
 }
 
 static void uvc_wait_prepare(struct vb2_queue *vq)
diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c
index 6f9171c..eccf84c 100644
--- a/drivers/staging/media/davinci_vpfe/vpfe_video.c
+++ b/drivers/staging/media/davinci_vpfe/vpfe_video.c
@@ -1133,9 +1133,8 @@ static int vpfe_buffer_prepare(struct vb2_buffer *vb)
 
 	/* Initialize buffer */
 	vb2_set_plane_payload(vb, 0, video->fmt.fmt.pix.sizeimage);
-	if (vb2_plane_vaddr(vb, 0) &&
-		vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0))
-			return -EINVAL;
+	if (vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0))
+		return -EINVAL;
 
 	addr = vb2_dma_contig_plane_dma_addr(vb, 0);
 	/* Make sure user addresses are aligned to 32 bytes */
diff --git a/drivers/usb/gadget/function/uvc_queue.c b/drivers/usb/gadget/function/uvc_queue.c
index 8ea8b3b..b4f6189 100644
--- a/drivers/usb/gadget/function/uvc_queue.c
+++ b/drivers/usb/gadget/function/uvc_queue.c
@@ -73,14 +73,19 @@ static int uvc_buffer_prepare(struct vb2_buffer *vb)
 		return -ENODEV;
 
 	buf->state = UVC_BUF_STATE_QUEUED;
-	buf->mem = vb2_plane_vaddr(vb, 0);
+	buf->mem = vb2_plane_begin_cpu_access(vb, 0);
 	buf->length = vb2_plane_size(vb, 0);
 	if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
 		buf->bytesused = 0;
 	else
 		buf->bytesused = vb2_get_plane_payload(vb, 0);
 
-	return 0;
+	return buf->mem ? 0 : -ENOMEM;
+}
+
+static void uvc_buffer_finish(struct vb2_buffer *vb)
+{
+	vb2_plane_end_cpu_access(vb, 0);
 }
 
 static void uvc_buffer_queue(struct vb2_buffer *vb)
@@ -121,6 +126,7 @@ static void uvc_wait_finish(struct vb2_queue *vq)
 static struct vb2_ops uvc_queue_qops = {
 	.queue_setup = uvc_queue_setup,
 	.buf_prepare = uvc_buffer_prepare,
+	.buf_finish = uvc_buffer_finish,
 	.buf_queue = uvc_buffer_queue,
 	.wait_prepare = uvc_wait_prepare,
 	.wait_finish = uvc_wait_finish,
-- 
2.1.1


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

* [RFCv6 PATCH 15/16] vb2: drop the unused vb2_plane_vaddr function.
  2014-11-10 12:49 [RFCv6 PATCH 00/16] vb2: improve dma-sg, expbuf Hans Verkuil
                   ` (13 preceding siblings ...)
  2014-11-10 12:49 ` [RFCv6 PATCH 14/16] v4l: convert vb2_plane_vaddr to vb2_plane_begin_cpu_access Hans Verkuil
@ 2014-11-10 12:49 ` Hans Verkuil
  2014-11-10 12:49 ` [RFCv6 PATCH 16/16] vb2: update the buf_prepare/finish documentation Hans Verkuil
  15 siblings, 0 replies; 29+ messages in thread
From: Hans Verkuil @ 2014-11-10 12:49 UTC (permalink / raw)
  To: linux-media; +Cc: m.szyprowski, pawel, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Now that all drivers have been converted, this function can be dropped.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/v4l2-core/videobuf2-core.c       |  8 +-------
 drivers/media/v4l2-core/videobuf2-dma-contig.c | 11 -----------
 drivers/media/v4l2-core/videobuf2-dma-sg.c     |  9 ++-------
 drivers/media/v4l2-core/videobuf2-vmalloc.c    |  1 -
 include/media/videobuf2-core.h                 |  6 +-----
 5 files changed, 4 insertions(+), 31 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index 036b947..5138a9f 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -1129,15 +1129,9 @@ void *vb2_plane_begin_cpu_access(struct vb2_buffer *vb, unsigned int plane_no)
 		return NULL;
 
 	return call_ptr_memop(vb, begin_cpu_access, vb->planes[plane_no].mem_priv);
-}
-EXPORT_SYMBOL_GPL(vb2_plane_begin_cpu_access);
 
-/* Keep this for backwards compatibility. Will be removed soon. */
-void *vb2_plane_vaddr(struct vb2_buffer *vb, unsigned int plane_no)
-{
-	return vb2_plane_begin_cpu_access(vb, plane_no);
 }
-EXPORT_SYMBOL_GPL(vb2_plane_vaddr);
+EXPORT_SYMBOL_GPL(vb2_plane_begin_cpu_access);
 
 /**
  * vb2_plane_end_cpu_access() - Return a kernel virtual address of a given plane
diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index 58a4bf2..629ca2e 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -94,16 +94,6 @@ static void *vb2_dc_cookie(void *buf_priv)
 	return &buf->dma_addr;
 }
 
-static void *vb2_dc_vaddr(void *buf_priv)
-{
-	struct vb2_dc_buf *buf = buf_priv;
-
-	if (!buf->vaddr && buf->db_attach)
-		buf->vaddr = dma_buf_vmap(buf->db_attach->dmabuf);
-
-	return buf->vaddr;
-}
-
 static unsigned int vb2_dc_num_users(void *buf_priv)
 {
 	struct vb2_dc_buf *buf = buf_priv;
@@ -895,7 +885,6 @@ const struct vb2_mem_ops vb2_dma_contig_memops = {
 	.put		= vb2_dc_put,
 	.get_dmabuf	= vb2_dc_get_dmabuf,
 	.cookie		= vb2_dc_cookie,
-	.vaddr		= vb2_dc_vaddr,
 	.mmap		= vb2_dc_mmap,
 	.get_userptr	= vb2_dc_get_userptr,
 	.put_userptr	= vb2_dc_put_userptr,
diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index 0148bd8..0773cd9 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -375,13 +375,9 @@ static void *vb2_dma_sg_vaddr(void *buf_priv)
 
 	BUG_ON(!buf);
 
-	if (!buf->vaddr) {
-		if (buf->db_attach)
-			buf->vaddr = dma_buf_vmap(buf->db_attach->dmabuf);
-		else
-			buf->vaddr = vm_map_ram(buf->pages,
+	if (!buf->vaddr)
+		buf->vaddr = vm_map_ram(buf->pages,
 					buf->num_pages, -1, PAGE_KERNEL);
-	}
 
 	/* add offset in case userptr is not page-aligned */
 	return buf->vaddr ? buf->vaddr + buf->offset : NULL;
@@ -780,7 +776,6 @@ const struct vb2_mem_ops vb2_dma_sg_memops = {
 	.put_userptr	= vb2_dma_sg_put_userptr,
 	.prepare	= vb2_dma_sg_prepare,
 	.finish		= vb2_dma_sg_finish,
-	.vaddr		= vb2_dma_sg_vaddr,
 	.mmap		= vb2_dma_sg_mmap,
 	.num_users	= vb2_dma_sg_num_users,
 	.get_dmabuf	= vb2_dma_sg_get_dmabuf,
diff --git a/drivers/media/v4l2-core/videobuf2-vmalloc.c b/drivers/media/v4l2-core/videobuf2-vmalloc.c
index 875a1b0..6957418 100644
--- a/drivers/media/v4l2-core/videobuf2-vmalloc.c
+++ b/drivers/media/v4l2-core/videobuf2-vmalloc.c
@@ -479,7 +479,6 @@ const struct vb2_mem_ops vb2_vmalloc_memops = {
 	.unmap_dmabuf	= vb2_vmalloc_unmap_dmabuf,
 	.attach_dmabuf	= vb2_vmalloc_attach_dmabuf,
 	.detach_dmabuf	= vb2_vmalloc_detach_dmabuf,
-	.vaddr		= vb2_vmalloc_vaddr,
 	.begin_cpu_access = vb2_vmalloc_begin_cpu_access,
 	.end_cpu_access = vb2_vmalloc_end_cpu_access,
 	.mmap		= vb2_vmalloc_mmap,
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index a22d17e..2f53252 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -63,7 +63,6 @@ struct vb2_threadio_data;
  *		driver, useful for cache synchronisation, optional.
  * @finish:	called every time the buffer is passed back from the driver
  *		to the userspace, also optional.
- * @vaddr:	return a kernel virtual address to a given memory buffer
  * @begin_cpu_access: return a kernel virtual address to a given memory buffer
  *		associated with the passed private structure or NULL if no
  *		such mapping exists. This memory buffer can be written by the
@@ -80,7 +79,7 @@ struct vb2_threadio_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 read/write access types: alloc, put, num_users,
  *			begin_cpu_access, end_cpu_access.
  * Required ops for DMABUF types: attach_dmabuf, detach_dmabuf, map_dmabuf,
  *			unmap_dmabuf, begin_cpu_access, end_cpu_access.
@@ -109,7 +108,6 @@ struct vb2_mem_ops {
 	void		*(*begin_cpu_access)(void *buf_priv);
 	void		(*end_cpu_access)(void *buf_priv);
 
-	void		*(*vaddr)(void *buf_priv);
 	void		*(*cookie)(void *buf_priv);
 
 	unsigned int	(*num_users)(void *buf_priv);
@@ -231,7 +229,6 @@ struct vb2_buffer {
 	u32		cnt_mem_detach_dmabuf;
 	u32		cnt_mem_map_dmabuf;
 	u32		cnt_mem_unmap_dmabuf;
-	u32		cnt_mem_vaddr;
 	u32		cnt_mem_begin_cpu_access;
 	u32		cnt_mem_end_cpu_access;
 	u32		cnt_mem_cookie;
@@ -454,7 +451,6 @@ struct vb2_queue {
 #endif
 };
 
-void *vb2_plane_vaddr(struct vb2_buffer *vb, unsigned int plane_no);
 void *vb2_plane_begin_cpu_access(struct vb2_buffer *vb, unsigned int plane_no);
 void vb2_plane_end_cpu_access(struct vb2_buffer *vb, unsigned int plane_no);
 void *vb2_plane_cookie(struct vb2_buffer *vb, unsigned int plane_no);
-- 
2.1.1


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

* [RFCv6 PATCH 16/16] vb2: update the buf_prepare/finish documentation
  2014-11-10 12:49 [RFCv6 PATCH 00/16] vb2: improve dma-sg, expbuf Hans Verkuil
                   ` (14 preceding siblings ...)
  2014-11-10 12:49 ` [RFCv6 PATCH 15/16] vb2: drop the unused vb2_plane_vaddr function Hans Verkuil
@ 2014-11-10 12:49 ` Hans Verkuil
  15 siblings, 0 replies; 29+ messages in thread
From: Hans Verkuil @ 2014-11-10 12:49 UTC (permalink / raw)
  To: linux-media; +Cc: m.szyprowski, pawel, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Document how the new vb2_plane_begin/end_cpu_access() functions should
be used in buf_prepare/finish.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 include/media/videobuf2-core.h | 35 ++++++++++++++++++++++-------------
 1 file changed, 22 insertions(+), 13 deletions(-)

diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 2f53252..1619248 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -282,21 +282,30 @@ struct vb2_buffer {
  *			perform any initialization required before each
  *			hardware operation in this callback; drivers can
  *			access/modify the buffer here as it is still synced for
- *			the CPU; drivers that support VIDIOC_CREATE_BUFS must
- *			also validate the buffer size; if an error is returned,
- *			the buffer will not be queued in driver; optional.
+ *			the CPU, provided you bracket the cpu access part with
+ *			@vb2_plane_begin_cpu_access and @vb2_plane_end_cpu_access;
+ *			when using videobuf2-vmalloc.h you can postpone the call
+ *			to @vb2_plane_end_cpu_access to @buf_finish; drivers
+ *			that support VIDIOC_CREATE_BUFS must also validate
+ *			the buffer size; if an error is returned, the buffer
+ *			will not be queued in driver; optional.
  * @buf_finish:		called before every dequeue of the buffer back to
  *			userspace; the buffer is synced for the CPU, so drivers
- *			can access/modify the buffer contents; drivers may
- *			perform any operations required before userspace
- *			accesses the buffer; optional. The buffer state can be
- *			one of the following: DONE and ERROR occur while
- *			streaming is in progress, and the PREPARED state occurs
- *			when the queue has been canceled and all pending
- *			buffers are being returned to their default DEQUEUED
- *			state. Typically you only have to do something if the
- *			state is VB2_BUF_STATE_DONE, since in all other cases
- *			the buffer contents will be ignored anyway.
+ *			can access/modify the buffer contents provided you
+ *			bracket the cpu access part with
+ *			@vb2_plane_begin_cpu_access and @vb2_plane_end_cpu_access;
+ *			when using videobuf2-vmalloc.h you can call
+ *			@vb2_plane_end_cpu_access here to bracket a corresponding
+ *			@vb2_plane_begin_cpu_access call in @buf_prepare;
+ *			drivers may perform any operations required before
+ *			userspace accesses the buffer; optional. The buffer
+ *			state can be one of the following: DONE and ERROR
+ *			occur while streaming is in progress, and the PREPARED
+ *			state occurs when the queue has been canceled and all
+ *			pending buffers are being returned to their default
+ *			DEQUEUED state. Typically you only have to do something
+ *			if the state is VB2_BUF_STATE_DONE, since in all other
+ *			cases the buffer contents will be ignored anyway.
  * @buf_cleanup:	called once before the buffer is freed; drivers may
  *			perform any additional cleanup; optional.
  * @start_streaming:	called once to enter 'streaming' state; the driver may
-- 
2.1.1


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

* Re: [RFCv6 PATCH 02/16] vb2: replace 'write' by 'dma_dir'
  2014-11-10 12:49 ` [RFCv6 PATCH 02/16] vb2: replace 'write' by 'dma_dir' Hans Verkuil
@ 2014-11-16 12:34   ` Pawel Osciak
  0 siblings, 0 replies; 29+ messages in thread
From: Pawel Osciak @ 2014-11-16 12:34 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: LMML, Marek Szyprowski, Hans Verkuil

On Mon, Nov 10, 2014 at 8:49 PM, Hans Verkuil <hverkuil@xs4all.nl> wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
>
> The 'write' argument is very ambiguous. I first assumed that if it is 1,
> then we're doing video output but instead it meant the reverse.
>
> Since it is used to setup the dma_dir value anyway it is now replaced by
> the correct dma_dir value which is unambiguous.
>
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>

Acked-by: Pawel Osciak <pawel@osciak.com>

-- 
Best regards,
Pawel Osciak

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

* Re: [RFCv6 PATCH 03/16] vb2: add dma_dir to the alloc memop.
  2014-11-10 12:49 ` [RFCv6 PATCH 03/16] vb2: add dma_dir to the alloc memop Hans Verkuil
@ 2014-11-16 12:47   ` Pawel Osciak
  0 siblings, 0 replies; 29+ messages in thread
From: Pawel Osciak @ 2014-11-16 12:47 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: LMML, Marek Szyprowski, Hans Verkuil

On Mon, Nov 10, 2014 at 8:49 PM, Hans Verkuil <hverkuil@xs4all.nl> wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
>
> This is needed for the next patch where the dma-sg alloc memop needs
> to know the dma_dir.
>
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>

Acked-by: Pawel Osciak <pawel@osciak.com>

-- 
Best regards,
Pawel Osciak

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

* Re: [RFCv6 PATCH 04/16] vb2-dma-sg: add allocation context to dma-sg
  2014-11-10 12:49 ` [RFCv6 PATCH 04/16] vb2-dma-sg: add allocation context to dma-sg Hans Verkuil
@ 2014-11-16 13:13   ` Pawel Osciak
  2014-11-17  9:18     ` Hans Verkuil
  0 siblings, 1 reply; 29+ messages in thread
From: Pawel Osciak @ 2014-11-16 13:13 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: LMML, Marek Szyprowski, Hans Verkuil

On Mon, Nov 10, 2014 at 8:49 PM, Hans Verkuil <hverkuil@xs4all.nl> wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
>
> Require that dma-sg also uses an allocation context. This is in preparation
> for adding prepare/finish memops to sync the memory between DMA and CPU.
>
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> ---

[...]

> @@ -166,6 +177,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
>                                     unsigned long size,
>                                     enum dma_data_direction dma_dir)
>  {
> +       struct vb2_dma_sg_conf *conf = alloc_ctx;
>         struct vb2_dma_sg_buf *buf;
>         unsigned long first, last;
>         int num_pages_from_user;
> @@ -235,6 +247,8 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
>                         buf->num_pages, buf->offset, size, 0))
>                 goto userptr_fail_alloc_table_from_pages;
>
> +       /* Prevent the device from being released while the buffer is used */
> +       buf->dev = get_device(conf->dev);

I'm not sure if we should be managing this... As far as I understand
the logic behind taking a ref in alloc, if we are the exporter, we may
have to keep it in case we need to free the buffers after our device
goes away. But for userptr, we only need this for syncs, and in that
case it's triggered by our driver, so I think we don't have to worry
about that. If we do though, then dma-contig should be doing this as
well.

>         return buf;
>
>  userptr_fail_alloc_table_from_pages:
> @@ -274,6 +288,7 @@ static void vb2_dma_sg_put_userptr(void *buf_priv)
>         }
>         kfree(buf->pages);
>         vb2_put_vma(buf->vma);
> +       put_device(buf->dev);
>         kfree(buf);
>  }
>
> @@ -356,6 +371,27 @@ const struct vb2_mem_ops vb2_dma_sg_memops = {
>  };
>  EXPORT_SYMBOL_GPL(vb2_dma_sg_memops);
>
> +void *vb2_dma_sg_init_ctx(struct device *dev)
> +{
> +       struct vb2_dma_sg_conf *conf;
> +
> +       conf = kzalloc(sizeof(*conf), GFP_KERNEL);
> +       if (!conf)
> +               return ERR_PTR(-ENOMEM);
> +
> +       conf->dev = dev;
> +
> +       return conf;
> +}
> +EXPORT_SYMBOL_GPL(vb2_dma_sg_init_ctx);
> +
> +void vb2_dma_sg_cleanup_ctx(void *alloc_ctx)
> +{
> +       if (!IS_ERR_OR_NULL(alloc_ctx))

I would prefer not doing this, it's very weird and would really just
be a programming bug.


-- 
Best regards,
Pawel Osciak

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

* Re: [RFCv6 PATCH 06/16] vb2-dma-sg: add dmabuf import support
  2014-11-10 12:49 ` [RFCv6 PATCH 06/16] vb2-dma-sg: add dmabuf import support Hans Verkuil
@ 2014-11-16 13:29   ` Pawel Osciak
  0 siblings, 0 replies; 29+ messages in thread
From: Pawel Osciak @ 2014-11-16 13:29 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: LMML, Marek Szyprowski, Hans Verkuil

On Mon, Nov 10, 2014 at 8:49 PM, Hans Verkuil <hverkuil@xs4all.nl> wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
>
> Add support for importing dmabuf to videobuf2-dma-sg.
>
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>

Acked-by: Pawel Osciak <pawel@osciak.com>


-- 
Best regards,
Pawel Osciak

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

* Re: [RFCv6 PATCH 07/16] vb2-dma-sg: add support for dmabuf exports
  2014-11-10 12:49 ` [RFCv6 PATCH 07/16] vb2-dma-sg: add support for dmabuf exports Hans Verkuil
@ 2014-11-16 13:35   ` Pawel Osciak
  0 siblings, 0 replies; 29+ messages in thread
From: Pawel Osciak @ 2014-11-16 13:35 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: LMML, Marek Szyprowski, Hans Verkuil

On Mon, Nov 10, 2014 at 8:49 PM, Hans Verkuil <hverkuil@xs4all.nl> wrote:
> From: Hans Verkuil <hansverk@cisco.com>
>
> Add DMABUF export support to vb2-dma-sg.
>
> Signed-off-by: Hans Verkuil <hansverk@cisco.com>

Acked-by: Pawel Osciak <pawel@osciak.com>

-- 
Best regards,
Pawel Osciak

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

* Re: [RFCv6 PATCH 04/16] vb2-dma-sg: add allocation context to dma-sg
  2014-11-16 13:13   ` Pawel Osciak
@ 2014-11-17  9:18     ` Hans Verkuil
  0 siblings, 0 replies; 29+ messages in thread
From: Hans Verkuil @ 2014-11-17  9:18 UTC (permalink / raw)
  To: Pawel Osciak; +Cc: LMML, Marek Szyprowski, Hans Verkuil

Hi Pawel,

On 11/16/2014 02:13 PM, Pawel Osciak wrote:
> On Mon, Nov 10, 2014 at 8:49 PM, Hans Verkuil <hverkuil@xs4all.nl> wrote:
>> From: Hans Verkuil <hans.verkuil@cisco.com>
>>
>> Require that dma-sg also uses an allocation context. This is in preparation
>> for adding prepare/finish memops to sync the memory between DMA and CPU.
>>
>> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
>> ---
> 
> [...]
> 
>> @@ -166,6 +177,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
>>                                     unsigned long size,
>>                                     enum dma_data_direction dma_dir)
>>  {
>> +       struct vb2_dma_sg_conf *conf = alloc_ctx;
>>         struct vb2_dma_sg_buf *buf;
>>         unsigned long first, last;
>>         int num_pages_from_user;
>> @@ -235,6 +247,8 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
>>                         buf->num_pages, buf->offset, size, 0))
>>                 goto userptr_fail_alloc_table_from_pages;
>>
>> +       /* Prevent the device from being released while the buffer is used */
>> +       buf->dev = get_device(conf->dev);
> 
> I'm not sure if we should be managing this... As far as I understand
> the logic behind taking a ref in alloc, if we are the exporter, we may
> have to keep it in case we need to free the buffers after our device
> goes away. But for userptr, we only need this for syncs, and in that
> case it's triggered by our driver, so I think we don't have to worry
> about that. If we do though, then dma-contig should be doing this as
> well.

You are correct. I'll remove this for get/put_userptr.

> 
>>         return buf;
>>
>>  userptr_fail_alloc_table_from_pages:
>> @@ -274,6 +288,7 @@ static void vb2_dma_sg_put_userptr(void *buf_priv)
>>         }
>>         kfree(buf->pages);
>>         vb2_put_vma(buf->vma);
>> +       put_device(buf->dev);
>>         kfree(buf);
>>  }
>>
>> @@ -356,6 +371,27 @@ const struct vb2_mem_ops vb2_dma_sg_memops = {
>>  };
>>  EXPORT_SYMBOL_GPL(vb2_dma_sg_memops);
>>
>> +void *vb2_dma_sg_init_ctx(struct device *dev)
>> +{
>> +       struct vb2_dma_sg_conf *conf;
>> +
>> +       conf = kzalloc(sizeof(*conf), GFP_KERNEL);
>> +       if (!conf)
>> +               return ERR_PTR(-ENOMEM);
>> +
>> +       conf->dev = dev;
>> +
>> +       return conf;
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_dma_sg_init_ctx);
>> +
>> +void vb2_dma_sg_cleanup_ctx(void *alloc_ctx)
>> +{
>> +       if (!IS_ERR_OR_NULL(alloc_ctx))
> 
> I would prefer not doing this, it's very weird and would really just
> be a programming bug.

Erm, I rather like it since it allows you to call cleanup_ctx even if init_ctx
failed. It's actually used like that in the solo driver. Basically for the same
reason that kfree can handle a NULL pointer. Although if I do it here, then it
should also be added to dma-contig.

Regards,

	Hans


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

* Re: [RFCv6 PATCH 08/16] vb2-vmalloc: add support for dmabuf exports
  2014-11-10 12:49 ` [RFCv6 PATCH 08/16] vb2-vmalloc: " Hans Verkuil
@ 2014-11-18  9:34   ` Pawel Osciak
  2014-11-18  9:44     ` Hans Verkuil
  0 siblings, 1 reply; 29+ messages in thread
From: Pawel Osciak @ 2014-11-18  9:34 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: LMML, Marek Szyprowski, Hans Verkuil

On Mon, Nov 10, 2014 at 8:49 PM, Hans Verkuil <hverkuil@xs4all.nl> wrote:
> From: Hans Verkuil <hansverk@cisco.com>
>
> Add support for DMABUF exporting to the vb2-vmalloc implementation.
>
> All memory models now have support for both importing and exporting of DMABUFs.
> Signed-off-by: Hans Verkuil <hansverk@cisco.com>
> ---
>  drivers/media/v4l2-core/videobuf2-vmalloc.c | 174 ++++++++++++++++++++++++++++
>  1 file changed, 174 insertions(+)
>
> diff --git a/drivers/media/v4l2-core/videobuf2-vmalloc.c b/drivers/media/v4l2-core/videobuf2-vmalloc.c
> index bba2460..dfbb6d5 100644
> --- a/drivers/media/v4l2-core/videobuf2-vmalloc.c
> +++ b/drivers/media/v4l2-core/videobuf2-vmalloc.c
> @@ -31,6 +31,9 @@ struct vb2_vmalloc_buf {
>         atomic_t                        refcount;
>         struct vb2_vmarea_handler       handler;
>         struct dma_buf                  *dbuf;
> +
> +       /* DMABUF related */
> +       struct dma_buf_attachment       *db_attach;

Unused?

-- 
Best regards,
Pawel Osciak

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

* Re: [RFCv6 PATCH 09/16] vivid: enable vb2_expbuf support.
  2014-11-10 12:49 ` [RFCv6 PATCH 09/16] vivid: enable vb2_expbuf support Hans Verkuil
@ 2014-11-18  9:38   ` Pawel Osciak
  0 siblings, 0 replies; 29+ messages in thread
From: Pawel Osciak @ 2014-11-18  9:38 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: LMML, Marek Szyprowski, Hans Verkuil

On Mon, Nov 10, 2014 at 8:49 PM, Hans Verkuil <hverkuil@xs4all.nl> wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
>
> Now that vb2 supports DMABUF export for dma-sg and vmalloc memory
> modes, we can enable the vb2_expbuf support in vivid.
>
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>

Reviewed-by: Pawel Osciak <pawel@osciak.com>

> ---
>  drivers/media/platform/vivid/vivid-core.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c
> index 2c61a62..7de8d9d 100644
> --- a/drivers/media/platform/vivid/vivid-core.c
> +++ b/drivers/media/platform/vivid/vivid-core.c
> @@ -588,7 +588,7 @@ static const struct v4l2_ioctl_ops vivid_ioctl_ops = {
>         .vidioc_querybuf                = vb2_ioctl_querybuf,
>         .vidioc_qbuf                    = vb2_ioctl_qbuf,
>         .vidioc_dqbuf                   = vb2_ioctl_dqbuf,
> -/* Not yet     .vidioc_expbuf          = vb2_ioctl_expbuf,*/
> +       .vidioc_expbuf                  = vb2_ioctl_expbuf,
>         .vidioc_streamon                = vb2_ioctl_streamon,
>         .vidioc_streamoff               = vb2_ioctl_streamoff,
>
> --
> 2.1.1
>


-- 
Best regards,
Pawel Osciak

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

* Re: [RFCv6 PATCH 10/16] vim2m: support expbuf
  2014-11-10 12:49 ` [RFCv6 PATCH 10/16] vim2m: support expbuf Hans Verkuil
@ 2014-11-18  9:40   ` Pawel Osciak
  0 siblings, 0 replies; 29+ messages in thread
From: Pawel Osciak @ 2014-11-18  9:40 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: LMML, Marek Szyprowski, Hans Verkuil

On Mon, Nov 10, 2014 at 8:49 PM, Hans Verkuil <hverkuil@xs4all.nl> wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
>
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>

Reviewed-by: Pawel Osciak <pawel@osciak.com>

> ---
>  drivers/media/platform/vim2m.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c
> index 87af47a..1105c11 100644
> --- a/drivers/media/platform/vim2m.c
> +++ b/drivers/media/platform/vim2m.c
> @@ -697,6 +697,7 @@ static const struct v4l2_ioctl_ops vim2m_ioctl_ops = {
>         .vidioc_querybuf        = v4l2_m2m_ioctl_querybuf,
>         .vidioc_qbuf            = v4l2_m2m_ioctl_qbuf,
>         .vidioc_dqbuf           = v4l2_m2m_ioctl_dqbuf,
> +       .vidioc_expbuf          = v4l2_m2m_ioctl_expbuf,
>
>         .vidioc_streamon        = v4l2_m2m_ioctl_streamon,
>         .vidioc_streamoff       = v4l2_m2m_ioctl_streamoff,
> --
> 2.1.1
>


-- 
Best regards,
Pawel Osciak

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

* Re: [RFCv6 PATCH 08/16] vb2-vmalloc: add support for dmabuf exports
  2014-11-18  9:34   ` Pawel Osciak
@ 2014-11-18  9:44     ` Hans Verkuil
  0 siblings, 0 replies; 29+ messages in thread
From: Hans Verkuil @ 2014-11-18  9:44 UTC (permalink / raw)
  To: Pawel Osciak; +Cc: LMML, Marek Szyprowski, Hans Verkuil

On 11/18/14 10:34, Pawel Osciak wrote:
> On Mon, Nov 10, 2014 at 8:49 PM, Hans Verkuil <hverkuil@xs4all.nl> wrote:
>> From: Hans Verkuil <hansverk@cisco.com>
>>
>> Add support for DMABUF exporting to the vb2-vmalloc implementation.
>>
>> All memory models now have support for both importing and exporting of DMABUFs.
>> Signed-off-by: Hans Verkuil <hansverk@cisco.com>
>> ---
>>  drivers/media/v4l2-core/videobuf2-vmalloc.c | 174 ++++++++++++++++++++++++++++
>>  1 file changed, 174 insertions(+)
>>
>> diff --git a/drivers/media/v4l2-core/videobuf2-vmalloc.c b/drivers/media/v4l2-core/videobuf2-vmalloc.c
>> index bba2460..dfbb6d5 100644
>> --- a/drivers/media/v4l2-core/videobuf2-vmalloc.c
>> +++ b/drivers/media/v4l2-core/videobuf2-vmalloc.c
>> @@ -31,6 +31,9 @@ struct vb2_vmalloc_buf {
>>         atomic_t                        refcount;
>>         struct vb2_vmarea_handler       handler;
>>         struct dma_buf                  *dbuf;
>> +
>> +       /* DMABUF related */
>> +       struct dma_buf_attachment       *db_attach;
> 
> Unused?
> 

Indeed. There is no device to be attached to this buffer, so this
copy-and-paste field can be removed.

Regards,

	Hans

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

* Re: [RFCv6 PATCH 11/16] vb2: use dma_map_sg_attrs to prevent unnecessary sync
  2014-11-10 12:49 ` [RFCv6 PATCH 11/16] vb2: use dma_map_sg_attrs to prevent unnecessary sync Hans Verkuil
@ 2014-11-18  9:55   ` Pawel Osciak
  2014-11-18 10:11     ` Hans Verkuil
  0 siblings, 1 reply; 29+ messages in thread
From: Pawel Osciak @ 2014-11-18  9:55 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: LMML, Marek Szyprowski, Hans Verkuil

On Mon, Nov 10, 2014 at 8:49 PM, Hans Verkuil <hverkuil@xs4all.nl> wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
>
> By default dma_map_sg syncs the mapped buffer to the device. But
> buf_prepare expects a buffer syncs for the cpu and the buffer
> will be synced to the device in the prepare memop.
>
> The reverse is true for dma_unmap_sg, buf_finish and the finish
> memop.
>
> To prevent unnecessary syncs we ask dma_(un)map_sg to skip the
> sync.
>
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> ---
>  drivers/media/v4l2-core/videobuf2-dma-contig.c | 29 +++++++++++++++++-----
>  drivers/media/v4l2-core/videobuf2-dma-sg.c     | 33 +++++++++++++++++++++-----
>  2 files changed, 50 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c
> index c4305bf..27f5926 100644
> --- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
> +++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
> @@ -317,8 +317,9 @@ static struct sg_table *vb2_dc_dmabuf_ops_map(
>                 attach->dma_dir = DMA_NONE;
>         }
>
> -       /* mapping to the client with new direction */
> -       ret = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, dma_dir);
> +       /* Mapping to the client with new direction */
> +       ret = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
> +                        dma_dir);

Do we need this chunk?

-- 
Best regards,
Pawel Osciak

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

* Re: [RFCv6 PATCH 11/16] vb2: use dma_map_sg_attrs to prevent unnecessary sync
  2014-11-18  9:55   ` Pawel Osciak
@ 2014-11-18 10:11     ` Hans Verkuil
  0 siblings, 0 replies; 29+ messages in thread
From: Hans Verkuil @ 2014-11-18 10:11 UTC (permalink / raw)
  To: Pawel Osciak; +Cc: LMML, Marek Szyprowski, Hans Verkuil

On 11/18/14 10:55, Pawel Osciak wrote:
> On Mon, Nov 10, 2014 at 8:49 PM, Hans Verkuil <hverkuil@xs4all.nl> wrote:
>> From: Hans Verkuil <hans.verkuil@cisco.com>
>>
>> By default dma_map_sg syncs the mapped buffer to the device. But
>> buf_prepare expects a buffer syncs for the cpu and the buffer
>> will be synced to the device in the prepare memop.
>>
>> The reverse is true for dma_unmap_sg, buf_finish and the finish
>> memop.
>>
>> To prevent unnecessary syncs we ask dma_(un)map_sg to skip the
>> sync.
>>
>> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
>> ---
>>  drivers/media/v4l2-core/videobuf2-dma-contig.c | 29 +++++++++++++++++-----
>>  drivers/media/v4l2-core/videobuf2-dma-sg.c     | 33 +++++++++++++++++++++-----
>>  2 files changed, 50 insertions(+), 12 deletions(-)
>>
>> diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c
>> index c4305bf..27f5926 100644
>> --- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
>> +++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
>> @@ -317,8 +317,9 @@ static struct sg_table *vb2_dc_dmabuf_ops_map(
>>                 attach->dma_dir = DMA_NONE;
>>         }
>>
>> -       /* mapping to the client with new direction */
>> -       ret = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, dma_dir);
>> +       /* Mapping to the client with new direction */
>> +       ret = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
>> +                        dma_dir);
> 
> Do we need this chunk?
> 

I'll drop it.

Regards,

	Hans

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

end of thread, other threads:[~2014-11-18 10:11 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-10 12:49 [RFCv6 PATCH 00/16] vb2: improve dma-sg, expbuf Hans Verkuil
2014-11-10 12:49 ` [RFCv6 PATCH 01/16] videobuf2-core.h: improve documentation Hans Verkuil
2014-11-10 12:49 ` [RFCv6 PATCH 02/16] vb2: replace 'write' by 'dma_dir' Hans Verkuil
2014-11-16 12:34   ` Pawel Osciak
2014-11-10 12:49 ` [RFCv6 PATCH 03/16] vb2: add dma_dir to the alloc memop Hans Verkuil
2014-11-16 12:47   ` Pawel Osciak
2014-11-10 12:49 ` [RFCv6 PATCH 04/16] vb2-dma-sg: add allocation context to dma-sg Hans Verkuil
2014-11-16 13:13   ` Pawel Osciak
2014-11-17  9:18     ` Hans Verkuil
2014-11-10 12:49 ` [RFCv6 PATCH 05/16] vb2-dma-sg: move dma_(un)map_sg here Hans Verkuil
2014-11-10 12:49 ` [RFCv6 PATCH 06/16] vb2-dma-sg: add dmabuf import support Hans Verkuil
2014-11-16 13:29   ` Pawel Osciak
2014-11-10 12:49 ` [RFCv6 PATCH 07/16] vb2-dma-sg: add support for dmabuf exports Hans Verkuil
2014-11-16 13:35   ` Pawel Osciak
2014-11-10 12:49 ` [RFCv6 PATCH 08/16] vb2-vmalloc: " Hans Verkuil
2014-11-18  9:34   ` Pawel Osciak
2014-11-18  9:44     ` Hans Verkuil
2014-11-10 12:49 ` [RFCv6 PATCH 09/16] vivid: enable vb2_expbuf support Hans Verkuil
2014-11-18  9:38   ` Pawel Osciak
2014-11-10 12:49 ` [RFCv6 PATCH 10/16] vim2m: support expbuf Hans Verkuil
2014-11-18  9:40   ` Pawel Osciak
2014-11-10 12:49 ` [RFCv6 PATCH 11/16] vb2: use dma_map_sg_attrs to prevent unnecessary sync Hans Verkuil
2014-11-18  9:55   ` Pawel Osciak
2014-11-18 10:11     ` Hans Verkuil
2014-11-10 12:49 ` [RFCv6 PATCH 12/16] vb2: add begin/end_cpu_access functions Hans Verkuil
2014-11-10 12:49 ` [RFCv6 PATCH 13/16] videobuf2-dvb.c: convert to vb2_plane_begin_cpu_access() Hans Verkuil
2014-11-10 12:49 ` [RFCv6 PATCH 14/16] v4l: convert vb2_plane_vaddr to vb2_plane_begin_cpu_access Hans Verkuil
2014-11-10 12:49 ` [RFCv6 PATCH 15/16] vb2: drop the unused vb2_plane_vaddr function Hans Verkuil
2014-11-10 12:49 ` [RFCv6 PATCH 16/16] vb2: update the buf_prepare/finish documentation Hans Verkuil

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