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

Changes since v4:
- Rebased to latest media_tree master

Changes since v3:

- Dropped patch 02/10: succeeded by patch 10/15 in this series
- Added patches 11-15 to correctly handle syncing/mapping dmabuf
  buffers for CPU access. This was never done correctly before.
  Many thanks to Pawel Osciak for helping me with this during the
  media mini-summit last week.

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_addr() 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 14 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-10 if there are no
new comments. The issues that patches 11-15 address are separate from
the patches 1-10 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] 23+ messages in thread

* [RFCv5 PATCH 01/15] videobuf2-core.h: improve documentation
  2014-11-07  8:50 [RFCv5 PATCH 00/15] vb2: improve dma-sg, expbuf Hans Verkuil
@ 2014-11-07  8:50 ` Hans Verkuil
  2014-11-07  8:50 ` [RFCv5 PATCH 02/15] vb2-dma-sg: add allocation context to dma-sg Hans Verkuil
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2014-11-07  8:50 UTC (permalink / raw)
  To: linux-media; +Cc: pawel, m.szyprowski, 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] 23+ messages in thread

* [RFCv5 PATCH 02/15] vb2-dma-sg: add allocation context to dma-sg
  2014-11-07  8:50 [RFCv5 PATCH 00/15] vb2: improve dma-sg, expbuf Hans Verkuil
  2014-11-07  8:50 ` [RFCv5 PATCH 01/15] videobuf2-core.h: improve documentation Hans Verkuil
@ 2014-11-07  8:50 ` Hans Verkuil
  2014-11-08  8:46   ` Pawel Osciak
  2014-11-07  8:50 ` [RFCv5 PATCH 03/15] vb2-dma-sg: move dma_(un)map_sg here Hans Verkuil
                   ` (13 subsequent siblings)
  15 siblings, 1 reply; 23+ messages in thread
From: Hans Verkuil @ 2014-11-07  8:50 UTC (permalink / raw)
  To: linux-media; +Cc: pawel, m.szyprowski, 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 |  7 ++++
 drivers/media/platform/marvell-ccic/mcam-core.h |  1 +
 drivers/media/v4l2-core/videobuf2-core.c        |  3 +-
 drivers/media/v4l2-core/videobuf2-dma-contig.c  |  4 ++-
 drivers/media/v4l2-core/videobuf2-dma-sg.c      | 44 +++++++++++++++++++++++--
 drivers/media/v4l2-core/videobuf2-vmalloc.c     |  3 +-
 include/media/videobuf2-core.h                  |  3 +-
 include/media/videobuf2-dma-sg.h                |  3 ++
 24 files changed, 118 insertions(+), 15 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..0451522 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 = -ENOMEM;
+		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..4f166c5 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 = -ENOMEM;
+		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..0517fc9 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 = -ENOMEM;
+		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..1e450ed 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 = -ENOMEM;
+		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..20d53b6 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;
 }
 
@@ -1298,6 +1300,7 @@ static int mcam_setup_vb2(struct mcam_camera *cam)
 		vq->ops = &mcam_vb2_sg_ops;
 		vq->mem_ops = &vb2_dma_sg_memops;
 		vq->buf_struct_size = sizeof(struct mcam_vb_buffer);
+		cam->vb_alloc_ctx_sg = vb2_dma_sg_init_ctx(cam->dev);
 		vq->io_modes = VB2_MMAP | VB2_USERPTR;
 		cam->dma_setup = mcam_ctlr_dma_sg;
 		cam->frame_complete = mcam_dma_sg_done;
@@ -1326,6 +1329,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-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index f2e43de..490defb 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -189,6 +189,7 @@ 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;
+	int write = !V4L2_TYPE_IS_OUTPUT(q->type);
 	void *mem_priv;
 	int plane;
 
@@ -200,7 +201,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, write, 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 4a02ade..6675f12 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, int write,
+			  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 = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
 
 	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 9b163a4..ff77be7 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -30,11 +30,17 @@ 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				write;
 	int				offset;
+	enum dma_data_direction		dma_dir;
 	struct sg_table			sg_table;
 	size_t				size;
 	unsigned int			num_pages;
@@ -86,22 +92,27 @@ 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, int write,
+			      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;
 
 	buf->vaddr = NULL;
-	buf->write = 0;
+	buf->write = write;
 	buf->offset = 0;
 	buf->size = size;
 	/* size is already page aligned */
 	buf->num_pages = size >> PAGE_SHIFT;
+	buf->dma_dir = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
 
 	buf->pages = kzalloc(buf->num_pages * sizeof(struct page *),
 			     GFP_KERNEL);
@@ -117,6 +128,8 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_fla
 	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;
@@ -152,6 +165,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);
 	}
 }
@@ -164,6 +178,7 @@ 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)
 {
+	struct vb2_dma_sg_conf *conf = alloc_ctx;
 	struct vb2_dma_sg_buf *buf;
 	unsigned long first, last;
 	int num_pages_from_user;
@@ -177,6 +192,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
 	buf->write = write;
 	buf->offset = vaddr & ~PAGE_MASK;
 	buf->size = size;
+	buf->dma_dir = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
 
 	first = (vaddr           & PAGE_MASK) >> PAGE_SHIFT;
 	last  = ((vaddr + size - 1) & PAGE_MASK) >> PAGE_SHIFT;
@@ -233,6 +249,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:
@@ -272,6 +290,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);
 }
 
@@ -354,6 +373,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/drivers/media/v4l2-core/videobuf2-vmalloc.c b/drivers/media/v4l2-core/videobuf2-vmalloc.c
index 313d977..d77e397 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, int write,
+			       gfp_t gfp_flags)
 {
 	struct vb2_vmalloc_buf *buf;
 
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 70ace7c..49e278b 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -82,7 +82,8 @@ 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, int write,
+				  gfp_t gfp_flags);
 	void		(*put)(void *buf_priv);
 	struct dma_buf *(*get_dmabuf)(void *buf_priv, unsigned long flags);
 
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] 23+ messages in thread

* [RFCv5 PATCH 03/15] vb2-dma-sg: move dma_(un)map_sg here
  2014-11-07  8:50 [RFCv5 PATCH 00/15] vb2: improve dma-sg, expbuf Hans Verkuil
  2014-11-07  8:50 ` [RFCv5 PATCH 01/15] videobuf2-core.h: improve documentation Hans Verkuil
  2014-11-07  8:50 ` [RFCv5 PATCH 02/15] vb2-dma-sg: add allocation context to dma-sg Hans Verkuil
@ 2014-11-07  8:50 ` Hans Verkuil
  2014-11-08  9:44   ` Pawel Osciak
  2014-11-07  8:50 ` [RFCv5 PATCH 04/15] vb2-dma-sg: add dmabuf import support Hans Verkuil
                   ` (12 subsequent siblings)
  15 siblings, 1 reply; 23+ messages in thread
From: Hans Verkuil @ 2014-11-07  8:50 UTC (permalink / raw)
  To: linux-media; +Cc: pawel, m.szyprowski, 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>
---
 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 0451522..ff11dfd 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 0517fc9..c7b12d8 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 20d53b6..d48c3d4 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 ff77be7..7375923 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -97,6 +97,7 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size, int write,
 {
 	struct vb2_dma_sg_conf *conf = alloc_ctx;
 	struct vb2_dma_sg_buf *buf;
+	struct sg_table *sgt;
 	int ret;
 	int num_pages;
 
@@ -130,6 +131,12 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size, int write,
 
 	/* 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;
@@ -140,6 +147,9 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size, int write,
 		__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--)
@@ -154,11 +164,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);
@@ -170,6 +182,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));
@@ -183,6 +211,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)
@@ -251,8 +280,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",
@@ -275,10 +311,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);
@@ -366,6 +404,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] 23+ messages in thread

* [RFCv5 PATCH 04/15] vb2-dma-sg: add dmabuf import support
  2014-11-07  8:50 [RFCv5 PATCH 00/15] vb2: improve dma-sg, expbuf Hans Verkuil
                   ` (2 preceding siblings ...)
  2014-11-07  8:50 ` [RFCv5 PATCH 03/15] vb2-dma-sg: move dma_(un)map_sg here Hans Verkuil
@ 2014-11-07  8:50 ` Hans Verkuil
  2014-11-08 10:20   ` Pawel Osciak
  2014-11-07  8:50 ` [RFCv5 PATCH 05/15] vb2-dma-sg: add get_dmabuf Hans Verkuil
                   ` (11 subsequent siblings)
  15 siblings, 1 reply; 23+ messages in thread
From: Hans Verkuil @ 2014-11-07  8:50 UTC (permalink / raw)
  To: linux-media; +Cc: pawel, m.szyprowski, Hans Verkuil

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

Add support for dmabuf to vb2-dma-sg.

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

diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index 7375923..2795c27 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -42,11 +42,15 @@ struct vb2_dma_sg_buf {
 	int				offset;
 	enum dma_data_direction		dma_dir;
 	struct sg_table			sg_table;
+	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;
+
+	/* DMABUF related */
+	struct dma_buf_attachment	*db_attach;
 };
 
 static void vb2_dma_sg_put(void *buf_priv);
@@ -114,6 +118,7 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size, int write,
 	/* size is already page aligned */
 	buf->num_pages = size >> PAGE_SHIFT;
 	buf->dma_dir = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+	buf->dma_sgt = &buf->sg_table;
 
 	buf->pages = kzalloc(buf->num_pages * sizeof(struct page *),
 			     GFP_KERNEL);
@@ -124,7 +129,7 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size, int write,
 	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;
@@ -173,7 +178,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);
@@ -185,7 +190,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);
 }
@@ -193,7 +202,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);
 }
@@ -222,6 +235,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
 	buf->offset = vaddr & ~PAGE_MASK;
 	buf->size = size;
 	buf->dma_dir = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+	buf->dma_sgt = &buf->sg_table;
 
 	first = (vaddr           & PAGE_MASK) >> PAGE_SHIFT;
 	last  = ((vaddr + size - 1) & PAGE_MASK) >> PAGE_SHIFT;
@@ -274,7 +288,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;
 
@@ -319,7 +333,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->write)
 			set_page_dirty_lock(buf->pages[i]);
@@ -392,11 +406,105 @@ 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_OR_NULL(sgt)) {
+		pr_err("Error getting dmabuf scatterlist\n");
+		return -EINVAL;
+	}
+
+	buf->dma_sgt = sgt;
+
+	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;
+	}
+
+	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, int write)
+{
+	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 = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+	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 = {
@@ -409,6 +517,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] 23+ messages in thread

* [RFCv5 PATCH 05/15] vb2-dma-sg: add get_dmabuf
  2014-11-07  8:50 [RFCv5 PATCH 00/15] vb2: improve dma-sg, expbuf Hans Verkuil
                   ` (3 preceding siblings ...)
  2014-11-07  8:50 ` [RFCv5 PATCH 04/15] vb2-dma-sg: add dmabuf import support Hans Verkuil
@ 2014-11-07  8:50 ` Hans Verkuil
  2014-11-08 10:45   ` Pawel Osciak
  2014-11-07  8:50 ` [RFCv5 PATCH 06/15] vb2-vmalloc: add get_dmabuf support Hans Verkuil
                   ` (10 subsequent siblings)
  15 siblings, 1 reply; 23+ messages in thread
From: Hans Verkuil @ 2014-11-07  8:50 UTC (permalink / raw)
  To: linux-media; +Cc: pawel, m.szyprowski, 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 2795c27..ca28a50 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -407,6 +407,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 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->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->dir != DMA_NONE)
+		dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
+			attach->dir);
+	sg_free_table(sgt);
+	kfree(attach);
+	db_attach->priv = NULL;
+}
+
+static struct sg_table *vb2_dma_sg_dmabuf_ops_map(
+	struct dma_buf_attachment *db_attach, enum dma_data_direction 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->dir == dir) {
+		mutex_unlock(lock);
+		return sgt;
+	}
+
+	/* release any previous cache */
+	if (attach->dir != DMA_NONE) {
+		dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
+			attach->dir);
+		attach->dir = DMA_NONE;
+	}
+
+	/* mapping to the client with new direction */
+	ret = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, dir);
+	if (ret <= 0) {
+		pr_err("failed to map scatterlist\n");
+		mutex_unlock(lock);
+		return ERR_PTR(-EIO);
+	}
+
+	attach->dir = dir;
+
+	mutex_unlock(lock);
+
+	return sgt;
+}
+
+static void vb2_dma_sg_dmabuf_ops_unmap(struct dma_buf_attachment *db_attach,
+	struct sg_table *sgt, enum dma_data_direction dir)
+{
+	/* nothing to be done here */
+}
+
+static void vb2_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 + pgnum * PAGE_SIZE;
+}
+
+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        */
 /*********************************************/
 
@@ -517,6 +686,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] 23+ messages in thread

* [RFCv5 PATCH 06/15] vb2-vmalloc: add get_dmabuf support
  2014-11-07  8:50 [RFCv5 PATCH 00/15] vb2: improve dma-sg, expbuf Hans Verkuil
                   ` (4 preceding siblings ...)
  2014-11-07  8:50 ` [RFCv5 PATCH 05/15] vb2-dma-sg: add get_dmabuf Hans Verkuil
@ 2014-11-07  8:50 ` Hans Verkuil
  2014-11-07  8:50 ` [RFCv5 PATCH 07/15] vb2: replace 'write' by 'dma_dir' Hans Verkuil
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2014-11-07  8:50 UTC (permalink / raw)
  To: linux-media; +Cc: pawel, m.szyprowski, 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 d77e397..437fbcd 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);
@@ -210,6 +213,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 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->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->dir != DMA_NONE)
+		dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
+			attach->dir);
+	sg_free_table(sgt);
+	kfree(attach);
+	db_attach->priv = NULL;
+}
+
+static struct sg_table *vb2_vmalloc_dmabuf_ops_map(
+	struct dma_buf_attachment *db_attach, enum dma_data_direction 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->dir == dir) {
+		mutex_unlock(lock);
+		return sgt;
+	}
+
+	/* release any previous cache */
+	if (attach->dir != DMA_NONE) {
+		dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
+			attach->dir);
+		attach->dir = DMA_NONE;
+	}
+
+	/* mapping to the client with new direction */
+	ret = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, dir);
+	if (ret <= 0) {
+		pr_err("failed to map scatterlist\n");
+		mutex_unlock(lock);
+		return ERR_PTR(-EIO);
+	}
+
+	attach->dir = dir;
+
+	mutex_unlock(lock);
+
+	return sgt;
+}
+
+static void vb2_vmalloc_dmabuf_ops_unmap(struct dma_buf_attachment *db_attach,
+	struct sg_table *sgt, enum dma_data_direction dir)
+{
+	/* nothing to be done here */
+}
+
+static void vb2_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        */
 /*********************************************/
 
@@ -265,6 +438,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] 23+ messages in thread

* [RFCv5 PATCH 07/15] vb2: replace 'write' by 'dma_dir'
  2014-11-07  8:50 [RFCv5 PATCH 00/15] vb2: improve dma-sg, expbuf Hans Verkuil
                   ` (5 preceding siblings ...)
  2014-11-07  8:50 ` [RFCv5 PATCH 06/15] vb2-vmalloc: add get_dmabuf support Hans Verkuil
@ 2014-11-07  8:50 ` Hans Verkuil
  2014-11-08 11:19   ` Pawel Osciak
  2014-11-07  8:50 ` [RFCv5 PATCH 08/15] vivid: enable vb2_expbuf support Hans Verkuil
                   ` (8 subsequent siblings)
  15 siblings, 1 reply; 23+ messages in thread
From: Hans Verkuil @ 2014-11-07  8:50 UTC (permalink / raw)
  To: linux-media; +Cc: pawel, m.szyprowski, 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       | 15 +++++----
 drivers/media/v4l2-core/videobuf2-dma-contig.c | 46 ++++++++++++++------------
 drivers/media/v4l2-core/videobuf2-dma-sg.c     | 46 ++++++++++++--------------
 drivers/media/v4l2-core/videobuf2-vmalloc.c    | 20 ++++++-----
 include/media/videobuf2-core.h                 | 11 +++---
 5 files changed, 73 insertions(+), 65 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index 490defb..7aed8f2 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -189,7 +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;
-	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;
 	void *mem_priv;
 	int plane;
 
@@ -201,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, write, q->gfp_flags);
+				      size, dma_dir, q->gfp_flags);
 		if (IS_ERR_OR_NULL(mem_priv))
 			goto free;
 
@@ -1359,7 +1360,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);
@@ -1401,7 +1403,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);
@@ -1462,7 +1464,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);
@@ -1510,7 +1513,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 6675f12..c4305bf 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -155,8 +155,8 @@ static void vb2_dc_put(void *buf_priv)
 	kfree(buf);
 }
 
-static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size, int write,
-			  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;
@@ -177,7 +177,7 @@ static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size, int write,
 	/* Prevent the device from being released while the buffer is used */
 	buf->dev = get_device(dev);
 	buf->size = size;
-	buf->dma_dir = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+	buf->dma_dir = dma_dir;
 
 	buf->handler.refcount = &buf->refcount;
 	buf->handler.put = vb2_dc_put;
@@ -231,7 +231,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,
@@ -266,7 +266,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;
@@ -284,16 +284,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 */
@@ -305,27 +305,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);
 
@@ -333,7 +333,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 */
 }
@@ -462,7 +462,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;
@@ -484,7 +485,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) {
@@ -553,7 +554,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;
@@ -584,7 +585,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;
@@ -620,7 +621,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) {
@@ -784,7 +786,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;
@@ -806,7 +808,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 ca28a50..49ba502 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -38,7 +38,6 @@ struct vb2_dma_sg_buf {
 	struct device			*dev;
 	void				*vaddr;
 	struct page			**pages;
-	int				write;
 	int				offset;
 	enum dma_data_direction		dma_dir;
 	struct sg_table			sg_table;
@@ -96,8 +95,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, int write,
-			      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_conf *conf = alloc_ctx;
 	struct vb2_dma_sg_buf *buf;
@@ -112,12 +111,11 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size, int write,
 		return NULL;
 
 	buf->vaddr = NULL;
-	buf->write = write;
 	buf->offset = 0;
 	buf->size = size;
 	/* size is already page aligned */
 	buf->num_pages = size >> PAGE_SHIFT;
-	buf->dma_dir = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+	buf->dma_dir = dma_dir;
 	buf->dma_sgt = &buf->sg_table;
 
 	buf->pages = kzalloc(buf->num_pages * sizeof(struct page *),
@@ -217,7 +215,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_conf *conf = alloc_ctx;
 	struct vb2_dma_sg_buf *buf;
@@ -231,10 +230,9 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
 		return NULL;
 
 	buf->vaddr = NULL;
-	buf->write = write;
 	buf->offset = vaddr & ~PAGE_MASK;
 	buf->size = size;
-	buf->dma_dir = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+	buf->dma_dir = dma_dir;
 	buf->dma_sgt = &buf->sg_table;
 
 	first = (vaddr           & PAGE_MASK) >> PAGE_SHIFT;
@@ -280,7 +278,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);
@@ -335,7 +333,7 @@ static void vb2_dma_sg_put_userptr(void *buf_priv)
 		vm_unmap_ram(buf->vaddr, buf->num_pages);
 	sg_free_table(buf->dma_sgt);
 	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]);
@@ -412,7 +410,7 @@ static int vb2_dma_sg_mmap(void *buf_priv, struct vm_area_struct *vma)
 
 struct vb2_dma_sg_attachment {
 	struct sg_table sgt;
-	enum dma_data_direction dir;
+	enum dma_data_direction dma_dir;
 };
 
 static int vb2_dma_sg_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev,
@@ -447,7 +445,7 @@ static int vb2_dma_sg_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;
@@ -465,16 +463,16 @@ static void vb2_dma_sg_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_dma_sg_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_dma_sg_attachment *attach = db_attach->priv;
 	/* stealing dmabuf mutex to serialize map/unmap operations */
@@ -486,27 +484,27 @@ static struct sg_table *vb2_dma_sg_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);
 
@@ -514,7 +512,7 @@ static struct sg_table *vb2_dma_sg_dmabuf_ops_map(
 }
 
 static void vb2_dma_sg_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 */
 }
@@ -640,7 +638,7 @@ static void vb2_dma_sg_detach_dmabuf(void *mem_priv)
 }
 
 static void *vb2_dma_sg_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_dma_sg_conf *conf = alloc_ctx;
 	struct vb2_dma_sg_buf *buf;
@@ -662,7 +660,7 @@ static void *vb2_dma_sg_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-vmalloc.c b/drivers/media/v4l2-core/videobuf2-vmalloc.c
index 437fbcd..0f79f8d 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;
@@ -38,8 +38,8 @@ struct vb2_vmalloc_buf {
 
 static void vb2_vmalloc_put(void *buf_priv);
 
-static void *vb2_vmalloc_alloc(void *alloc_ctx, unsigned long size, int write,
-			       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;
 
@@ -74,7 +74,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;
@@ -86,7 +87,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;
 
@@ -111,7 +112,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;
@@ -148,7 +150,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]);
 		}
@@ -414,7 +416,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;
 
@@ -426,7 +428,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 49e278b..fcd2af6 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -82,20 +82,23 @@ struct vb2_threadio_data;
  *				  unmap_dmabuf.
  */
 struct vb2_mem_ops {
-	void		*(*alloc)(void *alloc_ctx, unsigned long size, int write,
-				  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);
 
 	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] 23+ messages in thread

* [RFCv5 PATCH 08/15] vivid: enable vb2_expbuf support.
  2014-11-07  8:50 [RFCv5 PATCH 00/15] vb2: improve dma-sg, expbuf Hans Verkuil
                   ` (6 preceding siblings ...)
  2014-11-07  8:50 ` [RFCv5 PATCH 07/15] vb2: replace 'write' by 'dma_dir' Hans Verkuil
@ 2014-11-07  8:50 ` Hans Verkuil
  2014-11-07  8:50 ` [RFCv5 PATCH 09/15] vim2m: support expbuf Hans Verkuil
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2014-11-07  8:50 UTC (permalink / raw)
  To: linux-media; +Cc: pawel, m.szyprowski, 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] 23+ messages in thread

* [RFCv5 PATCH 09/15] vim2m: support expbuf
  2014-11-07  8:50 [RFCv5 PATCH 00/15] vb2: improve dma-sg, expbuf Hans Verkuil
                   ` (7 preceding siblings ...)
  2014-11-07  8:50 ` [RFCv5 PATCH 08/15] vivid: enable vb2_expbuf support Hans Verkuil
@ 2014-11-07  8:50 ` Hans Verkuil
  2014-11-07  8:50 ` [RFCv5 PATCH 10/15] vb2: use dma_map_sg_attrs to prevent unnecessary sync Hans Verkuil
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2014-11-07  8:50 UTC (permalink / raw)
  To: linux-media; +Cc: pawel, m.szyprowski, 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] 23+ messages in thread

* [RFCv5 PATCH 10/15] vb2: use dma_map_sg_attrs to prevent unnecessary sync
  2014-11-07  8:50 [RFCv5 PATCH 00/15] vb2: improve dma-sg, expbuf Hans Verkuil
                   ` (8 preceding siblings ...)
  2014-11-07  8:50 ` [RFCv5 PATCH 09/15] vim2m: support expbuf Hans Verkuil
@ 2014-11-07  8:50 ` Hans Verkuil
  2014-11-07  8:50 ` [RFCv5 PATCH 11/15] vb2: add begin/end_cpu_access functions Hans Verkuil
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2014-11-07  8:50 UTC (permalink / raw)
  To: linux-media; +Cc: pawel, m.szyprowski, 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 49ba502..4d0e552 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -103,6 +103,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;
@@ -136,9 +139,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;
@@ -171,9 +178,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);
@@ -224,6 +235,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)
@@ -294,9 +308,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:
@@ -325,10 +343,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] 23+ messages in thread

* [RFCv5 PATCH 11/15] vb2: add begin/end_cpu_access functions
  2014-11-07  8:50 [RFCv5 PATCH 00/15] vb2: improve dma-sg, expbuf Hans Verkuil
                   ` (9 preceding siblings ...)
  2014-11-07  8:50 ` [RFCv5 PATCH 10/15] vb2: use dma_map_sg_attrs to prevent unnecessary sync Hans Verkuil
@ 2014-11-07  8:50 ` Hans Verkuil
  2014-11-07  8:50 ` [RFCv5 PATCH 12/15] videobuf2-dvb.c: convert to vb2_plane_begin_cpu_access() Hans Verkuil
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2014-11-07  8:50 UTC (permalink / raw)
  To: linux-media; +Cc: pawel, m.szyprowski, 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     | 71 +++++++++++++++++++++++++-
 drivers/media/v4l2-core/videobuf2-vmalloc.c    | 39 +++++++++++++-
 include/media/videobuf2-core.h                 | 16 ++++--
 5 files changed, 228 insertions(+), 19 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 4d0e552..954ce74 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -544,18 +544,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 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;
 
+	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,
@@ -569,9 +602,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,
 };
@@ -688,6 +725,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;
@@ -710,6 +777,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 0f79f8d..8623752 100644
--- a/drivers/media/v4l2-core/videobuf2-vmalloc.c
+++ b/drivers/media/v4l2-core/videobuf2-vmalloc.c
@@ -337,15 +337,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,
@@ -434,6 +435,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,
@@ -446,6 +479,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 fcd2af6..91c1216 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] 23+ messages in thread

* [RFCv5 PATCH 12/15] videobuf2-dvb.c: convert to vb2_plane_begin_cpu_access()
  2014-11-07  8:50 [RFCv5 PATCH 00/15] vb2: improve dma-sg, expbuf Hans Verkuil
                   ` (10 preceding siblings ...)
  2014-11-07  8:50 ` [RFCv5 PATCH 11/15] vb2: add begin/end_cpu_access functions Hans Verkuil
@ 2014-11-07  8:50 ` Hans Verkuil
  2014-11-07  8:50 ` [RFCv5 PATCH 13/15] v4l: convert vb2_plane_vaddr to vb2_plane_begin_cpu_access Hans Verkuil
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2014-11-07  8:50 UTC (permalink / raw)
  To: linux-media; +Cc: pawel, m.szyprowski, 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] 23+ messages in thread

* [RFCv5 PATCH 13/15] v4l: convert vb2_plane_vaddr to vb2_plane_begin_cpu_access
  2014-11-07  8:50 [RFCv5 PATCH 00/15] vb2: improve dma-sg, expbuf Hans Verkuil
                   ` (11 preceding siblings ...)
  2014-11-07  8:50 ` [RFCv5 PATCH 12/15] videobuf2-dvb.c: convert to vb2_plane_begin_cpu_access() Hans Verkuil
@ 2014-11-07  8:50 ` Hans Verkuil
  2014-11-07  8:50 ` [RFCv5 PATCH 14/15] vb2: drop the unused vb2_plane_vaddr function Hans Verkuil
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2014-11-07  8:50 UTC (permalink / raw)
  To: linux-media; +Cc: pawel, m.szyprowski, 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 d48c3d4..7fa90c6 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] 23+ messages in thread

* [RFCv5 PATCH 14/15] vb2: drop the unused vb2_plane_vaddr function.
  2014-11-07  8:50 [RFCv5 PATCH 00/15] vb2: improve dma-sg, expbuf Hans Verkuil
                   ` (12 preceding siblings ...)
  2014-11-07  8:50 ` [RFCv5 PATCH 13/15] v4l: convert vb2_plane_vaddr to vb2_plane_begin_cpu_access Hans Verkuil
@ 2014-11-07  8:50 ` Hans Verkuil
  2014-11-07  8:50 ` [RFCv5 PATCH 15/15] vb2: update the buf_prepare/finish documentation Hans Verkuil
  2014-11-07  9:19 ` [RFCv5 PATCH 00/15] vb2: improve dma-sg, expbuf Hans Verkuil
  15 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2014-11-07  8:50 UTC (permalink / raw)
  To: linux-media; +Cc: pawel, m.szyprowski, 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     |  1 -
 drivers/media/v4l2-core/videobuf2-vmalloc.c    |  1 -
 include/media/videobuf2-core.h                 |  6 +-----
 5 files changed, 2 insertions(+), 25 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 954ce74..0281a85 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -769,7 +769,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 8623752..5c21190 100644
