Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

v4l:vb2: Add dma-contig allocator as dma_buf user

This patch makes changes for adding dma-contig as a dma_buf user. It provides
function implementations for the {import, acquire, release, put}_dmabuf()
mem_ops of DMABUF memory type.

Signed-off-by: Sumit Semwal <sumit.semwal@ti.com>
  • Loading branch information...
commit 0cb96b221cc28da2dea586279a5a1b7d696573a1 1 parent 704e1e1
authored October 24, 2011 Rob Clark committed December 20, 2011

Showing 1 changed file with 124 additions and 0 deletions. Show diff stats Hide diff stats

  1. 124  drivers/media/video/videobuf2-dma-contig.c
124  drivers/media/video/videobuf2-dma-contig.c
@@ -13,6 +13,8 @@
13 13
 #include <linux/module.h>
14 14
 #include <linux/slab.h>
15 15
 #include <linux/dma-mapping.h>
  16
+#include <linux/scatterlist.h>
  17
+#include <linux/dma-buf.h>
16 18
 
17 19
 #include <media/videobuf2-core.h>
18 20
 #include <media/videobuf2-memops.h>
@@ -27,16 +29,23 @@ struct vb2_dc_buf {
27 29
 	dma_addr_t			dma_addr;
28 30
 	unsigned long			size;
29 31
 	struct vm_area_struct		*vma;
  32
+	struct dma_buf_attachment	*db_attach;
30 33
 	atomic_t			refcount;
31 34
 	struct vb2_vmarea_handler	handler;
32 35
 };
33 36
 
  37
+struct vb2_dc_db_attach {
  38
+	struct vb2_dc_buf		*buf;
  39
+	struct dma_buf_attachment	db_attach;
  40
+};
  41
+
34 42
 static void vb2_dma_contig_put(void *buf_priv);
35 43
 
36 44
 static void *vb2_dma_contig_alloc(void *alloc_ctx, unsigned long size)
37 45
 {
38 46
 	struct vb2_dc_conf *conf = alloc_ctx;
39 47
 	struct vb2_dc_buf *buf;
  48
+	/* TODO: add db_attach processing while adding DMABUF as exporter */
40 49
 
41 50
 	buf = kzalloc(sizeof *buf, GFP_KERNEL);
42 51
 	if (!buf)
@@ -148,6 +157,117 @@ static void vb2_dma_contig_put_userptr(void *mem_priv)
148 157
 	kfree(buf);
149 158
 }
150 159
 
  160
+static void *vb2_dma_contig_import_dmabuf(void *alloc_ctx, int fd)
  161
+{
  162
+	struct vb2_dc_conf *conf = alloc_ctx;
  163
+	struct vb2_dc_buf *buf;
  164
+	struct dma_buf *dbuf;
  165
+	struct dma_buf_attachment *dba;
  166
+
  167
+	buf = kzalloc(sizeof *buf, GFP_KERNEL);
  168
+	if (!buf)
  169
+		return ERR_PTR(-ENOMEM);
  170
+
  171
+	/* Get the dmabuf for given fd */
  172
+	dbuf = dma_buf_get(fd);
  173
+	if (IS_ERR(dbuf)) {
  174
+		printk(KERN_ERR "failed to get dmabuf from fd %d\n", fd);
  175
+		kfree(buf);
  176
+		return dbuf;
  177
+	}
  178
+
  179
+	/* create attachment for the dmabuf with the user device */
  180
+	dba = dma_buf_attach(dbuf, conf->dev);
  181
+	if (IS_ERR(dba)) {
  182
+		printk(KERN_ERR "failed to attach dmabuf for fd %d\n", fd);
  183
+		kfree(buf);
  184
+		return dba;
  185
+	}
  186
+
  187
+	buf->conf = conf;
  188
+	buf->size = dba->dmabuf->size;
  189
+	buf->db_attach = dba;
  190
+	buf->dma_addr = 0; /* dma_addr is available only after acquire */
  191
+
  192
+	return buf;
  193
+}
  194
+
  195
+static void vb2_dma_contig_put_dmabuf(void *mem_priv)
  196
