GEM objects get mapped to user space in two ways - DIRECT and
INDIRECT mapping. DIRECT mapping is by calling an ioctl and it
maps all the pages to user space by calling remap-pfn-range.
Indirect mapping is done by calling 'mmap'. The actual mapping
is done when a page fault gets generated and is handled by
exynos_drm_gem_fault function where the required page is mapped.
Both the methods assume contiguous memory.

With this change, the mapping is done by dma_mmap_writecombine
which will support mapping of non-contiguous memory to user space.

This works similar to the previous approach for the case of
DIRECT mapping. But in the case of mapping when a page fault
occurs, dma_mmap_writecombine will map all the pages and not just
one page.

Signed-off-by: Prathyush K <prathyus...@samsung.com>
---
 drivers/gpu/drm/exynos/exynos_drm_gem.c |   70 ++++++++++++++----------------
 1 files changed, 33 insertions(+), 37 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c 
b/drivers/gpu/drm/exynos/exynos_drm_gem.c
index 807143e..a57a83a 100755
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
@@ -200,40 +200,27 @@ static int exynos_drm_gem_mmap_buffer(struct file *filp,
 {
        struct drm_gem_object *obj = filp->private_data;
        struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
-       struct exynos_drm_gem_buf *buffer;
-       unsigned long pfn, vm_size;
-
-       DRM_DEBUG_KMS("%s\n", __FILE__);
+       void *kva;
+       dma_addr_t dma_address;
+       unsigned long ret;
 
-       vma->vm_flags |= (VM_IO | VM_RESERVED);
+       kva = exynos_gem_obj->buffer->kvaddr;
 
-       /* in case of direct mapping, always having non-cachable attribute */
-       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-       vma->vm_file = filp;
-
-       vm_size = vma->vm_end - vma->vm_start;
-       /*
-        * a buffer contains information to physically continuous memory
-        * allocated by user request or at framebuffer creation.
-        */
-       buffer = exynos_gem_obj->buffer;
-
-       /* check if user-requested size is valid. */
-       if (vm_size > buffer->size)
-               return -EINVAL;
+       if (kva == NULL) {
+               DRM_ERROR("No KVA Found\n");
+               return -EAGAIN;
+       }
 
-       /*
-        * get page frame number to physical memory to be mapped
-        * to user space.
-        */
-       pfn = ((unsigned long)exynos_gem_obj->buffer->dma_addr) >> PAGE_SHIFT;
+       dma_address = exynos_gem_obj->buffer->dma_addr;
+       vma->vm_flags           |= VM_DONTEXPAND | VM_RESERVED;
+       vma->vm_pgoff = 0;
 
-       DRM_DEBUG_KMS("pfn = 0x%lx\n", pfn);
+       ret = dma_mmap_writecombine(obj->dev->dev, vma, kva,
+                               dma_address, vma->vm_end - vma->vm_start);
 
-       if (remap_pfn_range(vma, vma->vm_start, pfn, vm_size,
-                               vma->vm_page_prot)) {
-               DRM_ERROR("failed to remap pfn range.\n");
-               return -EAGAIN;
+       if (ret) {
+               DRM_ERROR("Remapping memory failed, error: %ld\n", ret);
+               return ret;
        }
 
        return 0;
@@ -433,19 +420,29 @@ int exynos_drm_gem_fault(struct vm_area_struct *vma, 
struct vm_fault *vmf)
        struct drm_gem_object *obj = vma->vm_private_data;
        struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
        struct drm_device *dev = obj->dev;
-       unsigned long pfn;
-       pgoff_t page_offset;
+       void *kva;
+       dma_addr_t dma_address;
        int ret;
 
-       page_offset = ((unsigned long)vmf->virtual_address -
-                       vma->vm_start) >> PAGE_SHIFT;
+       kva = exynos_gem_obj->buffer->kvaddr;
+
+       if (kva == NULL) {
+               DRM_ERROR("No KVA Found\n");
+               return -EAGAIN;
+       }
 
        mutex_lock(&dev->struct_mutex);
 
-       pfn = (((unsigned long)exynos_gem_obj->buffer->dma_addr) >>
-                       PAGE_SHIFT) + page_offset;
 
-       ret = vm_insert_mixed(vma, (unsigned long)vmf->virtual_address, pfn);
+       dma_address = exynos_gem_obj->buffer->dma_addr;
+       vma->vm_flags           |= VM_DONTEXPAND | VM_RESERVED;
+       vma->vm_pgoff = 0;
+
+       ret = dma_mmap_writecombine(obj->dev->dev, vma, kva,
+                               dma_address, vma->vm_end - vma->vm_start);
+
+       if (ret)
+               DRM_ERROR("Remapping memory failed, error: %d\n", ret);
 
        mutex_unlock(&dev->struct_mutex);
 
@@ -457,7 +454,6 @@ int exynos_drm_gem_mmap(struct file *filp, struct 
vm_area_struct *vma)
        int ret;
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
-
        /* set vm_area_struct. */
        ret = drm_gem_mmap(filp, vma);
        if (ret < 0) {
-- 
1.7.0.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to