--- a/drivers/media/v4l2-core/videobuf2-vmalloc.c
+++ b/drivers/media/v4l2-core/videobuf2-vmalloc.c
@@ -478,7 +478,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 91c1216..4632341 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] 23+ messages in thread

* [RFCv5 PATCH 15/15] vb2: update the buf_prepare/finish documentation
  2014-11-07  8:50 [RFCv5 PATCH 00/15] vb2: improve dma-sg, expbuf Hans Verkuil
                   ` (13 preceding siblings ...)
  2014-11-07  8:50 ` [RFCv5 PATCH 14/15] vb2: drop the unused vb2_plane_vaddr function Hans Verkuil
@ 2014-11-07  8:50 ` Hans Verkuil
  2014-11-07  9:19 ` [RFCv5 PATCH 00/15] vb2: improve dma-sg, expbuf Hans Verkuil
  15 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2014-11-07  8:50 UTC (permalink / raw)
  To: linux-media; +Cc: pawel, m.szyprowski, 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 4632341..6a15eb8 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] 23+ messages in thread

* Re: [RFCv5 PATCH 00/15] vb2: improve dma-sg, expbuf
  2014-11-07  8:50 [RFCv5 PATCH 00/15] vb2: improve dma-sg, expbuf Hans Verkuil
                   ` (14 preceding siblings ...)
  2014-11-07  8:50 ` [RFCv5 PATCH 15/15] vb2: update the buf_prepare/finish documentation Hans Verkuil