+{
  197
+	struct vb2_dc_buf *buf = mem_priv;
  198
+	struct dma_buf *dmabuf;
  199
+
  200
+	if (!buf)
  201
+		return;
  202
+	dmabuf = buf->db_attach->dmabuf;
  203
+
  204
+	/* detach this attachment */
  205
+	dma_buf_detach(dmabuf, buf->db_attach);
  206
+	buf->db_attach = NULL;
  207
+
  208
+	/* put the dmabuf reference */
  209
+	dma_buf_put(dmabuf);
  210
+
  211
+	kfree(buf);
  212
+}
  213
+
  214
+static void vb2_dma_contig_acquire_dmabuf(void *mem_priv)
  215
+{
  216
+	struct vb2_dc_buf *buf = mem_priv;
  217
+	struct dma_buf *dmabuf;
  218
+	struct sg_table *sg;
  219
+	enum dma_data_direction dir;
  220
+
  221
+	if (!buf || !buf->db_attach)
  222
+		return;
  223
+
  224
+	dmabuf = buf->db_attach->dmabuf;
  225
+
  226
+	// TODO need a way to know if we are camera or display, etc..
  227
+	dir = DMA_BIDIRECTIONAL;
  228
+
  229
+	/* get the associated sg for this buffer */
  230
+	sg = dma_buf_map_attachment(buf->db_attach, dir);
  231
+	if (!sg)
  232
+		return;
  233
+
  234
+	/*
  235
+	 *  convert sglist to paddr:
  236
+	 *  Assumption: for dma-contig, dmabuf would map to single entry
  237
+	 *  Will print a warning if it has more than one.
  238
+	 */
  239
+	if (sg->nents > 1)
  240
+		printk(KERN_WARNING
  241
+			"dmabuf scatterlist has more than 1 entry\n");
  242
+
  243
+	buf->dma_addr = sg_dma_address(sg->sgl);
  244
+	buf->size = sg_dma_len(sg->sgl);
  245
+
  246
+	/* save this sg in dmabuf for put_scatterlist */
  247
+	dmabuf->priv = sg;
  248
+}
  249
+
  250
+static void vb2_dma_contig_release_dmabuf(void *mem_priv)
  251
+{
  252
+	struct vb2_dc_buf *buf = mem_priv;
  253
+	struct dma_buf *dmabuf;
  254
+	struct sg_table *sg;
  255
+
  256
+	if (!buf || !buf->db_attach)
  257
+		return;
  258
+
  259
+	dmabuf = buf->db_attach->dmabuf;
  260
+	sg = dmabuf->priv;
  261
+
  262
+	/*
  263
+	 * Put the sg for this buffer:
  264
+	 */
  265
+	dma_buf_unmap_attachment(buf->db_attach, sg);
  266
+
  267
+	buf->dma_addr = 0;
  268
+	buf->size = 0;
  269
+}
  270
+
151 271
 const struct vb2_mem_ops vb2_dma_contig_memops = {
152 272
 	.alloc		= vb2_dma_contig_alloc,
153 273
 	.put		= vb2_dma_contig_put,
@@ -156,6 +276,10 @@ const struct vb2_mem_ops vb2_dma_contig_memops = {
156 276
 	.mmap		= vb2_dma_contig_mmap,
157 277
 	.get_userptr	= vb2_dma_contig_get_userptr,
158 278
 	.put_userptr	= vb2_dma_contig_put_userptr,
  279
+	.import_dmabuf	= vb2_dma_contig_import_dmabuf,
  280
+	.put_dmabuf	= vb2_dma_contig_put_dmabuf,
  281
+	.acquire_dmabuf	= vb2_dma_contig_acquire_dmabuf,
  282
+	.release_dmabuf	= vb2_dma_contig_release_dmabuf,
159 283
 	.num_users	= vb2_dma_contig_num_users,
160 284
 };
161 285
 EXPORT_SYMBOL_GPL(vb2_dma_contig_memops);

0 notes on commit 0cb96b2

Please sign in to comment.
Something went wrong with that request. Please try again.