Commit 7f5036d0 authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Mauro Carvalho Chehab

[media] omap3isp: queue: Allocate kernel buffers with dma_alloc_coherent

And retrieve the related sg table using dma_get_sgtable().
Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: default avatarSakari Ailus <sakari.ailus@iki.fi>
Signed-off-by: default avatarMauro Carvalho Chehab <m.chehab@samsung.com>
parent d13f19f2
...@@ -148,39 +148,18 @@ static int isp_video_buffer_lock_vma(struct isp_video_buffer *buf, int lock) ...@@ -148,39 +148,18 @@ static int isp_video_buffer_lock_vma(struct isp_video_buffer *buf, int lock)
} }
/* /*
* isp_video_buffer_prepare_kernel - Build scatter list for a vmalloc'ed buffer * isp_video_buffer_prepare_kernel - Build scatter list for a kernel-allocated
* buffer
* *
* Iterate over the vmalloc'ed area and create a scatter list entry for every * Retrieve the sgtable using the DMA API.
* page.
*/ */
static int isp_video_buffer_prepare_kernel(struct isp_video_buffer *buf) static int isp_video_buffer_prepare_kernel(struct isp_video_buffer *buf)
{ {
struct scatterlist *sg; struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue);
unsigned int npages; struct isp_video *video = vfh->video;
unsigned int i;
void *addr;
int ret;
addr = buf->vaddr;
npages = PAGE_ALIGN(buf->vbuf.length) >> PAGE_SHIFT;
ret = sg_alloc_table(&buf->sgt, npages, GFP_KERNEL);
if (ret < 0)
return ret;
for (sg = buf->sgt.sgl, i = 0; i < npages; ++i, addr += PAGE_SIZE) {
struct page *page = vmalloc_to_page(addr);
if (page == NULL || PageHighMem(page)) {
sg_free_table(&buf->sgt);
return -EINVAL;
}
sg_set_page(sg, page, PAGE_SIZE, 0);
sg = sg_next(sg);
}
return 0; return dma_get_sgtable(video->isp->dev, &buf->sgt, buf->vaddr,
buf->paddr, PAGE_ALIGN(buf->vbuf.length));
} }
/* /*
...@@ -601,8 +580,12 @@ static int isp_video_queue_free(struct isp_video_queue *queue) ...@@ -601,8 +580,12 @@ static int isp_video_queue_free(struct isp_video_queue *queue)
isp_video_buffer_cleanup(buf); isp_video_buffer_cleanup(buf);
vfree(buf->vaddr); if (buf->vaddr) {
buf->vaddr = NULL; dma_free_coherent(queue->dev,
PAGE_ALIGN(buf->vbuf.length),
buf->vaddr, buf->paddr);
buf->vaddr = NULL;
}
kfree(buf); kfree(buf);
queue->buffers[i] = NULL; queue->buffers[i] = NULL;
...@@ -623,6 +606,7 @@ static int isp_video_queue_alloc(struct isp_video_queue *queue, ...@@ -623,6 +606,7 @@ static int isp_video_queue_alloc(struct isp_video_queue *queue,
unsigned int size, enum v4l2_memory memory) unsigned int size, enum v4l2_memory memory)
{ {
struct isp_video_buffer *buf; struct isp_video_buffer *buf;
dma_addr_t dma;
unsigned int i; unsigned int i;
void *mem; void *mem;
int ret; int ret;
...@@ -646,7 +630,8 @@ static int isp_video_queue_alloc(struct isp_video_queue *queue, ...@@ -646,7 +630,8 @@ static int isp_video_queue_alloc(struct isp_video_queue *queue,
/* Allocate video buffers memory for mmap mode. Align /* Allocate video buffers memory for mmap mode. Align
* the size to the page size. * the size to the page size.
*/ */
mem = vmalloc_32_user(PAGE_ALIGN(size)); mem = dma_alloc_coherent(queue->dev, PAGE_ALIGN(size),
&dma, GFP_KERNEL);
if (mem == NULL) { if (mem == NULL) {
kfree(buf); kfree(buf);
break; break;
...@@ -654,6 +639,7 @@ static int isp_video_queue_alloc(struct isp_video_queue *queue, ...@@ -654,6 +639,7 @@ static int isp_video_queue_alloc(struct isp_video_queue *queue,
buf->vbuf.m.offset = i * PAGE_ALIGN(size); buf->vbuf.m.offset = i * PAGE_ALIGN(size);
buf->vaddr = mem; buf->vaddr = mem;
buf->paddr = dma;
} }
buf->vbuf.index = i; buf->vbuf.index = i;
...@@ -1094,10 +1080,17 @@ int omap3isp_video_queue_mmap(struct isp_video_queue *queue, ...@@ -1094,10 +1080,17 @@ int omap3isp_video_queue_mmap(struct isp_video_queue *queue,
goto done; goto done;
} }
ret = remap_vmalloc_range(vma, buf->vaddr, 0); /* dma_mmap_coherent() uses vm_pgoff as an offset inside the buffer
* while we used it to identify the buffer and want to map the whole
* buffer.
*/
vma->vm_pgoff = 0;
ret = dma_mmap_coherent(queue->dev, vma, buf->vaddr, buf->paddr, size);
if (ret < 0) if (ret < 0)
goto done; goto done;
vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
vma->vm_ops = &isp_video_queue_vm_ops; vma->vm_ops = &isp_video_queue_vm_ops;
vma->vm_private_data = buf; vma->vm_private_data = buf;
isp_video_queue_vm_open(vma); isp_video_queue_vm_open(vma);
......
...@@ -68,6 +68,7 @@ enum isp_video_buffer_state { ...@@ -68,6 +68,7 @@ enum isp_video_buffer_state {
* @prepared: Whether the buffer has been prepared * @prepared: Whether the buffer has been prepared
* @skip_cache: Whether to skip cache management operations for this buffer * @skip_cache: Whether to skip cache management operations for this buffer
* @vaddr: Memory virtual address (for kernel buffers) * @vaddr: Memory virtual address (for kernel buffers)
* @paddr: Memory physicall address (for kernel buffers)
* @vm_flags: Buffer VMA flags (for userspace buffers) * @vm_flags: Buffer VMA flags (for userspace buffers)
* @npages: Number of pages (for userspace buffers) * @npages: Number of pages (for userspace buffers)
* @pages: Pages table (for userspace non-VM_PFNMAP buffers) * @pages: Pages table (for userspace non-VM_PFNMAP buffers)
...@@ -86,6 +87,7 @@ struct isp_video_buffer { ...@@ -86,6 +87,7 @@ struct isp_video_buffer {
/* For kernel buffers. */ /* For kernel buffers. */
void *vaddr; void *vaddr;
dma_addr_t paddr;
/* For userspace buffers. */ /* For userspace buffers. */
vm_flags_t vm_flags; vm_flags_t vm_flags;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment