diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2015-11-24 09:28:23 +1000 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2015-12-22 13:22:10 +1000 |
commit | 343d1ee83e8bf833b575cc1df097d5202e11b8e8 (patch) | |
tree | 2629c09ecac05b825017025e4eb18a6ede14110c | |
parent | 0996ad0e12a25841f350b8c5cacccff3d0aa24d2 (diff) |
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.c | 64 |
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; } |