@@ -2,6 +2,7 @@
* drm gem CMA (contiguous memory allocator) helper functions
*
* Copyright (C) 2012 Sascha Hauer, Pengutronix
+ * Copyright (C) 2013 NVIDIA CORPORATION, All rights reserved.
*
* Based on Samsung Exynos code
*
@@ -40,30 +41,25 @@ static void drm_gem_cma_buf_destroy(struct drm_device *drm,
}
/*
- * drm_gem_cma_create - allocate an object with the given size
+ * drm_gem_cma_object_init - allocate buffer and initialize given cma object
*
- * returns a struct drm_gem_cma_object* on success or ERR_PTR values
- * on failure.
+ * this function allocates memory for a cma buffer and initializes the given
+ * cma object to use the allocated buffer.
*/
-struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm,
- unsigned int size)
+
+int drm_gem_cma_object_init(struct drm_device *drm,
+ struct drm_gem_cma_object *cma_obj, 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;
+ return -ENOMEM;
}
gem_obj = &cma_obj->base;
@@ -76,7 +72,7 @@ struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm,
if (ret)
goto err_create_mmap_offset;
- return cma_obj;
+ return 0;
err_create_mmap_offset:
drm_gem_object_release(gem_obj);
@@ -84,10 +80,36 @@ err_create_mmap_offset:
err_obj_init:
drm_gem_cma_buf_destroy(drm, cma_obj);
-err_dma_alloc:
- kfree(cma_obj);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(drm_gem_cma_object_init);
+
+/*
+ * 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;
+ int ret;
+
+ size = round_up(size, PAGE_SIZE);
+
+ cma_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL);
+ if (!cma_obj)
+ return ERR_PTR(-ENOMEM);
+
+ ret = drm_gem_cma_object_init(drm, cma_obj, size);
+ if (ret) {
+ kfree(cma_obj);
+ return ERR_PTR(ret);
+ }
+
+ return cma_obj;
- return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(drm_gem_cma_create);
@@ -133,22 +155,32 @@ err_handle_create:
}
/*
- * drm_gem_cma_free_object - (struct drm_driver)->gem_free_object callback
- * function
+ * drm_gem_cma_deinit_object - deinitialize cma object
+ *
+ * this function deinitializes the given cma object without releasing the
+ * object memory. this function is a counterpart for the function
+ * drm_gem_cma_object_init().
*/
-void drm_gem_cma_free_object(struct drm_gem_object *gem_obj)
+void drm_gem_cma_object_deinit(struct drm_gem_object *gem_obj)
{
- struct drm_gem_cma_object *cma_obj;
+ struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(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);
+}
+EXPORT_SYMBOL_GPL(drm_gem_cma_object_deinit);
+/*
+ * drm_gem_cma_free_object - (struct drm_driver)->gem_free_object callback
+ * function
+ */
+void drm_gem_cma_free_object(struct drm_gem_object *gem_obj)
+{
+ struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(gem_obj);
+ drm_gem_cma_object_deinit(gem_obj);
kfree(cma_obj);
}
EXPORT_SYMBOL_GPL(drm_gem_cma_free_object);
@@ -13,6 +13,10 @@ to_drm_gem_cma_obj(struct drm_gem_object *gem_obj)
return container_of(gem_obj, struct drm_gem_cma_object, base);
}
+/* deinitialize gem object and release the buffer. this variant does not
+ * release the cma object memory */
+void drm_gem_cma_object_deinit(struct drm_gem_object *gem_obj);
+
/* free gem object. */
void drm_gem_cma_free_object(struct drm_gem_object *gem_obj);
@@ -35,6 +39,11 @@ int drm_gem_cma_mmap(struct file *filp, struct vm_area_struct *vma);
int drm_gem_cma_dumb_destroy(struct drm_file *file_priv,
struct drm_device *drm, unsigned int handle);
+/* allocate physical memory for a buffer and initialize already allocated
+ * to use the buffer */
+int drm_gem_cma_object_init(struct drm_device *drm,
+ struct drm_gem_cma_object *cma_obj, unsigned int size);
+
/* allocate physical memory. */
struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm,
unsigned int size);