linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/25] OMAP3 ISP: Move to videobuf2
@ 2014-04-03 22:39 Laurent Pinchart
  2014-04-03 22:39 ` [PATCH 01/25] omap3isp: stat: Rename IS_COHERENT_BUF to ISP_STAT_USES_DMAENGINE Laurent Pinchart
                   ` (24 more replies)
  0 siblings, 25 replies; 26+ messages in thread
From: Laurent Pinchart @ 2014-04-03 22:39 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus

Hello,

I think the subject line should be enough to get everybody excited about this
patch series (everybody being Sakari, me, and possibly one or two other
developers). The idea is pretty clear, I've tried to keep patches small and
reviewable (24/25 is a bit too big for my taste, but splitting it further
would be pretty difficult), so please look at them for details.

The patches are based on top of the latest media master branch. They also
depend at runtime on an OMAP IOMMU cleanup series. I've asked Joerg Roedel to
provide a stable branch based on v3.15-rc1 (when it will be available).

Laurent Pinchart (25):
  omap3isp: stat: Rename IS_COHERENT_BUF to ISP_STAT_USES_DMAENGINE
  omap3isp: stat: Remove impossible WARN_ON
  omap3isp: stat: Share common code for buffer allocation
  omap3isp: stat: Merge dma_addr and iommu_addr fields
  omap3isp: stat: Store sg table in ispstat_buffer
  omap3isp: stat: Use the DMA API
  omap3isp: ccdc: Use the DMA API for LSC
  omap3isp: ccdc: Use the DMA API for FPC
  omap3isp: video: Set the buffer bytesused field at completion time
  omap3isp: queue: Move IOMMU handling code to the queue
  omap3isp: queue: Use sg_table structure
  omap3isp: queue: Merge the prepare and sglist functions
  omap3isp: queue: Inline the ispmmu_v(un)map functions
  omap3isp: queue: Allocate kernel buffers with dma_alloc_coherent
  omap3isp: queue: Fix the dma_map_sg() return value check
  omap3isp: queue: Map PFNMAP buffers to device
  omap3isp: queue: Use sg_alloc_table_from_pages()
  omap3isp: Use the ARM DMA IOMMU-aware operations
  omap3isp: queue: Don't build scatterlist for kernel buffer
  omap3isp: Move queue mutex to isp_video structure
  omap3isp: Move queue irqlock to isp_video structure
  omap3isp: Move buffer irqlist to isp_buffer structure
  v4l: vb2: Add a function to discard all DONE buffers
  omap3isp: Move to videobuf2
  omap3isp: Rename isp_buffer isp_addr field to dma

 drivers/media/platform/Kconfig                |    4 +-
 drivers/media/platform/omap3isp/Makefile      |    2 +-
 drivers/media/platform/omap3isp/isp.c         |  108 ++-
 drivers/media/platform/omap3isp/isp.h         |    8 +-
 drivers/media/platform/omap3isp/ispccdc.c     |  107 ++-
 drivers/media/platform/omap3isp/ispccdc.h     |   16 +-
 drivers/media/platform/omap3isp/ispccp2.c     |    4 +-
 drivers/media/platform/omap3isp/ispcsi2.c     |    4 +-
 drivers/media/platform/omap3isp/isph3a_aewb.c |    2 +-
 drivers/media/platform/omap3isp/isph3a_af.c   |    2 +-
 drivers/media/platform/omap3isp/isppreview.c  |    8 +-
 drivers/media/platform/omap3isp/ispqueue.c    | 1161 -------------------------
 drivers/media/platform/omap3isp/ispqueue.h    |  188 ----
 drivers/media/platform/omap3isp/ispresizer.c  |    8 +-
 drivers/media/platform/omap3isp/ispstat.c     |  197 ++---
 drivers/media/platform/omap3isp/ispstat.h     |    3 +-
 drivers/media/platform/omap3isp/ispvideo.c    |  323 +++----
 drivers/media/platform/omap3isp/ispvideo.h    |   29 +-
 drivers/media/v4l2-core/videobuf2-core.c      |   24 +
 drivers/staging/media/omap4iss/iss_video.c    |    2 +-
 include/media/videobuf2-core.h                |    1 +
 21 files changed, 456 insertions(+), 1745 deletions(-)
 delete mode 100644 drivers/media/platform/omap3isp/ispqueue.c
 delete mode 100644 drivers/media/platform/omap3isp/ispqueue.h

-- 
Regards,

Laurent Pinchart


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

* [PATCH 01/25] omap3isp: stat: Rename IS_COHERENT_BUF to ISP_STAT_USES_DMAENGINE
  2014-04-03 22:39 [PATCH 00/25] OMAP3 ISP: Move to videobuf2 Laurent Pinchart
@ 2014-04-03 22:39 ` Laurent Pinchart
  2014-04-03 22:39 ` [PATCH 02/25] omap3isp: stat: Remove impossible WARN_ON Laurent Pinchart
                   ` (23 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2014-04-03 22:39 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus

The macro is meant to test whether the statistics engine uses an
external DMA engine to transfer data or supports DMA directly. As both
cases will be supported by DMA coherent buffers rename the macro to
ISP_STAT_USES_DMAENGINE for improved clarity.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/omap3isp/ispstat.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispstat.c b/drivers/media/platform/omap3isp/ispstat.c
index 5707f85..48b702a 100644
--- a/drivers/media/platform/omap3isp/ispstat.c
+++ b/drivers/media/platform/omap3isp/ispstat.c
@@ -32,7 +32,7 @@
 
 #include "isp.h"
 
-#define IS_COHERENT_BUF(stat)	((stat)->dma_ch >= 0)
+#define ISP_STAT_USES_DMAENGINE(stat)	((stat)->dma_ch >= 0)
 
 /*
  * MAGIC_SIZE must always be the greatest common divisor of
@@ -99,7 +99,7 @@ static void isp_stat_buf_sync_magic_for_device(struct ispstat *stat,
 					       u32 buf_size,
 					       enum dma_data_direction dir)
 {
-	if (IS_COHERENT_BUF(stat))
+	if (ISP_STAT_USES_DMAENGINE(stat))
 		return;
 
 	__isp_stat_buf_sync_magic(stat, buf, buf_size, dir,
@@ -111,7 +111,7 @@ static void isp_stat_buf_sync_magic_for_cpu(struct ispstat *stat,
 					    u32 buf_size,
 					    enum dma_data_direction dir)
 {
-	if (IS_COHERENT_BUF(stat))
+	if (ISP_STAT_USES_DMAENGINE(stat))
 		return;
 
 	__isp_stat_buf_sync_magic(stat, buf, buf_size, dir,
@@ -180,7 +180,7 @@ static void isp_stat_buf_insert_magic(struct ispstat *stat,
 static void isp_stat_buf_sync_for_device(struct ispstat *stat,
 					 struct ispstat_buffer *buf)
 {
-	if (IS_COHERENT_BUF(stat))
+	if (ISP_STAT_USES_DMAENGINE(stat))
 		return;
 
 	dma_sync_sg_for_device(stat->isp->dev, buf->iovm->sgt->sgl,
@@ -190,7 +190,7 @@ static void isp_stat_buf_sync_for_device(struct ispstat *stat,
 static void isp_stat_buf_sync_for_cpu(struct ispstat *stat,
 				      struct ispstat_buffer *buf)
 {
-	if (IS_COHERENT_BUF(stat))
+	if (ISP_STAT_USES_DMAENGINE(stat))
 		return;
 
 	dma_sync_sg_for_cpu(stat->isp->dev, buf->iovm->sgt->sgl,
@@ -360,7 +360,7 @@ static void isp_stat_bufs_free(struct ispstat *stat)
 	for (i = 0; i < STAT_MAX_BUFS; i++) {
 		struct ispstat_buffer *buf = &stat->buf[i];
 
-		if (!IS_COHERENT_BUF(stat)) {
+		if (!ISP_STAT_USES_DMAENGINE(stat)) {
 			if (IS_ERR_OR_NULL((void *)buf->iommu_addr))
 				continue;
 			if (buf->iovm)
@@ -489,7 +489,7 @@ static int isp_stat_bufs_alloc(struct ispstat *stat, u32 size)
 
 	isp_stat_bufs_free(stat);
 
-	if (IS_COHERENT_BUF(stat))
+	if (ISP_STAT_USES_DMAENGINE(stat))
 		return isp_stat_bufs_alloc_dma(stat, size);
 	else
 		return isp_stat_bufs_alloc_iommu(stat, size);
-- 
1.8.3.2


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

* [PATCH 02/25] omap3isp: stat: Remove impossible WARN_ON
  2014-04-03 22:39 [PATCH 00/25] OMAP3 ISP: Move to videobuf2 Laurent Pinchart
  2014-04-03 22:39 ` [PATCH 01/25] omap3isp: stat: Rename IS_COHERENT_BUF to ISP_STAT_USES_DMAENGINE Laurent Pinchart
@ 2014-04-03 22:39 ` Laurent Pinchart
  2014-04-03 22:39 ` [PATCH 03/25] omap3isp: stat: Share common code for buffer allocation Laurent Pinchart
                   ` (22 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2014-04-03 22:39 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus

The WARN_ON statements in the buffer allocation functions try to catch
conditions where buffers would have already been allocated. As the
buffers are explicitly freed right before being allocated this can't
happen.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/omap3isp/ispstat.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispstat.c b/drivers/media/platform/omap3isp/ispstat.c
index 48b702a..c6c1290 100644
--- a/drivers/media/platform/omap3isp/ispstat.c
+++ b/drivers/media/platform/omap3isp/ispstat.c
@@ -400,7 +400,6 @@ static int isp_stat_bufs_alloc_iommu(struct ispstat *stat, unsigned int size)
 		struct ispstat_buffer *buf = &stat->buf[i];
 		struct iovm_struct *iovm;
 
-		WARN_ON(buf->dma_addr);
 		buf->iommu_addr = omap_iommu_vmalloc(isp->domain, isp->dev, 0,
 							size, IOMMU_FLAG);
 		if (IS_ERR((void *)buf->iommu_addr)) {
@@ -441,7 +440,6 @@ static int isp_stat_bufs_alloc_dma(struct ispstat *stat, unsigned int size)
 	for (i = 0; i < STAT_MAX_BUFS; i++) {
 		struct ispstat_buffer *buf = &stat->buf[i];
 
-		WARN_ON(buf->iommu_addr);
 		buf->virt_addr = dma_alloc_coherent(stat->isp->dev, size,
 					&buf->dma_addr, GFP_KERNEL | GFP_DMA);
 
-- 
1.8.3.2


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

* [PATCH 03/25] omap3isp: stat: Share common code for buffer allocation
  2014-04-03 22:39 [PATCH 00/25] OMAP3 ISP: Move to videobuf2 Laurent Pinchart
  2014-04-03 22:39 ` [PATCH 01/25] omap3isp: stat: Rename IS_COHERENT_BUF to ISP_STAT_USES_DMAENGINE Laurent Pinchart
  2014-04-03 22:39 ` [PATCH 02/25] omap3isp: stat: Remove impossible WARN_ON Laurent Pinchart
@ 2014-04-03 22:39 ` Laurent Pinchart
  2014-04-03 22:39 ` [PATCH 04/25] omap3isp: stat: Merge dma_addr and iommu_addr fields Laurent Pinchart
                   ` (21 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2014-04-03 22:39 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus

Move code common between the isp_stat_bufs_alloc_dma() and
isp_stat_bufs_alloc_iommu() functions to isp_stat_bufs_alloc().

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/omap3isp/ispstat.c | 114 ++++++++++++++----------------
 1 file changed, 54 insertions(+), 60 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispstat.c b/drivers/media/platform/omap3isp/ispstat.c
index c6c1290..b1eb902 100644
--- a/drivers/media/platform/omap3isp/ispstat.c
+++ b/drivers/media/platform/omap3isp/ispstat.c
@@ -389,74 +389,42 @@ static void isp_stat_bufs_free(struct ispstat *stat)
 	stat->active_buf = NULL;
 }
 
-static int isp_stat_bufs_alloc_iommu(struct ispstat *stat, unsigned int size)
+static int isp_stat_bufs_alloc_iommu(struct ispstat *stat,
+				     struct ispstat_buffer *buf,
+				     unsigned int size)
 {
 	struct isp_device *isp = stat->isp;
-	int i;
+	struct iovm_struct *iovm;
 
-	stat->buf_alloc_size = size;
+	buf->iommu_addr = omap_iommu_vmalloc(isp->domain, isp->dev, 0,
+						size, IOMMU_FLAG);
+	if (IS_ERR((void *)buf->iommu_addr))
+		return -ENOMEM;
 
-	for (i = 0; i < STAT_MAX_BUFS; i++) {
-		struct ispstat_buffer *buf = &stat->buf[i];
-		struct iovm_struct *iovm;
+	iovm = omap_find_iovm_area(isp->dev, buf->iommu_addr);
+	if (!iovm)
+		return -ENOMEM;
 
-		buf->iommu_addr = omap_iommu_vmalloc(isp->domain, isp->dev, 0,
-							size, IOMMU_FLAG);
-		if (IS_ERR((void *)buf->iommu_addr)) {
-			dev_err(stat->isp->dev,
-				 "%s: Can't acquire memory for "
-				 "buffer %d\n", stat->subdev.name, i);
-			isp_stat_bufs_free(stat);
-			return -ENOMEM;
-		}
+	if (!dma_map_sg(isp->dev, iovm->sgt->sgl, iovm->sgt->nents,
+			DMA_FROM_DEVICE))
+		return -ENOMEM;
 
-		iovm = omap_find_iovm_area(isp->dev, buf->iommu_addr);
-		if (!iovm ||
-		    !dma_map_sg(isp->dev, iovm->sgt->sgl, iovm->sgt->nents,
-				DMA_FROM_DEVICE)) {
-			isp_stat_bufs_free(stat);
-			return -ENOMEM;
-		}
-		buf->iovm = iovm;
-
-		buf->virt_addr = omap_da_to_va(stat->isp->dev,
-					  (u32)buf->iommu_addr);
-		buf->empty = 1;
-		dev_dbg(stat->isp->dev, "%s: buffer[%d] allocated."
-			"iommu_addr=0x%08lx virt_addr=0x%08lx",
-			stat->subdev.name, i, buf->iommu_addr,
-			(unsigned long)buf->virt_addr);
-	}
+	buf->iovm = iovm;
+	buf->virt_addr = omap_da_to_va(stat->isp->dev,
+				  (u32)buf->iommu_addr);
 
 	return 0;
 }
 
-static int isp_stat_bufs_alloc_dma(struct ispstat *stat, unsigned int size)
+static int isp_stat_bufs_alloc_dma(struct ispstat *stat,
+				   struct ispstat_buffer *buf,
+				   unsigned int size)
 {
-	int i;
-
-	stat->buf_alloc_size = size;
-
-	for (i = 0; i < STAT_MAX_BUFS; i++) {
-		struct ispstat_buffer *buf = &stat->buf[i];
-
-		buf->virt_addr = dma_alloc_coherent(stat->isp->dev, size,
-					&buf->dma_addr, GFP_KERNEL | GFP_DMA);
-
-		if (!buf->virt_addr || !buf->dma_addr) {
-			dev_info(stat->isp->dev,
-				 "%s: Can't acquire memory for "
-				 "DMA buffer %d\n", stat->subdev.name, i);
-			isp_stat_bufs_free(stat);
-			return -ENOMEM;
-		}
-		buf->empty = 1;
+	buf->virt_addr = dma_alloc_coherent(stat->isp->dev, size,
+				&buf->dma_addr, GFP_KERNEL | GFP_DMA);
 
-		dev_dbg(stat->isp->dev, "%s: buffer[%d] allocated."
-			"dma_addr=0x%08lx virt_addr=0x%08lx\n",
-			stat->subdev.name, i, (unsigned long)buf->dma_addr,
-			(unsigned long)buf->virt_addr);
-	}
+	if (!buf->virt_addr || !buf->dma_addr)
+		return -ENOMEM;
 
 	return 0;
 }
@@ -464,6 +432,7 @@ static int isp_stat_bufs_alloc_dma(struct ispstat *stat, unsigned int size)
 static int isp_stat_bufs_alloc(struct ispstat *stat, u32 size)
 {
 	unsigned long flags;
+	unsigned int i;
 
 	spin_lock_irqsave(&stat->isp->stat_lock, flags);
 
@@ -487,10 +456,35 @@ static int isp_stat_bufs_alloc(struct ispstat *stat, u32 size)
 
 	isp_stat_bufs_free(stat);
 
-	if (ISP_STAT_USES_DMAENGINE(stat))
-		return isp_stat_bufs_alloc_dma(stat, size);
-	else
-		return isp_stat_bufs_alloc_iommu(stat, size);
+	stat->buf_alloc_size = size;
+
+	for (i = 0; i < STAT_MAX_BUFS; i++) {
+		struct ispstat_buffer *buf = &stat->buf[i];
+		int ret;
+
+		if (ISP_STAT_USES_DMAENGINE(stat))
+			ret = isp_stat_bufs_alloc_dma(stat, buf, size);
+		else
+			ret = isp_stat_bufs_alloc_iommu(stat, buf, size);
+
+		if (ret < 0) {
+			dev_err(stat->isp->dev,
+				"%s: Failed to allocate DMA buffer %u\n",
+				stat->subdev.name, i);
+			isp_stat_bufs_free(stat);
+			return ret;
+		}
+
+		buf->empty = 1;
+
+		dev_dbg(stat->isp->dev,
+			"%s: buffer[%u] allocated. iommu=0x%08lx dma=0x%08lx virt=0x%08lx",
+			stat->subdev.name, i, buf->iommu_addr,
+			(unsigned long)buf->dma_addr,
+			(unsigned long)buf->virt_addr);
+	}
+
+	return 0;
 }
 
 static void isp_stat_queue_event(struct ispstat *stat, int err)
-- 
1.8.3.2


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

* [PATCH 04/25] omap3isp: stat: Merge dma_addr and iommu_addr fields
  2014-04-03 22:39 [PATCH 00/25] OMAP3 ISP: Move to videobuf2 Laurent Pinchart
                   ` (2 preceding siblings ...)
  2014-04-03 22:39 ` [PATCH 03/25] omap3isp: stat: Share common code for buffer allocation Laurent Pinchart
