[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>
This commit is contained in:
parent
d13f19f2ca
commit
7f5036d059
|
@ -148,39 +148,18 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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;
|
return dma_get_sgtable(video->isp->dev, &buf->sgt, buf->vaddr,
|
||||||
npages = PAGE_ALIGN(buf->vbuf.length) >> PAGE_SHIFT;
|
buf->paddr, PAGE_ALIGN(buf->vbuf.length));
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -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) {
|
||||||
|
dma_free_coherent(queue->dev,
|
||||||
|
PAGE_ALIGN(buf->vbuf.length),
|
||||||
|
buf->vaddr, buf->paddr);
|
||||||
buf->vaddr = NULL;
|
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,
|
||||||
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,
|
||||||
/* 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,
|
||||||
|
|
||||||
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,
|
||||||
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 {
|
||||||
* @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 {
|
||||||
|
|
||||||
/* 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;
|
||||||
|
|
Loading…
Reference in New Issue