Commit 73c1ea49 authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Mauro Carvalho Chehab

[media] omap3isp: queue: Use sg_table structure

Replace the sglen and sglist fields stored in the buffer structure with
an sg_table. This allows using the sg table allocation helper function.
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 9000427a
...@@ -45,33 +45,17 @@ ...@@ -45,33 +45,17 @@
#define IOMMU_FLAG (IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_8) #define IOMMU_FLAG (IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_8)
/* /*
* ispmmu_vmap - Wrapper for Virtual memory mapping of a scatter gather list * ispmmu_vmap - Wrapper for virtual memory mapping of a scatter gather table
* @dev: Device pointer specific to the OMAP3 ISP. * @dev: Device pointer specific to the OMAP3 ISP.
* @sglist: Pointer to source Scatter gather list to allocate. * @sgt: Pointer to source scatter gather table.
* @sglen: Number of elements of the scatter-gatter list.
* *
* Returns a resulting mapped device address by the ISP MMU, or -ENOMEM if * Returns a resulting mapped device address by the ISP MMU, or -ENOMEM if
* we ran out of memory. * we ran out of memory.
*/ */
static dma_addr_t static dma_addr_t
ispmmu_vmap(struct isp_device *isp, const struct scatterlist *sglist, int sglen) ispmmu_vmap(struct isp_device *isp, const struct sg_table *sgt)
{ {
struct sg_table *sgt; return omap_iommu_vmap(isp->domain, isp->dev, 0, sgt, IOMMU_FLAG);
u32 da;
sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
if (sgt == NULL)
return -ENOMEM;
sgt->sgl = (struct scatterlist *)sglist;
sgt->nents = sglen;
sgt->orig_nents = sglen;
da = omap_iommu_vmap(isp->domain, isp->dev, 0, sgt, IOMMU_FLAG);
if (IS_ERR_VALUE(da))
kfree(sgt);
return da;
} }
/* /*
...@@ -81,10 +65,7 @@ ispmmu_vmap(struct isp_device *isp, const struct scatterlist *sglist, int sglen) ...@@ -81,10 +65,7 @@ ispmmu_vmap(struct isp_device *isp, const struct scatterlist *sglist, int sglen)
*/ */
static void ispmmu_vunmap(struct isp_device *isp, dma_addr_t da) static void ispmmu_vunmap(struct isp_device *isp, dma_addr_t da)
{ {
struct sg_table *sgt; omap_iommu_vunmap(isp->domain, isp->dev, (u32)da);
sgt = omap_iommu_vunmap(isp->domain, isp->dev, (u32)da);
kfree(sgt);
} }
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
...@@ -204,34 +185,31 @@ static int isp_video_buffer_lock_vma(struct isp_video_buffer *buf, int lock) ...@@ -204,34 +185,31 @@ static int isp_video_buffer_lock_vma(struct isp_video_buffer *buf, int lock)
*/ */
static int isp_video_buffer_sglist_kernel(struct isp_video_buffer *buf) static int isp_video_buffer_sglist_kernel(struct isp_video_buffer *buf)
{ {
struct scatterlist *sglist; struct scatterlist *sg;
unsigned int npages; unsigned int npages;
unsigned int i; unsigned int i;
void *addr; void *addr;
int ret;
addr = buf->vaddr; addr = buf->vaddr;
npages = PAGE_ALIGN(buf->vbuf.length) >> PAGE_SHIFT; npages = PAGE_ALIGN(buf->vbuf.length) >> PAGE_SHIFT;
sglist = vmalloc(npages * sizeof(*sglist)); ret = sg_alloc_table(&buf->sgt, npages, GFP_KERNEL);
if (sglist == NULL) if (ret < 0)
return -ENOMEM; return ret;
sg_init_table(sglist, npages);
for (i = 0; i < npages; ++i, addr += PAGE_SIZE) { for (sg = buf->sgt.sgl, i = 0; i < npages; ++i, addr += PAGE_SIZE) {
struct page *page = vmalloc_to_page(addr); struct page *page = vmalloc_to_page(addr);
if (page == NULL || PageHighMem(page)) { if (page == NULL || PageHighMem(page)) {
vfree(sglist); sg_free_table(&buf->sgt);
return -EINVAL; return -EINVAL;
} }
sg_set_page(&sglist[i], page, PAGE_SIZE, 0); sg_set_page(sg, page, PAGE_SIZE, 0);
sg = sg_next(sg);
} }
buf->sglen = npages;
buf->sglist = sglist;
return 0; return 0;
} }
...@@ -242,30 +220,26 @@ static int isp_video_buffer_sglist_kernel(struct isp_video_buffer *buf) ...@@ -242,30 +220,26 @@ static int isp_video_buffer_sglist_kernel(struct isp_video_buffer *buf)
*/ */
static int isp_video_buffer_sglist_user(struct isp_video_buffer *buf) static int isp_video_buffer_sglist_user(struct isp_video_buffer *buf)
{ {
struct scatterlist *sglist;
unsigned int offset = buf->offset; unsigned int offset = buf->offset;
struct scatterlist *sg;
unsigned int i; unsigned int i;
int ret;
sglist = vmalloc(buf->npages * sizeof(*sglist)); ret = sg_alloc_table(&buf->sgt, buf->npages, GFP_KERNEL);
if (sglist == NULL) if (ret < 0)
return -ENOMEM; return ret;
sg_init_table(sglist, buf->npages);
for (i = 0; i < buf->npages; ++i) { for (sg = buf->sgt.sgl, i = 0; i < buf->npages; ++i) {
if (PageHighMem(buf->pages[i])) { if (PageHighMem(buf->pages[i])) {
vfree(sglist); sg_free_table(&buf->sgt);
return -EINVAL; return -EINVAL;
} }
sg_set_page(&sglist[i], buf->pages[i], PAGE_SIZE - offset, sg_set_page(sg, buf->pages[i], PAGE_SIZE - offset, offset);
offset); sg = sg_next(sg);
offset = 0; offset = 0;
} }
buf->sglen = buf->npages;
buf->sglist = sglist;
return 0; return 0;
} }
...@@ -277,30 +251,26 @@ static int isp_video_buffer_sglist_user(struct isp_video_buffer *buf) ...@@ -277,30 +251,26 @@ static int isp_video_buffer_sglist_user(struct isp_video_buffer *buf)
*/ */
static int isp_video_buffer_sglist_pfnmap(struct isp_video_buffer *buf) static int isp_video_buffer_sglist_pfnmap(struct isp_video_buffer *buf)
{ {
struct scatterlist *sglist; struct scatterlist *sg;
unsigned int offset = buf->offset; unsigned int offset = buf->offset;
unsigned long pfn = buf->paddr >> PAGE_SHIFT; unsigned long pfn = buf->paddr >> PAGE_SHIFT;
unsigned int i; unsigned int i;
int ret;
sglist = vmalloc(buf->npages * sizeof(*sglist)); ret = sg_alloc_table(&buf->sgt, buf->npages, GFP_KERNEL);
if (sglist == NULL) if (ret < 0)
return -ENOMEM; return ret;
sg_init_table(sglist, buf->npages);
for (i = 0; i < buf->npages; ++i, ++pfn) { for (sg = buf->sgt.sgl, i = 0; i < buf->npages; ++i, ++pfn) {
sg_set_page(&sglist[i], pfn_to_page(pfn), PAGE_SIZE - offset, sg_set_page(sg, pfn_to_page(pfn), PAGE_SIZE - offset, offset);
offset);
/* PFNMAP buffers will not get DMA-mapped, set the DMA address /* PFNMAP buffers will not get DMA-mapped, set the DMA address
* manually. * manually.
*/ */
sg_dma_address(&sglist[i]) = (pfn << PAGE_SHIFT) + offset; sg_dma_address(sg) = (pfn << PAGE_SHIFT) + offset;
sg = sg_next(sg);
offset = 0; offset = 0;
} }
buf->sglen = buf->npages;
buf->sglist = sglist;
return 0; return 0;
} }
...@@ -325,13 +295,11 @@ static void isp_video_buffer_cleanup(struct isp_video_buffer *buf) ...@@ -325,13 +295,11 @@ static void isp_video_buffer_cleanup(struct isp_video_buffer *buf)
if (!(buf->vm_flags & VM_PFNMAP)) { if (!(buf->vm_flags & VM_PFNMAP)) {
direction = buf->vbuf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE direction = buf->vbuf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE
? DMA_FROM_DEVICE : DMA_TO_DEVICE; ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
dma_unmap_sg(buf->queue->dev, buf->sglist, buf->sglen, dma_unmap_sg(buf->queue->dev, buf->sgt.sgl, buf->sgt.orig_nents,
direction); direction);
} }
vfree(buf->sglist); sg_free_table(&buf->sgt);
buf->sglist = NULL;
buf->sglen = 0;
if (buf->pages != NULL) { if (buf->pages != NULL) {
isp_video_buffer_lock_vma(buf, 0); isp_video_buffer_lock_vma(buf, 0);
...@@ -576,15 +544,15 @@ static int isp_video_buffer_prepare(struct isp_video_buffer *buf) ...@@ -576,15 +544,15 @@ static int isp_video_buffer_prepare(struct isp_video_buffer *buf)
if (!(buf->vm_flags & VM_PFNMAP)) { if (!(buf->vm_flags & VM_PFNMAP)) {
direction = buf->vbuf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE direction = buf->vbuf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE
? DMA_FROM_DEVICE : DMA_TO_DEVICE; ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
ret = dma_map_sg(buf->queue->dev, buf->sglist, buf->sglen, ret = dma_map_sg(buf->queue->dev, buf->sgt.sgl,
direction); buf->sgt.orig_nents, direction);
if (ret != buf->sglen) { if (ret != buf->sgt.orig_nents) {
ret = -EFAULT; ret = -EFAULT;
goto done; goto done;
} }
} }
addr = ispmmu_vmap(video->isp, buf->sglist, buf->sglen); addr = ispmmu_vmap(video->isp, &buf->sgt);
if (IS_ERR_VALUE(addr)) { if (IS_ERR_VALUE(addr)) {
ret = -EIO; ret = -EIO;
goto done; goto done;
......
...@@ -73,8 +73,7 @@ enum isp_video_buffer_state { ...@@ -73,8 +73,7 @@ enum isp_video_buffer_state {
* @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)
* @paddr: Memory physical address (for userspace VM_PFNMAP buffers) * @paddr: Memory physical address (for userspace VM_PFNMAP buffers)
* @sglen: Number of elements in the scatter list (for non-VM_PFNMAP buffers) * @sgt: Scatter gather table (for non-VM_PFNMAP buffers)
* @sglist: Scatter list (for non-VM_PFNMAP buffers)
* @vbuf: V4L2 buffer * @vbuf: V4L2 buffer
* @irqlist: List head for insertion into IRQ queue * @irqlist: List head for insertion into IRQ queue
* @state: Current buffer state * @state: Current buffer state
...@@ -98,8 +97,7 @@ struct isp_video_buffer { ...@@ -98,8 +97,7 @@ struct isp_video_buffer {
dma_addr_t paddr; dma_addr_t paddr;
/* For all buffers except VM_PFNMAP. */ /* For all buffers except VM_PFNMAP. */
unsigned int sglen; struct sg_table sgt;
struct scatterlist *sglist;
/* Touched by the interrupt handler. */ /* Touched by the interrupt handler. */
struct v4l2_buffer vbuf; struct v4l2_buffer vbuf;
......
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