[COMMON] media: m2m1shot: use exynos_iovmm_map_userptr()
authorCho KyongHo <pullip.cho@samsung.com>
Mon, 10 Oct 2016 14:23:54 +0000 (23:23 +0900)
committerSeungchul Kim <sc377.kim@samsung.com>
Mon, 28 May 2018 05:28:13 +0000 (14:28 +0900)
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 <pullip.cho@samsung.com>
drivers/media/m2m1shot-helper.c
drivers/media/m2m1shot.c
include/media/m2m1shot-helper.h

index 545b071352ab73b0a9925a035504dd792b0bcd07..4d9925c4d00801cf2315fdbf834f56ba5c46a21d 100644 (file)
@@ -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(&current->mm->mmap_sem);
+               iova = exynos_iovmm_map_userptr(dev,
+                               buf->buffer->plane[plane_idx].userptr,
+                               plane->bytes_used, prot);
+               up_read(&current->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);
index 926ae3f47b2ca17f7218f20f0240a9e43f162d4d..c9ea2d1c9bc03bba72467ca7c3dfd156611ae495 100644 (file)
@@ -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(&current->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(&current->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,
index 0778d3b8e7d6488fe37f4872dc23d204694d8df9..61318cee3ae94ed1e8ed3d87e519293d4f7ebf07 100644 (file)
@@ -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)
 {