Merge tag 'for-linus-20130509' of git://git.infradead.org/~dwmw2/random-2.6
[firefly-linux-kernel-4.4.55.git] / drivers / media / v4l2-core / videobuf-dma-contig.c
1 /*
2  * helper functions for physically contiguous capture buffers
3  *
4  * The functions support hardware lacking scatter gather support
5  * (i.e. the buffers must be linear in physical memory)
6  *
7  * Copyright (c) 2008 Magnus Damm
8  *
9  * Based on videobuf-vmalloc.c,
10  * (c) 2007 Mauro Carvalho Chehab, <mchehab@infradead.org>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2
15  */
16
17 #include <linux/init.h>
18 #include <linux/module.h>
19 #include <linux/mm.h>
20 #include <linux/pagemap.h>
21 #include <linux/dma-mapping.h>
22 #include <linux/sched.h>
23 #include <linux/slab.h>
24 #include <media/videobuf-dma-contig.h>
25
26 struct videobuf_dma_contig_memory {
27         u32 magic;
28         void *vaddr;
29         dma_addr_t dma_handle;
30         unsigned long size;
31 };
32
33 #define MAGIC_DC_MEM 0x0733ac61
34 #define MAGIC_CHECK(is, should)                                             \
35         if (unlikely((is) != (should))) {                                   \
36                 pr_err("magic mismatch: %x expected %x\n", (is), (should)); \
37                 BUG();                                                      \
38         }
39
40 static int __videobuf_dc_alloc(struct device *dev,
41                                struct videobuf_dma_contig_memory *mem,
42                                unsigned long size, gfp_t flags)
43 {
44         mem->size = size;
45         mem->vaddr = dma_alloc_coherent(dev, mem->size,
46                                         &mem->dma_handle, flags);
47
48         if (!mem->vaddr) {
49                 dev_err(dev, "memory alloc size %ld failed\n", mem->size);
50                 return -ENOMEM;
51         }
52
53         dev_dbg(dev, "dma mapped data is at %p (%ld)\n", mem->vaddr, mem->size);
54
55         return 0;
56 }
57
58 static void __videobuf_dc_free(struct device *dev,
59                                struct videobuf_dma_contig_memory *mem)
60 {
61         dma_free_coherent(dev, mem->size, mem->vaddr, mem->dma_handle);
62
63         mem->vaddr = NULL;
64 }
65
66 static void videobuf_vm_open(struct vm_area_struct *vma)
67 {
68         struct videobuf_mapping *map = vma->vm_private_data;
69
70         dev_dbg(map->q->dev, "vm_open %p [count=%u,vma=%08lx-%08lx]\n",
71                 map, map->count, vma->vm_start, vma->vm_end);
72
73         map->count++;
74 }
75
76 static void videobuf_vm_close(struct vm_area_struct *vma)
77 {
78         struct videobuf_mapping *map = vma->vm_private_data;
79         struct videobuf_queue *q = map->q;
80         int i;
81
82         dev_dbg(q->dev, "vm_close %p [count=%u,vma=%08lx-%08lx]\n",
83                 map, map->count, vma->vm_start, vma->vm_end);
84
85         map->count--;
86         if (0 == map->count) {
87                 struct videobuf_dma_contig_memory *mem;
88
89                 dev_dbg(q->dev, "munmap %p q=%p\n", map, q);
90                 videobuf_queue_lock(q);
91
92                 /* We need first to cancel streams, before unmapping */
93                 if (q->streaming)
94                         videobuf_queue_cancel(q);
95
96                 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
97                         if (NULL == q->bufs[i])
98                                 continue;
99
100                         if (q->bufs[i]->map != map)
101                                 continue;
102
103                         mem = q->bufs[i]->priv;
104                         if (mem) {
105                                 /* This callback is called only if kernel has
106                                    allocated memory and this memory is mmapped.
107                                    In this case, memory should be freed,
108                                    in order to do memory unmap.
109                                  */
110
111                                 MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
112
113                                 /* vfree is not atomic - can't be
114                                    called with IRQ's disabled
115                                  */
116                                 dev_dbg(q->dev, "buf[%d] freeing %p\n",
117                                         i, mem->vaddr);
118
119                                 __videobuf_dc_free(q->dev, mem);
120                                 mem->vaddr = NULL;
121                         }
122
123                         q->bufs[i]->map = NULL;
124                         q->bufs[i]->baddr = 0;
125                 }
126
127                 kfree(map);
128
129                 videobuf_queue_unlock(q);
130         }
131 }
132
133 static const struct vm_operations_struct videobuf_vm_ops = {
134         .open   = videobuf_vm_open,
135         .close  = videobuf_vm_close,
136 };
137
138 /**
139  * videobuf_dma_contig_user_put() - reset pointer to user space buffer
140  * @mem: per-buffer private videobuf-dma-contig data
141  *
142  * This function resets the user space pointer
143  */
144 static void videobuf_dma_contig_user_put(struct videobuf_dma_contig_memory *mem)
145 {
146         mem->dma_handle = 0;
147         mem->size = 0;
148 }
149
150 /**
151  * videobuf_dma_contig_user_get() - setup user space memory pointer
152  * @mem: per-buffer private videobuf-dma-contig data
153  * @vb: video buffer to map
154  *
155  * This function validates and sets up a pointer to user space memory.
156  * Only physically contiguous pfn-mapped memory is accepted.
157  *
158  * Returns 0 if successful.
159  */
160 static int videobuf_dma_contig_user_get(struct videobuf_dma_contig_memory *mem,
161                                         struct videobuf_buffer *vb)
162 {
163         struct mm_struct *mm = current->mm;
164         struct vm_area_struct *vma;
165         unsigned long prev_pfn, this_pfn;
166         unsigned long pages_done, user_address;
167         unsigned int offset;
168         int ret;
169
170         offset = vb->baddr & ~PAGE_MASK;
171         mem->size = PAGE_ALIGN(vb->size + offset);
172         ret = -EINVAL;
173
174         down_read(&mm->mmap_sem);
175
176         vma = find_vma(mm, vb->baddr);
177         if (!vma)
178                 goto out_up;
179
180         if ((vb->baddr + mem->size) > vma->vm_end)
181                 goto out_up;
182
183         pages_done = 0;
184         prev_pfn = 0; /* kill warning */
185         user_address = vb->baddr;
186
187         while (pages_done < (mem->size >> PAGE_SHIFT)) {
188                 ret = follow_pfn(vma, user_address, &this_pfn);
189                 if (ret)
190                         break;
191
192                 if (pages_done == 0)
193                         mem->dma_handle = (this_pfn << PAGE_SHIFT) + offset;
194                 else if (this_pfn != (prev_pfn + 1))
195                         ret = -EFAULT;
196
197                 if (ret)
198                         break;
199
200                 prev_pfn = this_pfn;
201                 user_address += PAGE_SIZE;
202                 pages_done++;
203         }
204
205 out_up:
206         up_read(&current->mm->mmap_sem);
207
208         return ret;
209 }
210
211 static struct videobuf_buffer *__videobuf_alloc(size_t size)
212 {
213         struct videobuf_dma_contig_memory *mem;
214         struct videobuf_buffer *vb;
215
216         vb = kzalloc(size + sizeof(*mem), GFP_KERNEL);
217         if (vb) {
218                 vb->priv = ((char *)vb) + size;
219                 mem = vb->priv;
220                 mem->magic = MAGIC_DC_MEM;
221         }
222
223         return vb;
224 }
225
226 static void *__videobuf_to_vaddr(struct videobuf_buffer *buf)
227 {
228         struct videobuf_dma_contig_memory *mem = buf->priv;
229
230         BUG_ON(!mem);
231         MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
232
233         return mem->vaddr;
234 }
235
236 static int __videobuf_iolock(struct videobuf_queue *q,
237                              struct videobuf_buffer *vb,
238                              struct v4l2_framebuffer *fbuf)
239 {
240         struct videobuf_dma_contig_memory *mem = vb->priv;
241
242         BUG_ON(!mem);
243         MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
244
245         switch (vb->memory) {
246         case V4L2_MEMORY_MMAP:
247                 dev_dbg(q->dev, "%s memory method MMAP\n", __func__);
248
249                 /* All handling should be done by __videobuf_mmap_mapper() */
250                 if (!mem->vaddr) {
251                         dev_err(q->dev, "memory is not alloced/mmapped.\n");
252                         return -EINVAL;
253                 }
254                 break;
255         case V4L2_MEMORY_USERPTR:
256                 dev_dbg(q->dev, "%s memory method USERPTR\n", __func__);
257
258                 /* handle pointer from user space */
259                 if (vb->baddr)
260                         return videobuf_dma_contig_user_get(mem, vb);
261
262                 /* allocate memory for the read() method */
263                 if (__videobuf_dc_alloc(q->dev, mem, PAGE_ALIGN(vb->size),
264                                         GFP_KERNEL))
265                         return -ENOMEM;
266                 break;
267         case V4L2_MEMORY_OVERLAY:
268         default:
269                 dev_dbg(q->dev, "%s memory method OVERLAY/unknown\n", __func__);
270                 return -EINVAL;
271         }
272
273         return 0;
274 }
275
276 static int __videobuf_mmap_mapper(struct videobuf_queue *q,
277                                   struct videobuf_buffer *buf,
278                                   struct vm_area_struct *vma)
279 {
280         struct videobuf_dma_contig_memory *mem;
281         struct videobuf_mapping *map;
282         int retval;
283         unsigned long size;
284
285         dev_dbg(q->dev, "%s\n", __func__);
286
287         /* create mapping + update buffer list */
288         map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL);
289         if (!map)
290                 return -ENOMEM;
291
292         buf->map = map;
293         map->q = q;
294
295         buf->baddr = vma->vm_start;
296
297         mem = buf->priv;
298         BUG_ON(!mem);
299         MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
300
301         if (__videobuf_dc_alloc(q->dev, mem, PAGE_ALIGN(buf->bsize),
302                                 GFP_KERNEL | __GFP_COMP))
303                 goto error;
304
305         /* Try to remap memory */
306
307         size = vma->vm_end - vma->vm_start;
308         size = (size < mem->size) ? size : mem->size;
309
310         vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
311         retval = remap_pfn_range(vma, vma->vm_start,
312                                  mem->dma_handle >> PAGE_SHIFT,
313                                  size, vma->vm_page_prot);
314         if (retval) {
315                 dev_err(q->dev, "mmap: remap failed with error %d. ",
316                         retval);
317                 dma_free_coherent(q->dev, mem->size,
318                                   mem->vaddr, mem->dma_handle);
319                 goto error;
320         }
321
322         vma->vm_ops = &videobuf_vm_ops;
323         vma->vm_flags |= VM_DONTEXPAND;
324         vma->vm_private_data = map;
325
326         dev_dbg(q->dev, "mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n",
327                 map, q, vma->vm_start, vma->vm_end,
328                 (long int)buf->bsize, vma->vm_pgoff, buf->i);
329
330         videobuf_vm_open(vma);
331
332         return 0;
333
334 error:
335         kfree(map);
336         return -ENOMEM;
337 }
338
339 static struct videobuf_qtype_ops qops = {
340         .magic          = MAGIC_QTYPE_OPS,
341         .alloc_vb       = __videobuf_alloc,
342         .iolock         = __videobuf_iolock,
343         .mmap_mapper    = __videobuf_mmap_mapper,
344         .vaddr          = __videobuf_to_vaddr,
345 };
346
347 void videobuf_queue_dma_contig_init(struct videobuf_queue *q,
348                                     const struct videobuf_queue_ops *ops,
349                                     struct device *dev,
350                                     spinlock_t *irqlock,
351                                     enum v4l2_buf_type type,
352                                     enum v4l2_field field,
353                                     unsigned int msize,
354                                     void *priv,
355                                     struct mutex *ext_lock)
356 {
357         videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize,
358                                  priv, &qops, ext_lock);
359 }
360 EXPORT_SYMBOL_GPL(videobuf_queue_dma_contig_init);
361
362 dma_addr_t videobuf_to_dma_contig(struct videobuf_buffer *buf)
363 {
364         struct videobuf_dma_contig_memory *mem = buf->priv;
365
366         BUG_ON(!mem);
367         MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
368
369         return mem->dma_handle;
370 }
371 EXPORT_SYMBOL_GPL(videobuf_to_dma_contig);
372
373 void videobuf_dma_contig_free(struct videobuf_queue *q,
374                               struct videobuf_buffer *buf)
375 {
376         struct videobuf_dma_contig_memory *mem = buf->priv;
377
378         /* mmapped memory can't be freed here, otherwise mmapped region
379            would be released, while still needed. In this case, the memory
380            release should happen inside videobuf_vm_close().
381            So, it should free memory only if the memory were allocated for
382            read() operation.
383          */
384         if (buf->memory != V4L2_MEMORY_USERPTR)
385                 return;
386
387         if (!mem)
388                 return;
389
390         MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
391
392         /* handle user space pointer case */
393         if (buf->baddr) {
394                 videobuf_dma_contig_user_put(mem);
395                 return;
396         }
397
398         /* read() method */
399         if (mem->vaddr) {
400                 __videobuf_dc_free(q->dev, mem);
401                 mem->vaddr = NULL;
402         }
403 }
404 EXPORT_SYMBOL_GPL(videobuf_dma_contig_free);
405
406 MODULE_DESCRIPTION("helper module to manage video4linux dma contig buffers");
407 MODULE_AUTHOR("Magnus Damm");
408 MODULE_LICENSE("GPL");