[PATCH 2/4] [RFC] drm/exynos: Mapping of gem objects uses dma_mmap_writecombine

Prathyush prathyush.k at samsung.com
Sat Apr 14 04:52:11 PDT 2012


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 <prathyush.k at 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



More information about the dri-devel mailing list