2 * Copyright 2012 Red Hat Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
25 #include <core/object.h>
26 #include <core/engine.h>
28 #ifdef NOUVEAU_OBJECT_MAGIC
29 static struct list_head _objlist = LIST_HEAD_INIT(_objlist);
30 static DEFINE_SPINLOCK(_objlist_lock);
34 nouveau_object_create_(struct nouveau_object *parent,
35 struct nouveau_object *engine,
36 struct nouveau_oclass *oclass, u32 pclass,
37 int size, void **pobject)
39 struct nouveau_object *object;
41 object = *pobject = kzalloc(size, GFP_KERNEL);
45 nouveau_object_ref(parent, &object->parent);
46 nouveau_object_ref(engine, &object->engine);
47 object->oclass = oclass;
48 object->oclass->handle |= pclass;
49 atomic_set(&object->refcount, 1);
50 atomic_set(&object->usecount, 0);
52 #ifdef NOUVEAU_OBJECT_MAGIC
53 object->_magic = NOUVEAU_OBJECT_MAGIC;
54 spin_lock(&_objlist_lock);
55 list_add(&object->list, &_objlist);
56 spin_unlock(&_objlist_lock);
62 _nouveau_object_ctor(struct nouveau_object *parent,
63 struct nouveau_object *engine,
64 struct nouveau_oclass *oclass, void *data, u32 size,
65 struct nouveau_object **pobject)
69 return nouveau_object_create(parent, engine, oclass, 0, pobject);
73 nouveau_object_destroy(struct nouveau_object *object)
75 #ifdef NOUVEAU_OBJECT_MAGIC
76 spin_lock(&_objlist_lock);
77 list_del(&object->list);
78 spin_unlock(&_objlist_lock);
80 nouveau_object_ref(NULL, &object->engine);
81 nouveau_object_ref(NULL, &object->parent);
86 nouveau_object_init(struct nouveau_object *object)
92 nouveau_object_fini(struct nouveau_object *object, bool suspend)
98 nouveau_object_ofuncs = {
99 .ctor = _nouveau_object_ctor,
100 .dtor = nouveau_object_destroy,
101 .init = nouveau_object_init,
102 .fini = nouveau_object_fini,
106 nouveau_object_ctor(struct nouveau_object *parent,
107 struct nouveau_object *engine,
108 struct nouveau_oclass *oclass, void *data, u32 size,
109 struct nouveau_object **pobject)
111 struct nouveau_ofuncs *ofuncs = oclass->ofuncs;
112 struct nouveau_object *object = NULL;
115 ret = ofuncs->ctor(parent, engine, oclass, data, size, &object);
118 if (ret != -ENODEV) {
119 nv_error(parent, "failed to create 0x%08x, %d\n",
120 oclass->handle, ret);
124 ofuncs->dtor(object);
132 nv_trace(object, "created\n");
133 atomic_set(&object->refcount, 1);
140 nouveau_object_dtor(struct nouveau_object *object)
142 nv_trace(object, "destroying\n");
143 nv_ofuncs(object)->dtor(object);
147 nouveau_object_ref(struct nouveau_object *obj, struct nouveau_object **ref)
150 atomic_inc(&obj->refcount);
151 nv_trace(obj, "inc() == %d\n", atomic_read(&obj->refcount));
155 int dead = atomic_dec_and_test(&(*ref)->refcount);
156 nv_trace(*ref, "dec() == %d\n", atomic_read(&(*ref)->refcount));
158 nouveau_object_dtor(*ref);
165 nouveau_object_inc(struct nouveau_object *object)
167 int ref = atomic_add_return(1, &object->usecount);
170 nv_trace(object, "use(+1) == %d\n", atomic_read(&object->usecount));
174 nv_trace(object, "initialising...\n");
175 if (object->parent) {
176 ret = nouveau_object_inc(object->parent);
178 nv_error(object, "parent failed, %d\n", ret);
183 if (object->engine) {
184 mutex_lock(&nv_subdev(object->engine)->mutex);
185 ret = nouveau_object_inc(object->engine);
186 mutex_unlock(&nv_subdev(object->engine)->mutex);
188 nv_error(object, "engine failed, %d\n", ret);
193 ret = nv_ofuncs(object)->init(object);
194 atomic_set(&object->usecount, 1);
196 nv_error(object, "init failed, %d\n", ret);
200 nv_trace(object, "initialised\n");
204 if (object->engine) {
205 mutex_lock(&nv_subdev(object->engine)->mutex);
206 nouveau_object_dec(object->engine, false);
207 mutex_unlock(&nv_subdev(object->engine)->mutex);
211 nouveau_object_dec(object->parent, false);
213 atomic_dec(&object->usecount);
218 nouveau_object_decf(struct nouveau_object *object)
222 nv_trace(object, "stopping...\n");
224 ret = nv_ofuncs(object)->fini(object, false);
225 atomic_set(&object->usecount, 0);
227 nv_warn(object, "failed fini, %d\n", ret);
229 if (object->engine) {
230 mutex_lock(&nv_subdev(object->engine)->mutex);
231 nouveau_object_dec(object->engine, false);
232 mutex_unlock(&nv_subdev(object->engine)->mutex);
236 nouveau_object_dec(object->parent, false);
238 nv_trace(object, "stopped\n");
243 nouveau_object_decs(struct nouveau_object *object)
247 nv_trace(object, "suspending...\n");
249 ret = nv_ofuncs(object)->fini(object, true);
250 atomic_set(&object->usecount, 0);
252 nv_error(object, "failed suspend, %d\n", ret);
256 if (object->engine) {
257 mutex_lock(&nv_subdev(object->engine)->mutex);
258 ret = nouveau_object_dec(object->engine, true);
259 mutex_unlock(&nv_subdev(object->engine)->mutex);
261 nv_warn(object, "engine failed suspend, %d\n", ret);
266 if (object->parent) {
267 ret = nouveau_object_dec(object->parent, true);
269 nv_warn(object, "parent failed suspend, %d\n", ret);
274 nv_trace(object, "suspended\n");
278 if (object->engine) {
279 mutex_lock(&nv_subdev(object->engine)->mutex);
280 rret = nouveau_object_inc(object->engine);
281 mutex_unlock(&nv_subdev(object->engine)->mutex);
283 nv_fatal(object, "engine failed to reinit, %d\n", rret);
287 rret = nv_ofuncs(object)->init(object);
289 nv_fatal(object, "failed to reinit, %d\n", rret);
295 nouveau_object_dec(struct nouveau_object *object, bool suspend)
297 int ref = atomic_add_return(-1, &object->usecount);
300 nv_trace(object, "use(-1) == %d\n", atomic_read(&object->usecount));
304 ret = nouveau_object_decs(object);
306 ret = nouveau_object_decf(object);
309 atomic_inc(&object->usecount);
318 nouveau_object_debug(void)
320 #ifdef NOUVEAU_OBJECT_MAGIC
321 struct nouveau_object *object;
322 if (!list_empty(&_objlist)) {
323 nv_fatal(NULL, "*******************************************\n");
324 nv_fatal(NULL, "* AIIIII! object(s) still exist!!!\n");
325 nv_fatal(NULL, "*******************************************\n");
326 list_for_each_entry(object, &_objlist, list) {
327 nv_fatal(object, "%p/%p/%d/%d\n",
328 object->parent, object->engine,
329 atomic_read(&object->refcount),
330 atomic_read(&object->usecount));