2 * helper functions for physically contiguous capture buffers
4 * The functions support hardware lacking scatter gather support
5 * (i.e. the buffers must be linear in physical memory)
7 * Copyright (c) 2008 Magnus Damm
9 * Based on videobuf-vmalloc.c,
10 * (c) 2007 Mauro Carvalho Chehab, <mchehab@infradead.org>
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
17 #include <linux/init.h>
18 #include <linux/module.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>
26 struct videobuf_dma_contig_memory
{
29 dma_addr_t dma_handle
;
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)); \
40 static int __videobuf_dc_alloc(struct device
*dev
,
41 struct videobuf_dma_contig_memory
*mem
,
42 unsigned long size
, gfp_t flags
)
45 mem
->vaddr
= dma_alloc_coherent(dev
, mem
->size
,
46 &mem
->dma_handle
, flags
);
49 dev_err(dev
, "memory alloc size %ld failed\n", mem
->size
);
53 dev_dbg(dev
, "dma mapped data is at %p (%ld)\n", mem
->vaddr
, mem
->size
);
58 static void __videobuf_dc_free(struct device
*dev
,
59 struct videobuf_dma_contig_memory
*mem
)
61 dma_free_coherent(dev
, mem
->size
, mem
->vaddr
, mem
->dma_handle
);
66 static void videobuf_vm_open(struct vm_area_struct
*vma
)
68 struct videobuf_mapping
*map
= vma
->vm_private_data
;
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
);
76 static void videobuf_vm_close(struct vm_area_struct
*vma
)
78 struct videobuf_mapping
*map
= vma
->vm_private_data
;
79 struct videobuf_queue
*q
= map
->q
;
82 dev_dbg(q
->dev
, "vm_close %p [count=%u,vma=%08lx-%08lx]\n",
83 map
, map
->count
, vma
->vm_start
, vma
->vm_end
);
86 if (0 == map
->count
) {
87 struct videobuf_dma_contig_memory
*mem
;
89 dev_dbg(q
->dev
, "munmap %p q=%p\n", map
, q
);
90 videobuf_queue_lock(q
);
92 /* We need first to cancel streams, before unmapping */
94 videobuf_queue_cancel(q
);
96 for (i
= 0; i
< VIDEO_MAX_FRAME
; i
++) {
97 if (NULL
== q
->bufs
[i
])
100 if (q
->bufs
[i
]->map
!= map
)
103 mem
= q
->bufs
[i
]->priv
;
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.
111 MAGIC_CHECK(mem
->magic
, MAGIC_DC_MEM
);
113 /* vfree is not atomic - can't be
114 called with IRQ's disabled
116 dev_dbg(q
->dev
, "buf[%d] freeing %p\n",
119 __videobuf_dc_free(q
->dev
, mem
);
123 q
->bufs
[i
]->map
= NULL
;
124 q
->bufs
[i
]->baddr
= 0;
129 videobuf_queue_unlock(q
);
133 static const struct vm_operations_struct videobuf_vm_ops
= {
134 .open
= videobuf_vm_open
,
135 .close
= videobuf_vm_close
,
139 * videobuf_dma_contig_user_put() - reset pointer to user space buffer
140 * @mem: per-buffer private videobuf-dma-contig data
142 * This function resets the user space pointer
144 static void videobuf_dma_contig_user_put(struct videobuf_dma_contig_memory
*mem
)
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
155 * This function validates and sets up a pointer to user space memory.
156 * Only physically contiguous pfn-mapped memory is accepted.
158 * Returns 0 if successful.
160 static int videobuf_dma_contig_user_get(struct videobuf_dma_contig_memory
*mem
,
161 struct videobuf_buffer
*vb
)
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
;
170 offset
= vb
->baddr
& ~PAGE_MASK
;
171 mem
->size
= PAGE_ALIGN(vb
->size
+ offset
);
174 down_read(&mm
->mmap_sem
);
176 vma
= find_vma(mm
, vb
->baddr
);
180 if ((vb
->baddr
+ mem
->size
) > vma
->vm_end
)
184 prev_pfn
= 0; /* kill warning */
185 user_address
= vb
->baddr
;
187 while (pages_done
< (mem
->size
>> PAGE_SHIFT
)) {
188 ret
= follow_pfn(vma
, user_address
, &this_pfn
);
193 mem
->dma_handle
= (this_pfn
<< PAGE_SHIFT
) + offset
;
194 else if (this_pfn
!= (prev_pfn
+ 1))
201 user_address
+= PAGE_SIZE
;
206 up_read(¤t
->mm
->mmap_sem
);
211 static struct videobuf_buffer
*__videobuf_alloc(size_t size
)
213 struct videobuf_dma_contig_memory
*mem
;
214 struct videobuf_buffer
*vb
;
216 vb
= kzalloc(size
+ sizeof(*mem
), GFP_KERNEL
);
218 vb
->priv
= ((char *)vb
) + size
;
220 mem
->magic
= MAGIC_DC_MEM
;
226 static void *__videobuf_to_vaddr(struct videobuf_buffer
*buf
)
228 struct videobuf_dma_contig_memory
*mem
= buf
->priv
;
231 MAGIC_CHECK(mem
->magic
, MAGIC_DC_MEM
);
236 static int __videobuf_iolock(struct videobuf_queue
*q
,
237 struct videobuf_buffer
*vb
,
238 struct v4l2_framebuffer
*fbuf
)
240 struct videobuf_dma_contig_memory
*mem
= vb
->priv
;
243 MAGIC_CHECK(mem
->magic
, MAGIC_DC_MEM
);
245 switch (vb
->memory
) {
246 case V4L2_MEMORY_MMAP
:
247 dev_dbg(q
->dev
, "%s memory method MMAP\n", __func__
);
249 /* All handling should be done by __videobuf_mmap_mapper() */
251 dev_err(q
->dev
, "memory is not alloced/mmapped.\n");
255 case V4L2_MEMORY_USERPTR
:
256 dev_dbg(q
->dev
, "%s memory method USERPTR\n", __func__
);
258 /* handle pointer from user space */
260 return videobuf_dma_contig_user_get(mem
, vb
);
262 /* allocate memory for the read() method */
263 if (__videobuf_dc_alloc(q
->dev
, mem
, PAGE_ALIGN(vb
->size
),
267 case V4L2_MEMORY_OVERLAY
:
269 dev_dbg(q
->dev
, "%s memory method OVERLAY/unknown\n", __func__
);
276 static int __videobuf_mmap_mapper(struct videobuf_queue
*q
,
277 struct videobuf_buffer
*buf
,
278 struct vm_area_struct
*vma
)
280 struct videobuf_dma_contig_memory
*mem
;
281 struct videobuf_mapping
*map
;
285 dev_dbg(q
->dev
, "%s\n", __func__
);
287 /* create mapping + update buffer list */
288 map
= kzalloc(sizeof(struct videobuf_mapping
), GFP_KERNEL
);
295 buf
->baddr
= vma
->vm_start
;
299 MAGIC_CHECK(mem
->magic
, MAGIC_DC_MEM
);
301 if (__videobuf_dc_alloc(q
->dev
, mem
, PAGE_ALIGN(buf
->bsize
),
302 GFP_KERNEL
| __GFP_COMP
))
305 /* Try to remap memory */
306 size
= vma
->vm_end
- vma
->vm_start
;
307 vma
->vm_page_prot
= pgprot_noncached(vma
->vm_page_prot
);
308 retval
= vm_iomap_memory(vma
, vma
->vm_start
, size
);
310 dev_err(q
->dev
, "mmap: remap failed with error %d. ",
312 dma_free_coherent(q
->dev
, mem
->size
,
313 mem
->vaddr
, mem
->dma_handle
);
317 vma
->vm_ops
= &videobuf_vm_ops
;
318 vma
->vm_flags
|= VM_DONTEXPAND
;
319 vma
->vm_private_data
= map
;
321 dev_dbg(q
->dev
, "mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n",
322 map
, q
, vma
->vm_start
, vma
->vm_end
,
323 (long int)buf
->bsize
, vma
->vm_pgoff
, buf
->i
);
325 videobuf_vm_open(vma
);
334 static struct videobuf_qtype_ops qops
= {
335 .magic
= MAGIC_QTYPE_OPS
,
336 .alloc_vb
= __videobuf_alloc
,
337 .iolock
= __videobuf_iolock
,
338 .mmap_mapper
= __videobuf_mmap_mapper
,
339 .vaddr
= __videobuf_to_vaddr
,
342 void videobuf_queue_dma_contig_init(struct videobuf_queue
*q
,
343 const struct videobuf_queue_ops
*ops
,
346 enum v4l2_buf_type type
,
347 enum v4l2_field field
,
350 struct mutex
*ext_lock
)
352 videobuf_queue_core_init(q
, ops
, dev
, irqlock
, type
, field
, msize
,
353 priv
, &qops
, ext_lock
);
355 EXPORT_SYMBOL_GPL(videobuf_queue_dma_contig_init
);
357 dma_addr_t
videobuf_to_dma_contig(struct videobuf_buffer
*buf
)
359 struct videobuf_dma_contig_memory
*mem
= buf
->priv
;
362 MAGIC_CHECK(mem
->magic
, MAGIC_DC_MEM
);
364 return mem
->dma_handle
;
366 EXPORT_SYMBOL_GPL(videobuf_to_dma_contig
);
368 void videobuf_dma_contig_free(struct videobuf_queue
*q
,
369 struct videobuf_buffer
*buf
)
371 struct videobuf_dma_contig_memory
*mem
= buf
->priv
;
373 /* mmapped memory can't be freed here, otherwise mmapped region
374 would be released, while still needed. In this case, the memory
375 release should happen inside videobuf_vm_close().
376 So, it should free memory only if the memory were allocated for
379 if (buf
->memory
!= V4L2_MEMORY_USERPTR
)
385 MAGIC_CHECK(mem
->magic
, MAGIC_DC_MEM
);
387 /* handle user space pointer case */
389 videobuf_dma_contig_user_put(mem
);
395 __videobuf_dc_free(q
->dev
, mem
);
399 EXPORT_SYMBOL_GPL(videobuf_dma_contig_free
);
401 MODULE_DESCRIPTION("helper module to manage video4linux dma contig buffers");
402 MODULE_AUTHOR("Magnus Damm");
403 MODULE_LICENSE("GPL");