diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2014-01-02 20:12:42 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2014-05-25 10:13:17 -0400 |
commit | 9000427aec61b2ae3766d0f635bf1d60fcb8c41b (patch) | |
tree | e191e5d12f8158c61c6e205c38cf7d753bc7f8a2 /drivers/media/platform | |
parent | 2a6dc96b973c8d1defd39bf21e89e6907b1c72f1 (diff) |
[media] omap3isp: queue: Move IOMMU handling code to the queue
As a preparation for the switch from the OMAP IOMMU API to the DMA API
move all IOMMU handling code from the video node implementation to the
buffers queue implementation.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Sakari Ailus <sakari.ailus@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media/platform')
-rw-r--r-- | drivers/media/platform/omap3isp/ispqueue.c | 78 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/ispqueue.h | 6 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/ispvideo.c | 77 |
3 files changed, 78 insertions, 83 deletions
diff --git a/drivers/media/platform/omap3isp/ispqueue.c b/drivers/media/platform/omap3isp/ispqueue.c index a5e65858e799..8623c058734e 100644 --- a/drivers/media/platform/omap3isp/ispqueue.c +++ b/drivers/media/platform/omap3isp/ispqueue.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <asm/cacheflush.h> | 26 | #include <asm/cacheflush.h> |
27 | #include <linux/dma-mapping.h> | 27 | #include <linux/dma-mapping.h> |
28 | #include <linux/mm.h> | 28 | #include <linux/mm.h> |
29 | #include <linux/omap-iommu.h> | ||
29 | #include <linux/pagemap.h> | 30 | #include <linux/pagemap.h> |
30 | #include <linux/poll.h> | 31 | #include <linux/poll.h> |
31 | #include <linux/scatterlist.h> | 32 | #include <linux/scatterlist.h> |
@@ -33,7 +34,58 @@ | |||
33 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
34 | #include <linux/vmalloc.h> | 35 | #include <linux/vmalloc.h> |
35 | 36 | ||
37 | #include "isp.h" | ||
36 | #include "ispqueue.h" | 38 | #include "ispqueue.h" |
39 | #include "ispvideo.h" | ||
40 | |||
41 | /* ----------------------------------------------------------------------------- | ||
42 | * IOMMU management | ||
43 | */ | ||
44 | |||
45 | #define IOMMU_FLAG (IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_8) | ||
46 | |||
47 | /* | ||
48 | * ispmmu_vmap - Wrapper for Virtual memory mapping of a scatter gather list | ||
49 | * @dev: Device pointer specific to the OMAP3 ISP. | ||
50 | * @sglist: Pointer to source Scatter gather list to allocate. | ||
51 | * @sglen: Number of elements of the scatter-gatter list. | ||
52 | * | ||
53 | * Returns a resulting mapped device address by the ISP MMU, or -ENOMEM if | ||
54 | * we ran out of memory. | ||
55 | */ | ||
56 | static dma_addr_t | ||
57 | ispmmu_vmap(struct isp_device *isp, const struct scatterlist *sglist, int sglen) | ||
58 | { | ||
59 | struct sg_table *sgt; | ||
60 | u32 da; | ||
61 | |||
62 | sgt = kmalloc(sizeof(*sgt), GFP_KERNEL); | ||
63 | if (sgt == NULL) | ||
64 | return -ENOMEM; | ||
65 | |||
66 | sgt->sgl = (struct scatterlist *)sglist; | ||
67 | sgt->nents = sglen; | ||
68 | sgt->orig_nents = sglen; | ||
69 | |||
70 | da = omap_iommu_vmap(isp->domain, isp->dev, 0, sgt, IOMMU_FLAG); | ||
71 | if (IS_ERR_VALUE(da)) | ||
72 | kfree(sgt); | ||
73 | |||
74 | return da; | ||
75 | } | ||
76 | |||
77 | /* | ||
78 | * ispmmu_vunmap - Unmap a device address from the ISP MMU | ||
79 | * @dev: Device pointer specific to the OMAP3 ISP. | ||
80 | * @da: Device address generated from a ispmmu_vmap call. | ||
81 | */ | ||
82 | static void ispmmu_vunmap(struct isp_device *isp, dma_addr_t da) | ||
83 | { | ||
84 | struct sg_table *sgt; | ||
85 | |||
86 | sgt = omap_iommu_vunmap(isp->domain, isp->dev, (u32)da); | ||
87 | kfree(sgt); | ||
88 | } | ||
37 | 89 | ||
38 | /* ----------------------------------------------------------------------------- | 90 | /* ----------------------------------------------------------------------------- |
39 | * Video buffers management | 91 | * Video buffers management |
@@ -260,11 +312,15 @@ static int isp_video_buffer_sglist_pfnmap(struct isp_video_buffer *buf) | |||
260 | */ | 312 | */ |
261 | static void isp_video_buffer_cleanup(struct isp_video_buffer *buf) | 313 | static void isp_video_buffer_cleanup(struct isp_video_buffer *buf) |
262 | { | 314 | { |
315 | struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue); | ||
316 | struct isp_video *video = vfh->video; | ||
263 | enum dma_data_direction direction; | 317 | enum dma_data_direction direction; |
264 | unsigned int i; | 318 | unsigned int i; |
265 | 319 | ||
266 | if (buf->queue->ops->buffer_cleanup) | 320 | if (buf->dma) { |
267 | buf->queue->ops->buffer_cleanup(buf); | 321 | ispmmu_vunmap(video->isp, buf->dma); |
322 | buf->dma = 0; | ||
323 | } | ||
268 | 324 | ||
269 | if (!(buf->vm_flags & VM_PFNMAP)) { | 325 | if (!(buf->vm_flags & VM_PFNMAP)) { |
270 | direction = buf->vbuf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE | 326 | direction = buf->vbuf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE |
@@ -479,7 +535,10 @@ done: | |||
479 | */ | 535 | */ |
480 | static int isp_video_buffer_prepare(struct isp_video_buffer *buf) | 536 | static int isp_video_buffer_prepare(struct isp_video_buffer *buf) |
481 | { | 537 | { |
538 | struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue); | ||
539 | struct isp_video *video = vfh->video; | ||
482 | enum dma_data_direction direction; | 540 | enum dma_data_direction direction; |
541 | unsigned long addr; | ||
483 | int ret; | 542 | int ret; |
484 | 543 | ||
485 | switch (buf->vbuf.memory) { | 544 | switch (buf->vbuf.memory) { |
@@ -525,6 +584,21 @@ static int isp_video_buffer_prepare(struct isp_video_buffer *buf) | |||
525 | } | 584 | } |
526 | } | 585 | } |
527 | 586 | ||
587 | addr = ispmmu_vmap(video->isp, buf->sglist, buf->sglen); | ||
588 | if (IS_ERR_VALUE(addr)) { | ||
589 | ret = -EIO; | ||
590 | goto done; | ||
591 | } | ||
592 | |||
593 | buf->dma = addr; | ||
594 | |||
595 | if (!IS_ALIGNED(addr, 32)) { | ||
596 | dev_dbg(video->isp->dev, | ||
597 | "Buffer address must be aligned to 32 bytes boundary.\n"); | ||
598 | ret = -EINVAL; | ||
599 | goto done; | ||
600 | } | ||
601 | |||
528 | if (buf->queue->ops->buffer_prepare) | 602 | if (buf->queue->ops->buffer_prepare) |
529 | ret = buf->queue->ops->buffer_prepare(buf); | 603 | ret = buf->queue->ops->buffer_prepare(buf); |
530 | 604 | ||
diff --git a/drivers/media/platform/omap3isp/ispqueue.h b/drivers/media/platform/omap3isp/ispqueue.h index 3e048ad65647..0899a116b4d5 100644 --- a/drivers/media/platform/omap3isp/ispqueue.h +++ b/drivers/media/platform/omap3isp/ispqueue.h | |||
@@ -106,6 +106,7 @@ struct isp_video_buffer { | |||
106 | struct list_head irqlist; | 106 | struct list_head irqlist; |
107 | enum isp_video_buffer_state state; | 107 | enum isp_video_buffer_state state; |
108 | wait_queue_head_t wait; | 108 | wait_queue_head_t wait; |
109 | dma_addr_t dma; | ||
109 | }; | 110 | }; |
110 | 111 | ||
111 | #define to_isp_video_buffer(vb) container_of(vb, struct isp_video_buffer, vb) | 112 | #define to_isp_video_buffer(vb) container_of(vb, struct isp_video_buffer, vb) |
@@ -121,17 +122,12 @@ struct isp_video_buffer { | |||
121 | * mapping the buffer memory in an IOMMU). This operation is optional. | 122 | * mapping the buffer memory in an IOMMU). This operation is optional. |
122 | * @buffer_queue: Called when a buffer is being added to the queue with the | 123 | * @buffer_queue: Called when a buffer is being added to the queue with the |
123 | * queue irqlock spinlock held. | 124 | * queue irqlock spinlock held. |
124 | * @buffer_cleanup: Called before freeing buffers, or before changing the | ||
125 | * userspace memory address for a USERPTR buffer, with the queue lock held. | ||
126 | * Drivers must perform cleanup operations required to undo the | ||
127 | * buffer_prepare call. This operation is optional. | ||
128 | */ | 125 | */ |
129 | struct isp_video_queue_operations { | 126 | struct isp_video_queue_operations { |
130 | void (*queue_prepare)(struct isp_video_queue *queue, | 127 | void (*queue_prepare)(struct isp_video_queue *queue, |
131 | unsigned int *nbuffers, unsigned int *size); | 128 | unsigned int *nbuffers, unsigned int *size); |
132 | int (*buffer_prepare)(struct isp_video_buffer *buf); | 129 | int (*buffer_prepare)(struct isp_video_buffer *buf); |
133 | void (*buffer_queue)(struct isp_video_buffer *buf); | 130 | void (*buffer_queue)(struct isp_video_buffer *buf); |
134 | void (*buffer_cleanup)(struct isp_video_buffer *buf); | ||
135 | }; | 131 | }; |
136 | 132 | ||
137 | /** | 133 | /** |
diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c index e0f594f34bec..a7ef0816230a 100644 --- a/drivers/media/platform/omap3isp/ispvideo.c +++ b/drivers/media/platform/omap3isp/ispvideo.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <linux/clk.h> | 27 | #include <linux/clk.h> |
28 | #include <linux/mm.h> | 28 | #include <linux/mm.h> |
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/omap-iommu.h> | ||
31 | #include <linux/pagemap.h> | 30 | #include <linux/pagemap.h> |
32 | #include <linux/scatterlist.h> | 31 | #include <linux/scatterlist.h> |
33 | #include <linux/sched.h> | 32 | #include <linux/sched.h> |
@@ -326,55 +325,6 @@ isp_video_check_format(struct isp_video *video, struct isp_video_fh *vfh) | |||
326 | } | 325 | } |
327 | 326 | ||
328 | /* ----------------------------------------------------------------------------- | 327 | /* ----------------------------------------------------------------------------- |
329 | * IOMMU management | ||
330 | */ | ||
331 | |||
332 | #define IOMMU_FLAG (IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_8) | ||
333 | |||
334 | /* | ||
335 | * ispmmu_vmap - Wrapper for Virtual memory mapping of a scatter gather list | ||
336 | * @isp: Device pointer specific to the OMAP3 ISP. | ||
337 | * @sglist: Pointer to source Scatter gather list to allocate. | ||
338 | * @sglen: Number of elements of the scatter-gatter list. | ||
339 | * | ||
340 | * Returns a resulting mapped device address by the ISP MMU, or -ENOMEM if | ||
341 | * we ran out of memory. | ||
342 | */ | ||
343 | static dma_addr_t | ||
344 | ispmmu_vmap(struct isp_device *isp, const struct scatterlist *sglist, int sglen) | ||
345 | { | ||
346 | struct sg_table *sgt; | ||
347 | u32 da; | ||
348 | |||
349 | sgt = kmalloc(sizeof(*sgt), GFP_KERNEL); | ||
350 | if (sgt == NULL) | ||
351 | return -ENOMEM; | ||
352 | |||
353 | sgt->sgl = (struct scatterlist *)sglist; | ||
354 | sgt->nents = sglen; | ||
355 | sgt->orig_nents = sglen; | ||
356 | |||
357 | da = omap_iommu_vmap(isp->domain, isp->dev, 0, sgt, IOMMU_FLAG); | ||
358 | if (IS_ERR_VALUE(da)) | ||
359 | kfree(sgt); | ||
360 | |||
361 | return da; | ||
362 | } | ||
363 | |||
364 | /* | ||
365 | * ispmmu_vunmap - Unmap a device address from the ISP MMU | ||
366 | * @isp: Device pointer specific to the OMAP3 ISP. | ||
367 | * @da: Device address generated from a ispmmu_vmap call. | ||
368 | */ | ||
369 | static void ispmmu_vunmap(struct isp_device *isp, dma_addr_t da) | ||
370 | { | ||
371 | struct sg_table *sgt; | ||
372 | |||
373 | sgt = omap_iommu_vunmap(isp->domain, isp->dev, (u32)da); | ||
374 | kfree(sgt); | ||
375 | } | ||
376 | |||
377 | /* ----------------------------------------------------------------------------- | ||
378 | * Video queue operations | 328 | * Video queue operations |
379 | */ | 329 | */ |
380 | 330 | ||
@@ -392,24 +342,11 @@ static void isp_video_queue_prepare(struct isp_video_queue *queue, | |||
392 | *nbuffers = min(*nbuffers, video->capture_mem / PAGE_ALIGN(*size)); | 342 | *nbuffers = min(*nbuffers, video->capture_mem / PAGE_ALIGN(*size)); |
393 | } | 343 | } |
394 | 344 | ||
395 | static void isp_video_buffer_cleanup(struct isp_video_buffer *buf) | ||
396 | { | ||
397 | struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue); | ||
398 | struct isp_buffer *buffer = to_isp_buffer(buf); | ||
399 | struct isp_video *video = vfh->video; | ||
400 | |||
401 | if (buffer->isp_addr) { | ||
402 | ispmmu_vunmap(video->isp, buffer->isp_addr); | ||
403 | buffer->isp_addr = 0; | ||
404 | } | ||
405 | } | ||
406 | |||
407 | static int isp_video_buffer_prepare(struct isp_video_buffer *buf) | 345 | static int isp_video_buffer_prepare(struct isp_video_buffer *buf) |
408 | { | 346 | { |
409 | struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue); | 347 | struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue); |
410 | struct isp_buffer *buffer = to_isp_buffer(buf); | 348 | struct isp_buffer *buffer = to_isp_buffer(buf); |
411 | struct isp_video *video = vfh->video; | 349 | struct isp_video *video = vfh->video; |
412 | unsigned long addr; | ||
413 | 350 | ||
414 | /* Refuse to prepare the buffer is the video node has registered an | 351 | /* Refuse to prepare the buffer is the video node has registered an |
415 | * error. We don't need to take any lock here as the operation is | 352 | * error. We don't need to take any lock here as the operation is |
@@ -420,18 +357,7 @@ static int isp_video_buffer_prepare(struct isp_video_buffer *buf) | |||
420 | if (unlikely(video->error)) | 357 | if (unlikely(video->error)) |
421 | return -EIO; | 358 | return -EIO; |
422 | 359 | ||
423 | addr = ispmmu_vmap(video->isp, buf->sglist, buf->sglen); | 360 | buffer->isp_addr = buf->dma; |
424 | if (IS_ERR_VALUE(addr)) | ||
425 | return -EIO; | ||
426 | |||
427 | if (!IS_ALIGNED(addr, 32)) { | ||
428 | dev_dbg(video->isp->dev, "Buffer address must be " | ||
429 | "aligned to 32 bytes boundary.\n"); | ||
430 | ispmmu_vunmap(video->isp, buffer->isp_addr); | ||
431 | return -EINVAL; | ||
432 | } | ||
433 | |||
434 | buffer->isp_addr = addr; | ||
435 | return 0; | 361 | return 0; |
436 | } | 362 | } |
437 | 363 | ||
@@ -490,7 +416,6 @@ static const struct isp_video_queue_operations isp_video_queue_ops = { | |||
490 | .queue_prepare = &isp_video_queue_prepare, | 416 | .queue_prepare = &isp_video_queue_prepare, |
491 | .buffer_prepare = &isp_video_buffer_prepare, | 417 | .buffer_prepare = &isp_video_buffer_prepare, |
492 | .buffer_queue = &isp_video_buffer_queue, | 418 | .buffer_queue = &isp_video_buffer_queue, |
493 | .buffer_cleanup = &isp_video_buffer_cleanup, | ||
494 | }; | 419 | }; |
495 | 420 | ||
496 | /* | 421 | /* |