[PATCH] DRM: add drm gem CMA helper

Laurent Pinchart laurent.pinchart at ideasonboard.com
Wed May 30 08:40:13 PDT 2012


Hi Sascha,

Thank you for the patch. I've successfully tested the helper with the new SH 
Mobile DRM driver. Just a couple of comments below in addition to Lars' 
comments (this is not a full review, just details that caught my attention 
when comparing the code with my implementation, and trying to use it).

On Tuesday 29 May 2012 16:10:27 Sascha Hauer wrote:
> Many embedded drm devices do not have a IOMMU and no dedicated
> memory for graphics. These devices use CMA (Contiguous Memory
> Allocator) backed graphics memory. This patch provides helper
> functions to be able to share the code.
> 
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> ---
> 
> Lars-Peter, please let me know if this fits your needs or if you are missing
> something.
> 
>  drivers/gpu/drm/Kconfig              |    6 +
>  drivers/gpu/drm/Makefile             |    1 +
>  drivers/gpu/drm/drm_gem_cma_helper.c |  321 +++++++++++++++++++++++++++++++
>  include/drm/drm_gem_cma_helper.h     |   47 +++++
>  4 files changed, 375 insertions(+)
>  create mode 100644 drivers/gpu/drm/drm_gem_cma_helper.c
>  create mode 100644 include/drm/drm_gem_cma_helper.h

[snip]

> diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c
> b/drivers/gpu/drm/drm_gem_cma_helper.c new file mode 100644
> index 0000000..75534ff
> --- /dev/null
> +++ b/drivers/gpu/drm/drm_gem_cma_helper.c
> @@ -0,0 +1,321 @@

[snip]

> +/*
> + * drm_gem_cma_create - allocate an object with the given size
> + *
> + * returns a struct drm_gem_cma_obj* on success or ERR_PTR values
> + * on failure.
> + */
> +struct drm_gem_cma_obj *drm_gem_cma_create(struct drm_device *drm,
> +		unsigned int size)
> +{
> +	struct drm_gem_cma_obj *cma_obj;
> +	struct drm_gem_object *gem_obj;
> +	int ret;
> +
> +	size = roundup(size, PAGE_SIZE);

As PAGE_SIZE is guaranteed to be a power of two, you can use round_up, which 
should be faster.

> +
> +	cma_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL);
> +	if (!cma_obj)
> +		return ERR_PTR(-ENOMEM);
> +
> +	cma_obj->vaddr = dma_alloc_writecombine(drm->dev, size,
> +			(dma_addr_t *)&cma_obj->paddr,
> +			GFP_KERNEL | __GFP_NOWARN);
> +	if (!cma_obj->vaddr) {
> +		dev_err(drm->dev, "failed to allocate buffer with size %d\n", size);
> +		ret = -ENOMEM;
> +		goto err_dma_alloc;
> +	}
> +
> +	gem_obj = &cma_obj->base;
> +
> +	ret = drm_gem_object_init(drm, gem_obj, size);
> +	if (ret)
> +		goto err_obj_init;
> +
> +	ret = drm_gem_create_mmap_offset(gem_obj);
> +	if (ret)
> +		goto err_create_mmap_offset;
> +
> +	return cma_obj;
> +
> +err_create_mmap_offset:
> +	drm_gem_object_release(gem_obj);
> +
> +err_obj_init:
> +	drm_gem_cma_buf_destroy(drm, cma_obj);
> +
> +err_dma_alloc:
> +	kfree(cma_obj);
> +
> +	return ERR_PTR(ret);
> +}
> +EXPORT_SYMBOL_GPL(drm_gem_cma_create);

[snip]

> +/*
> + * drm_gem_cma_mmap - (struct file_operation)->mmap callback function
> + */
> +int drm_gem_cma_mmap(struct file *filp, struct vm_area_struct *vma)
> +{
> +	int ret;
> +
> +	ret = drm_gem_mmap(filp, vma);
> +	if (ret)
> +		return ret;
> +
> +	vma->vm_flags &= ~VM_PFNMAP;
> +	vma->vm_flags |= VM_MIXEDMAP;

Why is this a mixed map ?

> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(drm_gem_cma_mmap);

My implementation maps the whole buffer in one go at mmap time, not page by 
page at page fault time. Isn't that more efficient when mapping frame buffer 
memory ?

[snip]

> diff --git a/include/drm/drm_gem_cma_helper.h
> b/include/drm/drm_gem_cma_helper.h new file mode 100644
> index 0000000..53b007c
> --- /dev/null
> +++ b/include/drm/drm_gem_cma_helper.h
> @@ -0,0 +1,47 @@
> +#ifndef __DRM_GEM_DMA_ALLOC_HELPER_H__
> +#define __DRM_GEM_DMA_ALLOC_HELPER_H__

Should this be __DRM_GEM_CMA_HELPER_H__ ?

> +
> +struct drm_gem_cma_obj {
> +	struct drm_gem_object base;
> +	dma_addr_t paddr;
> +	void __iomem *vaddr;
> +};

All drm objects end with _object, would it be better to rename this to struct 
drm_gem_cma_object ?

-- 
Regards,

Laurent Pinchart



More information about the dri-devel mailing list