@ 2014-04-03 22:39 ` Laurent Pinchart
  2014-04-03 22:39 ` [PATCH 05/25] omap3isp: stat: Store sg table in ispstat_buffer Laurent Pinchart
                   ` (20 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2014-04-03 22:39 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus

The fields store buffer addresses as seen from the device. The first one
is used with an external DMA engine while the second one is used with
the ISP DMA engine. As they're never used together, merge them.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/omap3isp/isph3a_aewb.c |  2 +-
 drivers/media/platform/omap3isp/isph3a_af.c   |  2 +-
 drivers/media/platform/omap3isp/ispstat.c     | 21 +++++++++------------
 drivers/media/platform/omap3isp/ispstat.h     |  1 -
 4 files changed, 11 insertions(+), 15 deletions(-)

diff --git a/drivers/media/platform/omap3isp/isph3a_aewb.c b/drivers/media/platform/omap3isp/isph3a_aewb.c
index 75fd82b..d6811ce 100644
--- a/drivers/media/platform/omap3isp/isph3a_aewb.c
+++ b/drivers/media/platform/omap3isp/isph3a_aewb.c
@@ -47,7 +47,7 @@ static void h3a_aewb_setup_regs(struct ispstat *aewb, void *priv)
 	if (aewb->state == ISPSTAT_DISABLED)
 		return;
 
-	isp_reg_writel(aewb->isp, aewb->active_buf->iommu_addr,
+	isp_reg_writel(aewb->isp, aewb->active_buf->dma_addr,
 		       OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWBUFST);
 
 	if (!aewb->update)
diff --git a/drivers/media/platform/omap3isp/isph3a_af.c b/drivers/media/platform/omap3isp/isph3a_af.c
index a0bf5af..6fc960c 100644
--- a/drivers/media/platform/omap3isp/isph3a_af.c
+++ b/drivers/media/platform/omap3isp/isph3a_af.c
@@ -51,7 +51,7 @@ static void h3a_af_setup_regs(struct ispstat *af, void *priv)
 	if (af->state == ISPSTAT_DISABLED)
 		return;
 
-	isp_reg_writel(af->isp, af->active_buf->iommu_addr, OMAP3_ISP_IOMEM_H3A,
+	isp_reg_writel(af->isp, af->active_buf->dma_addr, OMAP3_ISP_IOMEM_H3A,
 		       ISPH3A_AFBUFST);
 
 	if (!af->update)
diff --git a/drivers/media/platform/omap3isp/ispstat.c b/drivers/media/platform/omap3isp/ispstat.c
index b1eb902..dba713f 100644
--- a/drivers/media/platform/omap3isp/ispstat.c
+++ b/drivers/media/platform/omap3isp/ispstat.c
@@ -361,21 +361,19 @@ static void isp_stat_bufs_free(struct ispstat *stat)
 		struct ispstat_buffer *buf = &stat->buf[i];
 
 		if (!ISP_STAT_USES_DMAENGINE(stat)) {
-			if (IS_ERR_OR_NULL((void *)buf->iommu_addr))
+			if (IS_ERR_OR_NULL((void *)buf->dma_addr))
 				continue;
 			if (buf->iovm)
 				dma_unmap_sg(isp->dev, buf->iovm->sgt->sgl,
 					     buf->iovm->sgt->nents,
 					     DMA_FROM_DEVICE);
-			omap_iommu_vfree(isp->domain, isp->dev,
-							buf->iommu_addr);
+			omap_iommu_vfree(isp->domain, isp->dev, buf->dma_addr);
 		} else {
 			if (!buf->virt_addr)
 				continue;
 			dma_free_coherent(stat->isp->dev, stat->buf_alloc_size,
 					  buf->virt_addr, buf->dma_addr);
 		}
-		buf->iommu_addr = 0;
 		buf->iovm = NULL;
 		buf->dma_addr = 0;
 		buf->virt_addr = NULL;
@@ -396,12 +394,12 @@ static int isp_stat_bufs_alloc_iommu(struct ispstat *stat,
 	struct isp_device *isp = stat->isp;
 	struct iovm_struct *iovm;
 
-	buf->iommu_addr = omap_iommu_vmalloc(isp->domain, isp->dev, 0,
-						size, IOMMU_FLAG);
-	if (IS_ERR((void *)buf->iommu_addr))
+	buf->dma_addr = omap_iommu_vmalloc(isp->domain, isp->dev, 0,
+					   size, IOMMU_FLAG);
+	if (IS_ERR_VALUE(buf->dma_addr))
 		return -ENOMEM;
 
-	iovm = omap_find_iovm_area(isp->dev, buf->iommu_addr);
+	iovm = omap_find_iovm_area(isp->dev, buf->dma_addr);
 	if (!iovm)
 		return -ENOMEM;
 
@@ -410,8 +408,7 @@ static int isp_stat_bufs_alloc_iommu(struct ispstat *stat,
 		return -ENOMEM;
 
 	buf->iovm = iovm;
-	buf->virt_addr = omap_da_to_va(stat->isp->dev,
-				  (u32)buf->iommu_addr);
+	buf->virt_addr = omap_da_to_va(stat->isp->dev, buf->dma_addr);
 
 	return 0;
 }
@@ -478,8 +475,8 @@ static int isp_stat_bufs_alloc(struct ispstat *stat, u32 size)
 		buf->empty = 1;
 
 		dev_dbg(stat->isp->dev,
-			"%s: buffer[%u] allocated. iommu=0x%08lx dma=0x%08lx virt=0x%08lx",
-			stat->subdev.name, i, buf->iommu_addr,
+			"%s: buffer[%u] allocated. dma=0x%08lx virt=0x%08lx",
+			stat->subdev.name, i,
 			(unsigned long)buf->dma_addr,
 			(unsigned long)buf->virt_addr);
 	}
diff --git a/drivers/media/platform/omap3isp/ispstat.h b/drivers/media/platform/omap3isp/ispstat.h
index 9a047c9..8e76846 100644
--- a/drivers/media/platform/omap3isp/ispstat.h
+++ b/drivers/media/platform/omap3isp/ispstat.h
@@ -46,7 +46,6 @@
 struct ispstat;
 
 struct ispstat_buffer {
-	unsigned long iommu_addr;
 	struct iovm_struct *iovm;
 	void *virt_addr;
 	dma_addr_t dma_addr;
-- 
1.8.3.2


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

* [PATCH 05/25] omap3isp: stat: Store sg table in ispstat_buffer
  2014-04-03 22:39 [PATCH 00/25] OMAP3 ISP: Move to videobuf2 Laurent Pinchart
                   ` (3 preceding siblings ...)
  2014-04-03 22:39 ` [PATCH 04/25] omap3isp: stat: Merge dma_addr and iommu_addr fields Laurent Pinchart
@ 2014-04-03 22:39 ` Laurent Pinchart
  2014-04-03 22:39 ` [PATCH 06/25] omap3isp: stat: Use the DMA API Laurent Pinchart
                   ` (19 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2014-04-03 22:39 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus

The driver stores the IOMMU mapped iovm struct pointer in the buffer
structure but only needs the iovm sg table. Store the sg table instead
to prepare the migration to the DMA API.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/omap3isp/ispstat.c | 19 +++++++++----------
 drivers/media/platform/omap3isp/ispstat.h |  2 +-
 2 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispstat.c b/drivers/media/platform/omap3isp/ispstat.c
index dba713f..4cf7eb1 100644
--- a/drivers/media/platform/omap3isp/ispstat.c
+++ b/drivers/media/platform/omap3isp/ispstat.c
@@ -183,8 +183,8 @@ static void isp_stat_buf_sync_for_device(struct ispstat *stat,
 	if (ISP_STAT_USES_DMAENGINE(stat))
 		return;
 
-	dma_sync_sg_for_device(stat->isp->dev, buf->iovm->sgt->sgl,
-			       buf->iovm->sgt->nents, DMA_FROM_DEVICE);
+	dma_sync_sg_for_device(stat->isp->dev, buf->sgt->sgl,
+			       buf->sgt->nents, DMA_FROM_DEVICE);
 }
 
 static void isp_stat_buf_sync_for_cpu(struct ispstat *stat,
@@ -193,8 +193,8 @@ static void isp_stat_buf_sync_for_cpu(struct ispstat *stat,
 	if (ISP_STAT_USES_DMAENGINE(stat))
 		return;
 
-	dma_sync_sg_for_cpu(stat->isp->dev, buf->iovm->sgt->sgl,
-			    buf->iovm->sgt->nents, DMA_FROM_DEVICE);
+	dma_sync_sg_for_cpu(stat->isp->dev, buf->sgt->sgl,
+			    buf->sgt->nents, DMA_FROM_DEVICE);
 }
 
 static void isp_stat_buf_clear(struct ispstat *stat)
@@ -363,10 +363,9 @@ static void isp_stat_bufs_free(struct ispstat *stat)
 		if (!ISP_STAT_USES_DMAENGINE(stat)) {
 			if (IS_ERR_OR_NULL((void *)buf->dma_addr))
 				continue;
-			if (buf->iovm)
-				dma_unmap_sg(isp->dev, buf->iovm->sgt->sgl,
-					     buf->iovm->sgt->nents,
-					     DMA_FROM_DEVICE);
+			if (buf->sgt)
+				dma_unmap_sg(isp->dev, buf->sgt->sgl,
+					     buf->sgt->nents, DMA_FROM_DEVICE);
 			omap_iommu_vfree(isp->domain, isp->dev, buf->dma_addr);
 		} else {
 			if (!buf->virt_addr)
@@ -374,7 +373,7 @@ static void isp_stat_bufs_free(struct ispstat *stat)
 			dma_free_coherent(stat->isp->dev, stat->buf_alloc_size,
 					  buf->virt_addr, buf->dma_addr);
 		}
-		buf->iovm = NULL;
+		buf->sgt = NULL;
 		buf->dma_addr = 0;
 		buf->virt_addr = NULL;
 		buf->empty = 1;
@@ -407,7 +406,7 @@ static int isp_stat_bufs_alloc_iommu(struct ispstat *stat,
 			DMA_FROM_DEVICE))
 		return -ENOMEM;
 
-	buf->iovm = iovm;
+	buf->sgt = iovm->sgt;
 	buf->virt_addr = omap_da_to_va(stat->isp->dev, buf->dma_addr);
 
 	return 0;
diff --git a/drivers/media/platform/omap3isp/ispstat.h b/drivers/media/platform/omap3isp/ispstat.h
index 8e76846..857f45e 100644
--- a/drivers/media/platform/omap3isp/ispstat.h
+++ b/drivers/media/platform/omap3isp/ispstat.h
@@ -46,7 +46,7 @@
 struct ispstat;
 
 struct ispstat_buffer {
-	struct iovm_struct *iovm;
+	const struct sg_table *sgt;
 	void *virt_addr;
 	dma_addr_t dma_addr;
 	struct timespec ts;
-- 
1.8.3.2


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

* [PATCH 06/25] omap3isp: stat: Use the DMA API
  2014-04-03 22:39 [PATCH 00/25] OMAP3 ISP: Move to videobuf2 Laurent Pinchart
                   ` (4 preceding siblings ...)
  2014-04-03 22:39 ` [PATCH 05/25] omap3isp: stat: Store sg table in ispstat_buffer Laurent Pinchart
@ 2014-04-03 22:39 ` Laurent Pinchart
  2014-04-03 22:39 ` [PATCH 07/25] omap3isp: ccdc: Use the DMA API for LSC Laurent Pinchart
                   ` (18 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2014-04-03 22:39 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus

Replace the OMAP-specific IOMMU API usage by the DMA API. All buffers
are now allocated using dma_alloc_coherent() and the related sg table is
retrieved using dma_get_sgtable() for sync operations.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/omap3isp/ispstat.c | 123 +++++++++++++-----------------
 drivers/media/platform/omap3isp/ispstat.h |   2 +-
 2 files changed, 53 insertions(+), 72 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispstat.c b/drivers/media/platform/omap3isp/ispstat.c
index 4cf7eb1..e6cbc1e 100644
--- a/drivers/media/platform/omap3isp/ispstat.c
+++ b/drivers/media/platform/omap3isp/ispstat.c
@@ -26,7 +26,6 @@
  */
 
 #include <linux/dma-mapping.h>
-#include <linux/omap-iommu.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
 
@@ -77,21 +76,10 @@ static void __isp_stat_buf_sync_magic(struct ispstat *stat,
 					dma_addr_t, unsigned long, size_t,
 					enum dma_data_direction))
 {
-	struct device *dev = stat->isp->dev;
-	struct page *pg;
-	dma_addr_t dma_addr;
-	u32 offset;
-
-	/* Initial magic words */
-	pg = vmalloc_to_page(buf->virt_addr);
-	dma_addr = pfn_to_dma(dev, page_to_pfn(pg));
-	dma_sync(dev, dma_addr, 0, MAGIC_SIZE, dir);
-
-	/* Final magic words */
-	pg = vmalloc_to_page(buf->virt_addr + buf_size);
-	dma_addr = pfn_to_dma(dev, page_to_pfn(pg));
-	offset = ((u32)buf->virt_addr + buf_size) & ~PAGE_MASK;
-	dma_sync(dev, dma_addr, offset, MAGIC_SIZE, dir);
+	/* Sync the initial and final magic words. */
+	dma_sync(stat->isp->dev, buf->dma_addr, 0, MAGIC_SIZE, dir);
+	dma_sync(stat->isp->dev, buf->dma_addr + (buf_size & PAGE_MASK),
+		 buf_size & ~PAGE_MASK, MAGIC_SIZE, dir);
 }
 
 static void isp_stat_buf_sync_magic_for_device(struct ispstat *stat,
@@ -183,8 +171,8 @@ static void isp_stat_buf_sync_for_device(struct ispstat *stat,
 	if (ISP_STAT_USES_DMAENGINE(stat))
 		return;
 
-	dma_sync_sg_for_device(stat->isp->dev, buf->sgt->sgl,
-			       buf->sgt->nents, DMA_FROM_DEVICE);
+	dma_sync_sg_for_device(stat->isp->dev, buf->sgt.sgl,
+			       buf->sgt.nents, DMA_FROM_DEVICE);
 }
 
 static void isp_stat_buf_sync_for_cpu(struct ispstat *stat,
@@ -193,8 +181,8 @@ static void isp_stat_buf_sync_for_cpu(struct ispstat *stat,
 	if (ISP_STAT_USES_DMAENGINE(stat))
 		return;
 
-	dma_sync_sg_for_cpu(stat->isp->dev, buf->sgt->sgl,
-			    buf->sgt->nents, DMA_FROM_DEVICE);
+	dma_sync_sg_for_cpu(stat->isp->dev, buf->sgt.sgl,
+			    buf->sgt.nents, DMA_FROM_DEVICE);
 }
 
 static void isp_stat_buf_clear(struct ispstat *stat)
@@ -354,26 +342,21 @@ static struct ispstat_buffer *isp_stat_buf_get(struct ispstat *stat,
 
 static void isp_stat_bufs_free(struct ispstat *stat)
 {
-	struct isp_device *isp = stat->isp;
-	int i;
+	struct device *dev = ISP_STAT_USES_DMAENGINE(stat)
+			   ? NULL : stat->isp->dev;
+	unsigned int i;
 
 	for (i = 0; i < STAT_MAX_BUFS; i++) {
 		struct ispstat_buffer *buf = &stat->buf[i];
 
-		if (!ISP_STAT_USES_DMAENGINE(stat)) {
-			if (IS_ERR_OR_NULL((void *)buf->dma_addr))
-				continue;
-			if (buf->sgt)
-				dma_unmap_sg(isp->dev, buf->sgt->sgl,
-					     buf->sgt->nents, DMA_FROM_DEVICE);
-			omap_iommu_vfree(isp->domain, isp->dev, buf->dma_addr);
-		} else {
-			if (!buf->virt_addr)
-				continue;
-			dma_free_coherent(stat->isp->dev, stat->buf_alloc_size,
-					  buf->virt_addr, buf->dma_addr);
-		}
-		buf->sgt = NULL;
+		if (!buf->virt_addr)
+			continue;
+
+		sg_free_table(&buf->sgt);
+
+		dma_free_coherent(dev, stat->buf_alloc_size, buf->virt_addr,
+				  buf->dma_addr);
+
 		buf->dma_addr = 0;
 		buf->virt_addr = NULL;
 		buf->empty = 1;
@@ -386,47 +369,49 @@ static void isp_stat_bufs_free(struct ispstat *stat)
 	stat->active_buf = NULL;
 }
 
-static int isp_stat_bufs_alloc_iommu(struct ispstat *stat,
-				     struct ispstat_buffer *buf,
-				     unsigned int size)
-{
-	struct isp_device *isp = stat->isp;
-	struct iovm_struct *iovm;
-
-	buf->dma_addr = omap_iommu_vmalloc(isp->domain, isp->dev, 0,
-					   size, IOMMU_FLAG);
-	if (IS_ERR_VALUE(buf->dma_addr))
-		return -ENOMEM;
-
-	iovm = omap_find_iovm_area(isp->dev, buf->dma_addr);
-	if (!iovm)
-		return -ENOMEM;
-
-	if (!dma_map_sg(isp->dev, iovm->sgt->sgl, iovm->sgt->nents,
-			DMA_FROM_DEVICE))
-		return -ENOMEM;
-
-	buf->sgt = iovm->sgt;
-	buf->virt_addr = omap_da_to_va(stat->isp->dev, buf->dma_addr);
-
-	return 0;
-}
-
-static int isp_stat_bufs_alloc_dma(struct ispstat *stat,
+static int isp_stat_bufs_alloc_one(struct device *dev,
 				   struct ispstat_buffer *buf,
 				   unsigned int size)
 {
-	buf->virt_addr = dma_alloc_coherent(stat->isp->dev, size,
-				&buf->dma_addr, GFP_KERNEL | GFP_DMA);
+	int ret;
 
-	if (!buf->virt_addr || !buf->dma_addr)
+	buf->virt_addr = dma_alloc_coherent(dev, size, &buf->dma_addr,
+					    GFP_KERNEL | GFP_DMA);
+	if (!buf->virt_addr)
 		return -ENOMEM;
 
+	ret = dma_get_sgtable(dev, &buf->sgt, buf->virt_addr, buf->dma_addr,
+			      size);
+	if (ret < 0) {
+		dma_free_coherent(dev, size, buf->virt_addr, buf->dma_addr);
+		buf->virt_addr = NULL;
+		buf->dma_addr = 0;
+		return ret;
+	}
+
 	return 0;
 }
 
+/*
+ * The device passed to the DMA API depends on whether the statistics block uses
+ * ISP DMA, external DMA or PIO to transfer data.
+ *
+ * The first case (for the AEWB and AF engines) passes the ISP device, resulting
+ * in the DMA buffers being mapped through the ISP IOMMU.
+ *
+ * The second case (for the histogram engine) should pass the DMA engine device.
+ * As that device isn't accessible through the OMAP DMA engine API the driver
+ * passes NULL instead, resulting in the buffers being mapped directly as
+ * physical pages.
+ *
+ * The third case (for the histogram engine) doesn't require any mapping. The
+ * buffers could be allocated with kmalloc/vmalloc, but we still use
+ * dma_alloc_coherent() for consistency purpose.
+ */
 static int isp_stat_bufs_alloc(struct ispstat *stat, u32 size)
 {
+	struct device *dev = ISP_STAT_USES_DMAENGINE(stat)
+			   ? NULL : stat->isp->dev;
 	unsigned long flags;
 	unsigned int i;
 
@@ -458,11 +443,7 @@ static int isp_stat_bufs_alloc(struct ispstat *stat, u32 size)
 		struct ispstat_buffer *buf = &stat->buf[i];
 		int ret;
 
-		if (ISP_STAT_USES_DMAENGINE(stat))
-			ret = isp_stat_bufs_alloc_dma(stat, buf, size);
-		else
-			ret = isp_stat_bufs_alloc_iommu(stat, buf, size);
-
+		ret = isp_stat_bufs_alloc_one(dev, buf, size);
 		if (ret < 0) {
 			dev_err(stat->isp->dev,
 				"%s: Failed to allocate DMA buffer %u\n",
diff --git a/drivers/media/platform/omap3isp/ispstat.h b/drivers/media/platform/omap3isp/ispstat.h
index 857f45e..58d6ac7 100644
--- a/drivers/media/platform/omap3isp/ispstat.h
+++ b/drivers/media/platform/omap3isp/ispstat.h
@@ -46,7 +46,7 @@
 struct ispstat;
 
 struct ispstat_buffer {
-	const struct sg_table *sgt;
+	struct sg_table sgt;
 	void *virt_addr;
 	dma_addr_t dma_addr;
 	struct timespec ts;
-- 
1.8.3.2


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

* [PATCH 07/25] omap3isp: ccdc: Use the DMA API for LSC
  2014-04-03 22:39 [PATCH 00/25] OMAP3 ISP: Move to videobuf2 Laurent Pinchart
                   ` (5 preceding siblings ...)
  2014-04-03 22:39 ` [PATCH 06/25] omap3isp: stat: Use the DMA API Laurent Pinchart
@ 2014-04-03 22:39 ` Laurent Pinchart
  2014-04-03 22:39 ` [PATCH 08/25] omap3isp: ccdc: Use the DMA API for FPC Laurent Pinchart
                   ` (17 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2014-04-03 22:39 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus

Replace the OMAP-specific IOMMU API usage by the DMA API for LSC. The
table is now allocated using dma_alloc_coherent() and the related sg
table is retrieved using dma_get_sgtable() for sync operations.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/omap3isp/ispccdc.c | 52 ++++++++++++++-----------------
 drivers/media/platform/omap3isp/ispccdc.h |  8 +++--
 2 files changed, 29 insertions(+), 31 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispccdc.c b/drivers/media/platform/omap3isp/ispccdc.c
index 4d920c8..a907b20 100644
--- a/drivers/media/platform/omap3isp/ispccdc.c
+++ b/drivers/media/platform/omap3isp/ispccdc.c
@@ -206,7 +206,8 @@ static int ccdc_lsc_validate_config(struct isp_ccdc_device *ccdc,
  * ccdc_lsc_program_table - Program Lens Shading Compensation table address.
  * @ccdc: Pointer to ISP CCDC device.
  */
-static void ccdc_lsc_program_table(struct isp_ccdc_device *ccdc, u32 addr)
+static void ccdc_lsc_program_table(struct isp_ccdc_device *ccdc,
+				   dma_addr_t addr)
 {
 	isp_reg_writel(to_isp_device(ccdc), addr,
 		       OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_TABLE_BASE);
@@ -333,7 +334,7 @@ static int __ccdc_lsc_configure(struct isp_ccdc_device *ccdc,
 		return -EBUSY;
 
 	ccdc_lsc_setup_regs(ccdc, &req->config);
-	ccdc_lsc_program_table(ccdc, req->table);
+	ccdc_lsc_program_table(ccdc, req->table.dma);
 	return 0;
 }
 
@@ -368,11 +369,12 @@ static void ccdc_lsc_free_request(struct isp_ccdc_device *ccdc,
 	if (req == NULL)
 		return;
 
-	if (req->iovm)
-		dma_unmap_sg(isp->dev, req->iovm->sgt->sgl,
-			     req->iovm->sgt->nents, DMA_TO_DEVICE);
-	if (req->table)
-		omap_iommu_vfree(isp->domain, isp->dev, req->table);
+	if (req->table.addr) {
+		sg_free_table(&req->table.sgt);
+		dma_free_coherent(isp->dev, req->config.size, req->table.addr,
+				  req->table.dma);
+	}
+
 	kfree(req);
 }
 
@@ -416,7 +418,6 @@ static int ccdc_lsc_config(struct isp_ccdc_device *ccdc,
 	struct isp_device *isp = to_isp_device(ccdc);
 	struct ispccdc_lsc_config_req *req;
 	unsigned long flags;
-	void *table;
 	u16 update;
 	int ret;
 
@@ -444,38 +445,31 @@ static int ccdc_lsc_config(struct isp_ccdc_device *ccdc,
 
 		req->enable = 1;
 
-		req->table = omap_iommu_vmalloc(isp->domain, isp->dev, 0,
-					req->config.size, IOMMU_FLAG);
-		if (IS_ERR_VALUE(req->table)) {
-			req->table = 0;
-			ret = -ENOMEM;
-			goto done;
-		}
-
-		req->iovm = omap_find_iovm_area(isp->dev, req->table);
-		if (req->iovm == NULL) {
+		req->table.addr = dma_alloc_coherent(isp->dev, req->config.size,
+						     &req->table.dma,
+						     GFP_KERNEL);
+		if (req->table.addr == NULL) {
 			ret = -ENOMEM;
 			goto done;
 		}
 
-		if (!dma_map_sg(isp->dev, req->iovm->sgt->sgl,
-				req->iovm->sgt->nents, DMA_TO_DEVICE)) {
-			ret = -ENOMEM;
-			req->iovm = NULL;
+		ret = dma_get_sgtable(isp->dev, &req->table.sgt,
+				      req->table.addr, req->table.dma,
+				      req->config.size);
+		if (ret < 0)
 			goto done;
-		}
 
-		dma_sync_sg_for_cpu(isp->dev, req->iovm->sgt->sgl,
-				    req->iovm->sgt->nents, DMA_TO_DEVICE);
+		dma_sync_sg_for_cpu(isp->dev, req->table.sgt.sgl,
+				    req->table.sgt.nents, DMA_TO_DEVICE);
 
-		table = omap_da_to_va(isp->dev, req->table);
-		if (copy_from_user(table, config->lsc, req->config.size)) {
+		if (copy_from_user(req->table.addr, config->lsc,
+				   req->config.size)) {
 			ret = -EFAULT;
 			goto done;
 		}
 
-		dma_sync_sg_for_device(isp->dev, req->iovm->sgt->sgl,
-				       req->iovm->sgt->nents, DMA_TO_DEVICE);
+		dma_sync_sg_for_device(isp->dev, req->table.sgt.sgl,
+				       req->table.sgt.nents, DMA_TO_DEVICE);
 	}
 
 	spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
diff --git a/drivers/media/platform/omap3isp/ispccdc.h b/drivers/media/platform/omap3isp/ispccdc.h
index 9d24e41..20db3a0 100644
--- a/drivers/media/platform/omap3isp/ispccdc.h
+++ b/drivers/media/platform/omap3isp/ispccdc.h
@@ -57,8 +57,12 @@ struct ispccdc_lsc_config_req {
 	struct list_head list;
 	struct omap3isp_ccdc_lsc_config config;
 	unsigned char enable;
-	u32 table;
-	struct iovm_struct *iovm;
+
+	struct {
+		void *addr;
+		dma_addr_t dma;
+		struct sg_table sgt;
+	} table;
 };
 
 /*
-- 
1.8.3.2


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

* [PATCH 08/25] omap3isp: ccdc: Use the DMA API for FPC
  2014-04-03 22:39 [PATCH 00/25] OMAP3 ISP: Move to videobuf2 Laurent Pinchart
                   ` (6 preceding siblings ...)
  2014-04-03 22:39 ` [PATCH 07/25] omap3isp: ccdc: Use the DMA API for LSC Laurent Pinchart
@ 2014-04-03 22:39 ` Laurent Pinchart
  2014-04-03 22:39 ` [PATCH 09/25] omap3isp: video: Set the buffer bytesused field at completion time Laurent Pinchart
                   ` (16 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2014-04-03 22:39 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus

Replace the OMAP-specific IOMMU API usage by the DMA API for FPC. The
table is now allocated using dma_alloc_coherent() and the related sg
table is retrieved using dma_get_sgtable() for sync operations.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/omap3isp/ispccdc.c | 51 +++++++++++++++++--------------
 drivers/media/platform/omap3isp/ispccdc.h |  8 ++++-
 2 files changed, 35 insertions(+), 24 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispccdc.c b/drivers/media/platform/omap3isp/ispccdc.c
index a907b20..004a4f5 100644
--- a/drivers/media/platform/omap3isp/ispccdc.c
+++ b/drivers/media/platform/omap3isp/ispccdc.c
@@ -30,7 +30,6 @@
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
 #include <linux/mm.h>
-#include <linux/omap-iommu.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <media/v4l2-event.h>
@@ -578,7 +577,7 @@ static void ccdc_configure_fpc(struct isp_ccdc_device *ccdc)
 	if (!ccdc->fpc_en)
 		return;
 
-	isp_reg_writel(isp, ccdc->fpc.fpcaddr, OMAP3_ISP_IOMEM_CCDC,
+	isp_reg_writel(isp, ccdc->fpc.dma, OMAP3_ISP_IOMEM_CCDC,
 		       ISPCCDC_FPC_ADDR);
 	/* The FPNUM field must be set before enabling FPC. */
 	isp_reg_writel(isp, (ccdc->fpc.fpnum << ISPCCDC_FPC_FPNUM_SHIFT),
@@ -718,8 +717,9 @@ static int ccdc_config(struct isp_ccdc_device *ccdc,
 	ccdc->shadow_update = 0;
 
 	if (OMAP3ISP_CCDC_FPC & ccdc_struct->update) {
-		u32 table_old = 0;
-		u32 table_new;
+		struct omap3isp_ccdc_fpc fpc;
+		struct ispccdc_fpc fpc_old = { .addr = NULL, };
+		struct ispccdc_fpc fpc_new;
 		u32 size;
 
 		if (ccdc->state != ISP_PIPELINE_STREAM_STOPPED)
@@ -728,35 +728,39 @@ static int ccdc_config(struct isp_ccdc_device *ccdc,
 		ccdc->fpc_en = !!(OMAP3ISP_CCDC_FPC & ccdc_struct->flag);
 
 		if (ccdc->fpc_en) {
-			if (copy_from_user(&ccdc->fpc, ccdc_struct->fpc,
-					   sizeof(ccdc->fpc)))
+			if (copy_from_user(&fpc, ccdc_struct->fpc, sizeof(fpc)))
 				return -EFAULT;
 
+			size = fpc.fpnum * 4;
+
 			/*
-			 * table_new must be 64-bytes aligned, but it's
-			 * already done by omap_iommu_vmalloc().
+			 * The table address must be 64-bytes aligned, which is
+			 * guaranteed by dma_alloc_coherent().
 			 */
-			size = ccdc->fpc.fpnum * 4;
-			table_new = omap_iommu_vmalloc(isp->domain, isp->dev,
-							0, size, IOMMU_FLAG);
-			if (IS_ERR_VALUE(table_new))
+			fpc_new.fpnum = fpc.fpnum;
+			fpc_new.addr = dma_alloc_coherent(isp->dev, size,
+							  &fpc_new.dma,
+							  GFP_KERNEL);
+			if (fpc_new.addr == NULL)
 				return -ENOMEM;
 
-			if (copy_from_user(omap_da_to_va(isp->dev, table_new),
-					   (__force void __user *)
-					   ccdc->fpc.fpcaddr, size)) {
-				omap_iommu_vfree(isp->domain, isp->dev,
-								table_new);
+			if (copy_from_user(fpc_new.addr,
+					   (__force void __user *)fpc.fpcaddr,
+					   size)) {
+				dma_free_coherent(isp->dev, size, fpc_new.addr,
+						  fpc_new.dma);
 				return -EFAULT;
 			}
 
-			table_old = ccdc->fpc.fpcaddr;
-			ccdc->fpc.fpcaddr = table_new;
+			fpc_old = ccdc->fpc;
+			ccdc->fpc = fpc_new;
 		}
 
 		ccdc_configure_fpc(ccdc);
-		if (table_old != 0)
-			omap_iommu_vfree(isp->domain, isp->dev, table_old);
+
+		if (fpc_old.addr != NULL)
+			dma_free_coherent(isp->dev, fpc_old.fpnum * 4,
+					  fpc_old.addr, fpc_old.dma);
 	}
 
 	return ccdc_lsc_config(ccdc, ccdc_struct);
@@ -2574,8 +2578,9 @@ void omap3isp_ccdc_cleanup(struct isp_device *isp)
 	cancel_work_sync(&ccdc->lsc.table_work);
 	ccdc_lsc_free_queue(ccdc, &ccdc->lsc.free_queue);
 
-	if (ccdc->fpc.fpcaddr != 0)
-		omap_iommu_vfree(isp->domain, isp->dev, ccdc->fpc.fpcaddr);
+	if (ccdc->fpc.addr != NULL)
+		dma_free_coherent(isp->dev, ccdc->fpc.fpnum * 4, ccdc->fpc.addr,
+				  ccdc->fpc.dma);
 
 	mutex_destroy(&ccdc->ioctl_lock);
 }
diff --git a/drivers/media/platform/omap3isp/ispccdc.h b/drivers/media/platform/omap3isp/ispccdc.h
index 20db3a0..f650616 100644
--- a/drivers/media/platform/omap3isp/ispccdc.h
+++ b/drivers/media/platform/omap3isp/ispccdc.h
@@ -46,6 +46,12 @@ enum ccdc_input_entity {
 
 #define	OMAP3ISP_CCDC_NEVENTS	16
 
+struct ispccdc_fpc {
+	void *addr;
+	dma_addr_t dma;
+	unsigned int fpnum;
+};
+
 enum ispccdc_lsc_state {
 	LSC_STATE_STOPPED = 0,
 	LSC_STATE_STOPPING = 1,
@@ -140,7 +146,7 @@ struct isp_ccdc_device {
 		     fpc_en:1;
 	struct omap3isp_ccdc_blcomp blcomp;
 	struct omap3isp_ccdc_bclamp clamp;
-	struct omap3isp_ccdc_fpc fpc;
+	struct ispccdc_fpc fpc;
 	struct ispccdc_lsc lsc;
 	unsigned int update;
 	unsigned int shadow_update;
-- 
1.8.3.2


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

* [PATCH 09/25] omap3isp: video: Set the buffer bytesused field at completion time
  2014-04-03 22:39 [PATCH 00/25] OMAP3 ISP: Move to videobuf2 Laurent Pinchart
                   ` (7 preceding siblings ...)
  2014-04-03 22:39 ` [PATCH 08/25] omap3isp: ccdc: Use the DMA API for FPC Laurent Pinchart
@ 2014-04-03 22:39 ` Laurent Pinchart
  2014-04-03 22:39 ` [PATCH 10/25] omap3isp: queue: Move IOMMU handling code to the queue Laurent Pinchart
                   ` (15 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2014-04-03 22:39 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus

The v4l buffer bytesused field is a value that will be returned to
userspace when the buffer gets dequeued. As such it doesn't need to be
set early at buffer queue time. Move the assignment to buffer completion
in the omap3isp_video_buffer_next() function to prepare for the video
buffers queue refactoring.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/omap3isp/ispvideo.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c
index 85b4036..e0f594f3 100644
--- a/drivers/media/platform/omap3isp/ispvideo.c
+++ b/drivers/media/platform/omap3isp/ispvideo.c
@@ -431,7 +431,6 @@ static int isp_video_buffer_prepare(struct isp_video_buffer *buf)
 		return -EINVAL;
 	}
 
-	buf->vbuf.bytesused = vfh->format.fmt.pix.sizeimage;
 	buffer->isp_addr = addr;
 	return 0;
 }
@@ -514,6 +513,8 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video)
 {
 	struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity);
 	struct isp_video_queue *queue = video->queue;
+	struct isp_video_fh *vfh =
+		container_of(queue, struct isp_video_fh, queue);
 	enum isp_pipeline_state state;
 	struct isp_video_buffer *buf;
 	unsigned long flags;
@@ -530,6 +531,8 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video)
 	list_del(&buf->irqlist);
 	spin_unlock_irqrestore(&queue->irqlock, flags);
 
+	buf->vbuf.bytesused = vfh->format.fmt.pix.sizeimage;
+
 	ktime_get_ts(&ts);
 	buf->vbuf.timestamp.tv_sec = ts.tv_sec;
 	buf->vbuf.timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
-- 
1.8.3.2


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

* [PATCH 10/25] omap3isp: queue: Move IOMMU handling code to the queue
  2014-04-03 22:39 [PATCH 00/25] OMAP3 ISP: Move to videobuf2 Laurent Pinchart
                   ` (8 preceding siblings ...)
  2014-04-03 22:39 ` [PATCH 09/25] omap3isp: video: Set the buffer bytesused field at completion time Laurent Pinchart
@ 2014-04-03 22:39 ` Laurent Pinchart
  2014-04-03 22:39 ` [PATCH 11/25] omap3isp: queue: Use sg_table structure Laurent Pinchart
                   ` (14 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2014-04-03 22:39 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus

As a preparation for the switch from the OMAP IOMMU API to the DMA API
move all IOMMU handling code from the video node implementation to the
buffers queue implementation.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/omap3isp/ispqueue.c | 78 +++++++++++++++++++++++++++++-
 drivers/media/platform/omap3isp/ispqueue.h |  6 +--
 drivers/media/platform/omap3isp/ispvideo.c | 77 +----------------------------
 3 files changed, 78 insertions(+), 83 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispqueue.c b/drivers/media/platform/omap3isp/ispqueue.c
index a5e6585..8623c05 100644
--- a/drivers/media/platform/omap3isp/ispqueue.c
+++ b/drivers/media/platform/omap3isp/ispqueue.c
@@ -26,6 +26,7 @@
 #include <asm/cacheflush.h>
 #include <linux/dma-mapping.h>
 #include <linux/mm.h>
+#include <linux/omap-iommu.h>
 #include <linux/pagemap.h>
 #include <linux/poll.h>
 #include <linux/scatterlist.h>
@@ -33,7 +34,58 @@
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 
+#include "isp.h"
 #include "ispqueue.h"
+#include "ispvideo.h"
+
+/* -----------------------------------------------------------------------------
+ * IOMMU management
+ */
+
+#define IOMMU_FLAG	(IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_8)
+
+/*
+ * ispmmu_vmap - Wrapper for Virtual memory mapping of a scatter gather list
+ * @dev: Device pointer specific to the OMAP3 ISP.
+ * @sglist: Pointer to source Scatter gather list to allocate.
+ * @sglen: Number of elements of the scatter-gatter list.
+ *
+ * Returns a resulting mapped device address by the ISP MMU, or -ENOMEM if
+ * we ran out of memory.
+ */
+static dma_addr_t
+ispmmu_vmap(struct isp_device *isp, const struct scatterlist *sglist, int sglen)
+{
+	struct sg_table *sgt;
+	u32 da;
+
+	sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
+	if (sgt == NULL)
+		return -ENOMEM;
+
+	sgt->sgl = (struct scatterlist *)sglist;
+	sgt->nents = sglen;
+	sgt->orig_nents = sglen;
+
+	da = omap_iommu_vmap(isp->domain, isp->dev, 0, sgt, IOMMU_FLAG);
+	if (IS_ERR_VALUE(da))
+		kfree(sgt);
+
+	return da;
+}
+
+/*
+ * ispmmu_vunmap - Unmap a device address from the ISP MMU
+ * @dev: Device pointer specific to the OMAP3 ISP.
+ * @da: Device address generated from a ispmmu_vmap call.
+ */
+static void ispmmu_vunmap(struct isp_device *isp, dma_addr_t da)
+{
+	struct sg_table *sgt;
+
+	sgt = omap_iommu_vunmap(isp->domain, isp->dev, (u32)da);
+	kfree(sgt);
+}
 
 /* -----------------------------------------------------------------------------
  * Video buffers management
@@ -260,11 +312,15 @@ static int isp_video_buffer_sglist_pfnmap(struct isp_video_buffer *buf)
  */
 static void isp_video_buffer_cleanup(struct isp_video_buffer *buf)
 {
+	struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue);
+	struct isp_video *video = vfh->video;
 	enum dma_data_direction direction;
 	unsigned int i;
 
-	if (buf->queue->ops->buffer_cleanup)
-		buf->queue->ops->buffer_cleanup(buf);
+	if (buf->dma) {
+		ispmmu_vunmap(video->isp, buf->dma);
+		buf->dma = 0;
+	}
 
 	if (!(buf->vm_flags & VM_PFNMAP)) {
 		direction = buf->vbuf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE
@@ -479,7 +535,10 @@ done:
  */
 static int isp_video_buffer_prepare(struct isp_video_buffer *buf)
 {
+	struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue);
+	struct isp_video *video = vfh->video;
 	enum dma_data_direction direction;
+	unsigned long addr;
 	int ret;
 
 	switch (buf->vbuf.memory) {
@@ -525,6 +584,21 @@ static int isp_video_buffer_prepare(struct isp_video_buffer *buf)
 		}
 	}
 
+	addr = ispmmu_vmap(video->isp, buf->sglist, buf->sglen);
+	if (IS_ERR_VALUE(addr)) {
+		ret = -EIO;
+		goto done;
+	}
+
+	buf->dma = addr;
+
+	if (!IS_ALIGNED(addr, 32)) {
+		dev_dbg(video->isp->dev,
+			"Buffer address must be aligned to 32 bytes boundary.\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
 	if (buf->queue->ops->buffer_prepare)
 		ret = buf->queue->ops->buffer_prepare(buf);
 
diff --git a/drivers/media/platform/omap3isp/ispqueue.h b/drivers/media/platform/omap3isp/ispqueue.h
index 3e048ad..0899a11 100644
--- a/drivers/media/platform/omap3isp/ispqueue.h
+++ b/drivers/media/platform/omap3isp/ispqueue.h
@@ -106,6 +106,7 @@ struct isp_video_buffer {
 	struct list_head irqlist;
 	enum isp_video_buffer_state state;
 	wait_queue_head_t wait;
+	dma_addr_t dma;
 };
 
 #define to_isp_video_buffer(vb)	container_of(vb, struct isp_video_buffer, vb)
@@ -121,17 +122,12 @@ struct isp_video_buffer {
  *	mapping the buffer memory in an IOMMU). This operation is optional.
  * @buffer_queue: Called when a buffer is being added to the queue with the
  *	queue irqlock spinlock held.
- * @buffer_cleanup: Called before freeing buffers, or before changing the
- *	userspace memory address for a USERPTR buffer, with the queue lock held.
- *	Drivers must perform cleanup operations required to undo the
- *	buffer_prepare call. This operation is optional.
  */
 struct isp_video_queue_operations {
 	void (*queue_prepare)(struct isp_video_queue *queue,
 			      unsigned int *nbuffers, unsigned int *size);
 	int  (*buffer_prepare)(struct isp_video_buffer *buf);
 	void (*buffer_queue)(struct isp_video_buffer *buf);
-	void (*buffer_cleanup)(struct isp_video_buffer *buf);
 };
 
 /**
diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c
index e0f594f3..a7ef081 100644
--- a/drivers/media/platform/omap3isp/ispvideo.c
+++ b/drivers/media/platform/omap3isp/ispvideo.c
@@ -27,7 +27,6 @@
 #include <linux/clk.h>
 #include <linux/mm.h>
 #include <linux/module.h>
-#include <linux/omap-iommu.h>
 #include <linux/pagemap.h>
 #include <linux/scatterlist.h>
 #include <linux/sched.h>
@@ -326,55 +325,6 @@ isp_video_check_format(struct isp_video *video, struct isp_video_fh *vfh)
 }
 
 /* -----------------------------------------------------------------------------
- * IOMMU management
- */
-
-#define IOMMU_FLAG	(IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_8)
-
-/*
- * ispmmu_vmap - Wrapper for Virtual memory mapping of a scatter gather list
- * @isp: Device pointer specific to the OMAP3 ISP.
- * @sglist: Pointer to source Scatter gather list to allocate.
- * @sglen: Number of elements of the scatter-gatter list.
- *
- * Returns a resulting mapped device address by the ISP MMU, or -ENOMEM if
- * we ran out of memory.
- */
-static dma_addr_t
-ispmmu_vmap(struct isp_device *isp, const struct scatterlist *sglist, int sglen)
-{
-	struct sg_table *sgt;
-	u32 da;
-
-	sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
-	if (sgt == NULL)
-		return -ENOMEM;
-
-	sgt->sgl = (struct scatterlist *)sglist;
-	sgt->nents = sglen;
-	sgt->orig_nents = sglen;
-
-	da = omap_iommu_vmap(isp->domain, isp->dev, 0, sgt, IOMMU_FLAG);
-	if (IS_ERR_VALUE(da))
-		kfree(sgt);
-
-	return da;
-}
-
-/*
- * ispmmu_vunmap - Unmap a device address from the ISP MMU
- * @isp: Device pointer specific to the OMAP3 ISP.
- * @da: Device address generated from a ispmmu_vmap call.
- */
-static void ispmmu_vunmap(struct isp_device *isp, dma_addr_t da)
-{
-	struct sg_table *sgt;
-
-	sgt = omap_iommu_vunmap(isp->domain, isp->dev, (u32)da);
-	kfree(sgt);
-}
-
-/* -----------------------------------------------------------------------------
  * Video queue operations
  */
 
@@ -392,24 +342,11 @@ static void isp_video_queue_prepare(struct isp_video_queue *queue,
 	*nbuffers = min(*nbuffers, video->capture_mem / PAGE_ALIGN(*size));
 }
 
-static void isp_video_buffer_cleanup(struct isp_video_buffer *buf)
-{
-	struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue);
-	struct isp_buffer *buffer = to_isp_buffer(buf);
-	struct isp_video *video = vfh->video;
-
-	if (buffer->isp_addr) {
-		ispmmu_vunmap(video->isp, buffer->isp_addr);
-		buffer->isp_addr = 0;
-	}
-}
-
 static int isp_video_buffer_prepare(struct isp_video_buffer *buf)
 {
 	struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue);
 	struct isp_buffer *buffer = to_isp_buffer(buf);
 	struct isp_video *video = vfh->video;
-	unsigned long addr;
 
 	/* Refuse to prepare the buffer is the video node has registered an
 	 * error. We don't need to take any lock here as the operation is
@@ -420,18 +357,7 @@ static int isp_video_buffer_prepare(struct isp_video_buffer *buf)
 	if (unlikely(video->error))
 		return -EIO;
 
-	addr = ispmmu_vmap(video->isp, buf->sglist, buf->sglen);
-	if (IS_ERR_VALUE(addr))
-		return -EIO;
-
-	if (!IS_ALIGNED(addr, 32)) {
-		dev_dbg(video->isp->dev, "Buffer address must be "
-			"aligned to 32 bytes boundary.\n");
-		ispmmu_vunmap(video->isp, buffer->isp_addr);
-		return -EINVAL;
-	}
-
-	buffer->isp_addr = addr;
+	buffer->isp_addr = buf->dma;
 	return 0;
 }
 
@@ -490,7 +416,6 @@ static const struct isp_video_queue_operations isp_video_queue_ops = {
 	.queue_prepare = &isp_video_queue_prepare,
 	.buffer_prepare = &isp_video_buffer_prepare,
 	.buffer_queue = &isp_video_buffer_queue,
-	.buffer_cleanup = &isp_video_buffer_cleanup,
 };
 
 /*
-- 
1.8.3.2


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

* [PATCH 11/25] omap3isp: queue: Use sg_table structure
  2014-04-03 22:39 [PATCH 00/25] OMAP3 ISP: Move to videobuf2 Laurent Pinchart
                   ` (9 preceding siblings ...)
  2014-04-03 22:39 ` [PATCH 10/25] omap3isp: queue: Move IOMMU handling code to the queue Laurent Pinchart
@ 2014-04-03 22:39 ` Laurent Pinchart
  2014-04-03 22:39 ` [PATCH 12/25] omap3isp: queue: Merge the prepare and sglist functions Laurent Pinchart
                   ` (13 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2014-04-03 22:39 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus

Replace the sglen and sglist fields stored in the buffer structure with
an sg_table. This allows using the sg table allocation helper function.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/omap3isp/ispqueue.c | 108 ++++++++++-------------------
 drivers/media/platform/omap3isp/ispqueue.h |   6 +-
 2 files changed, 40 insertions(+), 74 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispqueue.c b/drivers/media/platform/omap3isp/ispqueue.c
index 8623c05..51ec40d 100644
--- a/drivers/media/platform/omap3isp/ispqueue.c
+++ b/drivers/media/platform/omap3isp/ispqueue.c
@@ -45,33 +45,17 @@
 #define IOMMU_FLAG	(IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_8)
 
 /*
- * ispmmu_vmap - Wrapper for Virtual memory mapping of a scatter gather list
+ * ispmmu_vmap - Wrapper for virtual memory mapping of a scatter gather table
  * @dev: Device pointer specific to the OMAP3 ISP.
- * @sglist: Pointer to source Scatter gather list to allocate.
- * @sglen: Number of elements of the scatter-gatter list.
+ * @sgt: Pointer to source scatter gather table.
  *
  * Returns a resulting mapped device address by the ISP MMU, or -ENOMEM if
  * we ran out of memory.
  */
 static dma_addr_t
-ispmmu_vmap(struct isp_device *isp, const struct scatterlist *sglist, int sglen)
+ispmmu_vmap(struct isp_device *isp, const struct sg_table *sgt)
 {
-	struct sg_table *sgt;
-	u32 da;
-
-	sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
-	if (sgt == NULL)
-		return -ENOMEM;
-
-	sgt->sgl = (struct scatterlist *)sglist;
-	sgt->nents = sglen;
-	sgt->orig_nents = sglen;
-
-	da = omap_iommu_vmap(isp->domain, isp->dev, 0, sgt, IOMMU_FLAG);
-	if (IS_ERR_VALUE(da))
-		kfree(sgt);
-
-	return da;
+	return omap_iommu_vmap(isp->domain, isp->dev, 0, sgt, IOMMU_FLAG);
 }
 
 /*
@@ -81,10 +65,7 @@ ispmmu_vmap(struct isp_device *isp, const struct scatterlist *sglist, int sglen)
  */
 static void ispmmu_vunmap(struct isp_device *isp, dma_addr_t da)
 {
-	struct sg_table *sgt;
-
-	sgt = omap_iommu_vunmap(isp->domain, isp->dev, (u32)da);
-	kfree(sgt);
+	omap_iommu_vunmap(isp->domain, isp->dev, (u32)da);
 }
 
 /* -----------------------------------------------------------------------------
@@ -204,34 +185,31 @@ out:
  */
 static int isp_video_buffer_sglist_kernel(struct isp_video_buffer *buf)
 {
-	struct scatterlist *sglist;
+	struct scatterlist *sg;
 	unsigned int npages;
 	unsigned int i;
 	void *addr;
+	int ret;
 
 	addr = buf->vaddr;
 	npages = PAGE_ALIGN(buf->vbuf.length) >> PAGE_SHIFT;
 
-	sglist = vmalloc(npages * sizeof(*sglist));
-	if (sglist == NULL)
-		return -ENOMEM;
-
-	sg_init_table(sglist, npages);
+	ret = sg_alloc_table(&buf->sgt, npages, GFP_KERNEL);
+	if (ret < 0)
+		return ret;
 
-	for (i = 0; i < npages; ++i, addr += PAGE_SIZE) {
+	for (sg = buf->sgt.sgl, i = 0; i < npages; ++i, addr += PAGE_SIZE) {
 		struct page *page = vmalloc_to_page(addr);
 
 		if (page == NULL || PageHighMem(page)) {
-			vfree(sglist);
+			sg_free_table(&buf->sgt);
 			return -EINVAL;
 		}
 
-		sg_set_page(&sglist[i], page, PAGE_SIZE, 0);
+		sg_set_page(sg, page, PAGE_SIZE, 0);
+		sg = sg_next(sg);
 	}
 
-	buf->sglen = npages;
-	buf->sglist = sglist;
-
 	return 0;
 }
 
@@ -242,30 +220,26 @@ static int isp_video_buffer_sglist_kernel(struct isp_video_buffer *buf)
  */
 static int isp_video_buffer_sglist_user(struct isp_video_buffer *buf)
 {
-	struct scatterlist *sglist;
 	unsigned int offset = buf->offset;
+	struct scatterlist *sg;
 	unsigned int i;
+	int ret;
 
-	sglist = vmalloc(buf->npages * sizeof(*sglist));
-	if (sglist == NULL)
-		return -ENOMEM;
-
-	sg_init_table(sglist, buf->npages);
+	ret = sg_alloc_table(&buf->sgt, buf->npages, GFP_KERNEL);
+	if (ret < 0)
+		return ret;
 
-	for (i = 0; i < buf->npages; ++i) {
+	for (sg = buf->sgt.sgl, i = 0; i < buf->npages; ++i) {
 		if (PageHighMem(buf->pages[i])) {
-			vfree(sglist);
+			sg_free_table(&buf->sgt);
 			return -EINVAL;
 		}
 
-		sg_set_page(&sglist[i], buf->pages[i], PAGE_SIZE - offset,
-			    offset);
+		sg_set_page(sg, buf->pages[i], PAGE_SIZE - offset, offset);
+		sg = sg_next(sg);
 		offset = 0;
 	}
 
-	buf->sglen = buf->npages;
-	buf->sglist = sglist;
-
 	return 0;
 }
 
@@ -277,30 +251,26 @@ static int isp_video_buffer_sglist_user(struct isp_video_buffer *buf)
  */
 static int isp_video_buffer_sglist_pfnmap(struct isp_video_buffer *buf)
 {
-	struct scatterlist *sglist;
+	struct scatterlist *sg;
 	unsigned int offset = buf->offset;
 	unsigned long pfn = buf->paddr >> PAGE_SHIFT;
 	unsigned int i;
+	int ret;
 
-	sglist = vmalloc(buf->npages * sizeof(*sglist));
-	if (sglist == NULL)
-		return -ENOMEM;
-
-	sg_init_table(sglist, buf->npages);
+	ret = sg_alloc_table(&buf->sgt, buf->npages, GFP_KERNEL);
+	if (ret < 0)
+		return ret;
 
-	for (i = 0; i < buf->npages; ++i, ++pfn) {
-		sg_set_page(&sglist[i], pfn_to_page(pfn), PAGE_SIZE - offset,
-			    offset);
+	for (sg = buf->sgt.sgl, i = 0; i < buf->npages; ++i, ++pfn) {
+		sg_set_page(sg, pfn_to_page(pfn), PAGE_SIZE - offset, offset);
 		/* PFNMAP buffers will not get DMA-mapped, set the DMA address
 		 * manually.
 		 */
-		sg_dma_address(&sglist[i]) = (pfn << PAGE_SHIFT) + offset;
+		sg_dma_address(sg) = (pfn << PAGE_SHIFT) + offset;
+		sg = sg_next(sg);
 		offset = 0;
 	}
 
-	buf->sglen = buf->npages;
-	buf->sglist = sglist;
-
 	return 0;
 }
 
@@ -325,13 +295,11 @@ static void isp_video_buffer_cleanup(struct isp_video_buffer *buf)
 	if (!(buf->vm_flags & VM_PFNMAP)) {
 		direction = buf->vbuf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE
 			  ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
-		dma_unmap_sg(buf->queue->dev, buf->sglist, buf->sglen,
+		dma_unmap_sg(buf->queue->dev, buf->sgt.sgl, buf->sgt.orig_nents,
 			     direction);
 	}
 
-	vfree(buf->sglist);
-	buf->sglist = NULL;
-	buf->sglen = 0;
+	sg_free_table(&buf->sgt);
 
 	if (buf->pages != NULL) {
 		isp_video_buffer_lock_vma(buf, 0);
@@ -576,15 +544,15 @@ static int isp_video_buffer_prepare(struct isp_video_buffer *buf)
 	if (!(buf->vm_flags & VM_PFNMAP)) {
 		direction = buf->vbuf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE
 			  ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
-		ret = dma_map_sg(buf->queue->dev, buf->sglist, buf->sglen,
-				 direction);
-		if (ret != buf->sglen) {
+		ret = dma_map_sg(buf->queue->dev, buf->sgt.sgl,
+				 buf->sgt.orig_nents, direction);
+		if (ret != buf->sgt.orig_nents) {
 			ret = -EFAULT;
 			goto done;
 		}
 	}
 
-	addr = ispmmu_vmap(video->isp, buf->sglist, buf->sglen);
+	addr = ispmmu_vmap(video->isp, &buf->sgt);
 	if (IS_ERR_VALUE(addr)) {
 		ret = -EIO;
 		goto done;
diff --git a/drivers/media/platform/omap3isp/ispqueue.h b/drivers/media/platform/omap3isp/ispqueue.h
index 0899a11..99c11e8 100644
--- a/drivers/media/platform/omap3isp/ispqueue.h
+++ b/drivers/media/platform/omap3isp/ispqueue.h
@@ -73,8 +73,7 @@ enum isp_video_buffer_state {
  * @npages: Number of pages (for userspace buffers)
  * @pages: Pages table (for userspace non-VM_PFNMAP buffers)
  * @paddr: Memory physical address (for userspace VM_PFNMAP buffers)
- * @sglen: Number of elements in the scatter list (for non-VM_PFNMAP buffers)
- * @sglist: Scatter list (for non-VM_PFNMAP buffers)
+ * @sgt: Scatter gather table (for non-VM_PFNMAP buffers)
  * @vbuf: V4L2 buffer
  * @irqlist: List head for insertion into IRQ queue
  * @state: Current buffer state
@@ -98,8 +97,7 @@ struct isp_video_buffer {
 	dma_addr_t paddr;
 
 	/* For all buffers except VM_PFNMAP. */
-	unsigned int sglen;
-	struct scatterlist *sglist;
+	struct sg_table sgt;
 
 	/* Touched by the interrupt handler. */
 	struct v4l2_buffer vbuf;
-- 
1.8.3.2


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

* [PATCH 12/25] omap3isp: queue: Merge the prepare and sglist functions
  2014-04-03 22:39 [PATCH 00/25] OMAP3 ISP: Move to videobuf2 Laurent Pinchart
                   ` (10 preceding siblings ...)
  2014-04-03 22:39 ` [PATCH 11/25] omap3isp: queue: Use sg_table structure Laurent Pinchart
@ 2014-04-03 22:39 ` Laurent Pinchart
  2014-04-03 22:39 ` [PATCH 13/25] omap3isp: queue: Inline the ispmmu_v(un)map functions Laurent Pinchart
                   ` (12 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2014-04-03 22:39 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus

In preparation for the switch to the DMA API merge the two functions
that handle buffer preparation for the USERPTR cases (both page-backed
and non page-backed memory).

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/omap3isp/ispqueue.c | 169 ++++++++++++-----------------
 drivers/media/platform/omap3isp/ispqueue.h |   4 -
 2 files changed, 69 insertions(+), 104 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispqueue.c b/drivers/media/platform/omap3isp/ispqueue.c
index 51ec40d..a7be7d7 100644
--- a/drivers/media/platform/omap3isp/ispqueue.c
+++ b/drivers/media/platform/omap3isp/ispqueue.c
@@ -178,12 +178,12 @@ out:
 }
 
 /*
- * isp_video_buffer_sglist_kernel - Build a scatter list for a vmalloc'ed buffer
+ * isp_video_buffer_prepare_kernel - Build scatter list for a vmalloc'ed buffer
  *
  * Iterate over the vmalloc'ed area and create a scatter list entry for every
  * page.
  */
-static int isp_video_buffer_sglist_kernel(struct isp_video_buffer *buf)
+static int isp_video_buffer_prepare_kernel(struct isp_video_buffer *buf)
 {
 	struct scatterlist *sg;
 	unsigned int npages;
@@ -214,67 +214,6 @@ static int isp_video_buffer_sglist_kernel(struct isp_video_buffer *buf)
 }
 
 /*
- * isp_video_buffer_sglist_user - Build a scatter list for a userspace buffer
- *
- * Walk the buffer pages list and create a 1:1 mapping to a scatter list.
- */
-static int isp_video_buffer_sglist_user(struct isp_video_buffer *buf)
-{
-	unsigned int offset = buf->offset;
-	struct scatterlist *sg;
-	unsigned int i;
-	int ret;
-
-	ret = sg_alloc_table(&buf->sgt, buf->npages, GFP_KERNEL);
-	if (ret < 0)
-		return ret;
-
-	for (sg = buf->sgt.sgl, i = 0; i < buf->npages; ++i) {
-		if (PageHighMem(buf->pages[i])) {
-			sg_free_table(&buf->sgt);
-			return -EINVAL;
-		}
-
-		sg_set_page(sg, buf->pages[i], PAGE_SIZE - offset, offset);
-		sg = sg_next(sg);
-		offset = 0;
-	}
-
-	return 0;
-}
-
-/*
- * isp_video_buffer_sglist_pfnmap - Build a scatter list for a VM_PFNMAP buffer
- *
- * Create a scatter list of physically contiguous pages starting at the buffer
- * memory physical address.
- */
-static int isp_video_buffer_sglist_pfnmap(struct isp_video_buffer *buf)
-{
-	struct scatterlist *sg;
-	unsigned int offset = buf->offset;
-	unsigned long pfn = buf->paddr >> PAGE_SHIFT;
-	unsigned int i;
-	int ret;
-
-	ret = sg_alloc_table(&buf->sgt, buf->npages, GFP_KERNEL);
-	if (ret < 0)
-		return ret;
-
-	for (sg = buf->sgt.sgl, i = 0; i < buf->npages; ++i, ++pfn) {
-		sg_set_page(sg, pfn_to_page(pfn), PAGE_SIZE - offset, offset);
-		/* PFNMAP buffers will not get DMA-mapped, set the DMA address
-		 * manually.
-		 */
-		sg_dma_address(sg) = (pfn << PAGE_SHIFT) + offset;
-		sg = sg_next(sg);
-		offset = 0;
-	}
-
-	return 0;
-}
-
-/*
  * isp_video_buffer_cleanup - Release pages for a userspace VMA.
  *
  * Release pages locked by a call isp_video_buffer_prepare_user and free the
@@ -316,11 +255,11 @@ static void isp_video_buffer_cleanup(struct isp_video_buffer *buf)
 }
 
 /*
- * isp_video_buffer_prepare_user - Pin userspace VMA pages to memory.
+ * isp_video_buffer_prepare_user - Prepare a userspace buffer.
  *
- * This function creates a list of pages for a userspace VMA. The number of
- * pages is first computed based on the buffer size, and pages are then
- * retrieved by a call to get_user_pages.
+ * This function creates a scatter list with a 1:1 mapping for a userspace VMA.
+ * The number of pages is first computed based on the buffer size, and pages are
+ * then retrieved by a call to get_user_pages.
  *
  * Pages are pinned to memory by get_user_pages, making them available for DMA
  * transfers. However, due to memory management optimization, it seems the
@@ -340,16 +279,19 @@ static void isp_video_buffer_cleanup(struct isp_video_buffer *buf)
  */
 static int isp_video_buffer_prepare_user(struct isp_video_buffer *buf)
 {
+	struct scatterlist *sg;
+	unsigned int offset;
 	unsigned long data;
 	unsigned int first;
 	unsigned int last;
+	unsigned int i;
 	int ret;
 
 	data = buf->vbuf.m.userptr;
 	first = (data & PAGE_MASK) >> PAGE_SHIFT;
 	last = ((data + buf->vbuf.length - 1) & PAGE_MASK) >> PAGE_SHIFT;
+	offset = data & ~PAGE_MASK;
 
-	buf->offset = data & ~PAGE_MASK;
 	buf->npages = last - first + 1;
 	buf->pages = vmalloc(buf->npages * sizeof(buf->pages[0]));
 	if (buf->pages == NULL)
@@ -364,68 +306,104 @@ static int isp_video_buffer_prepare_user(struct isp_video_buffer *buf)
 
 	if (ret != buf->npages) {
 		buf->npages = ret < 0 ? 0 : ret;
-		isp_video_buffer_cleanup(buf);
 		return -EFAULT;
 	}
 
 	ret = isp_video_buffer_lock_vma(buf, 1);
 	if (ret < 0)
-		isp_video_buffer_cleanup(buf);
+		return ret;
 
-	return ret;
+	ret = sg_alloc_table(&buf->sgt, buf->npages, GFP_KERNEL);
+	if (ret < 0)
+		return ret;
+
+	for (sg = buf->sgt.sgl, i = 0; i < buf->npages; ++i) {
+		if (PageHighMem(buf->pages[i])) {
+			sg_free_table(&buf->sgt);
+			return -EINVAL;
+		}
+
+		sg_set_page(sg, buf->pages[i], PAGE_SIZE - offset, offset);
+		sg = sg_next(sg);
+		offset = 0;
+	}
+
+	return 0;
 }
 
 /*
- * isp_video_buffer_prepare_pfnmap - Validate a VM_PFNMAP userspace buffer
+ * isp_video_buffer_prepare_pfnmap - Prepare a VM_PFNMAP userspace buffer
  *
  * Userspace VM_PFNMAP buffers are supported only if they are contiguous in
- * memory and if they span a single VMA.
+ * memory and if they span a single VMA. Start by validating the user pointer to
+ * make sure it fulfils that condition, and then build a scatter list of
+ * physically contiguous pages starting at the buffer memory physical address.
  *
- * Return 0 if the buffer is valid, or -EFAULT otherwise.
+ * Return 0 on success, -EFAULT if the buffer isn't valid or -ENOMEM if memory
+ * can't be allocated.
  */
 static int isp_video_buffer_prepare_pfnmap(struct isp_video_buffer *buf)
 {
 	struct vm_area_struct *vma;
+	struct scatterlist *sg;
 	unsigned long prev_pfn;
 	unsigned long this_pfn;
 	unsigned long start;
+	unsigned int offset;
 	unsigned long end;
-	dma_addr_t pa = 0;
-	int ret = -EFAULT;
+	unsigned long pfn;
+	unsigned int i;
+	int ret = 0;
 
 	start = buf->vbuf.m.userptr;
 	end = buf->vbuf.m.userptr + buf->vbuf.length - 1;
+	offset = start & ~PAGE_MASK;
 
-	buf->offset = start & ~PAGE_MASK;
 	buf->npages = (end >> PAGE_SHIFT) - (start >> PAGE_SHIFT) + 1;
 	buf->pages = NULL;
 
 	down_read(&current->mm->mmap_sem);
 	vma = find_vma(current->mm, start);
-	if (vma == NULL || vma->vm_end < end)
-		goto done;
+	if (vma == NULL || vma->vm_end < end) {
+		ret = -EFAULT;
+		goto unlock;
+	}
 
 	for (prev_pfn = 0; start <= end; start += PAGE_SIZE) {
 		ret = follow_pfn(vma, start, &this_pfn);
-		if (ret)
-			goto done;
+		if (ret < 0)
+			goto unlock;
 
 		if (prev_pfn == 0)
-			pa = this_pfn << PAGE_SHIFT;
+			pfn = this_pfn;
 		else if (this_pfn != prev_pfn + 1) {
 			ret = -EFAULT;
-			goto done;
+			goto unlock;
 		}
 
 		prev_pfn = this_pfn;
 	}
 
-	buf->paddr = pa + buf->offset;
-	ret = 0;
-
-done:
+unlock:
 	up_read(&current->mm->mmap_sem);
-	return ret;
+	if (ret < 0)
+		return ret;
+
+	ret = sg_alloc_table(&buf->sgt, buf->npages, GFP_KERNEL);
+	if (ret < 0)
+		return ret;
+
+	for (sg = buf->sgt.sgl, i = 0; i < buf->npages; ++i, ++pfn) {
+		sg_set_page(sg, pfn_to_page(pfn), PAGE_SIZE - offset, offset);
+		/* PFNMAP buffers will not get DMA-mapped, set the DMA address
+		 * manually.
+		 */
+		sg_dma_address(sg) = (pfn << PAGE_SHIFT) + offset;
+		sg = sg_next(sg);
+		offset = 0;
+	}
+
+	return 0;
 }
 
 /*
@@ -511,7 +489,7 @@ static int isp_video_buffer_prepare(struct isp_video_buffer *buf)
 
 	switch (buf->vbuf.memory) {
 	case V4L2_MEMORY_MMAP:
-		ret = isp_video_buffer_sglist_kernel(buf);
+		ret = isp_video_buffer_prepare_kernel(buf);
 		break;
 
 	case V4L2_MEMORY_USERPTR:
@@ -519,19 +497,10 @@ static int isp_video_buffer_prepare(struct isp_video_buffer *buf)
 		if (ret < 0)
 			return ret;
 
-		if (buf->vm_flags & VM_PFNMAP) {
+		if (buf->vm_flags & VM_PFNMAP)
 			ret = isp_video_buffer_prepare_pfnmap(buf);
-			if (ret < 0)
-				return ret;
-
-			ret = isp_video_buffer_sglist_pfnmap(buf);
-		} else {
+		else
 			ret = isp_video_buffer_prepare_user(buf);
-			if (ret < 0)
-				return ret;
-
-			ret = isp_video_buffer_sglist_user(buf);
-		}
 		break;
 
 	default:
diff --git a/drivers/media/platform/omap3isp/ispqueue.h b/drivers/media/platform/omap3isp/ispqueue.h
index 99c11e8..f78325d 100644
--- a/drivers/media/platform/omap3isp/ispqueue.h
+++ b/drivers/media/platform/omap3isp/ispqueue.h
@@ -69,10 +69,8 @@ enum isp_video_buffer_state {
  * @skip_cache: Whether to skip cache management operations for this buffer
  * @vaddr: Memory virtual address (for kernel buffers)
  * @vm_flags: Buffer VMA flags (for userspace buffers)
- * @offset: Offset inside the first page (for userspace buffers)
  * @npages: Number of pages (for userspace buffers)
  * @pages: Pages table (for userspace non-VM_PFNMAP buffers)
- * @paddr: Memory physical address (for userspace VM_PFNMAP buffers)
  * @sgt: Scatter gather table (for non-VM_PFNMAP buffers)
  * @vbuf: V4L2 buffer
  * @irqlist: List head for insertion into IRQ queue
@@ -91,10 +89,8 @@ struct isp_video_buffer {
 
 	/* For userspace buffers. */
 	vm_flags_t vm_flags;
-	unsigned long offset;
 	unsigned int npages;
 	struct page **pages;
-	dma_addr_t paddr;
 
 	/* For all buffers except VM_PFNMAP. */
 	struct sg_table sgt;
-- 
1.8.3.2


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

* [PATCH 13/25] omap3isp: queue: Inline the ispmmu_v(un)map functions
  2014-04-03 22:39 [PATCH 00/25] OMAP3 ISP: Move to videobuf2 Laurent Pinchart
                   ` (11 preceding siblings ...)
  2014-04-03 22:39 ` [PATCH 12/25] omap3isp: queue: Merge the prepare and sglist functions Laurent Pinchart
@ 2014-04-03 22:39 ` Laurent Pinchart
  2014-04-03 22:39 ` [PATCH 14/25] omap3isp: queue: Allocate kernel buffers with dma_alloc_coherent Laurent Pinchart
                   ` (11 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2014-04-03 22:39 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus

The ispmmu_vmap() and ispmmu_vunmap() functions are just wrappers around
omap_iommu_vmap() and omap_iommu_vunmap(). Inline them.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/omap3isp/ispqueue.c | 36 ++++--------------------------
 1 file changed, 4 insertions(+), 32 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispqueue.c b/drivers/media/platform/omap3isp/ispqueue.c
index a7be7d7..088710b 100644
--- a/drivers/media/platform/omap3isp/ispqueue.c
+++ b/drivers/media/platform/omap3isp/ispqueue.c
@@ -39,36 +39,6 @@
 #include "ispvideo.h"
 
 /* -----------------------------------------------------------------------------
- * IOMMU management
- */
-
-#define IOMMU_FLAG	(IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_8)
-
-/*
- * ispmmu_vmap - Wrapper for virtual memory mapping of a scatter gather table
- * @dev: Device pointer specific to the OMAP3 ISP.
- * @sgt: Pointer to source scatter gather table.
- *
- * Returns a resulting mapped device address by the ISP MMU, or -ENOMEM if
- * we ran out of memory.
- */
-static dma_addr_t
-ispmmu_vmap(struct isp_device *isp, const struct sg_table *sgt)
-{
-	return omap_iommu_vmap(isp->domain, isp->dev, 0, sgt, IOMMU_FLAG);
-}
-
-/*
- * ispmmu_vunmap - Unmap a device address from the ISP MMU
- * @dev: Device pointer specific to the OMAP3 ISP.
- * @da: Device address generated from a ispmmu_vmap call.
- */
-static void ispmmu_vunmap(struct isp_device *isp, dma_addr_t da)
-{
-	omap_iommu_vunmap(isp->domain, isp->dev, (u32)da);
-}
-
-/* -----------------------------------------------------------------------------
  * Video buffers management
  */
 
@@ -227,7 +197,8 @@ static void isp_video_buffer_cleanup(struct isp_video_buffer *buf)
 	unsigned int i;
 
 	if (buf->dma) {
-		ispmmu_vunmap(video->isp, buf->dma);
+		omap_iommu_vunmap(video->isp->domain, video->isp->dev,
+				  buf->dma);
 		buf->dma = 0;
 	}
 
@@ -521,7 +492,8 @@ static int isp_video_buffer_prepare(struct isp_video_buffer *buf)
 		}
 	}
 
-	addr = ispmmu_vmap(video->isp, &buf->sgt);
+	addr = omap_iommu_vmap(video->isp->domain, video->isp->dev, 0,
+			       &buf->sgt, IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_8);
 	if (IS_ERR_VALUE(addr)) {
 		ret = -EIO;
 		goto done;
-- 
1.8.3.2


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

* [PATCH 14/25] omap3isp: queue: Allocate kernel buffers with dma_alloc_coherent
  2014-04-03 22:39 [PATCH 00/25] OMAP3 ISP: Move to videobuf2 Laurent Pinchart
                   ` (12 preceding siblings ...)
  2014-04-03 22:39 ` [PATCH 13/25] omap3isp: queue: Inline the ispmmu_v(un)map functions Laurent Pinchart
@ 2014-04-03 22:39 ` Laurent Pinchart
  2014-04-03 22:39 ` [PATCH 15/25] omap3isp: queue: Fix the dma_map_sg() return value check Laurent Pinchart
                   ` (10 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2014-04-03 22:39 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus

And retrieve the related sg table using dma_get_sgtable().

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/omap3isp/ispqueue.c | 57 +++++++++++++-----------------
 drivers/media/platform/omap3isp/ispqueue.h |  2 ++
 2 files changed, 27 insertions(+), 32 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispqueue.c b/drivers/media/platform/omap3isp/ispqueue.c
index 088710b..2fd254f 100644
--- a/drivers/media/platform/omap3isp/ispqueue.c
+++ b/drivers/media/platform/omap3isp/ispqueue.c
@@ -148,39 +148,18 @@ out:
 }
 
 /*
- * isp_video_buffer_prepare_kernel - Build scatter list for a vmalloc'ed buffer
+ * isp_video_buffer_prepare_kernel - Build scatter list for a kernel-allocated
+ * buffer
  *
- * Iterate over the vmalloc'ed area and create a scatter list entry for every
- * page.
+ * Retrieve the sgtable using the DMA API.
  */
 static int isp_video_buffer_prepare_kernel(struct isp_video_buffer *buf)
 {
-	struct scatterlist *sg;
-	unsigned int npages;
-	unsigned int i;
-	void *addr;
-	int ret;
-
-	addr = buf->vaddr;
-	npages = PAGE_ALIGN(buf->vbuf.length) >> PAGE_SHIFT;
-
-	ret = sg_alloc_table(&buf->sgt, npages, GFP_KERNEL);
-	if (ret < 0)
-		return ret;
-
-	for (sg = buf->sgt.sgl, i = 0; i < npages; ++i, addr += PAGE_SIZE) {
-		struct page *page = vmalloc_to_page(addr);
-
-		if (page == NULL || PageHighMem(page)) {
-			sg_free_table(&buf->sgt);
-			return -EINVAL;
-		}
-
-		sg_set_page(sg, page, PAGE_SIZE, 0);
-		sg = sg_next(sg);
-	}
+	struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue);
+	struct isp_video *video = vfh->video;
 
-	return 0;
+	return dma_get_sgtable(video->isp->dev, &buf->sgt, buf->vaddr,
+			       buf->paddr, PAGE_ALIGN(buf->vbuf.length));
 }
 
 /*
@@ -601,8 +580,12 @@ static int isp_video_queue_free(struct isp_video_queue *queue)
 
 		isp_video_buffer_cleanup(buf);
 
-		vfree(buf->vaddr);
-		buf->vaddr = NULL;
+		if (buf->vaddr) {
+			dma_free_coherent(queue->dev,
+					  PAGE_ALIGN(buf->vbuf.length),
+					  buf->vaddr, buf->paddr);
+			buf->vaddr = NULL;
+		}
 
 		kfree(buf);
 		queue->buffers[i] = NULL;
@@ -623,6 +606,7 @@ static int isp_video_queue_alloc(struct isp_video_queue *queue,
 				 unsigned int size, enum v4l2_memory memory)
 {
 	struct isp_video_buffer *buf;
+	dma_addr_t dma;
 	unsigned int i;
 	void *mem;
 	int ret;
@@ -646,7 +630,8 @@ static int isp_video_queue_alloc(struct isp_video_queue *queue,
 			/* Allocate video buffers memory for mmap mode. Align
 			 * the size to the page size.
 			 */
-			mem = vmalloc_32_user(PAGE_ALIGN(size));
+			mem = dma_alloc_coherent(queue->dev, PAGE_ALIGN(size),
+						 &dma, GFP_KERNEL);
 			if (mem == NULL) {
 				kfree(buf);
 				break;
@@ -654,6 +639,7 @@ static int isp_video_queue_alloc(struct isp_video_queue *queue,
 
 			buf->vbuf.m.offset = i * PAGE_ALIGN(size);
 			buf->vaddr = mem;
+			buf->paddr = dma;
 		}
 
 		buf->vbuf.index = i;
@@ -1094,10 +1080,17 @@ int omap3isp_video_queue_mmap(struct isp_video_queue *queue,
 		goto done;
 	}
 
-	ret = remap_vmalloc_range(vma, buf->vaddr, 0);
+	/* dma_mmap_coherent() uses vm_pgoff as an offset inside the buffer
+	 * while we used it to identify the buffer and want to map the whole
+	 * buffer.
+	 */
+	vma->vm_pgoff = 0;
+
+	ret = dma_mmap_coherent(queue->dev, vma, buf->vaddr, buf->paddr, size);
 	if (ret < 0)
 		goto done;
 
+	vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
 	vma->vm_ops = &isp_video_queue_vm_ops;
 	vma->vm_private_data = buf;
 	isp_video_queue_vm_open(vma);
diff --git a/drivers/media/platform/omap3isp/ispqueue.h b/drivers/media/platform/omap3isp/ispqueue.h
index f78325d..e03af74 100644
--- a/drivers/media/platform/omap3isp/ispqueue.h
+++ b/drivers/media/platform/omap3isp/ispqueue.h
@@ -68,6 +68,7 @@ enum isp_video_buffer_state {
  * @prepared: Whether the buffer has been prepared
  * @skip_cache: Whether to skip cache management operations for this buffer
  * @vaddr: Memory virtual address (for kernel buffers)
+ * @paddr: Memory physicall address (for kernel buffers)
  * @vm_flags: Buffer VMA flags (for userspace buffers)
  * @npages: Number of pages (for userspace buffers)
  * @pages: Pages table (for userspace non-VM_PFNMAP buffers)
@@ -86,6 +87,7 @@ struct isp_video_buffer {
 
 	/* For kernel buffers. */
 	void *vaddr;
+	dma_addr_t paddr;
 
 	/* For userspace buffers. */
 	vm_flags_t vm_flags;
-- 
1.8.3.2


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

* [PATCH 15/25] omap3isp: queue: Fix the dma_map_sg() return value check
  2014-04-03 22:39 [PATCH 00/25] OMAP3 ISP: Move to videobuf2 Laurent Pinchart
                   ` (13 preceding siblings ...)
  2014-04-03 22:39 ` [PATCH 14/25] omap3isp: queue: Allocate kernel buffers with dma_alloc_coherent Laurent Pinchart
@ 2014-04-03 22:39 ` Laurent Pinchart
  2014-04-03 22:39 ` [PATCH 16/25] omap3isp: queue: Map PFNMAP buffers to device Laurent Pinchart
                   ` (9 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2014-04-03 22:39 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus

dma_map_sg() can merge sglist entries, and can thus return a number of
mapped entries different than the original value. Don't consider this as
an error.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/omap3isp/ispqueue.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/platform/omap3isp/ispqueue.c b/drivers/media/platform/omap3isp/ispqueue.c
index 2fd254f..479d348 100644
--- a/drivers/media/platform/omap3isp/ispqueue.c
+++ b/drivers/media/platform/omap3isp/ispqueue.c
@@ -465,7 +465,7 @@ static int isp_video_buffer_prepare(struct isp_video_buffer *buf)
 			  ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
 		ret = dma_map_sg(buf->queue->dev, buf->sgt.sgl,
 				 buf->sgt.orig_nents, direction);
-		if (ret != buf->sgt.orig_nents) {
+		if (ret <= 0) {
 			ret = -EFAULT;
 			goto done;
 		}
-- 
1.8.3.2


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

* [PATCH 16/25] omap3isp: queue: Map PFNMAP buffers to device
  2014-04-03 22:39 [PATCH 00/25] OMAP3 ISP: Move to videobuf2 Laurent Pinchart
                   ` (14 preceding siblings ...)
  2014-04-03 22:39 ` [PATCH 15/25] omap3isp: queue: Fix the dma_map_sg() return value check Laurent Pinchart
@ 2014-04-03 22:39 ` Laurent Pinchart
  2014-04-03 22:39 ` [PATCH 17/25] omap3isp: queue: Use sg_alloc_table_from_pages() Laurent Pinchart
                   ` (8 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2014-04-03 22:39 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus

Userspace PFNMAP buffers need to be mapped to the device like the
userspace non-PFNMAP buffers in order for the DMA mapping implementation
to create IOMMU mappings when we'll switch to the IOMMU-aware DMA
mapping backend.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/omap3isp/ispqueue.c | 37 +++++++++++++++++-------------
 drivers/media/platform/omap3isp/ispqueue.h |  4 ++--
 2 files changed, 23 insertions(+), 18 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispqueue.c b/drivers/media/platform/omap3isp/ispqueue.c
index 479d348..4a271c7 100644
--- a/drivers/media/platform/omap3isp/ispqueue.c
+++ b/drivers/media/platform/omap3isp/ispqueue.c
@@ -173,6 +173,7 @@ static void isp_video_buffer_cleanup(struct isp_video_buffer *buf)
 	struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue);
 	struct isp_video *video = vfh->video;
 	enum dma_data_direction direction;
+	DEFINE_DMA_ATTRS(attrs);
 	unsigned int i;
 
 	if (buf->dma) {
@@ -181,11 +182,14 @@ static void isp_video_buffer_cleanup(struct isp_video_buffer *buf)
 		buf->dma = 0;
 	}
 
-	if (!(buf->vm_flags & VM_PFNMAP)) {
+	if (buf->vbuf.memory == V4L2_MEMORY_USERPTR) {
+		if (buf->skip_cache)
+			dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
+
 		direction = buf->vbuf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE
 			  ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
-		dma_unmap_sg(buf->queue->dev, buf->sgt.sgl, buf->sgt.orig_nents,
-			     direction);
+		dma_unmap_sg_attrs(buf->queue->dev, buf->sgt.sgl,
+				   buf->sgt.orig_nents, direction, &attrs);
 	}
 
 	sg_free_table(&buf->sgt);
@@ -345,10 +349,6 @@ unlock:
 
 	for (sg = buf->sgt.sgl, i = 0; i < buf->npages; ++i, ++pfn) {
 		sg_set_page(sg, pfn_to_page(pfn), PAGE_SIZE - offset, offset);
-		/* PFNMAP buffers will not get DMA-mapped, set the DMA address
-		 * manually.
-		 */
-		sg_dma_address(sg) = (pfn << PAGE_SHIFT) + offset;
 		sg = sg_next(sg);
 		offset = 0;
 	}
@@ -434,12 +434,15 @@ static int isp_video_buffer_prepare(struct isp_video_buffer *buf)
 	struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue);
 	struct isp_video *video = vfh->video;
 	enum dma_data_direction direction;
+	DEFINE_DMA_ATTRS(attrs);
 	unsigned long addr;
 	int ret;
 
 	switch (buf->vbuf.memory) {
 	case V4L2_MEMORY_MMAP:
 		ret = isp_video_buffer_prepare_kernel(buf);
+		if (ret < 0)
+			goto done;
 		break;
 
 	case V4L2_MEMORY_USERPTR:
@@ -451,24 +454,26 @@ static int isp_video_buffer_prepare(struct isp_video_buffer *buf)
 			ret = isp_video_buffer_prepare_pfnmap(buf);
 		else
 			ret = isp_video_buffer_prepare_user(buf);
-		break;
 
-	default:
-		return -EINVAL;
-	}
+		if (ret < 0)
+			goto done;
 
-	if (ret < 0)
-		goto done;
+		if (buf->skip_cache)
+			dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
 
-	if (!(buf->vm_flags & VM_PFNMAP)) {
 		direction = buf->vbuf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE
 			  ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
-		ret = dma_map_sg(buf->queue->dev, buf->sgt.sgl,
-				 buf->sgt.orig_nents, direction);
+		ret = dma_map_sg_attrs(buf->queue->dev, buf->sgt.sgl,
+				       buf->sgt.orig_nents, direction, &attrs);
 		if (ret <= 0) {
 			ret = -EFAULT;
 			goto done;
 		}
+
+		break;
+
+	default:
+		return -EINVAL;
 	}
 
 	addr = omap_iommu_vmap(video->isp->domain, video->isp->dev, 0,
diff --git a/drivers/media/platform/omap3isp/ispqueue.h b/drivers/media/platform/omap3isp/ispqueue.h
index e03af74..d580f58 100644
--- a/drivers/media/platform/omap3isp/ispqueue.h
+++ b/drivers/media/platform/omap3isp/ispqueue.h
@@ -72,7 +72,7 @@ enum isp_video_buffer_state {
  * @vm_flags: Buffer VMA flags (for userspace buffers)
  * @npages: Number of pages (for userspace buffers)
  * @pages: Pages table (for userspace non-VM_PFNMAP buffers)
- * @sgt: Scatter gather table (for non-VM_PFNMAP buffers)
+ * @sgt: Scatter gather table
  * @vbuf: V4L2 buffer
  * @irqlist: List head for insertion into IRQ queue
  * @state: Current buffer state
@@ -94,7 +94,7 @@ struct isp_video_buffer {
 	unsigned int npages;
 	struct page **pages;
 
-	/* For all buffers except VM_PFNMAP. */
+	/* For all buffers. */
 	struct sg_table sgt;
 
 	/* Touched by the interrupt handler. */
-- 
1.8.3.2


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

* [PATCH 17/25] omap3isp: queue: Use sg_alloc_table_from_pages()
  2014-04-03 22:39 [PATCH 00/25] OMAP3 ISP: Move to videobuf2 Laurent Pinchart
                   ` (15 preceding siblings ...)
  2014-04-03 22:39 ` [PATCH 16/25] omap3isp: queue: Map PFNMAP buffers to device Laurent Pinchart
@ 2014-04-03 22:39 ` Laurent Pinchart
  2014-04-03 22:39 ` [PATCH 18/25] omap3isp: Use the ARM DMA IOMMU-aware operations Laurent Pinchart
                   ` (7 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2014-04-03 22:39 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus

Replace the custom implementation with a call to the scatterlist helper
function.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/omap3isp/ispqueue.c | 16 ++--------------
 1 file changed, 2 insertions(+), 14 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispqueue.c b/drivers/media/platform/omap3isp/ispqueue.c
index 4a271c7..cee1b5d 100644
--- a/drivers/media/platform/omap3isp/ispqueue.c
+++ b/drivers/media/platform/omap3isp/ispqueue.c
@@ -233,12 +233,10 @@ static void isp_video_buffer_cleanup(struct isp_video_buffer *buf)
  */
 static int isp_video_buffer_prepare_user(struct isp_video_buffer *buf)
 {
-	struct scatterlist *sg;
 	unsigned int offset;
 	unsigned long data;
 	unsigned int first;
 	unsigned int last;
-	unsigned int i;
 	int ret;
 
 	data = buf->vbuf.m.userptr;
@@ -267,21 +265,11 @@ static int isp_video_buffer_prepare_user(struct isp_video_buffer *buf)
 	if (ret < 0)
 		return ret;
 
-	ret = sg_alloc_table(&buf->sgt, buf->npages, GFP_KERNEL);
+	ret = sg_alloc_table_from_pages(&buf->sgt, buf->pages, buf->npages,
+					offset, buf->vbuf.length, GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 
-	for (sg = buf->sgt.sgl, i = 0; i < buf->npages; ++i) {
-		if (PageHighMem(buf->pages[i])) {
-			sg_free_table(&buf->sgt);
-			return -EINVAL;
-		}
-
-		sg_set_page(sg, buf->pages[i], PAGE_SIZE - offset, offset);
-		sg = sg_next(sg);
-		offset = 0;
-	}
-
 	return 0;
 }
 
-- 
1.8.3.2


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

* [PATCH 18/25] omap3isp: Use the ARM DMA IOMMU-aware operations
  2014-04-03 22:39 [PATCH 00/25] OMAP3 ISP: Move to videobuf2 Laurent Pinchart
                   ` (16 preceding siblings ...)
  2014-04-03 22:39 ` [PATCH 17/25] omap3isp: queue: Use sg_alloc_table_from_pages() Laurent Pinchart
@ 2014-04-03 22:39 ` Laurent Pinchart
  2014-04-03 22:39 ` [PATCH 19/25] omap3isp: queue: Don't build scatterlist for kernel buffer Laurent Pinchart
                   ` (6 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2014-04-03 22:39 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus

Attach an ARM DMA I/O virtual address space to the ISP device. This
switches to the IOMMU-aware ARM DMA backend, we can thus remove the
explicit calls to the OMAP IOMMU map and unmap functions.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/Kconfig             |   4 +-
 drivers/media/platform/omap3isp/isp.c      | 102 +++++++++++++++++++++--------
 drivers/media/platform/omap3isp/isp.h      |   8 +--
 drivers/media/platform/omap3isp/ispqueue.c |  34 ++--------
 drivers/media/platform/omap3isp/ispqueue.h |   2 -
 5 files changed, 89 insertions(+), 61 deletions(-)

diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index c137abf..2091b2b 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -93,7 +93,9 @@ config VIDEO_M32R_AR_M64278
 
 config VIDEO_OMAP3
 	tristate "OMAP 3 Camera support"
-	depends on OMAP_IOVMM && VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3
+	depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3
+	select ARM_DMA_USE_IOMMU
+	select OMAP_IOMMU
 	---help---
 	  Driver for an OMAP 3 camera controller.
 
diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c
index 06a0df4..af8bd21 100644
--- a/drivers/media/platform/omap3isp/isp.c
+++ b/drivers/media/platform/omap3isp/isp.c
@@ -69,6 +69,8 @@
 #include <linux/sched.h>
 #include <linux/vmalloc.h>
 
+#include <asm/dma-iommu.h>
+
 #include <media/v4l2-common.h>
 #include <media/v4l2-device.h>
 
@@ -1625,7 +1627,7 @@ struct isp_device *omap3isp_get(struct isp_device *isp)
  * Decrement the reference count on the ISP. If the last reference is released,
  * power-down all submodules, disable clocks and free temporary buffers.
  */
-void omap3isp_put(struct isp_device *isp)
+static void __omap3isp_put(struct isp_device *isp, bool save_ctx)
 {
 	if (isp == NULL)
 		return;
@@ -1634,7 +1636,7 @@ void omap3isp_put(struct isp_device *isp)
 	BUG_ON(isp->ref_count == 0);
 	if (--isp->ref_count == 0) {
 		isp_disable_interrupts(isp);
-		if (isp->domain) {
+		if (save_ctx) {
 			isp_save_ctx(isp);
 			isp->has_context = 1;
 		}
@@ -1648,6 +1650,11 @@ void omap3isp_put(struct isp_device *isp)
 	mutex_unlock(&isp->isp_mutex);
 }
 
+void omap3isp_put(struct isp_device *isp)
+{
+	__omap3isp_put(isp, true);
+}
+
 /* --------------------------------------------------------------------------
  * Platform device driver
  */
@@ -2120,6 +2127,61 @@ error_csiphy:
 	return ret;
 }
 
+static void isp_detach_iommu(struct isp_device *isp)
+{
+	arm_iommu_release_mapping(isp->mapping);
+	isp->mapping = NULL;
+	iommu_group_remove_device(isp->dev);
+}
+
+static int isp_attach_iommu(struct isp_device *isp)
+{
+	struct dma_iommu_mapping *mapping;
+	struct iommu_group *group;
+	int ret;
+
+	/* Create a device group and add the device to it. */
+	group = iommu_group_alloc();
+	if (IS_ERR(group)) {
+		dev_err(isp->dev, "failed to allocate IOMMU group\n");
+		return PTR_ERR(group);
+	}
+
+	ret = iommu_group_add_device(group, isp->dev);
+	iommu_group_put(group);
+
+	if (ret < 0) {
+		dev_err(isp->dev, "failed to add device to IPMMU group\n");
+		return ret;
+	}
+
+	/*
+	 * Create the ARM mapping, used by the ARM DMA mapping core to allocate
+	 * VAs. This will allocate a corresponding IOMMU domain.
+	 */
+	mapping = arm_iommu_create_mapping(&platform_bus_type, SZ_1G, SZ_2G, 0);
+	if (IS_ERR(mapping)) {
+		dev_err(isp->dev, "failed to create ARM IOMMU mapping\n");
+		ret = PTR_ERR(mapping);
+		goto error;
+	}
+
+	isp->mapping = mapping;
+
+	/* Attach the ARM VA mapping to the device. */
+	ret = arm_iommu_attach_device(isp->dev, mapping);
+	if (ret < 0) {
+		dev_err(isp->dev, "failed to attach device to VA mapping\n");
+		goto error;
+	}
+
+	return 0;
+
+error:
+	isp_detach_iommu(isp);
+	return ret;
+}
+
 /*
  * isp_remove - Remove ISP platform device
  * @pdev: Pointer to ISP platform device
@@ -2135,10 +2197,8 @@ static int isp_remove(struct platform_device *pdev)
 	isp_xclk_cleanup(isp);
 
 	__omap3isp_get(isp, false);
-	iommu_detach_device(isp->domain, &pdev->dev);
-	iommu_domain_free(isp->domain);
-	isp->domain = NULL;
-	omap3isp_put(isp);
+	isp_detach_iommu(isp);
+	__omap3isp_put(isp, false);
 
 	return 0;
 }
@@ -2265,39 +2325,32 @@ static int isp_probe(struct platform_device *pdev)
 		}
 	}
 
-	isp->domain = iommu_domain_alloc(pdev->dev.bus);
-	if (!isp->domain) {
-		dev_err(isp->dev, "can't alloc iommu domain\n");
-		ret = -ENOMEM;
+	/* IOMMU */
+	ret = isp_attach_iommu(isp);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "unable to attach to IOMMU\n");
 		goto error_isp;
 	}
 
-	ret = iommu_attach_device(isp->domain, &pdev->dev);
-	if (ret) {
-		dev_err(&pdev->dev, "can't attach iommu device: %d\n", ret);
-		ret = -EPROBE_DEFER;
-		goto free_domain;
-	}
-
 	/* Interrupt */
 	isp->irq_num = platform_get_irq(pdev, 0);
 	if (isp->irq_num <= 0) {
 		dev_err(isp->dev, "No IRQ resource\n");
 		ret = -ENODEV;
-		goto detach_dev;
+		goto error_iommu;
 	}
 
 	if (devm_request_irq(isp->dev, isp->irq_num, isp_isr, IRQF_SHARED,
 			     "OMAP3 ISP", isp)) {
 		dev_err(isp->dev, "Unable to request IRQ\n");
 		ret = -EINVAL;
-		goto detach_dev;
+		goto error_iommu;
 	}
 
 	/* Entities */
 	ret = isp_initialize_modules(isp);
 	if (ret < 0)
-		goto detach_dev;
+		goto error_iommu;
 
 	ret = isp_register_entities(isp);
 	if (ret < 0)
@@ -2310,14 +2363,11 @@ static int isp_probe(struct platform_device *pdev)
 
 error_modules:
 	isp_cleanup_modules(isp);
-detach_dev:
-	iommu_detach_device(isp->domain, &pdev->dev);
-free_domain:
-	iommu_domain_free(isp->domain);
-	isp->domain = NULL;
+error_iommu:
+	isp_detach_iommu(isp);
 error_isp:
 	isp_xclk_cleanup(isp);
-	omap3isp_put(isp);
+	__omap3isp_put(isp, false);
 error:
 	mutex_destroy(&isp->isp_mutex);
 
diff --git a/drivers/media/platform/omap3isp/isp.h b/drivers/media/platform/omap3isp/isp.h
index 6d5e697..2c314ee 100644
--- a/drivers/media/platform/omap3isp/isp.h
+++ b/drivers/media/platform/omap3isp/isp.h
@@ -45,8 +45,6 @@
 #include "ispcsi2.h"
 #include "ispccp2.h"
 
-#define IOMMU_FLAG (IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_8)
-
 #define ISP_TOK_TERM		0xFFFFFFFF	/*
 						 * terminating token for ISP
 						 * modules reg list
@@ -152,6 +150,7 @@ struct isp_xclk {
  *             regions.
  * @mmio_base_phys: Array with physical L4 bus addresses for ISP register
  *                  regions.
+ * @mapping: IOMMU mapping
  * @stat_lock: Spinlock for handling statistics
  * @isp_mutex: Mutex for serializing requests to ISP.
  * @stop_failure: Indicates that an entity failed to stop.
@@ -171,7 +170,6 @@ struct isp_xclk {
  * @isp_res: Pointer to current settings for ISP Resizer.
  * @isp_prev: Pointer to current settings for ISP Preview.
  * @isp_ccdc: Pointer to current settings for ISP CCDC.
- * @iommu: Pointer to requested IOMMU instance for ISP.
  * @platform_cb: ISP driver callback function pointers for platform code
  *
  * This structure is used to store the OMAP ISP Information.
@@ -189,6 +187,8 @@ struct isp_device {
 	void __iomem *mmio_base[OMAP3_ISP_IOMEM_LAST];
 	unsigned long mmio_base_phys[OMAP3_ISP_IOMEM_LAST];
 
+	struct dma_iommu_mapping *mapping;
+
 	/* ISP Obj */
 	spinlock_t stat_lock;	/* common lock for statistic drivers */
 	struct mutex isp_mutex;	/* For handling ref_count field */
@@ -219,8 +219,6 @@ struct isp_device {
 
 	unsigned int sbl_resources;
 	unsigned int subclk_resources;
-
-	struct iommu_domain *domain;
 };
 
 #define v4l2_dev_to_isp_device(dev) \
diff --git a/drivers/media/platform/omap3isp/ispqueue.c b/drivers/media/platform/omap3isp/ispqueue.c
index cee1b5d..9c90fb0 100644
--- a/drivers/media/platform/omap3isp/ispqueue.c
+++ b/drivers/media/platform/omap3isp/ispqueue.c
@@ -26,7 +26,6 @@
 #include <asm/cacheflush.h>
 #include <linux/dma-mapping.h>
 #include <linux/mm.h>
-#include <linux/omap-iommu.h>
 #include <linux/pagemap.h>
 #include <linux/poll.h>
 #include <linux/scatterlist.h>
@@ -159,7 +158,7 @@ static int isp_video_buffer_prepare_kernel(struct isp_video_buffer *buf)
 	struct isp_video *video = vfh->video;
 
 	return dma_get_sgtable(video->isp->dev, &buf->sgt, buf->vaddr,
-			       buf->paddr, PAGE_ALIGN(buf->vbuf.length));
+			       buf->dma, PAGE_ALIGN(buf->vbuf.length));
 }
 
 /*
@@ -170,18 +169,10 @@ static int isp_video_buffer_prepare_kernel(struct isp_video_buffer *buf)
  */
 static void isp_video_buffer_cleanup(struct isp_video_buffer *buf)
 {
-	struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue);
-	struct isp_video *video = vfh->video;
 	enum dma_data_direction direction;
 	DEFINE_DMA_ATTRS(attrs);
 	unsigned int i;
 
-	if (buf->dma) {
-		omap_iommu_vunmap(video->isp->domain, video->isp->dev,
-				  buf->dma);
-		buf->dma = 0;
-	}
-
 	if (buf->vbuf.memory == V4L2_MEMORY_USERPTR) {
 		if (buf->skip_cache)
 			dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
@@ -419,11 +410,8 @@ done:
  */
 static int isp_video_buffer_prepare(struct isp_video_buffer *buf)
 {
-	struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue);
-	struct isp_video *video = vfh->video;
 	enum dma_data_direction direction;
 	DEFINE_DMA_ATTRS(attrs);
-	unsigned long addr;
 	int ret;
 
 	switch (buf->vbuf.memory) {
@@ -458,23 +446,15 @@ static int isp_video_buffer_prepare(struct isp_video_buffer *buf)
 			goto done;
 		}
 
+		buf->dma = sg_dma_address(buf->sgt.sgl);
 		break;
 
 	default:
 		return -EINVAL;
 	}
 
-	addr = omap_iommu_vmap(video->isp->domain, video->isp->dev, 0,
-			       &buf->sgt, IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_8);
-	if (IS_ERR_VALUE(addr)) {
-		ret = -EIO;
-		goto done;
-	}
-
-	buf->dma = addr;
-
-	if (!IS_ALIGNED(addr, 32)) {
-		dev_dbg(video->isp->dev,
+	if (!IS_ALIGNED(buf->dma, 32)) {
+		dev_dbg(buf->queue->dev,
 			"Buffer address must be aligned to 32 bytes boundary.\n");
 		ret = -EINVAL;
 		goto done;
@@ -576,7 +556,7 @@ static int isp_video_queue_free(struct isp_video_queue *queue)
 		if (buf->vaddr) {
 			dma_free_coherent(queue->dev,
 					  PAGE_ALIGN(buf->vbuf.length),
-					  buf->vaddr, buf->paddr);
+					  buf->vaddr, buf->dma);
 			buf->vaddr = NULL;
 		}
 
@@ -632,7 +612,7 @@ static int isp_video_queue_alloc(struct isp_video_queue *queue,
 
 			buf->vbuf.m.offset = i * PAGE_ALIGN(size);
 			buf->vaddr = mem;
-			buf->paddr = dma;
+			buf->dma = dma;
 		}
 
 		buf->vbuf.index = i;
@@ -1079,7 +1059,7 @@ int omap3isp_video_queue_mmap(struct isp_video_queue *queue,
 	 */
 	vma->vm_pgoff = 0;
 
-	ret = dma_mmap_coherent(queue->dev, vma, buf->vaddr, buf->paddr, size);
+	ret = dma_mmap_coherent(queue->dev, vma, buf->vaddr, buf->dma, size);
 	if (ret < 0)
 		goto done;
 
diff --git a/drivers/media/platform/omap3isp/ispqueue.h b/drivers/media/platform/omap3isp/ispqueue.h
index d580f58..ae4acb9 100644
--- a/drivers/media/platform/omap3isp/ispqueue.h
+++ b/drivers/media/platform/omap3isp/ispqueue.h
@@ -68,7 +68,6 @@ enum isp_video_buffer_state {
  * @prepared: Whether the buffer has been prepared
  * @skip_cache: Whether to skip cache management operations for this buffer
  * @vaddr: Memory virtual address (for kernel buffers)
- * @paddr: Memory physicall address (for kernel buffers)
  * @vm_flags: Buffer VMA flags (for userspace buffers)
  * @npages: Number of pages (for userspace buffers)
  * @pages: Pages table (for userspace non-VM_PFNMAP buffers)
@@ -87,7 +86,6 @@ struct isp_video_buffer {
 
 	/* For kernel buffers. */
 	void *vaddr;
-	dma_addr_t paddr;
 
 	/* For userspace buffers. */
 	vm_flags_t vm_flags;
-- 
1.8.3.2


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

* [PATCH 19/25] omap3isp: queue: Don't build scatterlist for kernel buffer
  2014-04-03 22:39 [PATCH 00/25] OMAP3 ISP: Move to videobuf2 Laurent Pinchart
                   ` (17 preceding siblings ...)
  2014-04-03 22:39 ` [PATCH 18/25] omap3isp: Use the ARM DMA IOMMU-aware operations Laurent Pinchart
@ 2014-04-03 22:39 ` Laurent Pinchart
  2014-04-03 22:39 ` [PATCH 20/25] omap3isp: Move queue mutex to isp_video structure Laurent Pinchart
                   ` (5 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2014-04-03 22:39 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus

The scatterlist is not needed for those buffers, don't build it.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/omap3isp/ispqueue.c | 24 +++---------------------
 drivers/media/platform/omap3isp/ispqueue.h |  8 ++++----
 2 files changed, 7 insertions(+), 25 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispqueue.c b/drivers/media/platform/omap3isp/ispqueue.c
index 9c90fb0..515ed94 100644
--- a/drivers/media/platform/omap3isp/ispqueue.c
+++ b/drivers/media/platform/omap3isp/ispqueue.c
@@ -147,21 +147,6 @@ out:
 }
 
 /*
- * isp_video_buffer_prepare_kernel - Build scatter list for a kernel-allocated
- * buffer
- *
- * Retrieve the sgtable using the DMA API.
- */
-static int isp_video_buffer_prepare_kernel(struct isp_video_buffer *buf)
-{
-	struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue);
-	struct isp_video *video = vfh->video;
-
-	return dma_get_sgtable(video->isp->dev, &buf->sgt, buf->vaddr,
-			       buf->dma, PAGE_ALIGN(buf->vbuf.length));
-}
-
-/*
  * isp_video_buffer_cleanup - Release pages for a userspace VMA.
  *
  * Release pages locked by a call isp_video_buffer_prepare_user and free the
@@ -181,10 +166,9 @@ static void isp_video_buffer_cleanup(struct isp_video_buffer *buf)
 			  ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
 		dma_unmap_sg_attrs(buf->queue->dev, buf->sgt.sgl,
 				   buf->sgt.orig_nents, direction, &attrs);
+		sg_free_table(&buf->sgt);
 	}
 
-	sg_free_table(&buf->sgt);
-
 	if (buf->pages != NULL) {
 		isp_video_buffer_lock_vma(buf, 0);
 
@@ -400,7 +384,7 @@ done:
  *
  * - validating VMAs (userspace buffers only)
  * - locking pages and VMAs into memory (userspace buffers only)
- * - building page and scatter-gather lists
+ * - building page and scatter-gather lists (userspace buffers only)
  * - mapping buffers for DMA operation
  * - performing driver-specific preparation
  *
@@ -416,9 +400,7 @@ static int isp_video_buffer_prepare(struct isp_video_buffer *buf)
 
 	switch (buf->vbuf.memory) {
 	case V4L2_MEMORY_MMAP:
-		ret = isp_video_buffer_prepare_kernel(buf);
-		if (ret < 0)
-			goto done;
+		ret = 0;
 		break;
 
 	case V4L2_MEMORY_USERPTR:
diff --git a/drivers/media/platform/omap3isp/ispqueue.h b/drivers/media/platform/omap3isp/ispqueue.h
index ae4acb9..27189bb 100644
--- a/drivers/media/platform/omap3isp/ispqueue.h
+++ b/drivers/media/platform/omap3isp/ispqueue.h
@@ -70,8 +70,8 @@ enum isp_video_buffer_state {
  * @vaddr: Memory virtual address (for kernel buffers)
  * @vm_flags: Buffer VMA flags (for userspace buffers)
  * @npages: Number of pages (for userspace buffers)
+ * @sgt: Scatter gather table (for userspace buffers)
  * @pages: Pages table (for userspace non-VM_PFNMAP buffers)
- * @sgt: Scatter gather table
  * @vbuf: V4L2 buffer
  * @irqlist: List head for insertion into IRQ queue
  * @state: Current buffer state
@@ -90,11 +90,11 @@ struct isp_video_buffer {
 	/* For userspace buffers. */
 	vm_flags_t vm_flags;
 	unsigned int npages;
-	struct page **pages;
-
-	/* For all buffers. */
 	struct sg_table sgt;
 
+	/* For non-VM_PFNMAP userspace buffers. */
+	struct page **pages;
+
 	/* Touched by the interrupt handler. */
 	struct v4l2_buffer vbuf;
 	struct list_head irqlist;
-- 
1.8.3.2


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

* [PATCH 20/25] omap3isp: Move queue mutex to isp_video structure
  2014-04-03 22:39 [PATCH 00/25] OMAP3 ISP: Move to videobuf2 Laurent Pinchart
                   ` (18 preceding siblings ...)
  2014-04-03 22:39 ` [PATCH 19/25] omap3isp: queue: Don't build scatterlist for kernel buffer Laurent Pinchart
@ 2014-04-03 22:39 ` Laurent Pinchart
  2014-04-03 22:39 ` [PATCH 21/25] omap3isp: Move queue irqlock " Laurent Pinchart
                   ` (4 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2014-04-03 22:39 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus

This prepares for the move to videobuf2.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/omap3isp/ispqueue.c | 102 ++++++++---------------------
 drivers/media/platform/omap3isp/ispqueue.h |   2 -
 drivers/media/platform/omap3isp/ispvideo.c |  72 ++++++++++++++++----
 drivers/media/platform/omap3isp/ispvideo.h |   1 +
 4 files changed, 86 insertions(+), 91 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispqueue.c b/drivers/media/platform/omap3isp/ispqueue.c
index 515ed94..dcd9446 100644
--- a/drivers/media/platform/omap3isp/ispqueue.c
+++ b/drivers/media/platform/omap3isp/ispqueue.c
@@ -660,7 +660,6 @@ int omap3isp_video_queue_init(struct isp_video_queue *queue,
 			      struct device *dev, unsigned int bufsize)
 {
 	INIT_LIST_HEAD(&queue->queue);
-	mutex_init(&queue->lock);
 	spin_lock_init(&queue->irqlock);
 
 	queue->type = type;
@@ -712,18 +711,12 @@ int omap3isp_video_queue_reqbufs(struct isp_video_queue *queue,
 
 	nbuffers = min_t(unsigned int, nbuffers, ISP_VIDEO_MAX_BUFFERS);
 
-	mutex_lock(&queue->lock);
-
 	ret = isp_video_queue_alloc(queue, nbuffers, size, rb->memory);
 	if (ret < 0)
-		goto done;
+		return ret;
 
 	rb->count = ret;
-	ret = 0;
-
-done:
-	mutex_unlock(&queue->lock);
-	return ret;
+	return 0;
 }
 
 /**
@@ -738,24 +731,17 @@ int omap3isp_video_queue_querybuf(struct isp_video_queue *queue,
 				  struct v4l2_buffer *vbuf)
 {
 	struct isp_video_buffer *buf;
-	int ret = 0;
 
 	if (vbuf->type != queue->type)
 		return -EINVAL;
 
-	mutex_lock(&queue->lock);
-
-	if (vbuf->index >= queue->count) {
-		ret = -EINVAL;
-		goto done;
-	}
+	if (vbuf->index >= queue->count)
+		return -EINVAL;
 
 	buf = queue->buffers[vbuf->index];
 	isp_video_buffer_query(buf, vbuf);
 
-done:
-	mutex_unlock(&queue->lock);
-	return ret;
+	return 0;
 }
 
 /**
@@ -776,27 +762,25 @@ int omap3isp_video_queue_qbuf(struct isp_video_queue *queue,
 {
 	struct isp_video_buffer *buf;
 	unsigned long flags;
-	int ret = -EINVAL;
+	int ret;
 
 	if (vbuf->type != queue->type)
-		goto done;
-
-	mutex_lock(&queue->lock);
+		return -EINVAL;
 
 	if (vbuf->index >= queue->count)
-		goto done;
+		return -EINVAL;
 
 	buf = queue->buffers[vbuf->index];
 
 	if (vbuf->memory != buf->vbuf.memory)
-		goto done;
+		return -EINVAL;
 
 	if (buf->state != ISP_BUF_STATE_IDLE)
-		goto done;
+		return -EINVAL;
 
 	if (vbuf->memory == V4L2_MEMORY_USERPTR &&
 	    vbuf->length < buf->vbuf.length)
-		goto done;
+		return -EINVAL;
 
 	if (vbuf->memory == V4L2_MEMORY_USERPTR &&
 	    vbuf->m.userptr != buf->vbuf.m.userptr) {
@@ -808,7 +792,7 @@ int omap3isp_video_queue_qbuf(struct isp_video_queue *queue,
 	if (!buf->prepared) {
 		ret = isp_video_buffer_prepare(buf);
 		if (ret < 0)
-			goto done;
+			return ret;
 		buf->prepared = 1;
 	}
 
@@ -823,11 +807,7 @@ int omap3isp_video_queue_qbuf(struct isp_video_queue *queue,
 		spin_unlock_irqrestore(&queue->irqlock, flags);
 	}
 
-	ret = 0;
-
-done:
-	mutex_unlock(&queue->lock);
-	return ret;
+	return 0;
 }
 
 /**
@@ -853,17 +833,13 @@ int omap3isp_video_queue_dqbuf(struct isp_video_queue *queue,
 	if (vbuf->type != queue->type)
 		return -EINVAL;
 
-	mutex_lock(&queue->lock);
-
-	if (list_empty(&queue->queue)) {
-		ret = -EINVAL;
-		goto done;
-	}
+	if (list_empty(&queue->queue))
+		return -EINVAL;
 
 	buf = list_first_entry(&queue->queue, struct isp_video_buffer, stream);
 	ret = isp_video_buffer_wait(buf, nonblocking);
 	if (ret < 0)
-		goto done;
+		return ret;
 
 	list_del(&buf->stream);
 
@@ -871,9 +847,7 @@ int omap3isp_video_queue_dqbuf(struct isp_video_queue *queue,
 	buf->state = ISP_BUF_STATE_IDLE;
 	vbuf->flags &= ~V4L2_BUF_FLAG_QUEUED;
 
-done:
-	mutex_unlock(&queue->lock);
-	return ret;
+	return 0;
 }
 
 /**
@@ -890,10 +864,8 @@ int omap3isp_video_queue_streamon(struct isp_video_queue *queue)
 	struct isp_video_buffer *buf;
 	unsigned long flags;
 
-	mutex_lock(&queue->lock);
-
 	if (queue->streaming)
-		goto done;
+		return 0;
 
 	queue->streaming = 1;
 
@@ -902,8 +874,6 @@ int omap3isp_video_queue_streamon(struct isp_video_queue *queue)
 		queue->ops->buffer_queue(buf);
 	spin_unlock_irqrestore(&queue->irqlock, flags);
 
-done:
-	mutex_unlock(&queue->lock);
 	return 0;
 }
 
@@ -923,10 +893,8 @@ void omap3isp_video_queue_streamoff(struct isp_video_queue *queue)
 	unsigned long flags;
 	unsigned int i;
 
-	mutex_lock(&queue->lock);
-
 	if (!queue->streaming)
-		goto done;
+		return;
 
 	queue->streaming = 0;
 
@@ -942,9 +910,6 @@ void omap3isp_video_queue_streamoff(struct isp_video_queue *queue)
 	spin_unlock_irqrestore(&queue->irqlock, flags);
 
 	INIT_LIST_HEAD(&queue->queue);
-
-done:
-	mutex_unlock(&queue->lock);
 }
 
 /**
@@ -963,10 +928,8 @@ void omap3isp_video_queue_discard_done(struct isp_video_queue *queue)
 	struct isp_video_buffer *buf;
 	unsigned int i;
 
-	mutex_lock(&queue->lock);
-
 	if (!queue->streaming)
-		goto done;
+		return;
 
 	for (i = 0; i < queue->count; ++i) {
 		buf = queue->buffers[i];
@@ -974,9 +937,6 @@ void omap3isp_video_queue_discard_done(struct isp_video_queue *queue)
 		if (buf->state == ISP_BUF_STATE_DONE)
 			buf->state = ISP_BUF_STATE_ERROR;
 	}
-
-done:
-	mutex_unlock(&queue->lock);
 }
 
 static void isp_video_queue_vm_open(struct vm_area_struct *vma)
@@ -1014,26 +974,20 @@ int omap3isp_video_queue_mmap(struct isp_video_queue *queue,
 	unsigned int i;
 	int ret = 0;
 
-	mutex_lock(&queue->lock);
-
 	for (i = 0; i < queue->count; ++i) {
 		buf = queue->buffers[i];
 		if ((buf->vbuf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
 			break;
 	}
 
-	if (i == queue->count) {
-		ret = -EINVAL;
-		goto done;
-	}
+	if (i == queue->count)
+		return -EINVAL;
 
 	size = vma->vm_end - vma->vm_start;
 
 	if (buf->vbuf.memory != V4L2_MEMORY_MMAP ||
-	    size != PAGE_ALIGN(buf->vbuf.length)) {
-		ret = -EINVAL;
-		goto done;
-	}
+	    size != PAGE_ALIGN(buf->vbuf.length))
+		return -EINVAL;
 
 	/* dma_mmap_coherent() uses vm_pgoff as an offset inside the buffer
 	 * while we used it to identify the buffer and want to map the whole
@@ -1043,16 +997,14 @@ int omap3isp_video_queue_mmap(struct isp_video_queue *queue,
 
 	ret = dma_mmap_coherent(queue->dev, vma, buf->vaddr, buf->dma, size);
 	if (ret < 0)
-		goto done;
+		return ret;
 
 	vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
 	vma->vm_ops = &isp_video_queue_vm_ops;
 	vma->vm_private_data = buf;
 	isp_video_queue_vm_open(vma);
 
-done:
-	mutex_unlock(&queue->lock);
-	return ret;
+	return 0;
 }
 
 /**
@@ -1070,7 +1022,6 @@ unsigned int omap3isp_video_queue_poll(struct isp_video_queue *queue,
 	struct isp_video_buffer *buf;
 	unsigned int mask = 0;
 
-	mutex_lock(&queue->lock);
 	if (list_empty(&queue->queue)) {
 		mask |= POLLERR;
 		goto done;
@@ -1087,6 +1038,5 @@ unsigned int omap3isp_video_queue_poll(struct isp_video_queue *queue,
 	}
 
 done:
-	mutex_unlock(&queue->lock);
 	return mask;
 }
diff --git a/drivers/media/platform/omap3isp/ispqueue.h b/drivers/media/platform/omap3isp/ispqueue.h
index 27189bb..ecff055 100644
--- a/drivers/media/platform/omap3isp/ispqueue.h
+++ b/drivers/media/platform/omap3isp/ispqueue.h
@@ -132,7 +132,6 @@ struct isp_video_queue_operations {
  * @bufsize: Size of a driver-specific buffer object
  * @count: Number of currently allocated buffers
  * @buffers: ISP video buffers
- * @lock: Mutex to protect access to the buffers, main queue and state
  * @irqlock: Spinlock to protect access to the IRQ queue
  * @streaming: Queue state, indicates whether the queue is streaming
  * @queue: List of all queued buffers
@@ -145,7 +144,6 @@ struct isp_video_queue {
 
 	unsigned int count;
 	struct isp_video_buffer *buffers[ISP_VIDEO_MAX_BUFFERS];
-	struct mutex lock;
 	spinlock_t irqlock;
 
 	unsigned int streaming:1;
diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c
index a7ef081..12b0f8c 100644
--- a/drivers/media/platform/omap3isp/ispvideo.c
+++ b/drivers/media/platform/omap3isp/ispvideo.c
@@ -555,8 +555,11 @@ void omap3isp_video_resume(struct isp_video *video, int continuous)
 {
 	struct isp_buffer *buf = NULL;
 
-	if (continuous && video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+	if (continuous && video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+		mutex_lock(&video->queue_lock);
 		omap3isp_video_queue_discard_done(video->queue);
+		mutex_unlock(&video->queue_lock);
+	}
 
 	if (!list_empty(&video->dmaqueue)) {
 		buf = list_first_entry(&video->dmaqueue,
@@ -768,33 +771,57 @@ static int
 isp_video_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *rb)
 {
 	struct isp_video_fh *vfh = to_isp_video_fh(fh);
+	struct isp_video *video = video_drvdata(file);
+	int ret;
+
+	mutex_lock(&video->queue_lock);
+	ret = omap3isp_video_queue_reqbufs(&vfh->queue, rb);
+	mutex_unlock(&video->queue_lock);
 
-	return omap3isp_video_queue_reqbufs(&vfh->queue, rb);
+	return ret;
 }
 
 static int
 isp_video_querybuf(struct file *file, void *fh, struct v4l2_buffer *b)
 {
 	struct isp_video_fh *vfh = to_isp_video_fh(fh);
+	struct isp_video *video = video_drvdata(file);
+	int ret;
 
-	return omap3isp_video_queue_querybuf(&vfh->queue, b);
+	mutex_lock(&video->queue_lock);
+	ret = omap3isp_video_queue_querybuf(&vfh->queue, b);
+	mutex_unlock(&video->queue_lock);
+
+	return ret;
 }
 
 static int
 isp_video_qbuf(struct file *file, void *fh, struct v4l2_buffer *b)
 {
 	struct isp_video_fh *vfh = to_isp_video_fh(fh);
+	struct isp_video *video = video_drvdata(file);
+	int ret;
+
+	mutex_lock(&video->queue_lock);
+	ret = omap3isp_video_queue_qbuf(&vfh->queue, b);
+	mutex_unlock(&video->queue_lock);
 
-	return omap3isp_video_queue_qbuf(&vfh->queue, b);
+	return ret;
 }
 
 static int
 isp_video_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
 {
 	struct isp_video_fh *vfh = to_isp_video_fh(fh);
+	struct isp_video *video = video_drvdata(file);
+	int ret;
+
+	mutex_lock(&video->queue_lock);
+	ret = omap3isp_video_queue_dqbuf(&vfh->queue, b,
+					 file->f_flags & O_NONBLOCK);
+	mutex_unlock(&video->queue_lock);
 
-	return omap3isp_video_queue_dqbuf(&vfh->queue, b,
-					  file->f_flags & O_NONBLOCK);
+	return ret;
 }
 
 static int isp_video_check_external_subdevs(struct isp_video *video,
@@ -997,7 +1024,9 @@ isp_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
 	INIT_LIST_HEAD(&video->dmaqueue);
 	atomic_set(&pipe->frame_number, -1);
 
+	mutex_lock(&video->queue_lock);
 	ret = omap3isp_video_queue_streamon(&vfh->queue);
+	mutex_unlock(&video->queue_lock);
 	if (ret < 0)
 		goto err_check_format;
 
@@ -1022,7 +1051,9 @@ isp_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
 	return 0;
 
 err_set_stream:
+	mutex_lock(&video->queue_lock);
 	omap3isp_video_queue_streamoff(&vfh->queue);
+	mutex_unlock(&video->queue_lock);
 err_check_format:
 	media_entity_pipeline_stop(&video->video.entity);
 err_pipeline_start:
@@ -1058,9 +1089,9 @@ isp_video_streamoff(struct file *file, void *fh, enum v4l2_buf_type type)
 	mutex_lock(&video->stream_lock);
 
 	/* Make sure we're not streaming yet. */
-	mutex_lock(&vfh->queue.lock);
+	mutex_lock(&video->queue_lock);
 	streaming = vfh->queue.streaming;
-	mutex_unlock(&vfh->queue.lock);
+	mutex_unlock(&video->queue_lock);
 
 	if (!streaming)
 		goto done;
@@ -1079,7 +1110,9 @@ isp_video_streamoff(struct file *file, void *fh, enum v4l2_buf_type type)
 
 	/* Stop the stream. */
 	omap3isp_pipeline_set_stream(pipe, ISP_PIPELINE_STREAM_STOPPED);
+	mutex_lock(&video->queue_lock);
 	omap3isp_video_queue_streamoff(&vfh->queue);
+	mutex_unlock(&video->queue_lock);
 	video->queue = NULL;
 	video->streaming = 0;
 	video->error = false;
@@ -1201,9 +1234,9 @@ static int isp_video_release(struct file *file)
 	/* Disable streaming and free the buffers queue resources. */
 	isp_video_streamoff(file, vfh, video->type);
 
-	mutex_lock(&handle->queue.lock);
+	mutex_lock(&video->queue_lock);
 	omap3isp_video_queue_cleanup(&handle->queue);
-	mutex_unlock(&handle->queue.lock);
+	mutex_unlock(&video->queue_lock);
 
 	omap3isp_pipeline_pm_use(&video->video.entity, 0);
 
@@ -1220,16 +1253,27 @@ static int isp_video_release(struct file *file)
 static unsigned int isp_video_poll(struct file *file, poll_table *wait)
 {
 	struct isp_video_fh *vfh = to_isp_video_fh(file->private_data);
-	struct isp_video_queue *queue = &vfh->queue;
+	struct isp_video *video = video_drvdata(file);
+	int ret;
 
-	return omap3isp_video_queue_poll(queue, file, wait);
+	mutex_lock(&video->queue_lock);
+	ret = omap3isp_video_queue_poll(&vfh->queue, file, wait);
+	mutex_unlock(&video->queue_lock);
+
+	return ret;
 }
 
 static int isp_video_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	struct isp_video_fh *vfh = to_isp_video_fh(file->private_data);
+	struct isp_video *video = video_drvdata(file);
+	int ret;
+
+	mutex_lock(&video->queue_lock);
+	ret = omap3isp_video_queue_mmap(&vfh->queue, vma);
+	mutex_unlock(&video->queue_lock);
 
-	return omap3isp_video_queue_mmap(&vfh->queue, vma);
+	return ret;
 }
 
 static struct v4l2_file_operations isp_video_fops = {
@@ -1279,6 +1323,7 @@ int omap3isp_video_init(struct isp_video *video, const char *name)
 
 	spin_lock_init(&video->pipe.lock);
 	mutex_init(&video->stream_lock);
+	mutex_init(&video->queue_lock);
 
 	/* Initialize the video device. */
 	if (video->ops == NULL)
@@ -1300,6 +1345,7 @@ int omap3isp_video_init(struct isp_video *video, const char *name)
 void omap3isp_video_cleanup(struct isp_video *video)
 {
 	media_entity_cleanup(&video->video.entity);
+	mutex_destroy(&video->queue_lock);
 	mutex_destroy(&video->stream_lock);
 	mutex_destroy(&video->mutex);
 }
diff --git a/drivers/media/platform/omap3isp/ispvideo.h b/drivers/media/platform/omap3isp/ispvideo.h
index 4e19407..254e7d2 100644
--- a/drivers/media/platform/omap3isp/ispvideo.h
+++ b/drivers/media/platform/omap3isp/ispvideo.h
@@ -182,6 +182,7 @@ struct isp_video {
 
 	/* Video buffers queue */
 	struct isp_video_queue *queue;
+	struct mutex queue_lock;	/* protects the queue */
 	struct list_head dmaqueue;
 	enum isp_video_dmaqueue_flags dmaqueue_flags;
 
-- 
1.8.3.2


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

* [PATCH 21/25] omap3isp: Move queue irqlock to isp_video structure
  2014-04-03 22:39 [PATCH 00/25] OMAP3 ISP: Move to videobuf2 Laurent Pinchart
                   ` (19 preceding siblings ...)
  2014-04-03 22:39 ` [PATCH 20/25] omap3isp: Move queue mutex to isp_video structure Laurent Pinchart
@ 2014-04-03 22:39 ` Laurent Pinchart
  2014-04-03 22:39 ` [PATCH 22/25] omap3isp: Move buffer irqlist to isp_buffer structure Laurent Pinchart
                   ` (3 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2014-04-03 22:39 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus

This prepares for the move to videobuf2.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/omap3isp/isp.c      |  6 +++---
 drivers/media/platform/omap3isp/ispqueue.c | 13 +------------
 drivers/media/platform/omap3isp/ispqueue.h |  5 +----
 drivers/media/platform/omap3isp/ispvideo.c | 21 +++++++++++++--------
 drivers/media/platform/omap3isp/ispvideo.h |  1 +
 5 files changed, 19 insertions(+), 27 deletions(-)

diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c
index af8bd21..4395027 100644
--- a/drivers/media/platform/omap3isp/isp.c
+++ b/drivers/media/platform/omap3isp/isp.c
@@ -1399,14 +1399,14 @@ int omap3isp_module_sync_idle(struct media_entity *me, wait_queue_head_t *wait,
 	if (isp_pipeline_is_last(me)) {
 		struct isp_video *video = pipe->output;
 		unsigned long flags;
-		spin_lock_irqsave(&video->queue->irqlock, flags);
+		spin_lock_irqsave(&video->irqlock, flags);
 		if (video->dmaqueue_flags & ISP_VIDEO_DMAQUEUE_UNDERRUN) {
-			spin_unlock_irqrestore(&video->queue->irqlock, flags);
+			spin_unlock_irqrestore(&video->irqlock, flags);
 			atomic_set(stopping, 0);
 			smp_mb();
 			return 0;
 		}
-		spin_unlock_irqrestore(&video->queue->irqlock, flags);
+		spin_unlock_irqrestore(&video->irqlock, flags);
 		if (!wait_event_timeout(*wait, !atomic_read(stopping),
 					msecs_to_jiffies(1000))) {
 			atomic_set(stopping, 0);
diff --git a/drivers/media/platform/omap3isp/ispqueue.c b/drivers/media/platform/omap3isp/ispqueue.c
index dcd9446..77afb63 100644
--- a/drivers/media/platform/omap3isp/ispqueue.c
+++ b/drivers/media/platform/omap3isp/ispqueue.c
@@ -660,7 +660,6 @@ int omap3isp_video_queue_init(struct isp_video_queue *queue,
 			      struct device *dev, unsigned int bufsize)
 {
 	INIT_LIST_HEAD(&queue->queue);
-	spin_lock_init(&queue->irqlock);
 
 	queue->type = type;
 	queue->ops = ops;
@@ -761,7 +760,6 @@ int omap3isp_video_queue_qbuf(struct isp_video_queue *queue,
 			      struct v4l2_buffer *vbuf)
 {
 	struct isp_video_buffer *buf;
-	unsigned long flags;
 	int ret;
 
 	if (vbuf->type != queue->type)
@@ -801,11 +799,8 @@ int omap3isp_video_queue_qbuf(struct isp_video_queue *queue,
 	buf->state = ISP_BUF_STATE_QUEUED;
 	list_add_tail(&buf->stream, &queue->queue);
 
-	if (queue->streaming) {
-		spin_lock_irqsave(&queue->irqlock, flags);
+	if (queue->streaming)
 		queue->ops->buffer_queue(buf);
-		spin_unlock_irqrestore(&queue->irqlock, flags);
-	}
 
 	return 0;
 }
@@ -862,17 +857,14 @@ int omap3isp_video_queue_dqbuf(struct isp_video_queue *queue,
 int omap3isp_video_queue_streamon(struct isp_video_queue *queue)
 {
 	struct isp_video_buffer *buf;
-	unsigned long flags;
 
 	if (queue->streaming)
 		return 0;
 
 	queue->streaming = 1;
 
-	spin_lock_irqsave(&queue->irqlock, flags);
 	list_for_each_entry(buf, &queue->queue, stream)
 		queue->ops->buffer_queue(buf);
-	spin_unlock_irqrestore(&queue->irqlock, flags);
 
 	return 0;
 }
@@ -890,7 +882,6 @@ int omap3isp_video_queue_streamon(struct isp_video_queue *queue)
 void omap3isp_video_queue_streamoff(struct isp_video_queue *queue)
 {
 	struct isp_video_buffer *buf;
-	unsigned long flags;
 	unsigned int i;
 
 	if (!queue->streaming)
@@ -898,7 +889,6 @@ void omap3isp_video_queue_streamoff(struct isp_video_queue *queue)
 
 	queue->streaming = 0;
 
-	spin_lock_irqsave(&queue->irqlock, flags);
 	for (i = 0; i < queue->count; ++i) {
 		buf = queue->buffers[i];
 
@@ -907,7 +897,6 @@ void omap3isp_video_queue_streamoff(struct isp_video_queue *queue)
 
 		buf->state = ISP_BUF_STATE_IDLE;
 	}
-	spin_unlock_irqrestore(&queue->irqlock, flags);
 
 	INIT_LIST_HEAD(&queue->queue);
 }
diff --git a/drivers/media/platform/omap3isp/ispqueue.h b/drivers/media/platform/omap3isp/ispqueue.h
index ecff055..ecf3309 100644
--- a/drivers/media/platform/omap3isp/ispqueue.h
+++ b/drivers/media/platform/omap3isp/ispqueue.h
@@ -114,8 +114,7 @@ struct isp_video_buffer {
  *	the userspace memory address for a USERPTR buffer, with the queue lock
  *	held. Drivers should perform device-specific buffer preparation (such as
  *	mapping the buffer memory in an IOMMU). This operation is optional.
- * @buffer_queue: Called when a buffer is being added to the queue with the
- *	queue irqlock spinlock held.
+ * @buffer_queue: Called when a buffer is being added.
  */
 struct isp_video_queue_operations {
 	void (*queue_prepare)(struct isp_video_queue *queue,
@@ -132,7 +131,6 @@ struct isp_video_queue_operations {
  * @bufsize: Size of a driver-specific buffer object
  * @count: Number of currently allocated buffers
  * @buffers: ISP video buffers
- * @irqlock: Spinlock to protect access to the IRQ queue
  * @streaming: Queue state, indicates whether the queue is streaming
  * @queue: List of all queued buffers
  */
@@ -144,7 +142,6 @@ struct isp_video_queue {
 
 	unsigned int count;
 	struct isp_video_buffer *buffers[ISP_VIDEO_MAX_BUFFERS];
-	spinlock_t irqlock;
 
 	unsigned int streaming:1;
 
diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c
index 12b0f8c..85338d3 100644
--- a/drivers/media/platform/omap3isp/ispvideo.c
+++ b/drivers/media/platform/omap3isp/ispvideo.c
@@ -381,15 +381,20 @@ static void isp_video_buffer_queue(struct isp_video_buffer *buf)
 	unsigned int empty;
 	unsigned int start;
 
+	spin_lock_irqsave(&video->irqlock, flags);
+
 	if (unlikely(video->error)) {
 		buf->state = ISP_BUF_STATE_ERROR;
 		wake_up(&buf->wait);
+		spin_unlock_irqrestore(&video->irqlock, flags);
 		return;
 	}
 
 	empty = list_empty(&video->dmaqueue);
 	list_add_tail(&buffer->buffer.irqlist, &video->dmaqueue);
 
+	spin_unlock_irqrestore(&video->irqlock, flags);
+
 	if (empty) {
 		if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
 			state = ISP_PIPELINE_QUEUE_OUTPUT;
@@ -445,16 +450,16 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video)
 	unsigned long flags;
 	struct timespec ts;
 
-	spin_lock_irqsave(&queue->irqlock, flags);
+	spin_lock_irqsave(&video->irqlock, flags);
 	if (WARN_ON(list_empty(&video->dmaqueue))) {
-		spin_unlock_irqrestore(&queue->irqlock, flags);
+		spin_unlock_irqrestore(&video->irqlock, flags);
 		return NULL;
 	}
 
 	buf = list_first_entry(&video->dmaqueue, struct isp_video_buffer,
 			       irqlist);
 	list_del(&buf->irqlist);
-	spin_unlock_irqrestore(&queue->irqlock, flags);
+	spin_unlock_irqrestore(&video->irqlock, flags);
 
 	buf->vbuf.bytesused = vfh->format.fmt.pix.sizeimage;
 
@@ -520,10 +525,9 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video)
  */
 void omap3isp_video_cancel_stream(struct isp_video *video)
 {
-	struct isp_video_queue *queue = video->queue;
 	unsigned long flags;
 
-	spin_lock_irqsave(&queue->irqlock, flags);
+	spin_lock_irqsave(&video->irqlock, flags);
 
 	while (!list_empty(&video->dmaqueue)) {
 		struct isp_video_buffer *buf;
@@ -538,7 +542,7 @@ void omap3isp_video_cancel_stream(struct isp_video *video)
 
 	video->error = true;
 
-	spin_unlock_irqrestore(&queue->irqlock, flags);
+	spin_unlock_irqrestore(&video->irqlock, flags);
 }
 
 /*
@@ -1039,10 +1043,10 @@ isp_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
 					      ISP_PIPELINE_STREAM_CONTINUOUS);
 		if (ret < 0)
 			goto err_set_stream;
-		spin_lock_irqsave(&video->queue->irqlock, flags);
+		spin_lock_irqsave(&video->irqlock, flags);
 		if (list_empty(&video->dmaqueue))
 			video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_UNDERRUN;
-		spin_unlock_irqrestore(&video->queue->irqlock, flags);
+		spin_unlock_irqrestore(&video->irqlock, flags);
 	}
 
 	video->streaming = 1;
@@ -1324,6 +1328,7 @@ int omap3isp_video_init(struct isp_video *video, const char *name)
 	spin_lock_init(&video->pipe.lock);
 	mutex_init(&video->stream_lock);
 	mutex_init(&video->queue_lock);
+	spin_lock_init(&video->irqlock);
 
 	/* Initialize the video device. */
 	if (video->ops == NULL)
diff --git a/drivers/media/platform/omap3isp/ispvideo.h b/drivers/media/platform/omap3isp/ispvideo.h
index 254e7d2..0fa098c 100644
--- a/drivers/media/platform/omap3isp/ispvideo.h
+++ b/drivers/media/platform/omap3isp/ispvideo.h
@@ -183,6 +183,7 @@ struct isp_video {
 	/* Video buffers queue */
 	struct isp_video_queue *queue;
 	struct mutex queue_lock;	/* protects the queue */
+	spinlock_t irqlock;		/* protects dmaqueue */
 	struct list_head dmaqueue;
 	enum isp_video_dmaqueue_flags dmaqueue_flags;
 
-- 
1.8.3.2


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

* [PATCH 22/25] omap3isp: Move buffer irqlist to isp_buffer structure
  2014-04-03 22:39 [PATCH 00/25] OMAP3 ISP: Move to videobuf2 Laurent Pinchart
                   ` (20 preceding siblings ...)
  2014-04-03 22:39 ` [PATCH 21/25] omap3isp: Move queue irqlock " Laurent Pinchart
@ 2014-04-03 22:39 ` Laurent Pinchart
  2014-04-03 22:39 ` [PATCH 23/25] v4l: vb2: Add a function to discard all DONE buffers Laurent Pinchart
                   ` (2 subsequent siblings)
  24 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2014-04-03 22:39 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus

This prepares for the move to videobuf2.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/omap3isp/ispqueue.h |  2 --
 drivers/media/platform/omap3isp/ispvideo.c | 39 +++++++++++++++---------------
 drivers/media/platform/omap3isp/ispvideo.h |  2 ++
 3 files changed, 22 insertions(+), 21 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispqueue.h b/drivers/media/platform/omap3isp/ispqueue.h
index ecf3309..ff18208 100644
--- a/drivers/media/platform/omap3isp/ispqueue.h
+++ b/drivers/media/platform/omap3isp/ispqueue.h
@@ -73,7 +73,6 @@ enum isp_video_buffer_state {
  * @sgt: Scatter gather table (for userspace buffers)
  * @pages: Pages table (for userspace non-VM_PFNMAP buffers)
  * @vbuf: V4L2 buffer
- * @irqlist: List head for insertion into IRQ queue
  * @state: Current buffer state
  * @wait: Wait queue to signal buffer completion
  */
@@ -97,7 +96,6 @@ struct isp_video_buffer {
 
 	/* Touched by the interrupt handler. */
 	struct v4l2_buffer vbuf;
-	struct list_head irqlist;
 	enum isp_video_buffer_state state;
 	wait_queue_head_t wait;
 	dma_addr_t dma;
diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c
index 85338d3..e1f9983 100644
--- a/drivers/media/platform/omap3isp/ispvideo.c
+++ b/drivers/media/platform/omap3isp/ispvideo.c
@@ -391,7 +391,7 @@ static void isp_video_buffer_queue(struct isp_video_buffer *buf)
 	}
 
 	empty = list_empty(&video->dmaqueue);
-	list_add_tail(&buffer->buffer.irqlist, &video->dmaqueue);
+	list_add_tail(&buffer->irqlist, &video->dmaqueue);
 
 	spin_unlock_irqrestore(&video->irqlock, flags);
 
@@ -446,7 +446,7 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video)
 	struct isp_video_fh *vfh =
 		container_of(queue, struct isp_video_fh, queue);
 	enum isp_pipeline_state state;
-	struct isp_video_buffer *buf;
+	struct isp_buffer *buf;
 	unsigned long flags;
 	struct timespec ts;
 
@@ -456,16 +456,16 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video)
 		return NULL;
 	}
 
-	buf = list_first_entry(&video->dmaqueue, struct isp_video_buffer,
+	buf = list_first_entry(&video->dmaqueue, struct isp_buffer,
 			       irqlist);
 	list_del(&buf->irqlist);
 	spin_unlock_irqrestore(&video->irqlock, flags);
 
-	buf->vbuf.bytesused = vfh->format.fmt.pix.sizeimage;
+	buf->buffer.vbuf.bytesused = vfh->format.fmt.pix.sizeimage;
 
 	ktime_get_ts(&ts);
-	buf->vbuf.timestamp.tv_sec = ts.tv_sec;
-	buf->vbuf.timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
+	buf->buffer.vbuf.timestamp.tv_sec = ts.tv_sec;
+	buf->buffer.vbuf.timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
 
 	/* Do frame number propagation only if this is the output video node.
 	 * Frame number either comes from the CSI receivers or it gets
@@ -474,19 +474,20 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video)
 	 * first, so the input number might lag behind by 1 in some cases.
 	 */
 	if (video == pipe->output && !pipe->do_propagation)
-		buf->vbuf.sequence = atomic_inc_return(&pipe->frame_number);
+		buf->buffer.vbuf.sequence =
+			atomic_inc_return(&pipe->frame_number);
 	else
-		buf->vbuf.sequence = atomic_read(&pipe->frame_number);
+		buf->buffer.vbuf.sequence = atomic_read(&pipe->frame_number);
 
 	/* Report pipeline errors to userspace on the capture device side. */
 	if (queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->error) {
-		buf->state = ISP_BUF_STATE_ERROR;
+		buf->buffer.state = ISP_BUF_STATE_ERROR;
 		pipe->error = false;
 	} else {
-		buf->state = ISP_BUF_STATE_DONE;
+		buf->buffer.state = ISP_BUF_STATE_DONE;
 	}
 
-	wake_up(&buf->wait);
+	wake_up(&buf->buffer.wait);
 
 	if (list_empty(&video->dmaqueue)) {
 		if (queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
@@ -510,10 +511,10 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video)
 		spin_unlock_irqrestore(&pipe->lock, flags);
 	}
 
-	buf = list_first_entry(&video->dmaqueue, struct isp_video_buffer,
+	buf = list_first_entry(&video->dmaqueue, struct isp_buffer,
 			       irqlist);
-	buf->state = ISP_BUF_STATE_ACTIVE;
-	return to_isp_buffer(buf);
+	buf->buffer.state = ISP_BUF_STATE_ACTIVE;
+	return buf;
 }
 
 /*
@@ -530,14 +531,14 @@ void omap3isp_video_cancel_stream(struct isp_video *video)
 	spin_lock_irqsave(&video->irqlock, flags);
 
 	while (!list_empty(&video->dmaqueue)) {
-		struct isp_video_buffer *buf;
+		struct isp_buffer *buf;
 
 		buf = list_first_entry(&video->dmaqueue,
-				       struct isp_video_buffer, irqlist);
+				       struct isp_buffer, irqlist);
 		list_del(&buf->irqlist);
 
-		buf->state = ISP_BUF_STATE_ERROR;
-		wake_up(&buf->wait);
+		buf->buffer.state = ISP_BUF_STATE_ERROR;
+		wake_up(&buf->buffer.wait);
 	}
 
 	video->error = true;
@@ -567,7 +568,7 @@ void omap3isp_video_resume(struct isp_video *video, int continuous)
 
 	if (!list_empty(&video->dmaqueue)) {
 		buf = list_first_entry(&video->dmaqueue,
-				       struct isp_buffer, buffer.irqlist);
+				       struct isp_buffer, irqlist);
 		video->ops->queue(video, buf);
 		video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_QUEUED;
 	} else {
diff --git a/drivers/media/platform/omap3isp/ispvideo.h b/drivers/media/platform/omap3isp/ispvideo.h
index 0fa098c..1e3d17a 100644
--- a/drivers/media/platform/omap3isp/ispvideo.h
+++ b/drivers/media/platform/omap3isp/ispvideo.h
@@ -127,10 +127,12 @@ static inline int isp_pipeline_ready(struct isp_pipeline *pipe)
 /*
  * struct isp_buffer - ISP buffer
  * @buffer: ISP video buffer
+ * @irqlist: List head for insertion into IRQ queue
  * @isp_addr: MMU mapped address (a.k.a. device address) of the buffer.
  */
 struct isp_buffer {
 	struct isp_video_buffer buffer;
+	struct list_head irqlist;
 	dma_addr_t isp_addr;
 };
 
-- 
1.8.3.2


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

* [PATCH 23/25] v4l: vb2: Add a function to discard all DONE buffers
  2014-04-03 22:39 [PATCH 00/25] OMAP3 ISP: Move to videobuf2 Laurent Pinchart
                   ` (21 preceding siblings ...)
  2014-04-03 22:39 ` [PATCH 22/25] omap3isp: Move buffer irqlist to isp_buffer structure Laurent Pinchart
@ 2014-04-03 22:39 ` Laurent Pinchart
  2014-04-03 22:39 ` [PATCH 24/25] omap3isp: Move to videobuf2 Laurent Pinchart
  2014-04-03 22:39 ` [PATCH 25/25] omap3isp: Rename isp_buffer isp_addr field to dma Laurent Pinchart
  24 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2014-04-03 22:39 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus

When suspending a device while a video stream is active all buffers
marked as done but not dequeued yet will be kept across suspend and
given back to userspace after resume. This will result in outdated
buffers being dequeued.

Introduce a new vb2 function to mark all done buffers as erroneous
instead, to be used by drivers at resume time.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/media/v4l2-core/videobuf2-core.c | 24 ++++++++++++++++++++++++
 include/media/videobuf2-core.h           |  1 +
 2 files changed, 25 insertions(+)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index f9059bb..6ab13b7 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -1131,6 +1131,30 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
 EXPORT_SYMBOL_GPL(vb2_buffer_done);
 
 /**
+ * vb2_discard_done() - discard all buffers marked as DONE
+ * @q:		videobuf2 queue
+ *
+ * This function is intended to be used with suspend/resume operations. It
+ * discards all 'done' buffers as they would be too old to be requested after
+ * resume.
+ *
+ * Drivers must stop the hardware and synchronize with interrupt handlers and/or
+ * delayed works before calling this function to make sure no buffer will be
+ * touched by the driver and/or hardware.
+ */
+void vb2_discard_done(struct vb2_queue *q)
+{
+	struct vb2_buffer *vb;
+	unsigned long flags;
+
+	spin_lock_irqsave(&q->done_lock, flags);
+	list_for_each_entry(vb, &q->done_list, done_entry)
+		vb->state = VB2_BUF_STATE_ERROR;
+	spin_unlock_irqrestore(&q->done_lock, flags);
+}
+EXPORT_SYMBOL_GPL(vb2_discard_done);
+
+/**
  * __fill_vb2_buffer() - fill a vb2_buffer with information provided in a
  * v4l2_buffer by the userspace. The caller has already verified that struct
  * v4l2_buffer has a valid number of planes.
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index af46211..2c2f23b 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -429,6 +429,7 @@ void *vb2_plane_vaddr(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);
+void vb2_discard_done(struct vb2_queue *q);
 int vb2_wait_for_all_buffers(struct vb2_queue *q);
 
 int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b);
-- 
1.8.3.2


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

* [PATCH 24/25] omap3isp: Move to videobuf2
  2014-04-03 22:39 [PATCH 00/25] OMAP3 ISP: Move to videobuf2 Laurent Pinchart
                   ` (22 preceding siblings ...)
  2014-04-03 22:39 ` [PATCH 23/25] v4l: vb2: Add a function to discard all DONE buffers Laurent Pinchart
@ 2014-04-03 22:39 ` Laurent Pinchart
  2014-04-03 22:39 ` [PATCH 25/25] omap3isp: Rename isp_buffer isp_addr field to dma Laurent Pinchart
  24 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2014-04-03 22:39 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus

Replace the custom buffers queue implementation with a videobuf2 queue.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/omap3isp/Makefile   |    2 +-
 drivers/media/platform/omap3isp/ispqueue.c | 1031 ----------------------------
 drivers/media/platform/omap3isp/ispqueue.h |  171 -----
 drivers/media/platform/omap3isp/ispvideo.c |  167 +++--
 drivers/media/platform/omap3isp/ispvideo.h |   23 +-
 drivers/staging/media/omap4iss/iss_video.c |    2 +-
 6 files changed, 109 insertions(+), 1287 deletions(-)
 delete mode 100644 drivers/media/platform/omap3isp/ispqueue.c
 delete mode 100644 drivers/media/platform/omap3isp/ispqueue.h

diff --git a/drivers/media/platform/omap3isp/Makefile b/drivers/media/platform/omap3isp/Makefile
index e8847e7..254975a 100644
--- a/drivers/media/platform/omap3isp/Makefile
+++ b/drivers/media/platform/omap3isp/Makefile
@@ -3,7 +3,7 @@
 ccflags-$(CONFIG_VIDEO_OMAP3_DEBUG) += -DDEBUG
 
 omap3-isp-objs += \
-	isp.o ispqueue.o ispvideo.o \
+	isp.o ispvideo.o \
 	ispcsiphy.o ispccp2.o ispcsi2.o \
 	ispccdc.o isppreview.o ispresizer.o \
 	ispstat.o isph3a_aewb.o isph3a_af.o isphist.o
diff --git a/drivers/media/platform/omap3isp/ispqueue.c b/drivers/media/platform/omap3isp/ispqueue.c
deleted file mode 100644
index 77afb63..0000000
--- a/drivers/media/platform/omap3isp/ispqueue.c
+++ /dev/null
@@ -1,1031 +0,0 @@
-/*
- * ispqueue.c
- *
- * TI OMAP3 ISP - Video buffers queue handling
- *
- * Copyright (C) 2010 Nokia Corporation
- *
- * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
- *	     Sakari Ailus <sakari.ailus@iki.fi>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- */
-
-#include <asm/cacheflush.h>
-#include <linux/dma-mapping.h>
-#include <linux/mm.h>
-#include <linux/pagemap.h>
-#include <linux/poll.h>
-#include <linux/scatterlist.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-
-#include "isp.h"
-#include "ispqueue.h"
-#include "ispvideo.h"
-
-/* -----------------------------------------------------------------------------
- * Video buffers management
- */
-
-/*
- * isp_video_buffer_cache_sync - Keep the buffers coherent between CPU and ISP
- *
- * The typical operation required here is Cache Invalidation across
- * the (user space) buffer address range. And this _must_ be done
- * at QBUF stage (and *only* at QBUF).
- *
- * We try to use optimal cache invalidation function:
- * - dmac_map_area:
- *    - used when the number of pages are _low_.
- *    - it becomes quite slow as the number of pages increase.
- *       - for 648x492 viewfinder (150 pages) it takes 1.3 ms.
- *       - for 5 Mpix buffer (2491 pages) it takes between 25-50 ms.
- *
- * - flush_cache_all:
- *    - used when the number of pages are _high_.
- *    - time taken in the range of 500-900 us.
- *    - has a higher penalty but, as whole dcache + icache is invalidated
- */
-/*
- * FIXME: dmac_inv_range crashes randomly on the user space buffer
- *        address. Fall back to flush_cache_all for now.
- */
-#define ISP_CACHE_FLUSH_PAGES_MAX       0
-
-static void isp_video_buffer_cache_sync(struct isp_video_buffer *buf)
-{
-	if (buf->skip_cache)
-		return;
-
-	if (buf->vbuf.m.userptr == 0 || buf->npages == 0 ||
-	    buf->npages > ISP_CACHE_FLUSH_PAGES_MAX)
-		flush_cache_all();
-	else {
-		dmac_map_area((void *)buf->vbuf.m.userptr, buf->vbuf.length,
-			      DMA_FROM_DEVICE);
-		outer_inv_range(buf->vbuf.m.userptr,
-				buf->vbuf.m.userptr + buf->vbuf.length);
-	}
-}
-
-/*
- * isp_video_buffer_lock_vma - Prevent VMAs from being unmapped
- *
- * Lock the VMAs underlying the given buffer into memory. This avoids the
- * userspace buffer mapping from being swapped out, making VIPT cache handling
- * easier.
- *
- * Note that the pages will not be freed as the buffers have been locked to
- * memory using by a call to get_user_pages(), but the userspace mapping could
- * still disappear if the VMAs are not locked. This is caused by the memory
- * management code trying to be as lock-less as possible, which results in the
- * userspace mapping manager not finding out that the pages are locked under
- * some conditions.
- */
-static int isp_video_buffer_lock_vma(struct isp_video_buffer *buf, int lock)
-{
-	struct vm_area_struct *vma;
-	unsigned long start;
-	unsigned long end;
-	int ret = 0;
-
-	if (buf->vbuf.memory == V4L2_MEMORY_MMAP)
-		return 0;
-
-	/* We can be called from workqueue context if the current task dies to
-	 * unlock the VMAs. In that case there's no current memory management
-	 * context so unlocking can't be performed, but the VMAs have been or
-	 * are getting destroyed anyway so it doesn't really matter.
-	 */
-	if (!current || !current->mm)
-		return lock ? -EINVAL : 0;
-
-	start = buf->vbuf.m.userptr;
-	end = buf->vbuf.m.userptr + buf->vbuf.length - 1;
-
-	down_write(&current->mm->mmap_sem);
-	spin_lock(&current->mm->page_table_lock);
-
-	do {
-		vma = find_vma(current->mm, start);
-		if (vma == NULL) {
-			ret = -EFAULT;
-			goto out;
-		}
-
-		if (lock)
-			vma->vm_flags |= VM_LOCKED;
-		else
-			vma->vm_flags &= ~VM_LOCKED;
-
-		start = vma->vm_end + 1;
-	} while (vma->vm_end < end);
-
-	if (lock)
-		buf->vm_flags |= VM_LOCKED;
-	else
-		buf->vm_flags &= ~VM_LOCKED;
-
-out:
-	spin_unlock(&current->mm->page_table_lock);
-	up_write(&current->mm->mmap_sem);
-	return ret;
-}
-
-/*
- * isp_video_buffer_cleanup - Release pages for a userspace VMA.
- *
- * Release pages locked by a call isp_video_buffer_prepare_user and free the
- * pages table.
- */
-static void isp_video_buffer_cleanup(struct isp_video_buffer *buf)
-{
-	enum dma_data_direction direction;
-	DEFINE_DMA_ATTRS(attrs);
-	unsigned int i;
-
-	if (buf->vbuf.memory == V4L2_MEMORY_USERPTR) {
-		if (buf->skip_cache)
-			dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
-
-		direction = buf->vbuf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE
-			  ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
-		dma_unmap_sg_attrs(buf->queue->dev, buf->sgt.sgl,
-				   buf->sgt.orig_nents, direction, &attrs);
-		sg_free_table(&buf->sgt);
-	}
-
-	if (buf->pages != NULL) {
-		isp_video_buffer_lock_vma(buf, 0);
-
-		for (i = 0; i < buf->npages; ++i)
-			page_cache_release(buf->pages[i]);
-
-		vfree(buf->pages);
-		buf->pages = NULL;
-	}
-
-	buf->npages = 0;
-	buf->skip_cache = false;
-}
-
-/*
- * isp_video_buffer_prepare_user - Prepare a userspace buffer.
- *
- * This function creates a scatter list with a 1:1 mapping for a userspace VMA.
- * The number of pages is first computed based on the buffer size, and pages are
- * then retrieved by a call to get_user_pages.
- *
- * Pages are pinned to memory by get_user_pages, making them available for DMA
- * transfers. However, due to memory management optimization, it seems the
- * get_user_pages doesn't guarantee that the pinned pages will not be written
- * to swap and removed from the userspace mapping(s). When this happens, a page
- * fault can be generated when accessing those unmapped pages.
- *
- * If the fault is triggered by a page table walk caused by VIPT cache
- * management operations, the page fault handler might oops if the MM semaphore
- * is held, as it can't handle kernel page faults in that case. To fix that, a
- * fixup entry needs to be added to the cache management code, or the userspace
- * VMA must be locked to avoid removing pages from the userspace mapping in the
- * first place.
- *
- * If the number of pages retrieved is smaller than the number required by the
- * buffer size, the function returns -EFAULT.
- */
-static int isp_video_buffer_prepare_user(struct isp_video_buffer *buf)
-{
-	unsigned int offset;
-	unsigned long data;
-	unsigned int first;
-	unsigned int last;
-	int ret;
-
-	data = buf->vbuf.m.userptr;
-	first = (data & PAGE_MASK) >> PAGE_SHIFT;
-	last = ((data + buf->vbuf.length - 1) & PAGE_MASK) >> PAGE_SHIFT;
-	offset = data & ~PAGE_MASK;
-
-	buf->npages = last - first + 1;
-	buf->pages = vmalloc(buf->npages * sizeof(buf->pages[0]));
-	if (buf->pages == NULL)
-		return -ENOMEM;
-
-	down_read(&current->mm->mmap_sem);
-	ret = get_user_pages(current, current->mm, data & PAGE_MASK,
-			     buf->npages,
-			     buf->vbuf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE, 0,
-			     buf->pages, NULL);
-	up_read(&current->mm->mmap_sem);
-
-	if (ret != buf->npages) {
-		buf->npages = ret < 0 ? 0 : ret;
-		return -EFAULT;
-	}
-
-	ret = isp_video_buffer_lock_vma(buf, 1);
-	if (ret < 0)
-		return ret;
-
-	ret = sg_alloc_table_from_pages(&buf->sgt, buf->pages, buf->npages,
-					offset, buf->vbuf.length, GFP_KERNEL);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-/*
- * isp_video_buffer_prepare_pfnmap - Prepare a VM_PFNMAP userspace buffer
- *
- * Userspace VM_PFNMAP buffers are supported only if they are contiguous in
- * memory and if they span a single VMA. Start by validating the user pointer to
- * make sure it fulfils that condition, and then build a scatter list of
- * physically contiguous pages starting at the buffer memory physical address.
- *
- * Return 0 on success, -EFAULT if the buffer isn't valid or -ENOMEM if memory
- * can't be allocated.
- */
-static int isp_video_buffer_prepare_pfnmap(struct isp_video_buffer *buf)
-{
-	struct vm_area_struct *vma;
-	struct scatterlist *sg;
-	unsigned long prev_pfn;
-	unsigned long this_pfn;
-	unsigned long start;
-	unsigned int offset;
-	unsigned long end;
-	unsigned long pfn;
-	unsigned int i;
-	int ret = 0;
-
-	start = buf->vbuf.m.userptr;
-	end = buf->vbuf.m.userptr + buf->vbuf.length - 1;
-	offset = start & ~PAGE_MASK;
-
-	buf->npages = (end >> PAGE_SHIFT) - (start >> PAGE_SHIFT) + 1;
-	buf->pages = NULL;
-
-	down_read(&current->mm->mmap_sem);
-	vma = find_vma(current->mm, start);
-	if (vma == NULL || vma->vm_end < end) {
-		ret = -EFAULT;
-		goto unlock;
-	}
-
-	for (prev_pfn = 0; start <= end; start += PAGE_SIZE) {
-		ret = follow_pfn(vma, start, &this_pfn);
-		if (ret < 0)
-			goto unlock;
-
-		if (prev_pfn == 0)
-			pfn = this_pfn;
-		else if (this_pfn != prev_pfn + 1) {
-			ret = -EFAULT;
-			goto unlock;
-		}
-
-		prev_pfn = this_pfn;
-	}
-
-unlock:
-	up_read(&current->mm->mmap_sem);
-	if (ret < 0)
-		return ret;
-
-	ret = sg_alloc_table(&buf->sgt, buf->npages, GFP_KERNEL);
-	if (ret < 0)
-		return ret;
-
-	for (sg = buf->sgt.sgl, i = 0; i < buf->npages; ++i, ++pfn) {
-		sg_set_page(sg, pfn_to_page(pfn), PAGE_SIZE - offset, offset);
-		sg = sg_next(sg);
-		offset = 0;
-	}
-
-	return 0;
-}
-
-/*
- * isp_video_buffer_prepare_vm_flags - Get VMA flags for a userspace address
- *
- * This function locates the VMAs for the buffer's userspace address and checks
- * that their flags match. The only flag that we need to care for at the moment
- * is VM_PFNMAP.
- *
- * The buffer vm_flags field is set to the first VMA flags.
- *
- * Return -EFAULT if no VMA can be found for part of the buffer, or if the VMAs
- * have incompatible flags.
- */
-static int isp_video_buffer_prepare_vm_flags(struct isp_video_buffer *buf)
-{
-	struct vm_area_struct *vma;
-	pgprot_t uninitialized_var(vm_page_prot);
-	unsigned long start;
-	unsigned long end;
-	int ret = -EFAULT;
-
-	start = buf->vbuf.m.userptr;
-	end = buf->vbuf.m.userptr + buf->vbuf.length - 1;
-
-	down_read(&current->mm->mmap_sem);
-
-	do {
-		vma = find_vma(current->mm, start);
-		if (vma == NULL)
-			goto done;
-
-		if (start == buf->vbuf.m.userptr) {
-			buf->vm_flags = vma->vm_flags;
-			vm_page_prot = vma->vm_page_prot;
-		}
-
-		if ((buf->vm_flags ^ vma->vm_flags) & VM_PFNMAP)
-			goto done;
-
-		if (vm_page_prot != vma->vm_page_prot)
-			goto done;
-
-		start = vma->vm_end + 1;
-	} while (vma->vm_end < end);
-
-	/* Skip cache management to enhance performances for non-cached or
-	 * write-combining buffers.
-	 */
-	if (vm_page_prot == pgprot_noncached(vm_page_prot) ||
-	    vm_page_prot == pgprot_writecombine(vm_page_prot))
-		buf->skip_cache = true;
-
-	ret = 0;
-
-done:
-	up_read(&current->mm->mmap_sem);
-	return ret;
-}
-
-/*
- * isp_video_buffer_prepare - Make a buffer ready for operation
- *
- * Preparing a buffer involves:
- *
- * - validating VMAs (userspace buffers only)
- * - locking pages and VMAs into memory (userspace buffers only)
- * - building page and scatter-gather lists (userspace buffers only)
- * - mapping buffers for DMA operation
- * - performing driver-specific preparation
- *
- * The function must be called in userspace context with a valid mm context
- * (this excludes cleanup paths such as sys_close when the userspace process
- * segfaults).
- */
-static int isp_video_buffer_prepare(struct isp_video_buffer *buf)
-{
-	enum dma_data_direction direction;
-	DEFINE_DMA_ATTRS(attrs);
-	int ret;
-
-	switch (buf->vbuf.memory) {
-	case V4L2_MEMORY_MMAP:
-		ret = 0;
-		break;
-
-	case V4L2_MEMORY_USERPTR:
-		ret = isp_video_buffer_prepare_vm_flags(buf);
-		if (ret < 0)
-			return ret;
-
-		if (buf->vm_flags & VM_PFNMAP)
-			ret = isp_video_buffer_prepare_pfnmap(buf);
-		else
-			ret = isp_video_buffer_prepare_user(buf);
-
-		if (ret < 0)
-			goto done;
-
-		if (buf->skip_cache)
-			dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
-
-		direction = buf->vbuf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE
-			  ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
-		ret = dma_map_sg_attrs(buf->queue->dev, buf->sgt.sgl,
-				       buf->sgt.orig_nents, direction, &attrs);
-		if (ret <= 0) {
-			ret = -EFAULT;
-			goto done;
-		}
-
-		buf->dma = sg_dma_address(buf->sgt.sgl);
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	if (!IS_ALIGNED(buf->dma, 32)) {
-		dev_dbg(buf->queue->dev,
-			"Buffer address must be aligned to 32 bytes boundary.\n");
-		ret = -EINVAL;
-		goto done;
-	}
-
-	if (buf->queue->ops->buffer_prepare)
-		ret = buf->queue->ops->buffer_prepare(buf);
-
-done:
-	if (ret < 0) {
-		isp_video_buffer_cleanup(buf);
-		return ret;
-	}
-
-	return ret;
-}
-
-/*
- * isp_video_queue_query - Query the status of a given buffer
- *
- * Locking: must be called with the queue lock held.
- */
-static void isp_video_buffer_query(struct isp_video_buffer *buf,
-				   struct v4l2_buffer *vbuf)
-{
-	memcpy(vbuf, &buf->vbuf, sizeof(*vbuf));
-
-	if (buf->vma_use_count)
-		vbuf->flags |= V4L2_BUF_FLAG_MAPPED;
-
-	switch (buf->state) {
-	case ISP_BUF_STATE_ERROR:
-		vbuf->flags |= V4L2_BUF_FLAG_ERROR;
-		/* Fallthrough */
-	case ISP_BUF_STATE_DONE:
-		vbuf->flags |= V4L2_BUF_FLAG_DONE;
-		break;
-	case ISP_BUF_STATE_QUEUED:
-	case ISP_BUF_STATE_ACTIVE:
-		vbuf->flags |= V4L2_BUF_FLAG_QUEUED;
-		break;
-	case ISP_BUF_STATE_IDLE:
-	default:
-		break;
-	}
-}
-
-/*
- * isp_video_buffer_wait - Wait for a buffer to be ready
- *
- * In non-blocking mode, return immediately with 0 if the buffer is ready or
- * -EAGAIN if the buffer is in the QUEUED or ACTIVE state.
- *
- * In blocking mode, wait (interruptibly but with no timeout) on the buffer wait
- * queue using the same condition.
- */
-static int isp_video_buffer_wait(struct isp_video_buffer *buf, int nonblocking)
-{
-	if (nonblocking) {
-		return (buf->state != ISP_BUF_STATE_QUEUED &&
-			buf->state != ISP_BUF_STATE_ACTIVE)
-			? 0 : -EAGAIN;
-	}
-
-	return wait_event_interruptible(buf->wait,
-		buf->state != ISP_BUF_STATE_QUEUED &&
-		buf->state != ISP_BUF_STATE_ACTIVE);
-}
-
-/* -----------------------------------------------------------------------------
- * Queue management
- */
-
-/*
- * isp_video_queue_free - Free video buffers memory
- *
- * Buffers can only be freed if the queue isn't streaming and if no buffer is
- * mapped to userspace. Return -EBUSY if those conditions aren't satisfied.
- *
- * This function must be called with the queue lock held.
- */
-static int isp_video_queue_free(struct isp_video_queue *queue)
-{
-	unsigned int i;
-
-	if (queue->streaming)
-		return -EBUSY;
-
-	for (i = 0; i < queue->count; ++i) {
-		if (queue->buffers[i]->vma_use_count != 0)
-			return -EBUSY;
-	}
-
-	for (i = 0; i < queue->count; ++i) {
-		struct isp_video_buffer *buf = queue->buffers[i];
-
-		isp_video_buffer_cleanup(buf);
-
-		if (buf->vaddr) {
-			dma_free_coherent(queue->dev,
-					  PAGE_ALIGN(buf->vbuf.length),
-					  buf->vaddr, buf->dma);
-			buf->vaddr = NULL;
-		}
-
-		kfree(buf);
-		queue->buffers[i] = NULL;
-	}
-
-	INIT_LIST_HEAD(&queue->queue);
-	queue->count = 0;
-	return 0;
-}
-
-/*
- * isp_video_queue_alloc - Allocate video buffers memory
- *
- * This function must be called with the queue lock held.
- */
-static int isp_video_queue_alloc(struct isp_video_queue *queue,
-				 unsigned int nbuffers,
-				 unsigned int size, enum v4l2_memory memory)
-{
-	struct isp_video_buffer *buf;
-	dma_addr_t dma;
-	unsigned int i;
-	void *mem;
-	int ret;
-
-	/* Start by freeing the buffers. */
-	ret = isp_video_queue_free(queue);
-	if (ret < 0)
-		return ret;
-
-	/* Bail out if no buffers should be allocated. */
-	if (nbuffers == 0)
-		return 0;
-
-	/* Initialize the allocated buffers. */
-	for (i = 0; i < nbuffers; ++i) {
-		buf = kzalloc(queue->bufsize, GFP_KERNEL);
-		if (buf == NULL)
-			break;
-
-		if (memory == V4L2_MEMORY_MMAP) {
-			/* Allocate video buffers memory for mmap mode. Align
-			 * the size to the page size.
-			 */
-			mem = dma_alloc_coherent(queue->dev, PAGE_ALIGN(size),
-						 &dma, GFP_KERNEL);
-			if (mem == NULL) {
-				kfree(buf);
-				break;
-			}
-
-			buf->vbuf.m.offset = i * PAGE_ALIGN(size);
-			buf->vaddr = mem;
-			buf->dma = dma;
-		}
-
-		buf->vbuf.index = i;
-		buf->vbuf.length = size;
-		buf->vbuf.type = queue->type;
-		buf->vbuf.flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
-		buf->vbuf.field = V4L2_FIELD_NONE;
-		buf->vbuf.memory = memory;
-
-		buf->queue = queue;
-		init_waitqueue_head(&buf->wait);
-
-		queue->buffers[i] = buf;
-	}
-
-	if (i == 0)
-		return -ENOMEM;
-
-	queue->count = i;
-	return nbuffers;
-}
-
-/**
- * omap3isp_video_queue_cleanup - Clean up the video buffers queue
- * @queue: Video buffers queue
- *
- * Free all allocated resources and clean up the video buffers queue. The queue
- * must not be busy (no ongoing video stream) and buffers must have been
- * unmapped.
- *
- * Return 0 on success or -EBUSY if the queue is busy or buffers haven't been
- * unmapped.
- */
-int omap3isp_video_queue_cleanup(struct isp_video_queue *queue)
-{
-	return isp_video_queue_free(queue);
-}
-
-/**
- * omap3isp_video_queue_init - Initialize the video buffers queue
- * @queue: Video buffers queue
- * @type: V4L2 buffer type (capture or output)
- * @ops: Driver-specific queue operations
- * @dev: Device used for DMA operations
- * @bufsize: Size of the driver-specific buffer structure
- *
- * Initialize the video buffers queue with the supplied parameters.
- *
- * The queue type must be one of V4L2_BUF_TYPE_VIDEO_CAPTURE or
- * V4L2_BUF_TYPE_VIDEO_OUTPUT. Other buffer types are not supported yet.
- *
- * Buffer objects will be allocated using the given buffer size to allow room
- * for driver-specific fields. Driver-specific buffer structures must start
- * with a struct isp_video_buffer field. Drivers with no driver-specific buffer
- * structure must pass the size of the isp_video_buffer structure in the bufsize
- * parameter.
- *
- * Return 0 on success.
- */
-int omap3isp_video_queue_init(struct isp_video_queue *queue,
-			      enum v4l2_buf_type type,
-			      const struct isp_video_queue_operations *ops,
-			      struct device *dev, unsigned int bufsize)
-{
-	INIT_LIST_HEAD(&queue->queue);
-
-	queue->type = type;
-	queue->ops = ops;
-	queue->dev = dev;
-	queue->bufsize = bufsize;
-
-	return 0;
-}
-
-/* -----------------------------------------------------------------------------
- * V4L2 operations
- */
-
-/**
- * omap3isp_video_queue_reqbufs - Allocate video buffers memory
- *
- * This function is intended to be used as a VIDIOC_REQBUFS ioctl handler. It
- * allocated video buffer objects and, for MMAP buffers, buffer memory.
- *
- * If the number of buffers is 0, all buffers are freed and the function returns
- * without performing any allocation.
- *
- * If the number of buffers is not 0, currently allocated buffers (if any) are
- * freed and the requested number of buffers are allocated. Depending on
- * driver-specific requirements and on memory availability, a number of buffer
- * smaller or bigger than requested can be allocated. This isn't considered as
- * an error.
- *
- * Return 0 on success or one of the following error codes:
- *
- * -EINVAL if the buffer type or index are invalid
- * -EBUSY if the queue is busy (streaming or buffers mapped)
- * -ENOMEM if the buffers can't be allocated due to an out-of-memory condition
- */
-int omap3isp_video_queue_reqbufs(struct isp_video_queue *queue,
-				 struct v4l2_requestbuffers *rb)
-{
-	unsigned int nbuffers = rb->count;
-	unsigned int size;
-	int ret;
-
-	if (rb->type != queue->type)
-		return -EINVAL;
-
-	queue->ops->queue_prepare(queue, &nbuffers, &size);
-	if (size == 0)
-		return -EINVAL;
-
-	nbuffers = min_t(unsigned int, nbuffers, ISP_VIDEO_MAX_BUFFERS);
-
-	ret = isp_video_queue_alloc(queue, nbuffers, size, rb->memory);
-	if (ret < 0)
-		return ret;
-
-	rb->count = ret;
-	return 0;
-}
-
-/**
- * omap3isp_video_queue_querybuf - Query the status of a buffer in a queue
- *
- * This function is intended to be used as a VIDIOC_QUERYBUF ioctl handler. It
- * returns the status of a given video buffer.
- *
- * Return 0 on success or -EINVAL if the buffer type or index are invalid.
- */
-int omap3isp_video_queue_querybuf(struct isp_video_queue *queue,
-				  struct v4l2_buffer *vbuf)
-{
-	struct isp_video_buffer *buf;
-
-	if (vbuf->type != queue->type)
-		return -EINVAL;
-
-	if (vbuf->index >= queue->count)
-		return -EINVAL;
-
-	buf = queue->buffers[vbuf->index];
-	isp_video_buffer_query(buf, vbuf);
-
-	return 0;
-}
-
-/**
- * omap3isp_video_queue_qbuf - Queue a buffer
- *
- * This function is intended to be used as a VIDIOC_QBUF ioctl handler.
- *
- * The v4l2_buffer structure passed from userspace is first sanity tested. If
- * sane, the buffer is then processed and added to the main queue and, if the
- * queue is streaming, to the IRQ queue.
- *
- * Before being enqueued, USERPTR buffers are checked for address changes. If
- * the buffer has a different userspace address, the old memory area is unlocked
- * and the new memory area is locked.
- */
-int omap3isp_video_queue_qbuf(struct isp_video_queue *queue,
-			      struct v4l2_buffer *vbuf)
-{
-	struct isp_video_buffer *buf;
-	int ret;
-
-	if (vbuf->type != queue->type)
-		return -EINVAL;
-
-	if (vbuf->index >= queue->count)
-		return -EINVAL;
-
-	buf = queue->buffers[vbuf->index];
-
-	if (vbuf->memory != buf->vbuf.memory)
-		return -EINVAL;
-
-	if (buf->state != ISP_BUF_STATE_IDLE)
-		return -EINVAL;
-
-	if (vbuf->memory == V4L2_MEMORY_USERPTR &&
-	    vbuf->length < buf->vbuf.length)
-		return -EINVAL;
-
-	if (vbuf->memory == V4L2_MEMORY_USERPTR &&
-	    vbuf->m.userptr != buf->vbuf.m.userptr) {
-		isp_video_buffer_cleanup(buf);
-		buf->vbuf.m.userptr = vbuf->m.userptr;
-		buf->prepared = 0;
-	}
-
-	if (!buf->prepared) {
-		ret = isp_video_buffer_prepare(buf);
-		if (ret < 0)
-			return ret;
-		buf->prepared = 1;
-	}
-
-	isp_video_buffer_cache_sync(buf);
-
-	buf->state = ISP_BUF_STATE_QUEUED;
-	list_add_tail(&buf->stream, &queue->queue);
-
-	if (queue->streaming)
-		queue->ops->buffer_queue(buf);
-
-	return 0;
-}
-
-/**
- * omap3isp_video_queue_dqbuf - Dequeue a buffer
- *
- * This function is intended to be used as a VIDIOC_DQBUF ioctl handler.
- *
- * Wait until a buffer is ready to be dequeued, remove it from the queue and
- * copy its information to the v4l2_buffer structure.
- *
- * If the nonblocking argument is not zero and no buffer is ready, return
- * -EAGAIN immediately instead of waiting.
- *
- * If no buffer has been enqueued, or if the requested buffer type doesn't match
- * the queue type, return -EINVAL.
- */
-int omap3isp_video_queue_dqbuf(struct isp_video_queue *queue,
-			       struct v4l2_buffer *vbuf, int nonblocking)
-{
-	struct isp_video_buffer *buf;
-	int ret;
-
-	if (vbuf->type != queue->type)
-		return -EINVAL;
-
-	if (list_empty(&queue->queue))
-		return -EINVAL;
-
-	buf = list_first_entry(&queue->queue, struct isp_video_buffer, stream);
-	ret = isp_video_buffer_wait(buf, nonblocking);
-	if (ret < 0)
-		return ret;
-
-	list_del(&buf->stream);
-
-	isp_video_buffer_query(buf, vbuf);
-	buf->state = ISP_BUF_STATE_IDLE;
-	vbuf->flags &= ~V4L2_BUF_FLAG_QUEUED;
-
-	return 0;
-}
-
-/**
- * omap3isp_video_queue_streamon - Start streaming
- *
- * This function is intended to be used as a VIDIOC_STREAMON ioctl handler. It
- * starts streaming on the queue and calls the buffer_queue operation for all
- * queued buffers.
- *
- * Return 0 on success.
- */
-int omap3isp_video_queue_streamon(struct isp_video_queue *queue)
-{
-	struct isp_video_buffer *buf;
-
-	if (queue->streaming)
-		return 0;
-
-	queue->streaming = 1;
-
-	list_for_each_entry(buf, &queue->queue, stream)
-		queue->ops->buffer_queue(buf);
-
-	return 0;
-}
-
-/**
- * omap3isp_video_queue_streamoff - Stop streaming
- *
- * This function is intended to be used as a VIDIOC_STREAMOFF ioctl handler. It
- * stops streaming on the queue and wakes up all the buffers.
- *
- * Drivers must stop the hardware and synchronize with interrupt handlers and/or
- * delayed works before calling this function to make sure no buffer will be
- * touched by the driver and/or hardware.
- */
-void omap3isp_video_queue_streamoff(struct isp_video_queue *queue)
-{
-	struct isp_video_buffer *buf;
-	unsigned int i;
-
-	if (!queue->streaming)
-		return;
-
-	queue->streaming = 0;
-
-	for (i = 0; i < queue->count; ++i) {
-		buf = queue->buffers[i];
-
-		if (buf->state == ISP_BUF_STATE_ACTIVE)
-			wake_up(&buf->wait);
-
-		buf->state = ISP_BUF_STATE_IDLE;
-	}
-
-	INIT_LIST_HEAD(&queue->queue);
-}
-
-/**
- * omap3isp_video_queue_discard_done - Discard all buffers marked as DONE
- *
- * This function is intended to be used with suspend/resume operations. It
- * discards all 'done' buffers as they would be too old to be requested after
- * resume.
- *
- * Drivers must stop the hardware and synchronize with interrupt handlers and/or
- * delayed works before calling this function to make sure no buffer will be
- * touched by the driver and/or hardware.
- */
-void omap3isp_video_queue_discard_done(struct isp_video_queue *queue)
-{
-	struct isp_video_buffer *buf;
-	unsigned int i;
-
-	if (!queue->streaming)
-		return;
-
-	for (i = 0; i < queue->count; ++i) {
-		buf = queue->buffers[i];
-
-		if (buf->state == ISP_BUF_STATE_DONE)
-			buf->state = ISP_BUF_STATE_ERROR;
-	}
-}
-
-static void isp_video_queue_vm_open(struct vm_area_struct *vma)
-{
-	struct isp_video_buffer *buf = vma->vm_private_data;
-
-	buf->vma_use_count++;
-}
-
-static void isp_video_queue_vm_close(struct vm_area_struct *vma)
-{
-	struct isp_video_buffer *buf = vma->vm_private_data;
-
-	buf->vma_use_count--;
-}
-
-static const struct vm_operations_struct isp_video_queue_vm_ops = {
-	.open = isp_video_queue_vm_open,
-	.close = isp_video_queue_vm_close,
-};
-
-/**
- * omap3isp_video_queue_mmap - Map buffers to userspace
- *
- * This function is intended to be used as an mmap() file operation handler. It
- * maps a buffer to userspace based on the VMA offset.
- *
- * Only buffers of memory type MMAP are supported.
- */
-int omap3isp_video_queue_mmap(struct isp_video_queue *queue,
-			 struct vm_area_struct *vma)
-{
-	struct isp_video_buffer *uninitialized_var(buf);
-	unsigned long size;
-	unsigned int i;
-	int ret = 0;
-
-	for (i = 0; i < queue->count; ++i) {
-		buf = queue->buffers[i];
-		if ((buf->vbuf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
-			break;
-	}
-
-	if (i == queue->count)
-		return -EINVAL;
-
-	size = vma->vm_end - vma->vm_start;
-
-	if (buf->vbuf.memory != V4L2_MEMORY_MMAP ||
-	    size != PAGE_ALIGN(buf->vbuf.length))
-		return -EINVAL;
-
-	/* dma_mmap_coherent() uses vm_pgoff as an offset inside the buffer
-	 * while we used it to identify the buffer and want to map the whole
-	 * buffer.
-	 */
-	vma->vm_pgoff = 0;
-
-	ret = dma_mmap_coherent(queue->dev, vma, buf->vaddr, buf->dma, size);
-	if (ret < 0)
-		return ret;
-
-	vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
-	vma->vm_ops = &isp_video_queue_vm_ops;
-	vma->vm_private_data = buf;
-	isp_video_queue_vm_open(vma);
-
-	return 0;
-}
-
-/**
- * omap3isp_video_queue_poll - Poll video queue state
- *
- * This function is intended to be used as a poll() file operation handler. It
- * polls the state of the video buffer at the front of the queue and returns an
- * events mask.
- *
- * If no buffer is present at the front of the queue, POLLERR is returned.
- */
-unsigned int omap3isp_video_queue_poll(struct isp_video_queue *queue,
-				       struct file *file, poll_table *wait)
-{
-	struct isp_video_buffer *buf;
-	unsigned int mask = 0;
-
-	if (list_empty(&queue->queue)) {
-		mask |= POLLERR;
-		goto done;
-	}
-	buf = list_first_entry(&queue->queue, struct isp_video_buffer, stream);
-
-	poll_wait(file, &buf->wait, wait);
-	if (buf->state == ISP_BUF_STATE_DONE ||
-	    buf->state == ISP_BUF_STATE_ERROR) {
-		if (queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-			mask |= POLLIN | POLLRDNORM;
-		else
-			mask |= POLLOUT | POLLWRNORM;
-	}
-
-done:
-	return mask;
-}
diff --git a/drivers/media/platform/omap3isp/ispqueue.h b/drivers/media/platform/omap3isp/ispqueue.h
deleted file mode 100644
index ff18208..0000000
--- a/drivers/media/platform/omap3isp/ispqueue.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * ispqueue.h
- *
- * TI OMAP3 ISP - Video buffers queue handling
- *
- * Copyright (C) 2010 Nokia Corporation
- *
- * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
- *	     Sakari Ailus <sakari.ailus@iki.fi>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- */
-
-#ifndef OMAP3_ISP_QUEUE_H
-#define OMAP3_ISP_QUEUE_H
-
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/mm_types.h>
-#include <linux/mutex.h>
-#include <linux/videodev2.h>
-#include <linux/wait.h>
-
-struct isp_video_queue;
-struct page;
-struct scatterlist;
-
-#define ISP_VIDEO_MAX_BUFFERS		16
-
-/**
- * enum isp_video_buffer_state - ISP video buffer state
- * @ISP_BUF_STATE_IDLE:	The buffer is under userspace control (dequeued
- *	or not queued yet).
- * @ISP_BUF_STATE_QUEUED: The buffer has been queued but isn't used by the
- *	device yet.
- * @ISP_BUF_STATE_ACTIVE: The buffer is in use for an active video transfer.
- * @ISP_BUF_STATE_ERROR: The device is done with the buffer and an error
- *	occurred. For capture device the buffer likely contains corrupted data or
- *	no data at all.
- * @ISP_BUF_STATE_DONE: The device is done with the buffer and no error occurred.
- *	For capture devices the buffer contains valid data.
- */
-enum isp_video_buffer_state {
-	ISP_BUF_STATE_IDLE,
-	ISP_BUF_STATE_QUEUED,
-	ISP_BUF_STATE_ACTIVE,
-	ISP_BUF_STATE_ERROR,
-	ISP_BUF_STATE_DONE,
-};
-
-/**
- * struct isp_video_buffer - ISP video buffer
- * @vma_use_count: Number of times the buffer is mmap'ed to userspace
- * @stream: List head for insertion into main queue
- * @queue: ISP buffers queue this buffer belongs to
- * @prepared: Whether the buffer has been prepared
- * @skip_cache: Whether to skip cache management operations for this buffer
- * @vaddr: Memory virtual address (for kernel buffers)
- * @vm_flags: Buffer VMA flags (for userspace buffers)
- * @npages: Number of pages (for userspace buffers)
- * @sgt: Scatter gather table (for userspace buffers)
- * @pages: Pages table (for userspace non-VM_PFNMAP buffers)
- * @vbuf: V4L2 buffer
- * @state: Current buffer state
- * @wait: Wait queue to signal buffer completion
- */
-struct isp_video_buffer {
-	unsigned long vma_use_count;
-	struct list_head stream;
-	struct isp_video_queue *queue;
-	unsigned int prepared:1;
-	bool skip_cache;
-
-	/* For kernel buffers. */
-	void *vaddr;
-
-	/* For userspace buffers. */
-	vm_flags_t vm_flags;
-	unsigned int npages;
-	struct sg_table sgt;
-
-	/* For non-VM_PFNMAP userspace buffers. */
-	struct page **pages;
-
-	/* Touched by the interrupt handler. */
-	struct v4l2_buffer vbuf;
-	enum isp_video_buffer_state state;
-	wait_queue_head_t wait;
-	dma_addr_t dma;
-};
-
-#define to_isp_video_buffer(vb)	container_of(vb, struct isp_video_buffer, vb)
-
-/**
- * struct isp_video_queue_operations - Driver-specific operations
- * @queue_prepare: Called before allocating buffers. Drivers should clamp the
- *	number of buffers according to their requirements, and must return the
- *	buffer size in bytes.
- * @buffer_prepare: Called the first time a buffer is queued, or after changing
- *	the userspace memory address for a USERPTR buffer, with the queue lock
- *	held. Drivers should perform device-specific buffer preparation (such as
- *	mapping the buffer memory in an IOMMU). This operation is optional.
- * @buffer_queue: Called when a buffer is being added.
- */
-struct isp_video_queue_operations {
-	void (*queue_prepare)(struct isp_video_queue *queue,
-			      unsigned int *nbuffers, unsigned int *size);
-	int  (*buffer_prepare)(struct isp_video_buffer *buf);
-	void (*buffer_queue)(struct isp_video_buffer *buf);
-};
-
-/**
- * struct isp_video_queue - ISP video buffers queue
- * @type: Type of video buffers handled by this queue
- * @ops: Queue operations
- * @dev: Device used for DMA operations
- * @bufsize: Size of a driver-specific buffer object
- * @count: Number of currently allocated buffers
- * @buffers: ISP video buffers
- * @streaming: Queue state, indicates whether the queue is streaming
- * @queue: List of all queued buffers
- */
-struct isp_video_queue {
-	enum v4l2_buf_type type;
-	const struct isp_video_queue_operations *ops;
-	struct device *dev;
-	unsigned int bufsize;
-
-	unsigned int count;
-	struct isp_video_buffer *buffers[ISP_VIDEO_MAX_BUFFERS];
-
-	unsigned int streaming:1;
-
-	struct list_head queue;
-};
-
-int omap3isp_video_queue_cleanup(struct isp_video_queue *queue);
-int omap3isp_video_queue_init(struct isp_video_queue *queue,
-			      enum v4l2_buf_type type,
-			      const struct isp_video_queue_operations *ops,
-			      struct device *dev, unsigned int bufsize);
-
-int omap3isp_video_queue_reqbufs(struct isp_video_queue *queue,
-				 struct v4l2_requestbuffers *rb);
-int omap3isp_video_queue_querybuf(struct isp_video_queue *queue,
-				  struct v4l2_buffer *vbuf);
-int omap3isp_video_queue_qbuf(struct isp_video_queue *queue,
-			      struct v4l2_buffer *vbuf);
-int omap3isp_video_queue_dqbuf(struct isp_video_queue *queue,
-			       struct v4l2_buffer *vbuf, int nonblocking);
-int omap3isp_video_queue_streamon(struct isp_video_queue *queue);
-void omap3isp_video_queue_streamoff(struct isp_video_queue *queue);
-void omap3isp_video_queue_discard_done(struct isp_video_queue *queue);
-int omap3isp_video_queue_mmap(struct isp_video_queue *queue,
-			      struct vm_area_struct *vma);
-unsigned int omap3isp_video_queue_poll(struct isp_video_queue *queue,
-				       struct file *file, poll_table *wait);
-
-#endif /* OMAP3_ISP_QUEUE_H */
diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c
index e1f9983..be07f96 100644
--- a/drivers/media/platform/omap3isp/ispvideo.c
+++ b/drivers/media/platform/omap3isp/ispvideo.c
@@ -34,6 +34,7 @@
 #include <linux/vmalloc.h>
 #include <media/v4l2-dev.h>
 #include <media/v4l2-ioctl.h>
+#include <media/videobuf2-dma-contig.h>
 
 #include "ispvideo.h"
 #include "isp.h"
@@ -328,25 +329,33 @@ isp_video_check_format(struct isp_video *video, struct isp_video_fh *vfh)
  * Video queue operations
  */
 
-static void isp_video_queue_prepare(struct isp_video_queue *queue,
-				    unsigned int *nbuffers, unsigned int *size)
+static int isp_video_queue_setup(struct vb2_queue *queue,
+				 const struct v4l2_format *fmt,
+				 unsigned int *count, unsigned int *num_planes,
+				 unsigned int sizes[], void *alloc_ctxs[])
 {
-	struct isp_video_fh *vfh =
-		container_of(queue, struct isp_video_fh, queue);
+	struct isp_video_fh *vfh = vb2_get_drv_priv(queue);
 	struct isp_video *video = vfh->video;
 
-	*size = vfh->format.fmt.pix.sizeimage;
-	if (*size == 0)
-		return;
+	*num_planes = 1;
+
+	sizes[0] = vfh->format.fmt.pix.sizeimage;
+	if (sizes[0] == 0)
+		return -EINVAL;
+
+	alloc_ctxs[0] = video->alloc_ctx;
+
+	*count = min(*count, video->capture_mem / PAGE_ALIGN(sizes[0]));
 
-	*nbuffers = min(*nbuffers, video->capture_mem / PAGE_ALIGN(*size));
+	return 0;
 }
 
-static int isp_video_buffer_prepare(struct isp_video_buffer *buf)
+static int isp_video_buffer_prepare(struct vb2_buffer *buf)
 {
-	struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue);
+	struct isp_video_fh *vfh = vb2_get_drv_priv(buf->vb2_queue);
 	struct isp_buffer *buffer = to_isp_buffer(buf);
 	struct isp_video *video = vfh->video;
+	dma_addr_t addr;
 
 	/* Refuse to prepare the buffer is the video node has registered an
 	 * error. We don't need to take any lock here as the operation is
@@ -357,7 +366,16 @@ static int isp_video_buffer_prepare(struct isp_video_buffer *buf)
 	if (unlikely(video->error))
 		return -EIO;
 
-	buffer->isp_addr = buf->dma;
+	addr = vb2_dma_contig_plane_dma_addr(buf, 0);
+	if (!IS_ALIGNED(addr, 32)) {
+		dev_dbg(video->isp->dev,
+			"Buffer address must be aligned to 32 bytes boundary.\n");
+		return -EINVAL;
+	}
+
+	vb2_set_plane_payload(&buffer->vb, 0, vfh->format.fmt.pix.sizeimage);
+	buffer->isp_addr = addr;
+
 	return 0;
 }
 
@@ -370,9 +388,9 @@ static int isp_video_buffer_prepare(struct isp_video_buffer *buf)
  * If the pipeline is busy, it will be restarted in the output module interrupt
  * handler.
  */
-static void isp_video_buffer_queue(struct isp_video_buffer *buf)
+static void isp_video_buffer_queue(struct vb2_buffer *buf)
 {
-	struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue);
+	struct isp_video_fh *vfh = vb2_get_drv_priv(buf->vb2_queue);
 	struct isp_buffer *buffer = to_isp_buffer(buf);
 	struct isp_video *video = vfh->video;
 	struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity);
@@ -384,8 +402,7 @@ static void isp_video_buffer_queue(struct isp_video_buffer *buf)
 	spin_lock_irqsave(&video->irqlock, flags);
 
 	if (unlikely(video->error)) {
-		buf->state = ISP_BUF_STATE_ERROR;
-		wake_up(&buf->wait);
+		vb2_buffer_done(&buffer->vb, VB2_BUF_STATE_ERROR);
 		spin_unlock_irqrestore(&video->irqlock, flags);
 		return;
 	}
@@ -417,22 +434,22 @@ static void isp_video_buffer_queue(struct isp_video_buffer *buf)
 	}
 }
 
-static const struct isp_video_queue_operations isp_video_queue_ops = {
-	.queue_prepare = &isp_video_queue_prepare,
-	.buffer_prepare = &isp_video_buffer_prepare,
-	.buffer_queue = &isp_video_buffer_queue,
+static const struct vb2_ops isp_video_queue_ops = {
+	.queue_setup = isp_video_queue_setup,
+	.buf_prepare = isp_video_buffer_prepare,
+	.buf_queue = isp_video_buffer_queue,
 };
 
 /*
  * omap3isp_video_buffer_next - Complete the current buffer and return the next
  * @video: ISP video object
  *
- * Remove the current video buffer from the DMA queue and fill its timestamp,
- * field count and state fields before waking up its completion handler.
+ * Remove the current video buffer from the DMA queue and fill its timestamp and
+ * field count before handing it back to videobuf2.
  *
- * For capture video nodes the buffer state is set to ISP_BUF_STATE_DONE if no
- * error has been flagged in the pipeline, or to ISP_BUF_STATE_ERROR otherwise.
- * For video output nodes the buffer state is always set to ISP_BUF_STATE_DONE.
+ * For capture video nodes the buffer state is set to VB2_BUF_STATE_DONE if no
+ * error has been flagged in the pipeline, or to VB2_BUF_STATE_ERROR otherwise.
+ * For video output nodes the buffer state is always set to VB2_BUF_STATE_DONE.
  *
  * The DMA queue is expected to contain at least one buffer.
  *
@@ -442,9 +459,6 @@ static const struct isp_video_queue_operations isp_video_queue_ops = {
 struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video)
 {
 	struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity);
-	struct isp_video_queue *queue = video->queue;
-	struct isp_video_fh *vfh =
-		container_of(queue, struct isp_video_fh, queue);
 	enum isp_pipeline_state state;
 	struct isp_buffer *buf;
 	unsigned long flags;
@@ -461,11 +475,9 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video)
 	list_del(&buf->irqlist);
 	spin_unlock_irqrestore(&video->irqlock, flags);
 
-	buf->buffer.vbuf.bytesused = vfh->format.fmt.pix.sizeimage;
-
 	ktime_get_ts(&ts);
-	buf->buffer.vbuf.timestamp.tv_sec = ts.tv_sec;
-	buf->buffer.vbuf.timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
+	buf->vb.v4l2_buf.timestamp.tv_sec = ts.tv_sec;
+	buf->vb.v4l2_buf.timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
 
 	/* Do frame number propagation only if this is the output video node.
 	 * Frame number either comes from the CSI receivers or it gets
@@ -474,23 +486,27 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video)
 	 * first, so the input number might lag behind by 1 in some cases.
 	 */
 	if (video == pipe->output && !pipe->do_propagation)
-		buf->buffer.vbuf.sequence =
+		buf->vb.v4l2_buf.sequence =
 			atomic_inc_return(&pipe->frame_number);
 	else
-		buf->buffer.vbuf.sequence = atomic_read(&pipe->frame_number);
+		buf->vb.v4l2_buf.sequence = atomic_read(&pipe->frame_number);
 
 	/* Report pipeline errors to userspace on the capture device side. */
-	if (queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->error) {
-		buf->buffer.state = ISP_BUF_STATE_ERROR;
+	if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->error) {
+		state = VB2_BUF_STATE_ERROR;
 		pipe->error = false;
 	} else {
-		buf->buffer.state = ISP_BUF_STATE_DONE;
+		state = VB2_BUF_STATE_DONE;
 	}
 
-	wake_up(&buf->buffer.wait);
+	vb2_buffer_done(&buf->vb, state);
+
+	spin_lock_irqsave(&video->irqlock, flags);
 
 	if (list_empty(&video->dmaqueue)) {
-		if (queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		spin_unlock_irqrestore(&video->irqlock, flags);
+
+		if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
 			state = ISP_PIPELINE_QUEUE_OUTPUT
 			      | ISP_PIPELINE_STREAM;
 		else
@@ -505,15 +521,18 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video)
 		return NULL;
 	}
 
-	if (queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->input != NULL) {
-		spin_lock_irqsave(&pipe->lock, flags);
+	if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->input != NULL) {
+		spin_lock(&pipe->lock);
 		pipe->state &= ~ISP_PIPELINE_STREAM;
-		spin_unlock_irqrestore(&pipe->lock, flags);
+		spin_unlock(&pipe->lock);
 	}
 
 	buf = list_first_entry(&video->dmaqueue, struct isp_buffer,
 			       irqlist);
-	buf->buffer.state = ISP_BUF_STATE_ACTIVE;
+	buf->vb.state = VB2_BUF_STATE_ACTIVE;
+
+	spin_unlock_irqrestore(&video->irqlock, flags);
+
 	return buf;
 }
 
@@ -536,9 +555,7 @@ void omap3isp_video_cancel_stream(struct isp_video *video)
 		buf = list_first_entry(&video->dmaqueue,
 				       struct isp_buffer, irqlist);
 		list_del(&buf->irqlist);
-
-		buf->buffer.state = ISP_BUF_STATE_ERROR;
-		wake_up(&buf->buffer.wait);
+		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
 	}
 
 	video->error = true;
@@ -562,7 +579,7 @@ void omap3isp_video_resume(struct isp_video *video, int continuous)
 
 	if (continuous && video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
 		mutex_lock(&video->queue_lock);
-		omap3isp_video_queue_discard_done(video->queue);
+		vb2_discard_done(video->queue);
 		mutex_unlock(&video->queue_lock);
 	}
 
@@ -780,7 +797,7 @@ isp_video_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *rb)
 	int ret;
 
 	mutex_lock(&video->queue_lock);
-	ret = omap3isp_video_queue_reqbufs(&vfh->queue, rb);
+	ret = vb2_reqbufs(&vfh->queue, rb);
 	mutex_unlock(&video->queue_lock);
 
 	return ret;
@@ -794,7 +811,7 @@ isp_video_querybuf(struct file *file, void *fh, struct v4l2_buffer *b)
 	int ret;
 
 	mutex_lock(&video->queue_lock);
-	ret = omap3isp_video_queue_querybuf(&vfh->queue, b);
+	ret = vb2_querybuf(&vfh->queue, b);
 	mutex_unlock(&video->queue_lock);
 
 	return ret;
@@ -808,7 +825,7 @@ isp_video_qbuf(struct file *file, void *fh, struct v4l2_buffer *b)
 	int ret;
 
 	mutex_lock(&video->queue_lock);
-	ret = omap3isp_video_queue_qbuf(&vfh->queue, b);
+	ret = vb2_qbuf(&vfh->queue, b);
 	mutex_unlock(&video->queue_lock);
 
 	return ret;
@@ -822,8 +839,7 @@ isp_video_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
 	int ret;
 
 	mutex_lock(&video->queue_lock);
-	ret = omap3isp_video_queue_dqbuf(&vfh->queue, b,
-					 file->f_flags & O_NONBLOCK);
+	ret = vb2_dqbuf(&vfh->queue, b, file->f_flags & O_NONBLOCK);
 	mutex_unlock(&video->queue_lock);
 
 	return ret;
@@ -966,11 +982,6 @@ isp_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
 
 	mutex_lock(&video->stream_lock);
 
-	if (video->streaming) {
-		mutex_unlock(&video->stream_lock);
-		return -EBUSY;
-	}
-
 	/* Start streaming on the pipeline. No link touching an entity in the
 	 * pipeline can be activated or deactivated once streaming is started.
 	 */
@@ -1030,7 +1041,7 @@ isp_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
 	atomic_set(&pipe->frame_number, -1);
 
 	mutex_lock(&video->queue_lock);
-	ret = omap3isp_video_queue_streamon(&vfh->queue);
+	ret = vb2_streamon(&vfh->queue, type);
 	mutex_unlock(&video->queue_lock);
 	if (ret < 0)
 		goto err_check_format;
@@ -1050,14 +1061,12 @@ isp_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
 		spin_unlock_irqrestore(&video->irqlock, flags);
 	}
 
-	video->streaming = 1;
-
 	mutex_unlock(&video->stream_lock);
 	return 0;
 
 err_set_stream:
 	mutex_lock(&video->queue_lock);
-	omap3isp_video_queue_streamoff(&vfh->queue);
+	vb2_streamoff(&vfh->queue, type);
 	mutex_unlock(&video->queue_lock);
 err_check_format:
 	media_entity_pipeline_stop(&video->video.entity);
@@ -1095,7 +1104,7 @@ isp_video_streamoff(struct file *file, void *fh, enum v4l2_buf_type type)
 
 	/* Make sure we're not streaming yet. */
 	mutex_lock(&video->queue_lock);
-	streaming = vfh->queue.streaming;
+	streaming = vb2_is_streaming(&vfh->queue);
 	mutex_unlock(&video->queue_lock);
 
 	if (!streaming)
@@ -1116,10 +1125,9 @@ isp_video_streamoff(struct file *file, void *fh, enum v4l2_buf_type type)
 	/* Stop the stream. */
 	omap3isp_pipeline_set_stream(pipe, ISP_PIPELINE_STREAM_STOPPED);
 	mutex_lock(&video->queue_lock);
-	omap3isp_video_queue_streamoff(&vfh->queue);
+	vb2_streamoff(&vfh->queue, type);
 	mutex_unlock(&video->queue_lock);
 	video->queue = NULL;
-	video->streaming = 0;
 	video->error = false;
 
 	if (video->isp->pdata->set_constraints)
@@ -1189,6 +1197,7 @@ static int isp_video_open(struct file *file)
 {
 	struct isp_video *video = video_drvdata(file);
 	struct isp_video_fh *handle;
+	struct vb2_queue *queue;
 	int ret = 0;
 
 	handle = kzalloc(sizeof(*handle), GFP_KERNEL);
@@ -1210,9 +1219,20 @@ static int isp_video_open(struct file *file)
 		goto done;
 	}
 
-	omap3isp_video_queue_init(&handle->queue, video->type,
-				  &isp_video_queue_ops, video->isp->dev,
-				  sizeof(struct isp_buffer));
+	queue = &handle->queue;
+	queue->type = video->type;
+	queue->io_modes = VB2_MMAP | VB2_USERPTR;
+	queue->drv_priv = handle;
+	queue->ops = &isp_video_queue_ops;
+	queue->mem_ops = &vb2_dma_contig_memops;
+	queue->buf_struct_size = sizeof(struct isp_buffer);
+	queue->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+
+	ret = vb2_queue_init(&handle->queue);
+	if (ret < 0) {
+		omap3isp_put(video->isp);
+		goto done;
+	}
 
 	memset(&handle->format, 0, sizeof(handle->format));
 	handle->format.type = video->type;
@@ -1240,7 +1260,7 @@ static int isp_video_release(struct file *file)
 	isp_video_streamoff(file, vfh, video->type);
 
 	mutex_lock(&video->queue_lock);
-	omap3isp_video_queue_cleanup(&handle->queue);
+	vb2_queue_release(&handle->queue);
 	mutex_unlock(&video->queue_lock);
 
 	omap3isp_pipeline_pm_use(&video->video.entity, 0);
@@ -1262,7 +1282,7 @@ static unsigned int isp_video_poll(struct file *file, poll_table *wait)
 	int ret;
 
 	mutex_lock(&video->queue_lock);
-	ret = omap3isp_video_queue_poll(&vfh->queue, file, wait);
+	ret = vb2_poll(&vfh->queue, file, wait);
 	mutex_unlock(&video->queue_lock);
 
 	return ret;
@@ -1275,7 +1295,7 @@ static int isp_video_mmap(struct file *file, struct vm_area_struct *vma)
 	int ret;
 
 	mutex_lock(&video->queue_lock);
-	ret = omap3isp_video_queue_mmap(&vfh->queue, vma);
+	ret = vb2_mmap(&vfh->queue, vma);
 	mutex_unlock(&video->queue_lock);
 
 	return ret;
@@ -1319,9 +1339,15 @@ int omap3isp_video_init(struct isp_video *video, const char *name)
 		return -EINVAL;
 	}
 
+	video->alloc_ctx = vb2_dma_contig_init_ctx(video->isp->dev);
+	if (IS_ERR(video->alloc_ctx))
+		return PTR_ERR(video->alloc_ctx);
+
 	ret = media_entity_init(&video->video.entity, 1, &video->pad, 0);
-	if (ret < 0)
+	if (ret < 0) {
+		vb2_dma_contig_cleanup_ctx(video->alloc_ctx);
 		return ret;
+	}
 
 	mutex_init(&video->mutex);
 	atomic_set(&video->active, 0);
@@ -1350,6 +1376,7 @@ int omap3isp_video_init(struct isp_video *video, const char *name)
 
 void omap3isp_video_cleanup(struct isp_video *video)
 {
+	vb2_dma_contig_cleanup_ctx(video->alloc_ctx);
 	media_entity_cleanup(&video->video.entity);
 	mutex_destroy(&video->queue_lock);
 	mutex_destroy(&video->stream_lock);
diff --git a/drivers/media/platform/omap3isp/ispvideo.h b/drivers/media/platform/omap3isp/ispvideo.h
index 1e3d17a..1015505 100644
--- a/drivers/media/platform/omap3isp/ispvideo.h
+++ b/drivers/media/platform/omap3isp/ispvideo.h
@@ -30,8 +30,7 @@
 #include <media/media-entity.h>
 #include <media/v4l2-dev.h>
 #include <media/v4l2-fh.h>
-
-#include "ispqueue.h"
+#include <media/videobuf2-core.h>
 
 #define ISP_VIDEO_DRIVER_NAME		"ispvideo"
 #define ISP_VIDEO_DRIVER_VERSION	"0.0.2"
@@ -124,19 +123,19 @@ static inline int isp_pipeline_ready(struct isp_pipeline *pipe)
 			       ISP_PIPELINE_IDLE_OUTPUT);
 }
 
-/*
- * struct isp_buffer - ISP buffer
- * @buffer: ISP video buffer
+/**
+ * struct isp_buffer - ISP video buffer
+ * @vb: videobuf2 buffer
  * @irqlist: List head for insertion into IRQ queue
- * @isp_addr: MMU mapped address (a.k.a. device address) of the buffer.
+ * @isp_addr: DMA address
  */
 struct isp_buffer {
-	struct isp_video_buffer buffer;
+	struct vb2_buffer vb;
 	struct list_head irqlist;
 	dma_addr_t isp_addr;
 };
 
-#define to_isp_buffer(buf)	container_of(buf, struct isp_buffer, buffer)
+#define to_isp_buffer(buf)	container_of(buf, struct isp_buffer, vb)
 
 enum isp_video_dmaqueue_flags {
 	/* Set if DMA queue becomes empty when ISP_PIPELINE_STREAM_CONTINUOUS */
@@ -174,16 +173,14 @@ struct isp_video {
 	unsigned int bpl_value;		/* bytes per line value */
 	unsigned int bpl_padding;	/* padding at end of line */
 
-	/* Entity video node streaming */
-	unsigned int streaming:1;
-
 	/* Pipeline state */
 	struct isp_pipeline pipe;
 	struct mutex stream_lock;	/* pipeline and stream states */
 	bool error;
 
 	/* Video buffers queue */
-	struct isp_video_queue *queue;
+	void *alloc_ctx;
+	struct vb2_queue *queue;
 	struct mutex queue_lock;	/* protects the queue */
 	spinlock_t irqlock;		/* protects dmaqueue */
 	struct list_head dmaqueue;
@@ -197,7 +194,7 @@ struct isp_video {
 struct isp_video_fh {
 	struct v4l2_fh vfh;
 	struct isp_video *video;
-	struct isp_video_queue queue;
+	struct vb2_queue queue;
 	struct v4l2_format format;
 	struct v4l2_fract timeperframe;
 };
diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c
index ded31ea..cbf455d 100644
--- a/drivers/staging/media/omap4iss/iss_video.c
+++ b/drivers/staging/media/omap4iss/iss_video.c
@@ -396,7 +396,7 @@ static void iss_video_buf_queue(struct vb2_buffer *vb)
 	}
 }
 
-static struct vb2_ops iss_video_vb2ops = {
+static const struct vb2_ops iss_video_vb2ops = {
 	.queue_setup	= iss_video_queue_setup,
 	.buf_prepare	= iss_video_buf_prepare,
 	.buf_queue	= iss_video_buf_queue,
-- 
1.8.3.2


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

* [PATCH 25/25] omap3isp: Rename isp_buffer isp_addr field to dma
  2014-04-03 22:39 [PATCH 00/25] OMAP3 ISP: Move to videobuf2 Laurent Pinchart
                   ` (23 preceding siblings ...)
  2014-04-03 22:39 ` [PATCH 24/25] omap3isp: Move to videobuf2 Laurent Pinchart
@ 2014-04-03 22:39 ` Laurent Pinchart
  24 siblings, 0 replies; 26+ messages in thread
From: Laurent Pinchart @ 2014-04-03 22:39 UTC (permalink / raw)
  To: linux-media; +Cc: Sakari Ailus

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/omap3isp/ispccdc.c    | 4 ++--
 drivers/media/platform/omap3isp/ispccp2.c    | 4 ++--
 drivers/media/platform/omap3isp/ispcsi2.c    | 4 ++--
 drivers/media/platform/omap3isp/isppreview.c | 8 ++++----
 drivers/media/platform/omap3isp/ispresizer.c | 8 ++++----
 drivers/media/platform/omap3isp/ispvideo.c   | 2 +-
 drivers/media/platform/omap3isp/ispvideo.h   | 4 ++--
 7 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispccdc.c b/drivers/media/platform/omap3isp/ispccdc.c
index 004a4f5..9f727d2 100644
--- a/drivers/media/platform/omap3isp/ispccdc.c
+++ b/drivers/media/platform/omap3isp/ispccdc.c
@@ -1521,7 +1521,7 @@ static int ccdc_isr_buffer(struct isp_ccdc_device *ccdc)
 
 	buffer = omap3isp_video_buffer_next(&ccdc->video_out);
 	if (buffer != NULL) {
-		ccdc_set_outaddr(ccdc, buffer->isp_addr);
+		ccdc_set_outaddr(ccdc, buffer->dma);
 		restart = 1;
 	}
 
@@ -1660,7 +1660,7 @@ static int ccdc_video_queue(struct isp_video *video, struct isp_buffer *buffer)
 	if (!(ccdc->output & CCDC_OUTPUT_MEMORY))
 		return -ENODEV;
 
-	ccdc_set_outaddr(ccdc, buffer->isp_addr);
+	ccdc_set_outaddr(ccdc, buffer->dma);
 
 	/* We now have a buffer queued on the output, restart the pipeline
 	 * on the next CCDC interrupt if running in continuous mode (or when
diff --git a/drivers/media/platform/omap3isp/ispccp2.c b/drivers/media/platform/omap3isp/ispccp2.c
index b30b67d..f3801db 100644
--- a/drivers/media/platform/omap3isp/ispccp2.c
+++ b/drivers/media/platform/omap3isp/ispccp2.c
@@ -549,7 +549,7 @@ static void ccp2_isr_buffer(struct isp_ccp2_device *ccp2)
 
 	buffer = omap3isp_video_buffer_next(&ccp2->video_in);
 	if (buffer != NULL)
-		ccp2_set_inaddr(ccp2, buffer->isp_addr);
+		ccp2_set_inaddr(ccp2, buffer->dma);
 
 	pipe->state |= ISP_PIPELINE_IDLE_INPUT;
 
@@ -940,7 +940,7 @@ static int ccp2_video_queue(struct isp_video *video, struct isp_buffer *buffer)
 {
 	struct isp_ccp2_device *ccp2 = &video->isp->isp_ccp2;
 
-	ccp2_set_inaddr(ccp2, buffer->isp_addr);
+	ccp2_set_inaddr(ccp2, buffer->dma);
 	return 0;
 }
 
diff --git a/drivers/media/platform/omap3isp/ispcsi2.c b/drivers/media/platform/omap3isp/ispcsi2.c
index 6205608..5a2e47e 100644
--- a/drivers/media/platform/omap3isp/ispcsi2.c
+++ b/drivers/media/platform/omap3isp/ispcsi2.c
@@ -695,7 +695,7 @@ static void csi2_isr_buffer(struct isp_csi2_device *csi2)
 	if (buffer == NULL)
 		return;
 
-	csi2_set_outaddr(csi2, buffer->isp_addr);
+	csi2_set_outaddr(csi2, buffer->dma);
 	csi2_ctx_enable(isp, csi2, 0, 1);
 }
 
@@ -812,7 +812,7 @@ static int csi2_queue(struct isp_video *video, struct isp_buffer *buffer)
 	struct isp_device *isp = video->isp;
 	struct isp_csi2_device *csi2 = &isp->isp_csi2a;
 
-	csi2_set_outaddr(csi2, buffer->isp_addr);
+	csi2_set_outaddr(csi2, buffer->dma);
 
 	/*
 	 * If streaming was enabled before there was a buffer queued
diff --git a/drivers/media/platform/omap3isp/isppreview.c b/drivers/media/platform/omap3isp/isppreview.c
index 395b2b0..720809b 100644
--- a/drivers/media/platform/omap3isp/isppreview.c
+++ b/drivers/media/platform/omap3isp/isppreview.c
@@ -1499,14 +1499,14 @@ static void preview_isr_buffer(struct isp_prev_device *prev)
 	if (prev->input == PREVIEW_INPUT_MEMORY) {
 		buffer = omap3isp_video_buffer_next(&prev->video_in);
 		if (buffer != NULL)
-			preview_set_inaddr(prev, buffer->isp_addr);
+			preview_set_inaddr(prev, buffer->dma);
 		pipe->state |= ISP_PIPELINE_IDLE_INPUT;
 	}
 
 	if (prev->output & PREVIEW_OUTPUT_MEMORY) {
 		buffer = omap3isp_video_buffer_next(&prev->video_out);
 		if (buffer != NULL) {
-			preview_set_outaddr(prev, buffer->isp_addr);
+			preview_set_outaddr(prev, buffer->dma);
 			restart = 1;
 		}
 		pipe->state |= ISP_PIPELINE_IDLE_OUTPUT;
@@ -1577,10 +1577,10 @@ static int preview_video_queue(struct isp_video *video,
 	struct isp_prev_device *prev = &video->isp->isp_prev;
 
 	if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
-		preview_set_inaddr(prev, buffer->isp_addr);
+		preview_set_inaddr(prev, buffer->dma);
 
 	if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		preview_set_outaddr(prev, buffer->isp_addr);
+		preview_set_outaddr(prev, buffer->dma);
 
 	return 0;
 }
diff --git a/drivers/media/platform/omap3isp/ispresizer.c b/drivers/media/platform/omap3isp/ispresizer.c
index 86369df..6f077c2 100644
--- a/drivers/media/platform/omap3isp/ispresizer.c
+++ b/drivers/media/platform/omap3isp/ispresizer.c
@@ -1040,7 +1040,7 @@ static void resizer_isr_buffer(struct isp_res_device *res)
 	 */
 	buffer = omap3isp_video_buffer_next(&res->video_out);
 	if (buffer != NULL) {
-		resizer_set_outaddr(res, buffer->isp_addr);
+		resizer_set_outaddr(res, buffer->dma);
 		restart = 1;
 	}
 
@@ -1049,7 +1049,7 @@ static void resizer_isr_buffer(struct isp_res_device *res)
 	if (res->input == RESIZER_INPUT_MEMORY) {
 		buffer = omap3isp_video_buffer_next(&res->video_in);
 		if (buffer != NULL)
-			resizer_set_inaddr(res, buffer->isp_addr);
+			resizer_set_inaddr(res, buffer->dma);
 		pipe->state |= ISP_PIPELINE_IDLE_INPUT;
 	}
 
@@ -1101,7 +1101,7 @@ static int resizer_video_queue(struct isp_video *video,
 	struct isp_res_device *res = &video->isp->isp_res;
 
 	if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
-		resizer_set_inaddr(res, buffer->isp_addr);
+		resizer_set_inaddr(res, buffer->dma);
 
 	/*
 	 * We now have a buffer queued on the output. Despite what the
@@ -1116,7 +1116,7 @@ static int resizer_video_queue(struct isp_video *video,
 	 * continuous mode or when starting the stream.
 	 */
 	if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		resizer_set_outaddr(res, buffer->isp_addr);
+		resizer_set_outaddr(res, buffer->dma);
 
 	return 0;
 }
diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c
index be07f96..d9d8432 100644
--- a/drivers/media/platform/omap3isp/ispvideo.c
+++ b/drivers/media/platform/omap3isp/ispvideo.c
@@ -374,7 +374,7 @@ static int isp_video_buffer_prepare(struct vb2_buffer *buf)
 	}
 
 	vb2_set_plane_payload(&buffer->vb, 0, vfh->format.fmt.pix.sizeimage);
-	buffer->isp_addr = addr;
+	buffer->dma = addr;
 
 	return 0;
 }
diff --git a/drivers/media/platform/omap3isp/ispvideo.h b/drivers/media/platform/omap3isp/ispvideo.h
index 1015505..7d2e821 100644
--- a/drivers/media/platform/omap3isp/ispvideo.h
+++ b/drivers/media/platform/omap3isp/ispvideo.h
@@ -127,12 +127,12 @@ static inline int isp_pipeline_ready(struct isp_pipeline *pipe)
  * struct isp_buffer - ISP video buffer
  * @vb: videobuf2 buffer
  * @irqlist: List head for insertion into IRQ queue
- * @isp_addr: DMA address
+ * @dma: DMA address
  */
 struct isp_buffer {
 	struct vb2_buffer vb;
 	struct list_head irqlist;
-	dma_addr_t isp_addr;
+	dma_addr_t dma;
 };
 
 #define to_isp_buffer(buf)	container_of(buf, struct isp_buffer, vb)
-- 
1.8.3.2


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

end of thread, other threads:[~2014-04-03 22:38 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-04-03 22:39 [PATCH 00/25] OMAP3 ISP: Move to videobuf2 Laurent Pinchart
2014-04-03 22:39 ` [PATCH 01/25] omap3isp: stat: Rename IS_COHERENT_BUF to ISP_STAT_USES_DMAENGINE Laurent Pinchart
2014-04-03 22:39 ` [PATCH 02/25] omap3isp: stat: Remove impossible WARN_ON Laurent Pinchart
2014-04-03 22:39 ` [PATCH 03/25] omap3isp: stat: Share common code for buffer allocation Laurent Pinchart
2014-04-03 22:39 ` [PATCH 04/25] omap3isp: stat: Merge dma_addr and iommu_addr fields Laurent Pinchart
2014-04-03 22:39 ` [PATCH 05/25] omap3isp: stat: Store sg table in ispstat_buffer Laurent Pinchart
2014-04-03 22:39 ` [PATCH 06/25] omap3isp: stat: Use the DMA API Laurent Pinchart
2014-04-03 22:39 ` [PATCH 07/25] omap3isp: ccdc: Use the DMA API for LSC Laurent Pinchart
2014-04-03 22:39 ` [PATCH 08/25] omap3isp: ccdc: Use the DMA API for FPC Laurent Pinchart
2014-04-03 22:39 ` [PATCH 09/25] omap3isp: video: Set the buffer bytesused field at completion time Laurent Pinchart
2014-04-03 22:39 ` [PATCH 10/25] omap3isp: queue: Move IOMMU handling code to the queue Laurent Pinchart
2014-04-03 22:39 ` [PATCH 11/25] omap3isp: queue: Use sg_table structure Laurent Pinchart
2014-04-03 22:39 ` [PATCH 12/25] omap3isp: queue: Merge the prepare and sglist functions Laurent Pinchart
2014-04-03 22:39 ` [PATCH 13/25] omap3isp: queue: Inline the ispmmu_v(un)map functions Laurent Pinchart
2014-04-03 22:39 ` [PATCH 14/25] omap3isp: queue: Allocate kernel buffers with dma_alloc_coherent Laurent Pinchart
2014-04-03 22:39 ` [PATCH 15/25] omap3isp: queue: Fix the dma_map_sg() return value check Laurent Pinchart
2014-04-03 22:39 ` [PATCH 16/25] omap3isp: queue: Map PFNMAP buffers to device Laurent Pinchart
2014-04-03 22:39 ` [PATCH 17/25] omap3isp: queue: Use sg_alloc_table_from_pages() Laurent Pinchart
2014-04-03 22:39 ` [PATCH 18/25] omap3isp: Use the ARM DMA IOMMU-aware operations Laurent Pinchart
2014-04-03 22:39 ` [PATCH 19/25] omap3isp: queue: Don't build scatterlist for kernel buffer Laurent Pinchart
2014-04-03 22:39 ` [PATCH 20/25] omap3isp: Move queue mutex to isp_video structure Laurent Pinchart
2014-04-03 22:39 ` [PATCH 21/25] omap3isp: Move queue irqlock " Laurent Pinchart
2014-04-03 22:39 ` [PATCH 22/25] omap3isp: Move buffer irqlist to isp_buffer structure Laurent Pinchart
2014-04-03 22:39 ` [PATCH 23/25] v4l: vb2: Add a function to discard all DONE buffers Laurent Pinchart
2014-04-03 22:39 ` [PATCH 24/25] omap3isp: Move to videobuf2 Laurent Pinchart
2014-04-03 22:39 ` [PATCH 25/25] omap3isp: Rename isp_buffer isp_addr field to dma Laurent Pinchart

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).