diff mbox

[4/6] v4l: vb2: integrate dma-contig allocator with shrbuf

Message ID 4E37C8FE.1040207@samsung.com (mailing list archive)
State Not Applicable
Headers show

Commit Message

Marek Szyprowski Aug. 2, 2011, 9:53 a.m. UTC
From: Tomasz Stanislawski <t.stanislaws@samsung.com>

Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
  drivers/media/video/videobuf2-dma-contig.c |   90 
++++++++++++++++++++++++++++
  1 files changed, 90 insertions(+), 0 deletions(-)

          return ERR_PTR(-ENOMEM);
      }
@@ -54,6 +86,12 @@ static void *vb2_dma_contig_alloc(void *alloc_ctx, 
unsigned long size)
      buf->conf = conf;
      buf->size = size;

+    sb->buf = buf;
+    sb->sb.get = __dc_shrbuf_get;
+    sb->sb.put = __dc_shrbuf_put;
+    sb->sb.dma_addr = buf->paddr;
+    sb->sb.size = buf->size;
+
      buf->handler.refcount = &buf->refcount;
      buf->handler.put = vb2_dma_contig_put;
      buf->handler.arg = buf;
@@ -70,6 +108,7 @@ static void vb2_dma_contig_put(void *buf_priv)
      if (atomic_dec_and_test(&buf->refcount)) {
          dma_free_coherent(buf->conf->dev, buf->size, buf->vaddr,
                    buf->paddr);
+        kfree(container_of(buf->sb, struct vb2_dc_shrbuf, sb));
          kfree(buf);
      }
  }
@@ -148,6 +187,54 @@ static void vb2_dma_contig_put_userptr(void *mem_priv)
      kfree(buf);
  }

+static void *vb2_dma_contig_import_shrbuf(void *alloc_ctx, int fd)
+{
+    struct vb2_dc_buf *buf;
+    struct shrbuf *sb;
+
+    buf = kzalloc(sizeof *buf, GFP_KERNEL);
+    if (!buf)
+        return ERR_PTR(-ENOMEM);
+
+    sb = shrbuf_import(fd);
+    if (IS_ERR(sb)) {
+        printk(KERN_ERR "Failed acquiring shared buffer from fd %d\n",
+                fd);
+        kfree(buf);
+        return sb;
+    }
+
+    buf->size = sb->size;
+    buf->paddr = sb->dma_addr;
+    buf->sb = sb;
+
+    return buf;
+}
+
+static void vb2_dma_contig_put_shrbuf(void *mem_priv)
+{
+    struct vb2_dc_buf *buf = mem_priv;
+
+    if (!buf)
+        return;
+
+    buf->sb->put(buf->sb);
+    kfree(buf);
+}
+
+static int vb2_dma_contig_export_shrbuf(void *mem_priv)
+{
+    struct vb2_dc_buf *buf = mem_priv;
+
+    if (!buf)
+        return -EINVAL;
+
+    if (!buf->sb)
+        return -EINVAL;
+
+    return shrbuf_export(buf->sb);
+}
+
  const struct vb2_mem_ops vb2_dma_contig_memops = {
      .alloc        = vb2_dma_contig_alloc,
      .put        = vb2_dma_contig_put,
@@ -156,6 +243,9 @@ const struct vb2_mem_ops vb2_dma_contig_memops = {
      .mmap        = vb2_dma_contig_mmap,
      .get_userptr    = vb2_dma_contig_get_userptr,
      .put_userptr    = vb2_dma_contig_put_userptr,
+    .import_shrbuf    = vb2_dma_contig_import_shrbuf,
+    .export_shrbuf    = vb2_dma_contig_export_shrbuf,
+    .put_shrbuf    = vb2_dma_contig_put_shrbuf,
      .num_users    = vb2_dma_contig_num_users,
  };
  EXPORT_SYMBOL_GPL(vb2_dma_contig_memops);
diff mbox

Patch

diff --git a/drivers/media/video/videobuf2-dma-contig.c 
b/drivers/media/video/videobuf2-dma-contig.c
index a790a5f..7baac66 100644
--- a/drivers/media/video/videobuf2-dma-contig.c
+++ b/drivers/media/video/videobuf2-dma-contig.c
@@ -13,6 +13,7 @@ 
  #include <linux/module.h>
  #include <linux/slab.h>
  #include <linux/dma-mapping.h>
+#include <linux/shared-buffer.h>

  #include <media/videobuf2-core.h>
  #include <media/videobuf2-memops.h>
@@ -27,26 +28,57 @@  struct vb2_dc_buf {
      dma_addr_t            paddr;
      unsigned long            size;
      struct vm_area_struct        *vma;
+    struct shrbuf            *sb;
      atomic_t            refcount;
      struct vb2_vmarea_handler    handler;
  };

+struct vb2_dc_shrbuf {
+    struct vb2_dc_buf    *buf;
+    struct shrbuf        sb;
+};
+
  static void vb2_dma_contig_put(void *buf_priv);

+static void __dc_shrbuf_get(struct shrbuf *__sb)
+{
+    struct vb2_dc_shrbuf *sb = container_of(__sb, struct vb2_dc_shrbuf, 
sb);
+    struct vb2_dc_buf *buf = sb->buf;
+
+    atomic_inc(&buf->refcount);
+}
+
+static void __dc_shrbuf_put(struct shrbuf *__sb)
+{
+    struct vb2_dc_shrbuf *sb = container_of(__sb, struct vb2_dc_shrbuf, 
sb);
+    struct vb2_dc_buf *buf = sb->buf;
+
+    vb2_dma_contig_put(buf);
+}
+
  static void *vb2_dma_contig_alloc(void *alloc_ctx, unsigned long size)
  {
      struct vb2_dc_conf *conf = alloc_ctx;
      struct vb2_dc_buf *buf;
+    struct vb2_dc_shrbuf *sb;

      buf = kzalloc(sizeof *buf, GFP_KERNEL);
      if (!buf)
          return ERR_PTR(-ENOMEM);

+    sb = kzalloc(sizeof *sb, GFP_KERNEL);
+    if (!sb) {
+        kfree(buf);
+        return ERR_PTR(-ENOMEM);
+    }
+    buf->sb = &sb->sb;
+
      buf->vaddr = dma_alloc_coherent(conf->dev, size, &buf->paddr,
                      GFP_KERNEL);
      if (!buf->vaddr) {
          dev_err(conf->dev, "dma_alloc_coherent of size %ld failed\n",
              size);
+        kfree(sb);
          kfree(buf);