diff mbox

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

Message ID 1334404333-24592-3-git-send-email-prathyush.k@samsung.com
State New
Headers show

Commit Message

Prathyush April 14, 2012, 11:52 a.m. UTC
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@samsung.com>
---
 drivers/gpu/drm/exynos/exynos_drm_gem.c |   70 ++++++++++++++----------------
 1 files changed, 33 insertions(+), 37 deletions(-)

Comments

Inki Dae April 16, 2012, 2:21 a.m. UTC | #1
Hi,

This is also patch set based on old version and the feature below has
already been merged to mainline. Prathyush, please DO WORK patch set based
on latest drm-next for new feature and drm-fixes for bug fixes from next
time and also include me as Maintainer.

Thanks,
Inki Dae.

> -----Original Message-----
> From: Prathyush [mailto:prathyush.k@samsung.com]
> Sent: Saturday, April 14, 2012 8:52 PM
> To: dri-devel@lists.freedesktop.org; linaro-mm-sig@lists.linaro.org
> Cc: inki.dae@samsung.com; subash.rp@samsung.com; prashanth.g@samsung.com;
> sunilm@samsung.com; prathyush.k@samsung.com
> Subject: [PATCH 2/4] [RFC] drm/exynos: Mapping of gem objects uses
> dma_mmap_writecombine
> 
> 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@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
diff mbox

Patch

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) {