From: Tomasz Stanislawski <t.stanislaws@xxxxxxxxxxx>
Signed-off-by: Tomasz Stanislawski <t.stanislaws@xxxxxxxxxxx>
Signed-off-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx>
Signed-off-by: Marek Szyprowski <m.szyprowski@xxxxxxxxxxx>
---
drivers/media/video/videobuf2-dma-contig.c | 90
++++++++++++++++++++++++++++
1 files changed, 90 insertions(+), 0 deletions(-)
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);
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);
--
1.7.6
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html