From: Cho KyongHo Date: Mon, 10 Oct 2016 14:23:54 +0000 (+0900) Subject: [COMMON] media: m2m1shot: use exynos_iovmm_map_userptr() X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=7dad5ee207d8a6adc2592226b55858f56a25f048;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git [COMMON] media: m2m1shot: use exynos_iovmm_map_userptr() Pinning user buffer with get_user_pages() is very time-consuming. Discard using get_user_pages() and get benefit from exynos_iovmm_map_userptr(). Change-Id: I68c5a2c082d18e930cbc4908914d1af4e19ab7a0 Signed-off-by: Cho KyongHo --- diff --git a/drivers/media/m2m1shot-helper.c b/drivers/media/m2m1shot-helper.c index 545b071352ab..4d9925c4d008 100644 --- a/drivers/media/m2m1shot-helper.c +++ b/drivers/media/m2m1shot-helper.c @@ -37,12 +37,6 @@ int m2m1shot_map_dma_buf(struct device *dev, __func__); return PTR_ERR(plane->sgt); } - - exynos_ion_sync_dmabuf_for_device(dev, plane->dmabuf, - plane->bytes_used, dir); - } else { /* userptr */ - exynos_ion_sync_sg_for_device(dev, plane->bytes_used, - plane->sgt, dir); } return 0; @@ -53,14 +47,8 @@ void m2m1shot_unmap_dma_buf(struct device *dev, struct m2m1shot_buffer_plane_dma *plane, enum dma_data_direction dir) { - if (plane->dmabuf) { - exynos_ion_sync_dmabuf_for_cpu(dev, plane->dmabuf, - plane->bytes_used, dir); + if (plane->dmabuf) dma_buf_unmap_attachment(plane->attachment, plane->sgt, dir); - } else { - exynos_ion_sync_sg_for_cpu(dev, plane->bytes_used, - plane->sgt, dir); - } } EXPORT_SYMBOL(m2m1shot_unmap_dma_buf); @@ -75,8 +63,16 @@ int m2m1shot_dma_addr_map(struct device *dev, iova = ion_iovmm_map(plane->attachment, 0, plane->bytes_used, dir, 0); } else { - iova = iovmm_map(dev, plane->sgt->sgl, 0, - plane->bytes_used, dir, 0); + int prot = IOMMU_READ; + + if (dir == DMA_FROM_DEVICE) + prot |= IOMMU_WRITE; + + down_read(¤t->mm->mmap_sem); + iova = exynos_iovmm_map_userptr(dev, + buf->buffer->plane[plane_idx].userptr, + plane->bytes_used, prot); + up_read(¤t->mm->mmap_sem); } if (IS_ERR_VALUE(iova)) @@ -96,7 +92,33 @@ void m2m1shot_dma_addr_unmap(struct device *dev, if (plane->dmabuf) ion_iovmm_unmap(plane->attachment, dma_addr); else - iovmm_unmap(dev, dma_addr); + exynos_iovmm_unmap_userptr(dev, dma_addr); plane->dma_addr = 0; } + +void m2m1shot_sync_for_device(struct device *dev, + struct m2m1shot_buffer_plane_dma *plane, + enum dma_data_direction dir) +{ + if (plane->dmabuf) + dma_sync_sg_for_device(dev, plane->sgt->sgl, + plane->sgt->orig_nents, dir); + else + exynos_iommu_sync_for_device(dev, plane->dma_addr, + plane->bytes_used, dir); +} +EXPORT_SYMBOL(m2m1shot_sync_for_device); + +void m2m1shot_sync_for_cpu(struct device *dev, + struct m2m1shot_buffer_plane_dma *plane, + enum dma_data_direction dir) +{ + if (plane->dmabuf) + dma_sync_sg_for_cpu(dev, plane->sgt->sgl, + plane->sgt->orig_nents, dir); + else + exynos_iommu_sync_for_cpu(dev, plane->dma_addr, + plane->bytes_used, dir); +} +EXPORT_SYMBOL(m2m1shot_sync_for_cpu); diff --git a/drivers/media/m2m1shot.c b/drivers/media/m2m1shot.c index 926ae3f47b2c..c9ea2d1c9bc0 100644 --- a/drivers/media/m2m1shot.c +++ b/drivers/media/m2m1shot.c @@ -179,213 +179,6 @@ err: return ret; } -static int m2m1shot_buffer_get_userptr_plane(struct m2m1shot_device *m21dev, - struct m2m1shot_buffer_plane_dma *plane, - unsigned long start, size_t len, int write) -{ - size_t last_size = 0; - struct page **pages; - int nr_pages = 0; - int ret = 0, i; - off_t start_off; - struct scatterlist *sgl; - - last_size = (start + len) & ~PAGE_MASK; - if (last_size == 0) - last_size = PAGE_SIZE; - - start_off = offset_in_page(start); - - start = round_down(start, PAGE_SIZE); - - nr_pages = PFN_DOWN(PAGE_ALIGN(len + start_off)); - - pages = vmalloc(nr_pages * sizeof(*pages)); - if (!pages) - return -ENOMEM; - - ret = get_user_pages_fast(start, nr_pages, write, pages); - if (ret != nr_pages) { - dev_err(m21dev->dev, - "%s: failed to pin user pages in %#lx ~ %#lx\n", - __func__, start, start + len); - - if (ret < 0) - goto err_get; - - nr_pages = ret; - ret = -EFAULT; - goto err_pin; - } - - plane->sgt = kmalloc(sizeof(*plane->sgt), GFP_KERNEL); - if (!plane->sgt) { - dev_err(m21dev->dev, - "%s: failed to allocate sgtable\n", __func__); - ret = -ENOMEM; - goto err_sgtable; - } - - ret = sg_alloc_table(plane->sgt, nr_pages, GFP_KERNEL); - if (ret) { - dev_err(m21dev->dev, - "%s: failed to allocate sglist\n", __func__); - goto err_sg; - } - - sgl = plane->sgt->sgl; - - sg_set_page(sgl, pages[0], - (nr_pages == 1) ? len : PAGE_SIZE - start_off, - start_off); - sg_dma_address(sgl) = page_to_phys(sg_page(sgl)); - - sgl = sg_next(sgl); - - /* nr_pages == 1 if sgl == NULL here */ - for (i = 1; i < (nr_pages - 1); i++) { - sg_set_page(sgl, pages[i], PAGE_SIZE, 0); - sg_dma_address(sgl) = page_to_phys(sg_page(sgl)); - sgl = sg_next(sgl); - } - - if (sgl) { - sg_set_page(sgl, pages[i], last_size, 0); - sg_dma_address(sgl) = page_to_phys(sg_page(sgl)); - } - - vfree(pages); - - return 0; -err_sg: - kfree(plane->sgt); -err_sgtable: -err_pin: - for (i = 0; i < nr_pages; i++) - put_page(pages[i]); -err_get: - vfree(pages); - - return ret; -} - -static void m2m1shot_buffer_put_userptr_plane( - struct m2m1shot_buffer_plane_dma *plane, int write) -{ - if (plane->dmabuf) { - m2m1shot_buffer_put_dma_buf_plane(plane); - } else { - struct sg_table *sgt = plane->sgt; - struct scatterlist *sg; - int i; - - for_each_sg(sgt->sgl, sg, sgt->orig_nents, i) { - if (write) - set_page_dirty_lock(sg_page(sg)); - put_page(sg_page(sg)); - } - - sg_free_table(sgt); - kfree(sgt); - } -} - -static struct dma_buf *m2m1shot_buffer_check_userptr( - struct m2m1shot_device *m21dev, unsigned long start, size_t len, - off_t *out_offset) -{ - struct dma_buf *dmabuf = NULL; - struct vm_area_struct *vma; - - down_read(¤t->mm->mmap_sem); - vma = find_vma(current->mm, start); - if (!vma || (start < vma->vm_start)) { - dev_err(m21dev->dev, "%s: Incorrect user buffer @ %#lx/%#zx\n", - __func__, start, len); - dmabuf = ERR_PTR(-EINVAL); - goto finish; - } - - if (!vma->vm_file) - goto finish; - - dmabuf = get_dma_buf_file(vma->vm_file); - if (dmabuf != NULL) - *out_offset = start - vma->vm_start; -finish: - up_read(¤t->mm->mmap_sem); - return dmabuf; -} - -static int m2m1shot_buffer_get_userptr(struct m2m1shot_device *m21dev, - struct m2m1shot_buffer *buffer, - struct m2m1shot_buffer_dma *dma_buffer, - int write) -{ - int i, ret = 0; - struct dma_buf *dmabuf; - off_t offset; - - for (i = 0; i < buffer->num_planes; i++) { - dmabuf = m2m1shot_buffer_check_userptr(m21dev, - buffer->plane[i].userptr, buffer->plane[i].len, - &offset); - if (IS_ERR(dmabuf)) { - ret = PTR_ERR(dmabuf); - goto err; - } else if (dmabuf) { - if (dmabuf->size < dma_buffer->plane[i].bytes_used) { - dev_err(m21dev->dev, - "%s: needs %zu bytes but dmabuf is %zu\n", - __func__, - dma_buffer->plane[i].bytes_used, - dmabuf->size); - ret = -EINVAL; - goto err; - } - - dma_buffer->plane[i].dmabuf = dmabuf; - dma_buffer->plane[i].attachment = dma_buf_attach( - dmabuf, m21dev->dev); - dma_buffer->plane[i].offset = offset; - if (IS_ERR(dma_buffer->plane[i].attachment)) { - dev_err(m21dev->dev, - "%s: Failed to attach dmabuf\n", - __func__); - ret = PTR_ERR(dma_buffer->plane[i].attachment); - dma_buf_put(dmabuf); - goto err; - } - } else { - ret = m2m1shot_buffer_get_userptr_plane(m21dev, - &dma_buffer->plane[i], - buffer->plane[i].userptr, - buffer->plane[i].len, - write); - } - - if (ret) - goto err; - } - - return 0; -err: - while (i-- > 0) - m2m1shot_buffer_put_userptr_plane(&dma_buffer->plane[i], write); - - return ret; -} - -static void m2m1shot_buffer_put_userptr(struct m2m1shot_buffer *buffer, - struct m2m1shot_buffer_dma *dma_buffer, - int write) -{ - int i; - - for (i = 0; i < buffer->num_planes; i++) - m2m1shot_buffer_put_userptr_plane(&dma_buffer->plane[i], write); -} - static int m2m1shot_prepare_get_buffer(struct m2m1shot_context *ctx, struct m2m1shot_buffer *buffer, struct m2m1shot_buffer_dma *dma_buffer, @@ -424,14 +217,11 @@ static int m2m1shot_prepare_get_buffer(struct m2m1shot_context *ctx, return -EINVAL; } - if (buffer->type == M2M1SHOT_BUFFER_DMABUF) + if (buffer->type == M2M1SHOT_BUFFER_DMABUF) { ret = m2m1shot_buffer_get_dma_buf(m21dev, buffer, dma_buffer); - else - ret = m2m1shot_buffer_get_userptr(m21dev, buffer, dma_buffer, - (dir == DMA_TO_DEVICE) ? 0 : 1); - - if (ret) - return ret; + if (ret) + return ret; + } dma_buffer->buffer = buffer; @@ -451,9 +241,6 @@ err: if (buffer->type == M2M1SHOT_BUFFER_DMABUF) m2m1shot_buffer_put_dma_buf(buffer, dma_buffer); - else - m2m1shot_buffer_put_userptr(buffer, dma_buffer, - (dir == DMA_TO_DEVICE) ? 0 : 1); return ret; } @@ -471,9 +258,6 @@ static void m2m1shot_finish_buffer(struct m2m1shot_device *m21dev, if (buffer->type == M2M1SHOT_BUFFER_DMABUF) m2m1shot_buffer_put_dma_buf(buffer, dma_buffer); - else - m2m1shot_buffer_put_userptr(buffer, dma_buffer, - (dir == DMA_TO_DEVICE) ? 0 : 1); } static int m2m1shot_prepare_format(struct m2m1shot_device *m21dev, diff --git a/include/media/m2m1shot-helper.h b/include/media/m2m1shot-helper.h index 0778d3b8e7d6..61318cee3ae9 100644 --- a/include/media/m2m1shot-helper.h +++ b/include/media/m2m1shot-helper.h @@ -43,6 +43,14 @@ int m2m1shot_dma_addr_map(struct device *dev, void m2m1shot_dma_addr_unmap(struct device *dev, struct m2m1shot_buffer_dma *buf, int plane_idx); +void m2m1shot_sync_for_device(struct device *dev, + struct m2m1shot_buffer_plane_dma *plane, + enum dma_data_direction dir); + +void m2m1shot_sync_for_cpu(struct device *dev, + struct m2m1shot_buffer_plane_dma *plane, + enum dma_data_direction dir); + static inline dma_addr_t m2m1shot_dma_address( struct m2m1shot_buffer_plane_dma *plane) {