@ 2014-11-07  9:19 ` Hans Verkuil
  15 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2014-11-07  9:19 UTC (permalink / raw)
  To: linux-media; +Cc: pawel, m.szyprowski

On 11/07/2014 09:50 AM, Hans Verkuil wrote:
> Changes since v4:
> - Rebased to latest media_tree master
> 
> Changes since v3:
> 
> - Dropped patch 02/10: succeeded by patch 10/15 in this series
> - Added patches 11-15 to correctly handle syncing/mapping dmabuf
>   buffers for CPU access. This was never done correctly before.
>   Many thanks to Pawel Osciak for helping me with this during the
>   media mini-summit last week.
> 
> 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_addr() 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 14 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-10 if there are no
> new comments. The issues that patches 11-15 address are separate from
> the patches 1-10 and this is only an issue when using dmabuf with
> drivers that need cpu access.

To be specific: consider patches 1-10 as being patches ready to merge,
while patches 11-15 are still in the RFC stage.

Regards,

	Hans

> 
> Reviews are very welcome.
> 
> Regards,
> 
> 	Hans
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


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

* Re: [RFCv5 PATCH 02/15] vb2-dma-sg: add allocation context to dma-sg
  2014-11-07  8:50 ` [RFCv5 PATCH 02/15] vb2-dma-sg: add allocation context to dma-sg Hans Verkuil
