diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2014-03-08 07:38:38 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2014-05-25 10:15:47 -0400 |
commit | 7f5036d059fbd263b5322a4298a9935698e7625d (patch) | |
tree | 5e877a7e2c4fb8baf4f065f70b931c1df6b8f6c6 /drivers/media | |
parent | d13f19f2ca7fb6b545915e96ffe19bb405b72037 (diff) |
[media] omap3isp: queue: Allocate kernel buffers with dma_alloc_coherent
And retrieve the related sg table using dma_get_sgtable().
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')
-rw-r--r-- | drivers/media/platform/omap3isp/ispqueue.c | 57 | ||||
-rw-r--r-- | drivers/media/platform/omap3isp/ispqueue.h | 2 |
2 files changed, 27 insertions, 32 deletions
diff --git a/drivers/media/platform/omap3isp/ispqueue.c b/drivers/media/platform/omap3isp/ispqueue.c index 088710b2a5ea..2fd254f4dbe2 100644 --- a/drivers/media/platform/omap3isp/ispqueue.c +++ b/drivers/media/platform/omap3isp/ispqueue.c | |||
@@ -148,39 +148,18 @@ out: | |||
148 | } | 148 | } |
149 | 149 | ||
150 | /* | 150 | /* |
151 | * isp_video_buffer_prepare_kernel - Build scatter list for a vmalloc'ed buffer | 151 | * isp_video_buffer_prepare_kernel - Build scatter list for a kernel-allocated |
152 | * buffer | ||
152 | * | 153 | * |
153 | * Iterate over the vmalloc'ed area and create a scatter list entry for every | 154 | * Retrieve the sgtable using the DMA API. |
154 | * page. | ||
155 | */ | 155 | */ |
156 | static int isp_video_buffer_prepare_kernel(struct isp_video_buffer *buf) | 156 | static int isp_video_buffer_prepare_kernel(struct isp_video_buffer *buf) |
157 | { | 157 | { |
158 | struct scatterlist *sg; | 158 | struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue); |
159 | unsigned int npages; | 159 | struct isp_video *video = vfh->video; |
160 | unsigned int i; | ||
161 | void *addr; | ||
162 | int ret; | ||
163 | |||
164 | addr = buf->vaddr; | ||
165 | npages = PAGE_ALIGN(buf->vbuf.length) >> PAGE_SHIFT; | ||
166 | |||
167 | ret = sg_alloc_table(&buf->sgt, npages, GFP_KERNEL); | ||
168 | if (ret < 0) | ||
169 | return ret; | ||
170 | |||
171 | for (sg = buf->sgt.sgl, i = 0; i < npages; ++i, addr += PAGE_SIZE) { | ||
172 | struct page *page = vmalloc_to_page(addr); | ||
173 | |||
174 | if (page == NULL || PageHighMem(page)) { | ||
175 | sg_free_table(&buf->sgt); | ||
176 | return -EINVAL; | ||
177 | } | ||
178 | |||
179 | sg_set_page(sg, page, PAGE_SIZE, 0); | ||
180 | sg = sg_next(sg); | ||
181 | } | ||
182 | 160 | ||
183 | return 0; | 161 | return dma_get_sgtable(video->isp->dev, &buf->sgt, buf->vaddr, |
162 | buf->paddr, PAGE_ALIGN(buf->vbuf.length)); | ||
184 | } | 163 | } |
185 | 164 | ||
186 | /* | 165 | /* |
@@ -601,8 +580,12 @@ static int isp_video_queue_free(struct isp_video_queue *queue) | |||
601 | 580 | ||
602 | isp_video_buffer_cleanup(buf); | 581 | isp_video_buffer_cleanup(buf); |
603 | 582 | ||
604 | vfree(buf->vaddr); | 583 | if (buf->vaddr) { |
605 | buf->vaddr = NULL; | 584 | dma_free_coherent(queue->dev, |
585 | PAGE_ALIGN(buf->vbuf.length), | ||
586 | buf->vaddr, buf->paddr); | ||
587 | buf->vaddr = NULL; | ||
588 | } | ||
606 | 589 | ||
607 | kfree(buf); | 590 | kfree(buf); |
608 | queue->buffers[i] = NULL; | 591 | queue->buffers[i] = NULL; |
@@ -623,6 +606,7 @@ static int isp_video_queue_alloc(struct isp_video_queue *queue, | |||
623 | unsigned int size, enum v4l2_memory memory) | 606 | unsigned int size, enum v4l2_memory memory) |
624 | { | 607 | { |
625 | struct isp_video_buffer *buf; | 608 | struct isp_video_buffer *buf; |
609 | dma_addr_t dma; | ||
626 | unsigned int i; | 610 | unsigned int i; |
627 | void *mem; | 611 | void *mem; |
628 | int ret; | 612 | int ret; |
@@ -646,7 +630,8 @@ static int isp_video_queue_alloc(struct isp_video_queue *queue, | |||
646 | /* Allocate video buffers memory for mmap mode. Align | 630 | /* Allocate video buffers memory for mmap mode. Align |
647 | * the size to the page size. | 631 | * the size to the page size. |
648 | */ | 632 | */ |
649 | mem = vmalloc_32_user(PAGE_ALIGN(size)); | 633 | mem = dma_alloc_coherent(queue->dev, PAGE_ALIGN(size), |
634 | &dma, GFP_KERNEL); | ||
650 | if (mem == NULL) { | 635 | if (mem == NULL) { |
651 | kfree(buf); | 636 | kfree(buf); |
652 | break; | 637 | break; |
@@ -654,6 +639,7 @@ static int isp_video_queue_alloc(struct isp_video_queue *queue, | |||
654 | 639 | ||
655 | buf->vbuf.m.offset = i * PAGE_ALIGN(size); | 640 | buf->vbuf.m.offset = i * PAGE_ALIGN(size); |
656 | buf->vaddr = mem; | 641 | buf->vaddr = mem; |
642 | buf->paddr = dma; | ||
657 | } | 643 | } |
658 | 644 | ||
659 | buf->vbuf.index = i; | 645 | buf->vbuf.index = i; |
@@ -1094,10 +1080,17 @@ int omap3isp_video_queue_mmap(struct isp_video_queue *queue, | |||
1094 | goto done; | 1080 | goto done; |
1095 | } | 1081 | } |
1096 | 1082 | ||
1097 | ret = remap_vmalloc_range(vma, buf->vaddr, 0); | 1083 | /* dma_mmap_coherent() uses vm_pgoff as an offset inside the buffer |
1084 | * while we used it to identify the buffer and want to map the whole | ||
1085 | * buffer. | ||
1086 | */ | ||
1087 | vma->vm_pgoff = 0; | ||
1088 | |||
1089 | ret = dma_mmap_coherent(queue->dev, vma, buf->vaddr, buf->paddr, size); | ||
1098 | if (ret < 0) | 1090 | if (ret < 0) |
1099 | goto done; | 1091 | goto done; |
1100 | 1092 | ||
1093 | vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; | ||
1101 | vma->vm_ops = &isp_video_queue_vm_ops; | 1094 | vma->vm_ops = &isp_video_queue_vm_ops; |
1102 | vma->vm_private_data = buf; | 1095 | vma->vm_private_data = buf; |
1103 | isp_video_queue_vm_open(vma); | 1096 | isp_video_queue_vm_open(vma); |
diff --git a/drivers/media/platform/omap3isp/ispqueue.h b/drivers/media/platform/omap3isp/ispqueue.h index f78325dbcf49..e03af74ded28 100644 --- a/drivers/media/platform/omap3isp/ispqueue.h +++ b/drivers/media/platform/omap3isp/ispqueue.h | |||
@@ -68,6 +68,7 @@ enum isp_video_buffer_state { | |||
68 | * @prepared: Whether the buffer has been prepared | 68 | * @prepared: Whether the buffer has been prepared |
69 | * @skip_cache: Whether to skip cache management operations for this buffer | 69 | * @skip_cache: Whether to skip cache management operations for this buffer |
70 | * @vaddr: Memory virtual address (for kernel buffers) | 70 | * @vaddr: Memory virtual address (for kernel buffers) |
71 | * @paddr: Memory physicall address (for kernel buffers) | ||
71 | * @vm_flags: Buffer VMA flags (for userspace buffers) | 72 | * @vm_flags: Buffer VMA flags (for userspace buffers) |
72 | * @npages: Number of pages (for userspace buffers) | 73 | * @npages: Number of pages (for userspace buffers) |
73 | * @pages: Pages table (for userspace non-VM_PFNMAP buffers) | 74 | * @pages: Pages table (for userspace non-VM_PFNMAP buffers) |
@@ -86,6 +87,7 @@ struct isp_video_buffer { | |||
86 | 87 | ||
87 | /* For kernel buffers. */ | 88 | /* For kernel buffers. */ |
88 | void *vaddr; | 89 | void *vaddr; |
90 | dma_addr_t paddr; | ||
89 | 91 | ||
90 | /* For userspace buffers. */ | 92 | /* For userspace buffers. */ |
91 | vm_flags_t vm_flags; | 93 | vm_flags_t vm_flags; |