Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
videobuf2-dma-contig.c
Go to the documentation of this file.
1 /*
2  * videobuf2-dma-contig.c - DMA contig memory allocator for videobuf2
3  *
4  * Copyright (C) 2010 Samsung Electronics
5  *
6  * Author: Pawel Osciak <[email protected]>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation.
11  */
12 
13 #include <linux/module.h>
14 #include <linux/slab.h>
15 #include <linux/dma-mapping.h>
16 
17 #include <media/videobuf2-core.h>
19 #include <media/videobuf2-memops.h>
20 
21 struct vb2_dc_conf {
22  struct device *dev;
23 };
24 
25 struct vb2_dc_buf {
26  struct vb2_dc_conf *conf;
27  void *vaddr;
29  unsigned long size;
33 };
34 
35 static void vb2_dma_contig_put(void *buf_priv);
36 
37 static void *vb2_dma_contig_alloc(void *alloc_ctx, unsigned long size)
38 {
39  struct vb2_dc_conf *conf = alloc_ctx;
40  struct vb2_dc_buf *buf;
41 
42  buf = kzalloc(sizeof *buf, GFP_KERNEL);
43  if (!buf)
44  return ERR_PTR(-ENOMEM);
45 
46  buf->vaddr = dma_alloc_coherent(conf->dev, size, &buf->dma_addr,
47  GFP_KERNEL);
48  if (!buf->vaddr) {
49  dev_err(conf->dev, "dma_alloc_coherent of size %ld failed\n",
50  size);
51  kfree(buf);
52  return ERR_PTR(-ENOMEM);
53  }
54 
55  buf->conf = conf;
56  buf->size = size;
57 
58  buf->handler.refcount = &buf->refcount;
59  buf->handler.put = vb2_dma_contig_put;
60  buf->handler.arg = buf;
61 
62  atomic_inc(&buf->refcount);
63 
64  return buf;
65 }
66 
67 static void vb2_dma_contig_put(void *buf_priv)
68 {
69  struct vb2_dc_buf *buf = buf_priv;
70 
71  if (atomic_dec_and_test(&buf->refcount)) {
72  dma_free_coherent(buf->conf->dev, buf->size, buf->vaddr,
73  buf->dma_addr);
74  kfree(buf);
75  }
76 }
77 
78 static void *vb2_dma_contig_cookie(void *buf_priv)
79 {
80  struct vb2_dc_buf *buf = buf_priv;
81 
82  return &buf->dma_addr;
83 }
84 
85 static void *vb2_dma_contig_vaddr(void *buf_priv)
86 {
87  struct vb2_dc_buf *buf = buf_priv;
88  if (!buf)
89  return NULL;
90 
91  return buf->vaddr;
92 }
93 
94 static unsigned int vb2_dma_contig_num_users(void *buf_priv)
95 {
96  struct vb2_dc_buf *buf = buf_priv;
97 
98  return atomic_read(&buf->refcount);
99 }
100 
101 static int vb2_dma_contig_mmap(void *buf_priv, struct vm_area_struct *vma)
102 {
103  struct vb2_dc_buf *buf = buf_priv;
104 
105  if (!buf) {
106  printk(KERN_ERR "No buffer to map\n");
107  return -EINVAL;
108  }
109 
110  return vb2_mmap_pfn_range(vma, buf->dma_addr, buf->size,
111  &vb2_common_vm_ops, &buf->handler);
112 }
113 
114 static void *vb2_dma_contig_get_userptr(void *alloc_ctx, unsigned long vaddr,
115  unsigned long size, int write)
116 {
117  struct vb2_dc_buf *buf;
118  struct vm_area_struct *vma;
119  dma_addr_t dma_addr = 0;
120  int ret;
121 
122  buf = kzalloc(sizeof *buf, GFP_KERNEL);
123  if (!buf)
124  return ERR_PTR(-ENOMEM);
125 
126  ret = vb2_get_contig_userptr(vaddr, size, &vma, &dma_addr);
127  if (ret) {
128  printk(KERN_ERR "Failed acquiring VMA for vaddr 0x%08lx\n",
129  vaddr);
130  kfree(buf);
131  return ERR_PTR(ret);
132  }
133 
134  buf->size = size;
135  buf->dma_addr = dma_addr;
136  buf->vma = vma;
137 
138  return buf;
139 }
140 
141 static void vb2_dma_contig_put_userptr(void *mem_priv)
142 {
143  struct vb2_dc_buf *buf = mem_priv;
144 
145  if (!buf)
146  return;
147 
148  vb2_put_vma(buf->vma);
149  kfree(buf);
150 }
151 
153  .alloc = vb2_dma_contig_alloc,
154  .put = vb2_dma_contig_put,
155  .cookie = vb2_dma_contig_cookie,
156  .vaddr = vb2_dma_contig_vaddr,
157  .mmap = vb2_dma_contig_mmap,
158  .get_userptr = vb2_dma_contig_get_userptr,
159  .put_userptr = vb2_dma_contig_put_userptr,
160  .num_users = vb2_dma_contig_num_users,
161 };
162 EXPORT_SYMBOL_GPL(vb2_dma_contig_memops);
163 
165 {
166  struct vb2_dc_conf *conf;
167 
168  conf = kzalloc(sizeof *conf, GFP_KERNEL);
169  if (!conf)
170  return ERR_PTR(-ENOMEM);
171 
172  conf->dev = dev;
173 
174  return conf;
175 }
177 
178 void vb2_dma_contig_cleanup_ctx(void *alloc_ctx)
179 {
180  kfree(alloc_ctx);
181 }
183 
184 MODULE_DESCRIPTION("DMA-contig memory handling routines for videobuf2");
185 MODULE_AUTHOR("Pawel Osciak <[email protected]>");
186 MODULE_LICENSE("GPL");