| From 05cf3547ea572cf46fe55f55d83b887bb9acb97c Mon Sep 17 00:00:00 2001 |
| From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> |
| Date: Sun, 17 Feb 2013 01:54:26 +0100 |
| Subject: drm: GEM CMA: Split object creation into object alloc and DMA memory |
| alloc |
| |
| This allows creating a GEM CMA object without an associated DMA memory |
| buffer, and will be used to implement DRM PRIME support. |
| |
| Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> |
| Reviewed-by: Rob Clark <robdclark@gmail.com> |
| (cherry picked from commit a5ed8940d3f99f05d460ce31583182539f07fa0e) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| --- |
| drivers/gpu/drm/drm_gem_cma_helper.c | 83 +++++++++++++++++++++--------------- |
| 1 file changed, 48 insertions(+), 35 deletions(-) |
| |
| diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c b/drivers/gpu/drm/drm_gem_cma_helper.c |
| index 0a7e011509bd..8cce3302b690 100644 |
| --- a/drivers/gpu/drm/drm_gem_cma_helper.c |
| +++ b/drivers/gpu/drm/drm_gem_cma_helper.c |
| @@ -32,62 +32,73 @@ static unsigned int get_gem_mmap_offset(struct drm_gem_object *obj) |
| return (unsigned int)obj->map_list.hash.key << PAGE_SHIFT; |
| } |
| |
| -static void drm_gem_cma_buf_destroy(struct drm_device *drm, |
| - struct drm_gem_cma_object *cma_obj) |
| -{ |
| - dma_free_writecombine(drm->dev, cma_obj->base.size, cma_obj->vaddr, |
| - cma_obj->paddr); |
| -} |
| - |
| /* |
| - * drm_gem_cma_create - allocate an object with the given size |
| + * __drm_gem_cma_create - Create a GEM CMA object without allocating memory |
| + * @drm: The drm device |
| + * @size: The GEM object size |
| * |
| - * returns a struct drm_gem_cma_object* on success or ERR_PTR values |
| - * on failure. |
| + * This function creates and initializes a GEM CMA object of the given size, but |
| + * doesn't allocate any memory to back the object. |
| + * |
| + * Return a struct drm_gem_cma_object* on success or ERR_PTR values on failure. |
| */ |
| -struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm, |
| - unsigned int size) |
| +static struct drm_gem_cma_object * |
| +__drm_gem_cma_create(struct drm_device *drm, unsigned int size) |
| { |
| struct drm_gem_cma_object *cma_obj; |
| struct drm_gem_object *gem_obj; |
| int ret; |
| |
| - size = round_up(size, PAGE_SIZE); |
| - |
| cma_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL); |
| if (!cma_obj) |
| return ERR_PTR(-ENOMEM); |
| |
| - cma_obj->vaddr = dma_alloc_writecombine(drm->dev, size, |
| - &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; |
| + goto error; |
| |
| ret = drm_gem_create_mmap_offset(gem_obj); |
| - if (ret) |
| - goto err_create_mmap_offset; |
| + if (ret) { |
| + drm_gem_object_release(gem_obj); |
| + goto error; |
| + } |
| |
| return cma_obj; |
| |
| -err_create_mmap_offset: |
| - drm_gem_object_release(gem_obj); |
| +error: |
| + kfree(cma_obj); |
| + return ERR_PTR(ret); |
| +} |
| |
| -err_obj_init: |
| - drm_gem_cma_buf_destroy(drm, cma_obj); |
| +/* |
| + * drm_gem_cma_create - allocate an object with the given size |
| + * |
| + * returns a struct drm_gem_cma_object* on success or ERR_PTR values |
| + * on failure. |
| + */ |
| +struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm, |
| + unsigned int size) |
| +{ |
| + struct drm_gem_cma_object *cma_obj; |
| |
| -err_dma_alloc: |
| - kfree(cma_obj); |
| + size = round_up(size, PAGE_SIZE); |
| |
| - return ERR_PTR(ret); |
| + cma_obj = __drm_gem_cma_create(drm, size); |
| + if (IS_ERR(cma_obj)) |
| + return cma_obj; |
| + |
| + cma_obj->vaddr = dma_alloc_writecombine(drm->dev, size, |
| + &cma_obj->paddr, GFP_KERNEL | __GFP_NOWARN); |
| + if (!cma_obj->vaddr) { |
| + dev_err(drm->dev, "failed to allocate buffer with size %d\n", |
| + size); |
| + drm_gem_cma_free_object(&cma_obj->base); |
| + return ERR_PTR(-ENOMEM); |
| + } |
| + |
| + return cma_obj; |
| } |
| EXPORT_SYMBOL_GPL(drm_gem_cma_create); |
| |
| @@ -143,11 +154,13 @@ void drm_gem_cma_free_object(struct drm_gem_object *gem_obj) |
| if (gem_obj->map_list.map) |
| drm_gem_free_mmap_offset(gem_obj); |
| |
| - drm_gem_object_release(gem_obj); |
| - |
| cma_obj = to_drm_gem_cma_obj(gem_obj); |
| |
| - drm_gem_cma_buf_destroy(gem_obj->dev, cma_obj); |
| + if (cma_obj->vaddr) |
| + dma_free_writecombine(gem_obj->dev->dev, cma_obj->base.size, |
| + cma_obj->vaddr, cma_obj->paddr); |
| + |
| + drm_gem_object_release(gem_obj); |
| |
| kfree(cma_obj); |
| } |
| -- |
| 1.8.5.rc3 |
| |