diff options
Diffstat (limited to 'drivers/media/common/videobuf2/videobuf2-vmalloc.c')
| -rw-r--r-- | drivers/media/common/videobuf2/videobuf2-vmalloc.c | 112 |
1 files changed, 53 insertions, 59 deletions
diff --git a/drivers/media/common/videobuf2/videobuf2-vmalloc.c b/drivers/media/common/videobuf2/videobuf2-vmalloc.c index 6dfbd5b05907..3f777068cd34 100644 --- a/drivers/media/common/videobuf2/videobuf2-vmalloc.c +++ b/drivers/media/common/videobuf2/videobuf2-vmalloc.c @@ -34,29 +34,28 @@ struct vb2_vmalloc_buf { static void vb2_vmalloc_put(void *buf_priv); -static void *vb2_vmalloc_alloc(struct device *dev, unsigned long attrs, - unsigned long size, enum dma_data_direction dma_dir, - gfp_t gfp_flags) +static void *vb2_vmalloc_alloc(struct vb2_buffer *vb, struct device *dev, + unsigned long size) { struct vb2_vmalloc_buf *buf; - buf = kzalloc(sizeof(*buf), GFP_KERNEL | gfp_flags); + buf = kzalloc(sizeof(*buf), GFP_KERNEL | vb->vb2_queue->gfp_flags); if (!buf) return ERR_PTR(-ENOMEM); buf->size = size; buf->vaddr = vmalloc_user(buf->size); - buf->dma_dir = dma_dir; - buf->handler.refcount = &buf->refcount; - buf->handler.put = vb2_vmalloc_put; - buf->handler.arg = buf; - if (!buf->vaddr) { pr_debug("vmalloc of size %ld failed\n", buf->size); kfree(buf); return ERR_PTR(-ENOMEM); } + buf->dma_dir = vb->vb2_queue->dma_dir; + buf->handler.refcount = &buf->refcount; + buf->handler.put = vb2_vmalloc_put; + buf->handler.arg = buf; + refcount_set(&buf->refcount, 1); return buf; } @@ -71,9 +70,8 @@ static void vb2_vmalloc_put(void *buf_priv) } } -static void *vb2_vmalloc_get_userptr(struct device *dev, unsigned long vaddr, - unsigned long size, - enum dma_data_direction dma_dir) +static void *vb2_vmalloc_get_userptr(struct vb2_buffer *vb, struct device *dev, + unsigned long vaddr, unsigned long size) { struct vb2_vmalloc_buf *buf; struct frame_vector *vec; @@ -84,11 +82,12 @@ static void *vb2_vmalloc_get_userptr(struct device *dev, unsigned long vaddr, if (!buf) return ERR_PTR(-ENOMEM); - buf->dma_dir = dma_dir; + buf->dma_dir = vb->vb2_queue->dma_dir; offset = vaddr & ~PAGE_MASK; buf->size = size; - vec = vb2_create_framevec(vaddr, size, dma_dir == DMA_FROM_DEVICE || - dma_dir == DMA_BIDIRECTIONAL); + vec = vb2_create_framevec(vaddr, size, + buf->dma_dir == DMA_FROM_DEVICE || + buf->dma_dir == DMA_BIDIRECTIONAL); if (IS_ERR(vec)) { ret = PTR_ERR(vec); goto fail_pfnvec_create; @@ -106,10 +105,9 @@ static void *vb2_vmalloc_get_userptr(struct device *dev, unsigned long vaddr, if (nums[i-1] + 1 != nums[i]) goto fail_map; buf->vaddr = (__force void *) - ioremap_nocache(__pfn_to_phys(nums[0]), size + offset); + ioremap(__pfn_to_phys(nums[0]), size + offset); } else { - buf->vaddr = vm_map_ram(frame_vector_pages(vec), n_pages, -1, - PAGE_KERNEL); + buf->vaddr = vm_map_ram(frame_vector_pages(vec), n_pages, -1); } if (!buf->vaddr) @@ -135,13 +133,15 @@ static void vb2_vmalloc_put_userptr(void *buf_priv) if (!buf->vec->is_pfns) { n_pages = frame_vector_count(buf->vec); - pages = frame_vector_pages(buf->vec); if (vaddr) vm_unmap_ram((void *)vaddr, n_pages); if (buf->dma_dir == DMA_FROM_DEVICE || - buf->dma_dir == DMA_BIDIRECTIONAL) - for (i = 0; i < n_pages; i++) - set_page_dirty_lock(pages[i]); + buf->dma_dir == DMA_BIDIRECTIONAL) { + pages = frame_vector_pages(buf->vec); + if (!WARN_ON_ONCE(IS_ERR(pages))) + for (i = 0; i < n_pages; i++) + set_page_dirty_lock(pages[i]); + } } else { iounmap((__force void __iomem *)buf->vaddr); } @@ -149,7 +149,7 @@ static void vb2_vmalloc_put_userptr(void *buf_priv) kfree(buf); } -static void *vb2_vmalloc_vaddr(void *buf_priv) +static void *vb2_vmalloc_vaddr(struct vb2_buffer *vb, void *buf_priv) { struct vb2_vmalloc_buf *buf = buf_priv; @@ -186,7 +186,7 @@ static int vb2_vmalloc_mmap(void *buf_priv, struct vm_area_struct *vma) /* * Make sure that vm_areas for 2 buffers won't be merged together */ - vma->vm_flags |= VM_DONTEXPAND; + vm_flags_set(vma, VM_DONTEXPAND); /* * Use common vm_area operations to track buffer refcount. @@ -231,7 +231,7 @@ static int vb2_vmalloc_dmabuf_ops_attach(struct dma_buf *dbuf, kfree(attach); return ret; } - for_each_sg(sgt->sgl, sg, sgt->nents, i) { + for_each_sgtable_sg(sgt, sg, i) { struct page *page = vmalloc_to_page(vaddr); if (!page) { @@ -261,8 +261,7 @@ static void vb2_vmalloc_dmabuf_ops_detach(struct dma_buf *dbuf, /* release the scatterlist cache */ if (attach->dma_dir != DMA_NONE) - dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, - attach->dma_dir); + dma_unmap_sgtable(db_attach->dev, sgt, attach->dma_dir, 0); sg_free_table(sgt); kfree(attach); db_attach->priv = NULL; @@ -272,39 +271,27 @@ static struct sg_table *vb2_vmalloc_dmabuf_ops_map( struct dma_buf_attachment *db_attach, enum dma_data_direction dma_dir) { struct vb2_vmalloc_attachment *attach = db_attach->priv; - /* stealing dmabuf mutex to serialize map/unmap operations */ - struct mutex *lock = &db_attach->dmabuf->lock; struct sg_table *sgt; - mutex_lock(lock); - sgt = &attach->sgt; /* return previously mapped sg table */ - if (attach->dma_dir == dma_dir) { - mutex_unlock(lock); + if (attach->dma_dir == dma_dir) return sgt; - } /* release any previous cache */ if (attach->dma_dir != DMA_NONE) { - dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, - attach->dma_dir); + dma_unmap_sgtable(db_attach->dev, sgt, attach->dma_dir, 0); attach->dma_dir = DMA_NONE; } /* mapping to the client with new direction */ - sgt->nents = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, - dma_dir); - if (!sgt->nents) { + if (dma_map_sgtable(db_attach->dev, sgt, dma_dir, 0)) { pr_err("failed to map scatterlist\n"); - mutex_unlock(lock); return ERR_PTR(-EIO); } attach->dma_dir = dma_dir; - mutex_unlock(lock); - return sgt; } @@ -320,18 +307,14 @@ static void vb2_vmalloc_dmabuf_ops_release(struct dma_buf *dbuf) vb2_vmalloc_put(dbuf->priv); } -static void *vb2_vmalloc_dmabuf_ops_kmap(struct dma_buf *dbuf, unsigned long pgnum) +static int vb2_vmalloc_dmabuf_ops_vmap(struct dma_buf *dbuf, + struct iosys_map *map) { struct vb2_vmalloc_buf *buf = dbuf->priv; - return buf->vaddr + pgnum * PAGE_SIZE; -} - -static void *vb2_vmalloc_dmabuf_ops_vmap(struct dma_buf *dbuf) -{ - struct vb2_vmalloc_buf *buf = dbuf->priv; + iosys_map_set_vaddr(map, buf->vaddr); - return buf->vaddr; + return 0; } static int vb2_vmalloc_dmabuf_ops_mmap(struct dma_buf *dbuf, @@ -345,13 +328,14 @@ static const struct dma_buf_ops vb2_vmalloc_dmabuf_ops = { .detach = vb2_vmalloc_dmabuf_ops_detach, .map_dma_buf = vb2_vmalloc_dmabuf_ops_map, .unmap_dma_buf = vb2_vmalloc_dmabuf_ops_unmap, - .map = vb2_vmalloc_dmabuf_ops_kmap, .vmap = vb2_vmalloc_dmabuf_ops_vmap, .mmap = vb2_vmalloc_dmabuf_ops_mmap, .release = vb2_vmalloc_dmabuf_ops_release, }; -static struct dma_buf *vb2_vmalloc_get_dmabuf(void *buf_priv, unsigned long flags) +static struct dma_buf *vb2_vmalloc_get_dmabuf(struct vb2_buffer *vb, + void *buf_priv, + unsigned long flags) { struct vb2_vmalloc_buf *buf = buf_priv; struct dma_buf *dbuf; @@ -384,32 +368,41 @@ static struct dma_buf *vb2_vmalloc_get_dmabuf(void *buf_priv, unsigned long flag static int vb2_vmalloc_map_dmabuf(void *mem_priv) { struct vb2_vmalloc_buf *buf = mem_priv; + struct iosys_map map; + int ret; - buf->vaddr = dma_buf_vmap(buf->dbuf); + ret = dma_buf_vmap_unlocked(buf->dbuf, &map); + if (ret) + return -EFAULT; + buf->vaddr = map.vaddr; - return buf->vaddr ? 0 : -EFAULT; + return 0; } static void vb2_vmalloc_unmap_dmabuf(void *mem_priv) { struct vb2_vmalloc_buf *buf = mem_priv; + struct iosys_map map = IOSYS_MAP_INIT_VADDR(buf->vaddr); - dma_buf_vunmap(buf->dbuf, buf->vaddr); + dma_buf_vunmap_unlocked(buf->dbuf, &map); buf->vaddr = NULL; } static void vb2_vmalloc_detach_dmabuf(void *mem_priv) { struct vb2_vmalloc_buf *buf = mem_priv; + struct iosys_map map = IOSYS_MAP_INIT_VADDR(buf->vaddr); if (buf->vaddr) - dma_buf_vunmap(buf->dbuf, buf->vaddr); + dma_buf_vunmap_unlocked(buf->dbuf, &map); kfree(buf); } -static void *vb2_vmalloc_attach_dmabuf(struct device *dev, struct dma_buf *dbuf, - unsigned long size, enum dma_data_direction dma_dir) +static void *vb2_vmalloc_attach_dmabuf(struct vb2_buffer *vb, + struct device *dev, + struct dma_buf *dbuf, + unsigned long size) { struct vb2_vmalloc_buf *buf; @@ -421,7 +414,7 @@ static void *vb2_vmalloc_attach_dmabuf(struct device *dev, struct dma_buf *dbuf, return ERR_PTR(-ENOMEM); buf->dbuf = dbuf; - buf->dma_dir = dma_dir; + buf->dma_dir = vb->vb2_queue->dma_dir; buf->size = size; return buf; @@ -449,3 +442,4 @@ EXPORT_SYMBOL_GPL(vb2_vmalloc_memops); MODULE_DESCRIPTION("vmalloc memory handling routines for videobuf2"); MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>"); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS("DMA_BUF"); |
