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