__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;
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);
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))
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);
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,
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;
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;
}
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,