[PATCHv10 11/26] v4l: vb2-dma-contig: add support for dma_buf importing

2012-10-10 Thread Tomasz Stanislawski
From: Sumit Semwal 

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

Signed-off-by: Sumit Semwal 
Signed-off-by: Sumit Semwal 
[author of the original patch]
Signed-off-by: Tomasz Stanislawski 
[integration with refactored dma-contig allocator]
Acked-by: Laurent Pinchart 
---
 drivers/media/v4l2-core/Kconfig|1 +
 drivers/media/v4l2-core/videobuf2-dma-contig.c |  120 +++-
 2 files changed, 119 insertions(+), 2 deletions(-)

diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig
index 2e787cc..e30583b 100644
--- a/drivers/media/v4l2-core/Kconfig
+++ b/drivers/media/v4l2-core/Kconfig
@@ -69,6 +69,7 @@ config VIDEOBUF2_DMA_CONTIG
tristate
select VIDEOBUF2_CORE
select VIDEOBUF2_MEMOPS
+   select DMA_SHARED_BUFFER

 config VIDEOBUF2_VMALLOC
tristate
diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c 
b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index 494a824..a5804cf 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -10,6 +10,7 @@
  * the Free Software Foundation.
  */

+#include 
 #include 
 #include 
 #include 
@@ -38,6 +39,9 @@ struct vb2_dc_buf {

/* USERPTR related */
struct vm_area_struct   *vma;
+
+   /* DMABUF related */
+   struct dma_buf_attachment   *db_attach;
 };

 /*/
@@ -108,7 +112,8 @@ static void vb2_dc_prepare(void *buf_priv)
struct vb2_dc_buf *buf = buf_priv;
struct sg_table *sgt = buf->dma_sgt;

-   if (!sgt)
+   /* DMABUF exporter will flush the cache for us */
+   if (!sgt || buf->db_attach)
return;

dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
@@ -119,7 +124,8 @@ static void vb2_dc_finish(void *buf_priv)
struct vb2_dc_buf *buf = buf_priv;
struct sg_table *sgt = buf->dma_sgt;

-   if (!sgt)
+   /* DMABUF exporter will flush the cache for us */
+   if (!sgt || buf->db_attach)
return;

dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
@@ -377,6 +383,112 @@ fail_buf:
 }

 /*/
+/*   callbacks for DMABUF buffers*/
+/*/
+
+static int vb2_dc_map_dmabuf(void *mem_priv)
+{
+   struct vb2_dc_buf *buf = mem_priv;
+   struct sg_table *sgt;
+   unsigned long contig_size;
+
+   if (WARN_ON(!buf->db_attach)) {
+   pr_err("trying to pin a non attached buffer\n");
+   return -EINVAL;
+   }
+
+   if (WARN_ON(buf->dma_sgt)) {
+   pr_err("dmabuf buffer is already pinned\n");
+   return 0;
+   }
+
+   /* get the associated scatterlist for this buffer */
+   sgt = dma_buf_map_attachment(buf->db_attach, buf->dma_dir);
+   if (IS_ERR_OR_NULL(sgt)) {
+   pr_err("Error getting dmabuf scatterlist\n");
+   return -EINVAL;
+   }
+
+   /* checking if dmabuf is big enough to store contiguous chunk */
+   contig_size = vb2_dc_get_contiguous_size(sgt);
+   if (contig_size < buf->size) {
+   pr_err("contiguous chunk is too small %lu/%lu b\n",
+   contig_size, buf->size);
+   dma_buf_unmap_attachment(buf->db_attach, sgt, buf->dma_dir);
+   return -EFAULT;
+   }
+
+   buf->dma_addr = sg_dma_address(sgt->sgl);
+   buf->dma_sgt = sgt;
+
+   return 0;
+}
+
+static void vb2_dc_unmap_dmabuf(void *mem_priv)
+{
+   struct vb2_dc_buf *buf = mem_priv;
+   struct sg_table *sgt = buf->dma_sgt;
+
+   if (WARN_ON(!buf->db_attach)) {
+   pr_err("trying to unpin a not attached buffer\n");
+   return;
+   }
+
+   if (WARN_ON(!sgt)) {
+   pr_err("dmabuf buffer is already unpinned\n");
+   return;
+   }
+
+   dma_buf_unmap_attachment(buf->db_attach, sgt, buf->dma_dir);
+
+   buf->dma_addr = 0;
+   buf->dma_sgt = NULL;
+}
+
+static void vb2_dc_detach_dmabuf(void *mem_priv)
+{
+   struct vb2_dc_buf *buf = mem_priv;
+
+   /* if vb2 works correctly you should never detach mapped buffer */
+   if (WARN_ON(buf->dma_addr))
+   vb2_dc_unmap_dmabuf(buf);
+
+   /* detach this attachment */
+   dma_buf_detach(buf->db_attach->dmabuf, buf->db_attach);
+   kfree(buf);
+}
+
+static void *vb2_dc_attach_dmabuf(void *alloc_ctx, struct dma_buf *dbuf,
+   unsigned long size, int write)
+{
+   struct vb2_dc_conf *conf = alloc_ctx;
+   struct vb2_dc_buf *buf;
+   struct dma_buf_attachment *dba;
+
+   if (dbuf->size < size)
+   return ERR_PTR(-EFAULT);
+
+   

[PATCHv10 11/26] v4l: vb2-dma-contig: add support for dma_buf importing

2012-10-10 Thread Tomasz Stanislawski
From: Sumit Semwal sumit.sem...@ti.com

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

Signed-off-by: Sumit Semwal sumit.sem...@ti.com
Signed-off-by: Sumit Semwal sumit.sem...@linaro.org
[author of the original patch]
Signed-off-by: Tomasz Stanislawski t.stanisl...@samsung.com
[integration with refactored dma-contig allocator]
Acked-by: Laurent Pinchart laurent.pinch...@ideasonboard.com
---
 drivers/media/v4l2-core/Kconfig|1 +
 drivers/media/v4l2-core/videobuf2-dma-contig.c |  120 +++-
 2 files changed, 119 insertions(+), 2 deletions(-)

diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig
index 2e787cc..e30583b 100644
--- a/drivers/media/v4l2-core/Kconfig
+++ b/drivers/media/v4l2-core/Kconfig
@@ -69,6 +69,7 @@ config VIDEOBUF2_DMA_CONTIG
tristate
select VIDEOBUF2_CORE
select VIDEOBUF2_MEMOPS
+   select DMA_SHARED_BUFFER
 
 config VIDEOBUF2_VMALLOC
tristate
diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c 
b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index 494a824..a5804cf 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -10,6 +10,7 @@
  * the Free Software Foundation.
  */
 
+#include linux/dma-buf.h
 #include linux/module.h
 #include linux/scatterlist.h
 #include linux/sched.h
@@ -38,6 +39,9 @@ struct vb2_dc_buf {
 
/* USERPTR related */
struct vm_area_struct   *vma;
+
+   /* DMABUF related */
+   struct dma_buf_attachment   *db_attach;
 };
 
 /*/
@@ -108,7 +112,8 @@ static void vb2_dc_prepare(void *buf_priv)
struct vb2_dc_buf *buf = buf_priv;
struct sg_table *sgt = buf-dma_sgt;
 
-   if (!sgt)
+   /* DMABUF exporter will flush the cache for us */
+   if (!sgt || buf-db_attach)
return;
 
dma_sync_sg_for_device(buf-dev, sgt-sgl, sgt-nents, buf-dma_dir);
@@ -119,7 +124,8 @@ static void vb2_dc_finish(void *buf_priv)
struct vb2_dc_buf *buf = buf_priv;
struct sg_table *sgt = buf-dma_sgt;
 
-   if (!sgt)
+   /* DMABUF exporter will flush the cache for us */
+   if (!sgt || buf-db_attach)
return;
 
dma_sync_sg_for_cpu(buf-dev, sgt-sgl, sgt-nents, buf-dma_dir);
@@ -377,6 +383,112 @@ fail_buf:
 }
 
 /*/
+/*   callbacks for DMABUF buffers*/
+/*/
+
+static int vb2_dc_map_dmabuf(void *mem_priv)
+{
+   struct vb2_dc_buf *buf = mem_priv;
+   struct sg_table *sgt;
+   unsigned long contig_size;
+
+   if (WARN_ON(!buf-db_attach)) {
+   pr_err(trying to pin a non attached buffer\n);
+   return -EINVAL;
+   }
+
+   if (WARN_ON(buf-dma_sgt)) {
+   pr_err(dmabuf buffer is already pinned\n);
+   return 0;
+   }
+
+   /* get the associated scatterlist for this buffer */
+   sgt = dma_buf_map_attachment(buf-db_attach, buf-dma_dir);
+   if (IS_ERR_OR_NULL(sgt)) {
+   pr_err(Error getting dmabuf scatterlist\n);
+   return -EINVAL;
+   }
+
+   /* checking if dmabuf is big enough to store contiguous chunk */
+   contig_size = vb2_dc_get_contiguous_size(sgt);
+   if (contig_size  buf-size) {
+   pr_err(contiguous chunk is too small %lu/%lu b\n,
+   contig_size, buf-size);
+   dma_buf_unmap_attachment(buf-db_attach, sgt, buf-dma_dir);
+   return -EFAULT;
+   }
+
+   buf-dma_addr = sg_dma_address(sgt-sgl);
+   buf-dma_sgt = sgt;
+
+   return 0;
+}
+
+static void vb2_dc_unmap_dmabuf(void *mem_priv)
+{
+   struct vb2_dc_buf *buf = mem_priv;
+   struct sg_table *sgt = buf-dma_sgt;
+
+   if (WARN_ON(!buf-db_attach)) {
+   pr_err(trying to unpin a not attached buffer\n);
+   return;
+   }
+
+   if (WARN_ON(!sgt)) {
+   pr_err(dmabuf buffer is already unpinned\n);
+   return;
+   }
+
+   dma_buf_unmap_attachment(buf-db_attach, sgt, buf-dma_dir);
+
+   buf-dma_addr = 0;
+   buf-dma_sgt = NULL;
+}
+
+static void vb2_dc_detach_dmabuf(void *mem_priv)
+{
+   struct vb2_dc_buf *buf = mem_priv;
+
+   /* if vb2 works correctly you should never detach mapped buffer */
+   if (WARN_ON(buf-dma_addr))
+   vb2_dc_unmap_dmabuf(buf);
+
+   /* detach this attachment */
+   dma_buf_detach(buf-db_attach-dmabuf, buf-db_attach);
+   kfree(buf);
+}
+
+static void *vb2_dc_attach_dmabuf(void *alloc_ctx, struct dma_buf *dbuf,
+   unsigned long size, int write)
+{
+   struct vb2_dc_conf *conf = alloc_ctx;
+   struct vb2_dc_buf