of/device: add helper to get cpu device node from logical cpu index
[linux-2.6.git] / drivers / media / v4l2-core / videobuf-vmalloc.c
blob1365c651c1777bd5f7973281f26baccdad6c8995
1 /*
2 * helper functions for vmalloc video4linux capture buffers
4 * The functions expect the hardware being able to scatter gather
5 * (i.e. the buffers are not linear in physical memory, but fragmented
6 * into PAGE_SIZE chunks). They also assume the driver does not need
7 * to touch the video data.
9 * (c) 2007 Mauro Carvalho Chehab, <mchehab@infradead.org>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2
16 #include <linux/init.h>
17 #include <linux/module.h>
18 #include <linux/moduleparam.h>
19 #include <linux/slab.h>
20 #include <linux/interrupt.h>
22 #include <linux/pci.h>
23 #include <linux/vmalloc.h>
24 #include <linux/pagemap.h>
25 #include <asm/page.h>
26 #include <asm/pgtable.h>
28 #include <media/videobuf-vmalloc.h>
30 #define MAGIC_DMABUF 0x17760309
31 #define MAGIC_VMAL_MEM 0x18221223
33 #define MAGIC_CHECK(is, should) \
34 if (unlikely((is) != (should))) { \
35 printk(KERN_ERR "magic mismatch: %x (expected %x)\n", \
36 is, should); \
37 BUG(); \
40 static int debug;
41 module_param(debug, int, 0644);
43 MODULE_DESCRIPTION("helper module to manage video4linux vmalloc buffers");
44 MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
45 MODULE_LICENSE("GPL");
47 #define dprintk(level, fmt, arg...) \
48 if (debug >= level) \
49 printk(KERN_DEBUG "vbuf-vmalloc: " fmt , ## arg)
52 /***************************************************************************/
54 static void videobuf_vm_open(struct vm_area_struct *vma)
56 struct videobuf_mapping *map = vma->vm_private_data;
57 struct videobuf_queue *q = map->q;
59 dprintk(2, "vm_open %p [count=%u,vma=%08lx-%08lx]\n", map,
60 map->count, vma->vm_start, vma->vm_end);
62 videobuf_queue_lock(q);
63 map->count++;
64 videobuf_queue_unlock(q);
67 static void videobuf_vm_close(struct vm_area_struct *vma)
69 struct videobuf_mapping *map = vma->vm_private_data;
70 struct videobuf_queue *q = map->q;
71 int i;
73 dprintk(2, "vm_close %p [count=%u,vma=%08lx-%08lx]\n", map,
74 map->count, vma->vm_start, vma->vm_end);
76 videobuf_queue_lock(q);
77 if (!--map->count) {
78 struct videobuf_vmalloc_memory *mem;
80 dprintk(1, "munmap %p q=%p\n", map, q);
82 /* We need first to cancel streams, before unmapping */
83 if (q->streaming)
84 videobuf_queue_cancel(q);
86 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
87 if (NULL == q->bufs[i])
88 continue;
90 if (q->bufs[i]->map != map)
91 continue;
93 mem = q->bufs[i]->priv;
94 if (mem) {
95 /* This callback is called only if kernel has
96 allocated memory and this memory is mmapped.
97 In this case, memory should be freed,
98 in order to do memory unmap.
101 MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
103 /* vfree is not atomic - can't be
104 called with IRQ's disabled
106 dprintk(1, "%s: buf[%d] freeing (%p)\n",
107 __func__, i, mem->vaddr);
109 vfree(mem->vaddr);
110 mem->vaddr = NULL;
113 q->bufs[i]->map = NULL;
114 q->bufs[i]->baddr = 0;
117 kfree(map);
120 videobuf_queue_unlock(q);
122 return;
125 static const struct vm_operations_struct videobuf_vm_ops = {
126 .open = videobuf_vm_open,
127 .close = videobuf_vm_close,
130 /* ---------------------------------------------------------------------
131 * vmalloc handlers for the generic methods
134 /* Allocated area consists on 3 parts:
135 struct video_buffer
136 struct <driver>_buffer (cx88_buffer, saa7134_buf, ...)
137 struct videobuf_dma_sg_memory
140 static struct videobuf_buffer *__videobuf_alloc_vb(size_t size)
142 struct videobuf_vmalloc_memory *mem;
143 struct videobuf_buffer *vb;
145 vb = kzalloc(size + sizeof(*mem), GFP_KERNEL);
146 if (!vb)
147 return vb;
149 mem = vb->priv = ((char *)vb) + size;
150 mem->magic = MAGIC_VMAL_MEM;
152 dprintk(1, "%s: allocated at %p(%ld+%ld) & %p(%ld)\n",
153 __func__, vb, (long)sizeof(*vb), (long)size - sizeof(*vb),
154 mem, (long)sizeof(*mem));
156 return vb;
159 static int __videobuf_iolock(struct videobuf_queue *q,
160 struct videobuf_buffer *vb,
161 struct v4l2_framebuffer *fbuf)
163 struct videobuf_vmalloc_memory *mem = vb->priv;
164 int pages;
166 BUG_ON(!mem);
168 MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
170 switch (vb->memory) {
171 case V4L2_MEMORY_MMAP:
172 dprintk(1, "%s memory method MMAP\n", __func__);
174 /* All handling should be done by __videobuf_mmap_mapper() */
175 if (!mem->vaddr) {
176 printk(KERN_ERR "memory is not alloced/mmapped.\n");
177 return -EINVAL;
179 break;
180 case V4L2_MEMORY_USERPTR:
181 pages = PAGE_ALIGN(vb->size);
183 dprintk(1, "%s memory method USERPTR\n", __func__);
185 if (vb->baddr) {
186 printk(KERN_ERR "USERPTR is currently not supported\n");
187 return -EINVAL;
190 /* The only USERPTR currently supported is the one needed for
191 * read() method.
194 mem->vaddr = vmalloc_user(pages);
195 if (!mem->vaddr) {
196 printk(KERN_ERR "vmalloc (%d pages) failed\n", pages);
197 return -ENOMEM;
199 dprintk(1, "vmalloc is at addr %p (%d pages)\n",
200 mem->vaddr, pages);
202 #if 0
203 int rc;
204 /* Kernel userptr is used also by read() method. In this case,
205 there's no need to remap, since data will be copied to user
207 if (!vb->baddr)
208 return 0;
210 /* FIXME: to properly support USERPTR, remap should occur.
211 The code below won't work, since mem->vma = NULL
213 /* Try to remap memory */
214 rc = remap_vmalloc_range(mem->vma, (void *)vb->baddr, 0);
215 if (rc < 0) {
216 printk(KERN_ERR "mmap: remap failed with error %d", rc);
217 return -ENOMEM;
219 #endif
221 break;
222 case V4L2_MEMORY_OVERLAY:
223 default:
224 dprintk(1, "%s memory method OVERLAY/unknown\n", __func__);
226 /* Currently, doesn't support V4L2_MEMORY_OVERLAY */
227 printk(KERN_ERR "Memory method currently unsupported.\n");
228 return -EINVAL;
231 return 0;
234 static int __videobuf_mmap_mapper(struct videobuf_queue *q,
235 struct videobuf_buffer *buf,
236 struct vm_area_struct *vma)
238 struct videobuf_vmalloc_memory *mem;
239 struct videobuf_mapping *map;
240 int retval, pages;
242 dprintk(1, "%s\n", __func__);
244 /* create mapping + update buffer list */
245 map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL);
246 if (NULL == map)
247 return -ENOMEM;
249 buf->map = map;
250 map->q = q;
252 buf->baddr = vma->vm_start;
254 mem = buf->priv;
255 BUG_ON(!mem);
256 MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
258 pages = PAGE_ALIGN(vma->vm_end - vma->vm_start);
259 mem->vaddr = vmalloc_user(pages);
260 if (!mem->vaddr) {
261 printk(KERN_ERR "vmalloc (%d pages) failed\n", pages);
262 goto error;
264 dprintk(1, "vmalloc is at addr %p (%d pages)\n", mem->vaddr, pages);
266 /* Try to remap memory */
267 retval = remap_vmalloc_range(vma, mem->vaddr, 0);
268 if (retval < 0) {
269 printk(KERN_ERR "mmap: remap failed with error %d. ", retval);
270 vfree(mem->vaddr);
271 goto error;
274 vma->vm_ops = &videobuf_vm_ops;
275 vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
276 vma->vm_private_data = map;
278 dprintk(1, "mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n",
279 map, q, vma->vm_start, vma->vm_end,
280 (long int)buf->bsize,
281 vma->vm_pgoff, buf->i);
283 videobuf_vm_open(vma);
285 return 0;
287 error:
288 mem = NULL;
289 kfree(map);
290 return -ENOMEM;
293 static struct videobuf_qtype_ops qops = {
294 .magic = MAGIC_QTYPE_OPS,
296 .alloc_vb = __videobuf_alloc_vb,
297 .iolock = __videobuf_iolock,
298 .mmap_mapper = __videobuf_mmap_mapper,
299 .vaddr = videobuf_to_vmalloc,
302 void videobuf_queue_vmalloc_init(struct videobuf_queue *q,
303 const struct videobuf_queue_ops *ops,
304 struct device *dev,
305 spinlock_t *irqlock,
306 enum v4l2_buf_type type,
307 enum v4l2_field field,
308 unsigned int msize,
309 void *priv,
310 struct mutex *ext_lock)
312 videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize,
313 priv, &qops, ext_lock);
315 EXPORT_SYMBOL_GPL(videobuf_queue_vmalloc_init);
317 void *videobuf_to_vmalloc(struct videobuf_buffer *buf)
319 struct videobuf_vmalloc_memory *mem = buf->priv;
320 BUG_ON(!mem);
321 MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
323 return mem->vaddr;
325 EXPORT_SYMBOL_GPL(videobuf_to_vmalloc);
327 void videobuf_vmalloc_free(struct videobuf_buffer *buf)
329 struct videobuf_vmalloc_memory *mem = buf->priv;
331 /* mmapped memory can't be freed here, otherwise mmapped region
332 would be released, while still needed. In this case, the memory
333 release should happen inside videobuf_vm_close().
334 So, it should free memory only if the memory were allocated for
335 read() operation.
337 if ((buf->memory != V4L2_MEMORY_USERPTR) || buf->baddr)
338 return;
340 if (!mem)
341 return;
343 MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
345 vfree(mem->vaddr);
346 mem->vaddr = NULL;
348 return;
350 EXPORT_SYMBOL_GPL(videobuf_vmalloc_free);