@ 2014-11-08  8:46   ` Pawel Osciak
  0 siblings, 0 replies; 23+ messages in thread
From: Pawel Osciak @ 2014-11-08  8:46 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: LMML, Marek Szyprowski, Hans Verkuil

Hi Hans,
Thank you for the patch!

On Fri, Nov 7, 2014 at 5:50 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.

This patch does a bit more, i.e. adds DMA direction. Perhaps it should
be split into two?
>
> 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 |  7 ++++
>  drivers/media/platform/marvell-ccic/mcam-core.h |  1 +
>  drivers/media/v4l2-core/videobuf2-core.c        |  3 +-
>  drivers/media/v4l2-core/videobuf2-dma-contig.c  |  4 ++-
>  drivers/media/v4l2-core/videobuf2-dma-sg.c      | 44 +++++++++++++++++++++++--
>  drivers/media/v4l2-core/videobuf2-vmalloc.c     |  3 +-
>  include/media/videobuf2-core.h                  |  3 +-
>  include/media/videobuf2-dma-sg.h                |  3 ++
>  24 files changed, 118 insertions(+), 15 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..0451522 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 = -ENOMEM;

Perhaps:
err = PTR_ERR(dev->alloc->ctx);
Here and in other places.

> +               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..4f166c5 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 = -ENOMEM;
> +               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..0517fc9 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 = -ENOMEM;
> +               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..1e450ed 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 = -ENOMEM;
> +               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..20d53b6 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;
>  }
>
> @@ -1298,6 +1300,7 @@ static int mcam_setup_vb2(struct mcam_camera *cam)
>                 vq->ops = &mcam_vb2_sg_ops;
>                 vq->mem_ops = &vb2_dma_sg_memops;
>                 vq->buf_struct_size = sizeof(struct mcam_vb_buffer);
> +               cam->vb_alloc_ctx_sg = vb2_dma_sg_init_ctx(cam->dev);

Need to check return value. dma-contig path seems to be missing this too?

>                 vq->io_modes = VB2_MMAP | VB2_USERPTR;
>                 cam->dma_setup = mcam_ctlr_dma_sg;
>                 cam->frame_complete = mcam_dma_sg_done;
> @@ -1326,6 +1329,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-core.c b/drivers/media/v4l2-core/videobuf2-core.c
> index f2e43de..490defb 100644
> --- a/drivers/media/v4l2-core/videobuf2-core.c
> +++ b/drivers/media/v4l2-core/videobuf2-core.c
> @@ -189,6 +189,7 @@ 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;
> +       int write = !V4L2_TYPE_IS_OUTPUT(q->type);
>         void *mem_priv;
>         int plane;
>
> @@ -200,7 +201,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, write, 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 4a02ade..6675f12 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, int write,
> +                         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 = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
>
>         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 9b163a4..ff77be7 100644
> --- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
> +++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
> @@ -30,11 +30,17 @@ 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                             write;
>         int                             offset;
> +       enum dma_data_direction         dma_dir;

Do we need both dma_dir and write?

>         struct sg_table                 sg_table;
>         size_t                          size;
>         unsigned int                    num_pages;
> @@ -86,22 +92,27 @@ 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, int write,
> +                             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;
>
>         buf->vaddr = NULL;
> -       buf->write = 0;
> +       buf->write = write;
>         buf->offset = 0;
>         buf->size = size;
>         /* size is already page aligned */
>         buf->num_pages = size >> PAGE_SHIFT;
> +       buf->dma_dir = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
>
>         buf->pages = kzalloc(buf->num_pages * sizeof(struct page *),
>                              GFP_KERNEL);
> @@ -117,6 +128,8 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_fla
>         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;
> @@ -152,6 +165,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);
>         }
>  }
> @@ -164,6 +178,7 @@ 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)
>  {
> +       struct vb2_dma_sg_conf *conf = alloc_ctx;
>         struct vb2_dma_sg_buf *buf;
>         unsigned long first, last;
>         int num_pages_from_user;
> @@ -177,6 +192,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
>         buf->write = write;
>         buf->offset = vaddr & ~PAGE_MASK;
>         buf->size = size;
> +       buf->dma_dir = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
>
>         first = (vaddr           & PAGE_MASK) >> PAGE_SHIFT;
>         last  = ((vaddr + size - 1) & PAGE_MASK) >> PAGE_SHIFT;
> @@ -233,6 +249,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:
> @@ -272,6 +290,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);
>  }
>
> @@ -354,6 +373,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/drivers/media/v4l2-core/videobuf2-vmalloc.c b/drivers/media/v4l2-core/videobuf2-vmalloc.c
> index 313d977..d77e397 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, int write,
> +                              gfp_t gfp_flags)
>  {
>         struct vb2_vmalloc_buf *buf;
>
> diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
> index 70ace7c..49e278b 100644
> --- a/include/media/videobuf2-core.h
> +++ b/include/media/videobuf2-core.h
> @@ -82,7 +82,8 @@ 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, int write,
> +                                 gfp_t gfp_flags);
>         void            (*put)(void *buf_priv);
>         struct dma_buf *(*get_dmabuf)(void *buf_priv, unsigned long flags);
>
> 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
>



-- 
Best regards,
Pawel Osciak

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

* Re: [RFCv5 PATCH 03/15] vb2-dma-sg: move dma_(un)map_sg here
  2014-11-07  8:50 ` [RFCv5 PATCH 03/15] vb2-dma-sg: move dma_(un)map_sg here Hans Verkuil
