aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/videobuf-dma-contig.c199
-rw-r--r--include/media/videobuf-dma-contig.h10
2 files changed, 159 insertions, 50 deletions
diff --git a/drivers/media/video/videobuf-dma-contig.c b/drivers/media/video/videobuf-dma-contig.c
index c9691115f2d2..b6b5cc1a43cb 100644
--- a/drivers/media/video/videobuf-dma-contig.c
+++ b/drivers/media/video/videobuf-dma-contig.c
@@ -27,6 +27,7 @@ struct videobuf_dma_contig_memory {
27 u32 magic; 27 u32 magic;
28 void *vaddr; 28 void *vaddr;
29 dma_addr_t dma_handle; 29 dma_addr_t dma_handle;
30 bool cached;
30 unsigned long size; 31 unsigned long size;
31}; 32};
32 33
@@ -37,8 +38,58 @@ struct videobuf_dma_contig_memory {
37 BUG(); \ 38 BUG(); \
38 } 39 }
39 40
40static void 41static int __videobuf_dc_alloc(struct device *dev,
41videobuf_vm_open(struct vm_area_struct *vma) 42 struct videobuf_dma_contig_memory *mem,
43 unsigned long size, unsigned long flags)
44{
45 mem->size = size;
46 if (mem->cached) {
47 mem->vaddr = alloc_pages_exact(mem->size, flags | GFP_DMA);
48 if (mem->vaddr) {
49 int err;
50
51 mem->dma_handle = dma_map_single(dev, mem->vaddr,
52 mem->size,
53 DMA_FROM_DEVICE);
54 err = dma_mapping_error(dev, mem->dma_handle);
55 if (err) {
56 dev_err(dev, "dma_map_single failed\n");
57
58 free_pages_exact(mem->vaddr, mem->size);
59 mem->vaddr = 0;
60 return err;
61 }
62 }
63 } else
64 mem->vaddr = dma_alloc_coherent(dev, mem->size,
65 &mem->dma_handle, flags);
66
67 if (!mem->vaddr) {
68 dev_err(dev, "memory alloc size %ld failed\n", mem->size);
69 return -ENOMEM;
70 }
71
72 dev_dbg(dev, "dma mapped data is at %p (%ld)\n", mem->vaddr, mem->size);
73
74 return 0;
75}
76
77static void __videobuf_dc_free(struct device *dev,
78 struct videobuf_dma_contig_memory *mem)
79{
80 if (mem->cached) {
81 if (!mem->vaddr)
82 return;
83 dma_unmap_single(dev, mem->dma_handle, mem->size,
84 DMA_FROM_DEVICE);
85 free_pages_exact(mem->vaddr, mem->size);
86 } else
87 dma_free_coherent(dev, mem->size, mem->vaddr, mem->dma_handle);
88
89 mem->vaddr = NULL;
90}
91
92static void videobuf_vm_open(struct vm_area_struct *vma)
42{ 93{
43 struct videobuf_mapping *map = vma->vm_private_data; 94 struct videobuf_mapping *map = vma->vm_private_data;
44 95
@@ -91,12 +142,11 @@ static void videobuf_vm_close(struct vm_area_struct *vma)
91 dev_dbg(q->dev, "buf[%d] freeing %p\n", 142 dev_dbg(q->dev, "buf[%d] freeing %p\n",
92 i, mem->vaddr); 143 i, mem->vaddr);
93 144
94 dma_free_coherent(q->dev, mem->size, 145 __videobuf_dc_free(q->dev, mem);
95 mem->vaddr, mem->dma_handle);
96 mem->vaddr = NULL; 146 mem->vaddr = NULL;
97 } 147 }
98 148
99 q->bufs[i]->map = NULL; 149 q->bufs[i]->map = NULL;
100 q->bufs[i]->baddr = 0; 150 q->bufs[i]->baddr = 0;
101 } 151 }
102 152
@@ -107,8 +157,8 @@ static void videobuf_vm_close(struct vm_area_struct *vma)
107} 157}
108 158
109static const struct vm_operations_struct videobuf_vm_ops = { 159static const struct vm_operations_struct videobuf_vm_ops = {
110 .open = videobuf_vm_open, 160 .open = videobuf_vm_open,
111 .close = videobuf_vm_close, 161 .close = videobuf_vm_close,
112}; 162};
113 163
114/** 164/**
@@ -178,26 +228,38 @@ static int videobuf_dma_contig_user_get(struct videobuf_dma_contig_memory *mem,
178 pages_done++; 228 pages_done++;
179 } 229 }
180 230
181 out_up: 231out_up:
182 up_read(&current->mm->mmap_sem); 232 up_read(&current->mm->mmap_sem);
183 233
184 return ret; 234 return ret;
185} 235}
186 236
187static struct videobuf_buffer *__videobuf_alloc_vb(size_t size) 237static struct videobuf_buffer *__videobuf_alloc_vb(size_t size, bool cached)
188{ 238{
189 struct videobuf_dma_contig_memory *mem; 239 struct videobuf_dma_contig_memory *mem;
190 struct videobuf_buffer *vb; 240 struct videobuf_buffer *vb;
191 241
192 vb = kzalloc(size + sizeof(*mem), GFP_KERNEL); 242 vb = kzalloc(size + sizeof(*mem), GFP_KERNEL);
193 if (vb) { 243 if (vb) {
194 mem = vb->priv = ((char *)vb) + size; 244 vb->priv = ((char *)vb) + size;
245 mem = vb->priv;
195 mem->magic = MAGIC_DC_MEM; 246 mem->magic = MAGIC_DC_MEM;
247 mem->cached = cached;
196 } 248 }
197 249
198 return vb; 250 return vb;
199} 251}
200 252
253static struct videobuf_buffer *__videobuf_alloc_uncached(size_t size)
254{
255 return __videobuf_alloc_vb(size, false);
256}
257
258static struct videobuf_buffer *__videobuf_alloc_cached(size_t size)
259{
260 return __videobuf_alloc_vb(size, true);
261}
262
201static void *__videobuf_to_vaddr(struct videobuf_buffer *buf) 263static void *__videobuf_to_vaddr(struct videobuf_buffer *buf)
202{ 264{
203 struct videobuf_dma_contig_memory *mem = buf->priv; 265 struct videobuf_dma_contig_memory *mem = buf->priv;
@@ -235,28 +297,32 @@ static int __videobuf_iolock(struct videobuf_queue *q,
235 return videobuf_dma_contig_user_get(mem, vb); 297 return videobuf_dma_contig_user_get(mem, vb);
236 298
237 /* allocate memory for the read() method */ 299 /* allocate memory for the read() method */
238 mem->size = PAGE_ALIGN(vb->size); 300 if (__videobuf_dc_alloc(q->dev, mem, PAGE_ALIGN(vb->size),
239 mem->vaddr = dma_alloc_coherent(q->dev, mem->size, 301 GFP_KERNEL))
240 &mem->dma_handle, GFP_KERNEL);
241 if (!mem->vaddr) {
242 dev_err(q->dev, "dma_alloc_coherent %ld failed\n",
243 mem->size);
244 return -ENOMEM; 302 return -ENOMEM;
245 }
246
247 dev_dbg(q->dev, "dma_alloc_coherent data is at %p (%ld)\n",
248 mem->vaddr, mem->size);
249 break; 303 break;
250 case V4L2_MEMORY_OVERLAY: 304 case V4L2_MEMORY_OVERLAY:
251 default: 305 default:
252 dev_dbg(q->dev, "%s memory method OVERLAY/unknown\n", 306 dev_dbg(q->dev, "%s memory method OVERLAY/unknown\n", __func__);
253 __func__);
254 return -EINVAL; 307 return -EINVAL;
255 } 308 }
256 309
257 return 0; 310 return 0;
258} 311}
259 312
313static int __videobuf_sync(struct videobuf_queue *q,
314 struct videobuf_buffer *buf)
315{
316 struct videobuf_dma_contig_memory *mem = buf->priv;
317 BUG_ON(!mem);
318 MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
319
320 dma_sync_single_for_cpu(q->dev, mem->dma_handle, mem->size,
321 DMA_FROM_DEVICE);
322
323 return 0;
324}
325
260static int __videobuf_mmap_mapper(struct videobuf_queue *q, 326static int __videobuf_mmap_mapper(struct videobuf_queue *q,
261 struct videobuf_buffer *buf, 327 struct videobuf_buffer *buf,
262 struct vm_area_struct *vma) 328 struct vm_area_struct *vma)
@@ -265,6 +331,8 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
265 struct videobuf_mapping *map; 331 struct videobuf_mapping *map;
266 int retval; 332 int retval;
267 unsigned long size; 333 unsigned long size;
334 unsigned long pos, start = vma->vm_start;
335 struct page *page;
268 336
269 dev_dbg(q->dev, "%s\n", __func__); 337 dev_dbg(q->dev, "%s\n", __func__);
270 338
@@ -282,41 +350,50 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
282 BUG_ON(!mem); 350 BUG_ON(!mem);
283 MAGIC_CHECK(mem->magic, MAGIC_DC_MEM); 351 MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
284 352
285 mem->size = PAGE_ALIGN(buf->bsize); 353 if (__videobuf_dc_alloc(q->dev, mem, PAGE_ALIGN(buf->bsize),
286 mem->vaddr = dma_alloc_coherent(q->dev, mem->size, 354 GFP_KERNEL | __GFP_COMP))
287 &mem->dma_handle, GFP_KERNEL);
288 if (!mem->vaddr) {
289 dev_err(q->dev, "dma_alloc_coherent size %ld failed\n",
290 mem->size);
291 goto error; 355 goto error;
292 }
293 dev_dbg(q->dev, "dma_alloc_coherent data is at addr %p (size %ld)\n",
294 mem->vaddr, mem->size);
295 356
296 /* Try to remap memory */ 357 /* Try to remap memory */
297 358
298 size = vma->vm_end - vma->vm_start; 359 size = vma->vm_end - vma->vm_start;
299 size = (size < mem->size) ? size : mem->size; 360 size = (size < mem->size) ? size : mem->size;
300 361
301 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); 362 if (!mem->cached)
302 retval = remap_pfn_range(vma, vma->vm_start, 363 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
303 mem->dma_handle >> PAGE_SHIFT, 364
304 size, vma->vm_page_prot); 365 pos = (unsigned long)mem->vaddr;
305 if (retval) { 366
306 dev_err(q->dev, "mmap: remap failed with error %d. ", retval); 367 while (size > 0) {
307 dma_free_coherent(q->dev, mem->size, 368 page = virt_to_page((void *)pos);
308 mem->vaddr, mem->dma_handle); 369 if (NULL == page) {
309 goto error; 370 dev_err(q->dev, "mmap: virt_to_page failed\n");
371 __videobuf_dc_free(q->dev, mem);
372 goto error;
373 }
374 retval = vm_insert_page(vma, start, page);
375 if (retval) {
376 dev_err(q->dev, "mmap: insert failed with error %d\n",
377 retval);
378 __videobuf_dc_free(q->dev, mem);
379 goto error;
380 }
381 start += PAGE_SIZE;
382 pos += PAGE_SIZE;
383
384 if (size > PAGE_SIZE)
385 size -= PAGE_SIZE;
386 else
387 size = 0;
310 } 388 }
311 389
312 vma->vm_ops = &videobuf_vm_ops; 390 vma->vm_ops = &videobuf_vm_ops;
313 vma->vm_flags |= VM_DONTEXPAND; 391 vma->vm_flags |= VM_DONTEXPAND;
314 vma->vm_private_data = map; 392 vma->vm_private_data = map;
315 393
316 dev_dbg(q->dev, "mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n", 394 dev_dbg(q->dev, "mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n",
317 map, q, vma->vm_start, vma->vm_end, 395 map, q, vma->vm_start, vma->vm_end,
318 (long int)buf->bsize, 396 (long int)buf->bsize, vma->vm_pgoff, buf->i);
319 vma->vm_pgoff, buf->i);
320 397
321 videobuf_vm_open(vma); 398 videobuf_vm_open(vma);
322 399
@@ -328,12 +405,20 @@ error:
328} 405}
329 406
330static struct videobuf_qtype_ops qops = { 407static struct videobuf_qtype_ops qops = {
331 .magic = MAGIC_QTYPE_OPS, 408 .magic = MAGIC_QTYPE_OPS,
409 .alloc_vb = __videobuf_alloc_uncached,
410 .iolock = __videobuf_iolock,
411 .mmap_mapper = __videobuf_mmap_mapper,
412 .vaddr = __videobuf_to_vaddr,
413};
332 414
333 .alloc_vb = __videobuf_alloc_vb, 415static struct videobuf_qtype_ops qops_cached = {
334 .iolock = __videobuf_iolock, 416 .magic = MAGIC_QTYPE_OPS,
335 .mmap_mapper = __videobuf_mmap_mapper, 417 .alloc_vb = __videobuf_alloc_cached,
336 .vaddr = __videobuf_to_vaddr, 418 .iolock = __videobuf_iolock,
419 .sync = __videobuf_sync,
420 .mmap_mapper = __videobuf_mmap_mapper,
421 .vaddr = __videobuf_to_vaddr,
337}; 422};
338 423
339void videobuf_queue_dma_contig_init(struct videobuf_queue *q, 424void videobuf_queue_dma_contig_init(struct videobuf_queue *q,
@@ -351,6 +436,20 @@ void videobuf_queue_dma_contig_init(struct videobuf_queue *q,
351} 436}
352EXPORT_SYMBOL_GPL(videobuf_queue_dma_contig_init); 437EXPORT_SYMBOL_GPL(videobuf_queue_dma_contig_init);
353 438
439void videobuf_queue_dma_contig_init_cached(struct videobuf_queue *q,
440 const struct videobuf_queue_ops *ops,
441 struct device *dev,
442 spinlock_t *irqlock,
443 enum v4l2_buf_type type,
444 enum v4l2_field field,
445 unsigned int msize,
446 void *priv, struct mutex *ext_lock)
447{
448 videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize,
449 priv, &qops_cached, ext_lock);
450}
451EXPORT_SYMBOL_GPL(videobuf_queue_dma_contig_init_cached);
452
354dma_addr_t videobuf_to_dma_contig(struct videobuf_buffer *buf) 453dma_addr_t videobuf_to_dma_contig(struct videobuf_buffer *buf)
355{ 454{
356 struct videobuf_dma_contig_memory *mem = buf->priv; 455 struct videobuf_dma_contig_memory *mem = buf->priv;
@@ -389,7 +488,7 @@ void videobuf_dma_contig_free(struct videobuf_queue *q,
389 488
390 /* read() method */ 489 /* read() method */
391 if (mem->vaddr) { 490 if (mem->vaddr) {
392 dma_free_coherent(q->dev, mem->size, mem->vaddr, mem->dma_handle); 491 __videobuf_dc_free(q->dev, mem);
393 mem->vaddr = NULL; 492 mem->vaddr = NULL;
394 } 493 }
395} 494}
diff --git a/include/media/videobuf-dma-contig.h b/include/media/videobuf-dma-contig.h
index f0ed82543d9f..f473aeb86d3f 100644
--- a/include/media/videobuf-dma-contig.h
+++ b/include/media/videobuf-dma-contig.h
@@ -26,6 +26,16 @@ void videobuf_queue_dma_contig_init(struct videobuf_queue *q,
26 void *priv, 26 void *priv,
27 struct mutex *ext_lock); 27 struct mutex *ext_lock);
28 28
29void videobuf_queue_dma_contig_init_cached(struct videobuf_queue *q,
30 const struct videobuf_queue_ops *ops,
31 struct device *dev,
32 spinlock_t *irqlock,
33 enum v4l2_buf_type type,
34 enum v4l2_field field,
35 unsigned int msize,
36 void *priv,
37 struct mutex *ext_lock);
38
29dma_addr_t videobuf_to_dma_contig(struct videobuf_buffer *buf); 39dma_addr_t videobuf_to_dma_contig(struct videobuf_buffer *buf);
30void videobuf_dma_contig_free(struct videobuf_queue *q, 40void videobuf_dma_contig_free(struct videobuf_queue *q,
31 struct videobuf_buffer *buf); 41 struct videobuf_buffer *buf);