aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2013-04-24 03:34:18 -0400
committerBen Skeggs <bskeggs@redhat.com>2013-04-26 01:37:57 -0400
commitdb91d68c9b5ca22e1fa25569bbde4895ade9dac0 (patch)
tree761803aca660b59a9cc71cfd60cd4c3388213400 /drivers/gpu/drm/nouveau
parent43e6e51c037cafac5047a65cfa9d37b450157af1 (diff)
drm/nouveau/core: rebase object ref/use counts after ctor/init/fini events
This is intended to support named (with a handle, etc) objects having children that don't have an outside reference. This will replace the various hacks around the place where subdev objects have children, and have to manually drop the self-refs so that they can be destroyed etc when all the outside refs have gone. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau')
-rw-r--r--drivers/gpu/drm/nouveau/core/core/object.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/drivers/gpu/drm/nouveau/core/core/object.c b/drivers/gpu/drm/nouveau/core/core/object.c
index 3b2e7b6304d3..7f48e288215f 100644
--- a/drivers/gpu/drm/nouveau/core/core/object.c
+++ b/drivers/gpu/drm/nouveau/core/core/object.c
@@ -136,26 +136,30 @@ nouveau_object_ctor(struct nouveau_object *parent,
136 struct nouveau_object **pobject) 136 struct nouveau_object **pobject)
137{ 137{
138 struct nouveau_ofuncs *ofuncs = oclass->ofuncs; 138 struct nouveau_ofuncs *ofuncs = oclass->ofuncs;
139 struct nouveau_object *object = NULL;
139 int ret; 140 int ret;
140 141
141 *pobject = NULL; 142 ret = ofuncs->ctor(parent, engine, oclass, data, size, &object);
142 143 *pobject = object;
143 ret = ofuncs->ctor(parent, engine, oclass, data, size, pobject);
144 if (ret < 0) { 144 if (ret < 0) {
145 if (ret != -ENODEV) { 145 if (ret != -ENODEV) {
146 nv_error(parent, "failed to create 0x%08x, %d\n", 146 nv_error(parent, "failed to create 0x%08x, %d\n",
147 oclass->handle, ret); 147 oclass->handle, ret);
148 } 148 }
149 149
150 if (*pobject) { 150 if (object) {
151 ofuncs->dtor(*pobject); 151 ofuncs->dtor(object);
152 *pobject = NULL; 152 *pobject = NULL;
153 } 153 }
154 154
155 return ret; 155 return ret;
156 } 156 }
157 157
158 nv_debug(*pobject, "created\n"); 158 if (ret == 0) {
159 nv_debug(object, "created\n");
160 atomic_set(&object->refcount, 1);
161 }
162
159 return 0; 163 return 0;
160} 164}
161 165
@@ -327,6 +331,7 @@ nouveau_object_inc(struct nouveau_object *object)
327 } 331 }
328 332
329 ret = nv_ofuncs(object)->init(object); 333 ret = nv_ofuncs(object)->init(object);
334 atomic_set(&object->usecount, 1);
330 if (ret) { 335 if (ret) {
331 nv_error(object, "init failed, %d\n", ret); 336 nv_error(object, "init failed, %d\n", ret);
332 goto fail_self; 337 goto fail_self;
@@ -357,6 +362,7 @@ nouveau_object_decf(struct nouveau_object *object)
357 nv_trace(object, "stopping...\n"); 362 nv_trace(object, "stopping...\n");
358 363
359 ret = nv_ofuncs(object)->fini(object, false); 364 ret = nv_ofuncs(object)->fini(object, false);
365 atomic_set(&object->usecount, 0);
360 if (ret) 366 if (ret)
361 nv_warn(object, "failed fini, %d\n", ret); 367 nv_warn(object, "failed fini, %d\n", ret);
362 368
@@ -381,6 +387,7 @@ nouveau_object_decs(struct nouveau_object *object)
381 nv_trace(object, "suspending...\n"); 387 nv_trace(object, "suspending...\n");
382 388
383 ret = nv_ofuncs(object)->fini(object, true); 389 ret = nv_ofuncs(object)->fini(object, true);
390 atomic_set(&object->usecount, 0);
384 if (ret) { 391 if (ret) {
385 nv_error(object, "failed suspend, %d\n", ret); 392 nv_error(object, "failed suspend, %d\n", ret);
386 return ret; 393 return ret;