Commit a5ed8940 authored by Laurent Pinchart's avatar Laurent Pinchart

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: default avatarLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: default avatarRob Clark <robdclark@gmail.com>
parent bda3fdaa
...@@ -32,62 +32,73 @@ static unsigned int get_gem_mmap_offset(struct drm_gem_object *obj) ...@@ -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; 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 * This function creates and initializes a GEM CMA object of the given size, but
* on failure. * 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, static struct drm_gem_cma_object *
unsigned int size) __drm_gem_cma_create(struct drm_device *drm, unsigned int size)
{ {
struct drm_gem_cma_object *cma_obj; struct drm_gem_cma_object *cma_obj;
struct drm_gem_object *gem_obj; struct drm_gem_object *gem_obj;
int ret; int ret;
size = round_up(size, PAGE_SIZE);
cma_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL); cma_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL);
if (!cma_obj) if (!cma_obj)
return ERR_PTR(-ENOMEM); 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; gem_obj = &cma_obj->base;
ret = drm_gem_object_init(drm, gem_obj, size); ret = drm_gem_object_init(drm, gem_obj, size);
if (ret) if (ret)
goto err_obj_init; goto error;
ret = drm_gem_create_mmap_offset(gem_obj); ret = drm_gem_create_mmap_offset(gem_obj);
if (ret) if (ret) {
goto err_create_mmap_offset; drm_gem_object_release(gem_obj);
goto error;
}
return cma_obj; return cma_obj;
err_create_mmap_offset: error:
drm_gem_object_release(gem_obj); 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: size = round_up(size, PAGE_SIZE);
kfree(cma_obj);
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); EXPORT_SYMBOL_GPL(drm_gem_cma_create);
...@@ -143,11 +154,13 @@ void drm_gem_cma_free_object(struct drm_gem_object *gem_obj) ...@@ -143,11 +154,13 @@ void drm_gem_cma_free_object(struct drm_gem_object *gem_obj)
if (gem_obj->map_list.map) if (gem_obj->map_list.map)
drm_gem_free_mmap_offset(gem_obj); drm_gem_free_mmap_offset(gem_obj);
drm_gem_object_release(gem_obj);
cma_obj = to_drm_gem_cma_obj(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); kfree(cma_obj);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment