summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2015-11-24 09:28:23 +1000
committerBen Skeggs <bskeggs@redhat.com>2015-12-22 13:22:10 +1000
commit343d1ee83e8bf833b575cc1df097d5202e11b8e8 (patch)
tree2629c09ecac05b825017025e4eb18a6ede14110c
parent0996ad0e12a25841f350b8c5cacccff3d0aa24d2 (diff)
downloaddrm-343d1ee83e8bf833b575cc1df097d5202e11b8e8.tar.gz
nouveau: make it possible to init object in pre-allocated memory
Required for an upcoming patch, not exposed to library clients. Signed-off-by: Ben Skeggs <bskeggs@redhat.com> Tested-by: Samuel Pitoiset <samuel.pitoiset@gmail.com> Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>
-rw-r--r--nouveau/nouveau.c64
1 files changed, 48 insertions, 16 deletions
diff --git a/nouveau/nouveau.c b/nouveau/nouveau.c
index 8035c6a0..eb741c7d 100644
--- a/nouveau/nouveau.c
+++ b/nouveau/nouveau.c
@@ -59,31 +59,63 @@ debug_init(char *args)
}
#endif
-int
-nouveau_object_new(struct nouveau_object *parent, uint64_t handle,
- uint32_t oclass, void *data, uint32_t length,
- struct nouveau_object **pobj)
+static void
+nouveau_object_fini(struct nouveau_object *obj)
+{
+ if (obj->data) {
+ abi16_delete(obj);
+ free(obj->data);
+ obj->data = NULL;
+ return;
+ }
+}
+
+static int
+nouveau_object_init(struct nouveau_object *parent, uint32_t handle,
+ int32_t oclass, void *data, uint32_t size,
+ struct nouveau_object *obj)
{
- struct nouveau_object *obj;
int (*func)(struct nouveau_object *);
- int ret = -EINVAL;
+ int ret = -ENOSYS;
- if (length == 0)
- length = sizeof(struct nouveau_object *);
- obj = malloc(sizeof(*obj) + length);
obj->parent = parent;
obj->handle = handle;
obj->oclass = oclass;
- obj->length = length;
- obj->data = obj + 1;
- if (data)
- memcpy(obj->data, data, length);
- *(struct nouveau_object **)obj->data = obj;
+ obj->length = 0;
+ obj->data = NULL;
abi16_object(obj, &func);
- if (func)
+ if (func) {
+ obj->length = size ? size : sizeof(struct nouveau_object *);
+ if (!(obj->data = malloc(obj->length)))
+ return -ENOMEM;
+ if (data)
+ memcpy(obj->data, data, obj->length);
+ *(struct nouveau_object **)obj->data = obj;
+
ret = func(obj);
+ }
+
+ if (ret) {
+ nouveau_object_fini(obj);
+ return ret;
+ }
+
+ return 0;
+}
+
+int
+nouveau_object_new(struct nouveau_object *parent, uint64_t handle,
+ uint32_t oclass, void *data, uint32_t length,
+ struct nouveau_object **pobj)
+{
+ struct nouveau_object *obj;
+ int ret;
+
+ if (!(obj = malloc(sizeof(*obj))))
+ return -ENOMEM;
+ ret = nouveau_object_init(parent, handle, oclass, data, length, obj);
if (ret) {
free(obj);
return ret;
@@ -98,7 +130,7 @@ nouveau_object_del(struct nouveau_object **pobj)
{
struct nouveau_object *obj = *pobj;
if (obj) {
- abi16_delete(obj);
+ nouveau_object_fini(obj);
free(obj);
*pobj = NULL;
}