@ 2014-11-08  9:44   ` Pawel Osciak
  0 siblings, 0 replies; 23+ messages in thread
From: Pawel Osciak @ 2014-11-08  9:44 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: LMML, Marek Szyprowski, Hans Verkuil

Hi Hans,
Thank you for the patch.

On Fri, Nov 7, 2014 at 5:50 PM, Hans Verkuil <hverkuil@xs4all.nl> wrote:
> 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>

-- 
Best regards,
Pawel Osciak

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

* Re: [RFCv5 PATCH 04/15] vb2-dma-sg: add dmabuf import support
  2014-11-07  8:50 ` [RFCv5 PATCH 04/15] vb2-dma-sg: add dmabuf import support Hans Verkuil
@ 2014-11-08 10:20   ` Pawel Osciak
  2014-11-08 10:43     ` Pawel Osciak
  0 siblings, 1 reply; 23+ messages in thread
From: Pawel Osciak @ 2014-11-08 10:20 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: LMML, Marek Szyprowski, Hans Verkuil

Hi Hans,
Thank you for the patch.

On Fri, Nov 7, 2014 at 5:50 PM, Hans Verkuil <hverkuil@xs4all.nl> wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
>
> Add support for dmabuf to vb2-dma-sg.

importing dmabuf into videobuf2-dma-sg.

>
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> ---
>  drivers/media/v4l2-core/videobuf2-dma-sg.c | 126 +++++++++++++++++++++++++++--
>  1 file changed, 119 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c
> index 7375923..2795c27 100644
> --- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
> +++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
> @@ -42,11 +42,15 @@ struct vb2_dma_sg_buf {
>         int                             offset;
>         enum dma_data_direction         dma_dir;
>         struct sg_table                 sg_table;
> +       struct sg_table                 *dma_sgt;

Perhaps it would be useful to add a comment when this points to
sg_table and when not...

>         size_t                          size;
>         unsigned int                    num_pages;
>         atomic_t                        refcount;
>         struct vb2_vmarea_handler       handler;
>         struct vm_area_struct           *vma;
> +
> +       /* DMABUF related */

I'd remove this comment.

> +       struct dma_buf_attachment       *db_attach;
>  };
>
>  static void vb2_dma_sg_put(void *buf_priv);
> @@ -114,6 +118,7 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size, int write,
>         /* size is already page aligned */
>         buf->num_pages = size >> PAGE_SHIFT;
>         buf->dma_dir = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
> +       buf->dma_sgt = &buf->sg_table;
>
>         buf->pages = kzalloc(buf->num_pages * sizeof(struct page *),
>                              GFP_KERNEL);
> @@ -124,7 +129,7 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size, int write,
>         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;
> @@ -173,7 +178,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);
> @@ -185,7 +190,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);
>  }
> @@ -193,7 +202,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);
>  }
> @@ -222,6 +235,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
>         buf->offset = vaddr & ~PAGE_MASK;
>         buf->size = size;
>         buf->dma_dir = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
> +       buf->dma_sgt = &buf->sg_table;
>
>         first = (vaddr           & PAGE_MASK) >> PAGE_SHIFT;
>         last  = ((vaddr + size - 1) & PAGE_MASK) >> PAGE_SHIFT;
> @@ -274,7 +288,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;
>
> @@ -319,7 +333,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->write)
>                         set_page_dirty_lock(buf->pages[i]);
> @@ -392,11 +406,105 @@ 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_OR_NULL(sgt)) {

Hm, this was changed to IS_ERR() in dma-contig quite a long time ago
(see http://git.linuxtv.org/cgit.cgi/media_tree.git/commit/drivers/media/v4l2-core/videobuf2-dma-contig.c?id=fee0c54e28f6ca187add93dfca226a8093cfa931).
Are you basing this on an old version of dma-contig?

> +               pr_err("Error getting dmabuf scatterlist\n");
> +               return -EINVAL;
> +       }
> +
> +       buf->dma_sgt = sgt;

In another patch also upstream in contig
(http://git.linuxtv.org/cgit.cgi/media_tree.git/commit/drivers/media/v4l2-core/videobuf2-dma-contig.c?id=6bbd4fec0cd93823fe651fa3907bee2bc6c814f6),
we have

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;
> +       }
> +
> +       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, int write)
> +{
> +       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 */

I'd remove this comment, it's not that correct either.

> +       dba = dma_buf_attach(dbuf, buf->dev);
> +       if (IS_ERR(dba)) {
> +               pr_err("failed to attach dmabuf\n");
> +               kfree(buf);
> +               return dba;
> +       }
> +
> +       buf->dma_dir = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
> +       buf->size = size;
> +       buf->db_attach = dba;
> +
> +       return buf;
> +}
> +
>  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 = {
> @@ -409,6 +517,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
>



-- 
Best regards,
Pawel Osciak

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

* Re: [RFCv5 PATCH 04/15] vb2-dma-sg: add dmabuf import support
  2014-11-08 10:20   ` Pawel Osciak
@ 2014-11-08 10:43     ` Pawel Osciak
  0 siblings, 0 replies; 23+ messages in thread
From: Pawel Osciak @ 2014-11-08 10:43 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: LMML, Marek Szyprowski, Hans Verkuil

On Sat, Nov 8, 2014 at 7:20 PM, Pawel Osciak <pawel@osciak.com> wrote:
> Hi Hans,
> Thank you for the patch.
>
> On Fri, Nov 7, 2014 at 5:50 PM, Hans Verkuil <hverkuil@xs4all.nl> wrote:
>> From: Hans Verkuil <hans.verkuil@cisco.com>
>>
>> Add support for dmabuf to vb2-dma-sg.
>
> importing dmabuf into videobuf2-dma-sg.
>

One thing I missed in the review, I think vb2_dma_sg_vaddr() needs to
be updated in this patch to take into account that we may have an
attachment present, just like it's done in dma-contig, i.e. if !vaddr
and attachment present, call the dma_buf_vmap() dmabuf op instead of
vm_map_ram.

-- 
Best regards,
Pawel Osciak

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

* Re: [RFCv5 PATCH 05/15] vb2-dma-sg: add get_dmabuf
  2014-11-07  8:50 ` [RFCv5 PATCH 05/15] vb2-dma-sg: add get_dmabuf Hans Verkuil
@ 2014-11-08 10:45   ` Pawel Osciak
  0 siblings, 0 replies; 23+ messages in thread
From: Pawel Osciak @ 2014-11-08 10:45 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: LMML, Marek Szyprowski, Hans Verkuil

Hi Hans,
Thank you for the patch.

On Fri, Nov 7, 2014 at 5:50 PM, Hans Verkuil <hverkuil@xs4all.nl> wrote:
> From: Hans Verkuil <hansverk@cisco.com>
>
> Add DMABUF export support to vb2-dma-sg.

I think we should mention in the subject that this adds dmabuf export to 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 2795c27..ca28a50 100644
> --- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
> +++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
> @@ -407,6 +407,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 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->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->dir != DMA_NONE)
> +               dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
> +                       attach->dir);
> +       sg_free_table(sgt);
> +       kfree(attach);
> +       db_attach->priv = NULL;
> +}
> +
> +static struct sg_table *vb2_dma_sg_dmabuf_ops_map(
> +       struct dma_buf_attachment *db_attach, enum dma_data_direction 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->dir == dir) {
> +               mutex_unlock(lock);
> +               return sgt;
> +       }
> +
> +       /* release any previous cache */
> +       if (attach->dir != DMA_NONE) {
> +               dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
> +                       attach->dir);
> +               attach->dir = DMA_NONE;
> +       }
> +
> +       /* mapping to the client with new direction */
> +       ret = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, dir);
> +       if (ret <= 0) {
> +               pr_err("failed to map scatterlist\n");
> +               mutex_unlock(lock);
> +               return ERR_PTR(-EIO);
> +       }
> +
> +       attach->dir = dir;
> +
> +       mutex_unlock(lock);
> +
> +       return sgt;
> +}
> +
> +static void vb2_dma_sg_dmabuf_ops_unmap(struct dma_buf_attachment *db_attach,
> +       struct sg_table *sgt, enum dma_data_direction dir)
> +{
> +       /* nothing to be done here */
> +}
> +
> +static void vb2_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 + pgnum * PAGE_SIZE;

