[media] omap3isp: queue: Move IOMMU handling code to the queue
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Fri, 3 Jan 2014 01:12:42 +0000 (22:12 -0300)
committerMauro Carvalho Chehab <m.chehab@samsung.com>
Sun, 25 May 2014 14:13:17 +0000 (11:13 -0300)
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>
Acked-by: Sakari Ailus <sakari.ailus@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
drivers/media/platform/omap3isp/ispqueue.c
drivers/media/platform/omap3isp/ispqueue.h
drivers/media/platform/omap3isp/ispvideo.c

index a5e65858e7991b5f961ff671d1a8e36f4657ecad..8623c058734ee50c484d962ed55a7e0469f95788 100644 (file)
@@ -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>
 #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);
 
index 3e048ad65647460dfdbb596f67443d4842faec65..0899a116b4d52737f154aa9339671f7176ee31f0 100644 (file)
@@ -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);
 };
 
 /**
index e0f594f34becb79fab7bb9e4daea897a90940e0b..a7ef0816230aea9f6f46d95b2e4db333cdb1da2d 100644 (file)
@@ -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>
@@ -325,55 +324,6 @@ isp_video_check_format(struct isp_video *video, struct isp_video_fh *vfh)
        return ret;
 }
 
-/* -----------------------------------------------------------------------------
- * 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,
 };
 
 /*