As opposed to contig, which assigns vaddr on alloc(), vaddr can very
well be NULL here for sg.

-- 
Best regards,
Pawel Osciak

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

* Re: [RFCv5 PATCH 07/15] vb2: replace 'write' by 'dma_dir'
  2014-11-07  8:50 ` [RFCv5 PATCH 07/15] vb2: replace 'write' by 'dma_dir' Hans Verkuil
@ 2014-11-08 11:19   ` Pawel Osciak
  0 siblings, 0 replies; 23+ messages in thread
From: Pawel Osciak @ 2014-11-08 11:19 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: LMML, Marek Szyprowski, Hans Verkuil

Hi Hans,

On Fri, Nov 7, 2014 at 5:50 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.

Do we need the first patch adding write then? Maybe we could squash
somehow and redo the series please?

-- 
Best regards,
Pawel Osciak

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

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

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-07  8:50 [RFCv5 PATCH 00/15] vb2: improve dma-sg, expbuf Hans Verkuil
2014-11-07  8:50 ` [RFCv5 PATCH 01/15] videobuf2-core.h: improve documentation Hans Verkuil
2014-11-07  8:50 ` [RFCv5 PATCH 02/15] vb2-dma-sg: add allocation context to dma-sg Hans Verkuil
2014-11-08  8:46   ` Pawel Osciak
2014-11-07  8:50 ` [RFCv5 PATCH 03/15] vb2-dma-sg: move dma_(un)map_sg here Hans Verkuil
2014-11-08  9:44   ` Pawel Osciak
2014-11-07  8:50 ` [RFCv5 PATCH 04/15] vb2-dma-sg: add dmabuf import support Hans Verkuil
2014-11-08 10:20   ` Pawel Osciak
2014-11-08 10:43     ` Pawel Osciak
2014-11-07  8:50 ` [RFCv5 PATCH 05/15] vb2-dma-sg: add get_dmabuf Hans Verkuil
2014-11-08 10:45   ` Pawel Osciak
2014-11-07  8:50 ` [RFCv5 PATCH 06/15] vb2-vmalloc: add get_dmabuf support Hans Verkuil
2014-11-07  8:50 ` [RFCv5 PATCH 07/15] vb2: replace 'write' by 'dma_dir' Hans Verkuil
2014-11-08 11:19   ` Pawel Osciak
2014-11-07  8:50 ` [RFCv5 PATCH 08/15] vivid: enable vb2_expbuf support Hans Verkuil
2014-11-07  8:50 ` [RFCv5 PATCH 09/15] vim2m: support expbuf Hans Verkuil
2014-11-07  8:50 ` [RFCv5 PATCH 10/15] vb2: use dma_map_sg_attrs to prevent unnecessary sync Hans Verkuil
2014-11-07  8:50 ` [RFCv5 PATCH 11/15] vb2: add begin/end_cpu_access functions Hans Verkuil
2014-11-07  8:50 ` [RFCv5 PATCH 12/15] videobuf2-dvb.c: convert to vb2_plane_begin_cpu_access() Hans Verkuil
2014-11-07  8:50 ` [RFCv5 PATCH 13/15] v4l: convert vb2_plane_vaddr to vb2_plane_begin_cpu_access Hans Verkuil
2014-11-07  8:50 ` [RFCv5 PATCH 14/15] vb2: drop the unused vb2_plane_vaddr function Hans Verkuil
2014-11-07  8:50 ` [RFCv5 PATCH 15/15] vb2: update the buf_prepare/finish documentation Hans Verkuil
2014-11-07  9:19 ` [RFCv5 PATCH 00/15] vb2: improve dma-sg, expbuf 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).