]>
git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blob - drivers/gpu/drm/nouveau/core/core/object.c
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/parent.h>
27 #include <core/namedb.h>
28 #include <core/handle.h>
29 #include <core/engine.h>
31 #ifdef NOUVEAU_OBJECT_MAGIC
32 static struct list_head _objlist
= LIST_HEAD_INIT(_objlist
);
33 static DEFINE_SPINLOCK(_objlist_lock
);
37 nouveau_object_create_(struct nouveau_object
*parent
,
38 struct nouveau_object
*engine
,
39 struct nouveau_oclass
*oclass
, u32 pclass
,
40 int size
, void **pobject
)
42 struct nouveau_object
*object
;
44 object
= *pobject
= kzalloc(size
, GFP_KERNEL
);
48 nouveau_object_ref(parent
, &object
->parent
);
49 nouveau_object_ref(engine
, &object
->engine
);
50 object
->oclass
= oclass
;
51 object
->oclass
->handle
|= pclass
;
52 atomic_set(&object
->refcount
, 1);
53 atomic_set(&object
->usecount
, 0);
55 #ifdef NOUVEAU_OBJECT_MAGIC
56 object
->_magic
= NOUVEAU_OBJECT_MAGIC
;
57 spin_lock(&_objlist_lock
);
58 list_add(&object
->list
, &_objlist
);
59 spin_unlock(&_objlist_lock
);
65 _nouveau_object_ctor(struct nouveau_object
*parent
,
66 struct nouveau_object
*engine
,
67 struct nouveau_oclass
*oclass
, void *data
, u32 size
,
68 struct nouveau_object
**pobject
)
70 struct nouveau_object
*object
;
73 ret
= nouveau_object_create(parent
, engine
, oclass
, 0, &object
);
74 *pobject
= nv_object(object
);
82 nouveau_object_destroy(struct nouveau_object
*object
)
84 #ifdef NOUVEAU_OBJECT_MAGIC
85 spin_lock(&_objlist_lock
);
86 list_del(&object
->list
);
87 spin_unlock(&_objlist_lock
);
89 nouveau_object_ref(NULL
, &object
->engine
);
90 nouveau_object_ref(NULL
, &object
->parent
);
95 _nouveau_object_dtor(struct nouveau_object
*object
)
97 nouveau_object_destroy(object
);
101 nouveau_object_init(struct nouveau_object
*object
)
107 _nouveau_object_init(struct nouveau_object
*object
)
109 return nouveau_object_init(object
);
113 nouveau_object_fini(struct nouveau_object
*object
, bool suspend
)
119 _nouveau_object_fini(struct nouveau_object
*object
, bool suspend
)
121 return nouveau_object_fini(object
, suspend
);
124 struct nouveau_ofuncs
125 nouveau_object_ofuncs
= {
126 .ctor
= _nouveau_object_ctor
,
127 .dtor
= _nouveau_object_dtor
,
128 .init
= _nouveau_object_init
,
129 .fini
= _nouveau_object_fini
,
133 nouveau_object_ctor(struct nouveau_object
*parent
,
134 struct nouveau_object
*engine
,
135 struct nouveau_oclass
*oclass
, void *data
, u32 size
,
136 struct nouveau_object
**pobject
)
138 struct nouveau_ofuncs
*ofuncs
= oclass
->ofuncs
;
143 ret
= ofuncs
->ctor(parent
, engine
, oclass
, data
, size
, pobject
);
145 if (ret
!= -ENODEV
) {
146 nv_error(parent
, "failed to create 0x%08x, %d\n",
147 oclass
->handle
, ret
);
151 ofuncs
->dtor(*pobject
);
158 nv_debug(*pobject
, "created\n");
163 nouveau_object_dtor(struct nouveau_object
*object
)
165 nv_debug(object
, "destroying\n");
166 nv_ofuncs(object
)->dtor(object
);
170 nouveau_object_ref(struct nouveau_object
*obj
, struct nouveau_object
**ref
)
173 atomic_inc(&obj
->refcount
);
174 nv_trace(obj
, "inc() == %d\n", atomic_read(&obj
->refcount
));
178 int dead
= atomic_dec_and_test(&(*ref
)->refcount
);
179 nv_trace(*ref
, "dec() == %d\n", atomic_read(&(*ref
)->refcount
));
181 nouveau_object_dtor(*ref
);
188 nouveau_object_new(struct nouveau_object
*client
, u32 _parent
, u32 _handle
,
189 u16 _oclass
, void *data
, u32 size
,
190 struct nouveau_object
**pobject
)
192 struct nouveau_object
*parent
= NULL
;
193 struct nouveau_object
*engctx
= NULL
;
194 struct nouveau_object
*object
= NULL
;
195 struct nouveau_object
*engine
;
196 struct nouveau_oclass
*oclass
;
197 struct nouveau_handle
*handle
;
200 /* lookup parent object and ensure it *is* a parent */
201 parent
= nouveau_handle_ref(client
, _parent
);
203 nv_error(client
, "parent 0x%08x not found\n", _parent
);
207 if (!nv_iclass(parent
, NV_PARENT_CLASS
)) {
208 nv_error(parent
, "cannot have children\n");
213 /* check that parent supports the requested subclass */
214 ret
= nouveau_parent_sclass(parent
, _oclass
, &engine
, &oclass
);
216 nv_debug(parent
, "illegal class 0x%04x\n", _oclass
);
220 /* make sure engine init has been completed *before* any objects
221 * it controls are created - the constructors may depend on
222 * state calculated at init (ie. default context construction)
225 ret
= nouveau_object_inc(engine
);
230 /* if engine requires it, create a context object to insert
231 * between the parent and its children (eg. PGRAPH context)
233 if (engine
&& nv_engine(engine
)->cclass
) {
234 ret
= nouveau_object_ctor(parent
, engine
,
235 nv_engine(engine
)->cclass
,
236 data
, size
, &engctx
);
240 nouveau_object_ref(parent
, &engctx
);
243 /* finally, create new object and bind it to its handle */
244 ret
= nouveau_object_ctor(engctx
, engine
, oclass
, data
, size
, &object
);
249 ret
= nouveau_object_inc(object
);
253 ret
= nouveau_handle_create(parent
, _parent
, _handle
, object
, &handle
);
257 ret
= nouveau_handle_init(handle
);
259 nouveau_handle_destroy(handle
);
262 nouveau_object_dec(object
, false);
264 nouveau_object_ref(NULL
, &object
);
266 nouveau_object_ref(NULL
, &engctx
);
269 nouveau_object_dec(engine
, false);
271 nouveau_object_ref(NULL
, &parent
);
276 nouveau_object_del(struct nouveau_object
*client
, u32 _parent
, u32 _handle
)
278 struct nouveau_object
*parent
= NULL
;
279 struct nouveau_object
*namedb
= NULL
;
280 struct nouveau_handle
*handle
= NULL
;
282 parent
= nouveau_handle_ref(client
, _parent
);
286 namedb
= nv_pclass(parent
, NV_NAMEDB_CLASS
);
288 handle
= nouveau_namedb_get(nv_namedb(namedb
), _handle
);
290 nouveau_namedb_put(handle
);
291 nouveau_handle_fini(handle
, false);
292 nouveau_handle_destroy(handle
);
296 nouveau_object_ref(NULL
, &parent
);
297 return handle
? 0 : -EINVAL
;
301 nouveau_object_inc(struct nouveau_object
*object
)
303 int ref
= atomic_add_return(1, &object
->usecount
);
306 nv_trace(object
, "use(+1) == %d\n", atomic_read(&object
->usecount
));
310 nv_trace(object
, "initialising...\n");
311 if (object
->parent
) {
312 ret
= nouveau_object_inc(object
->parent
);
314 nv_error(object
, "parent failed, %d\n", ret
);
319 if (object
->engine
) {
320 mutex_lock(&nv_subdev(object
->engine
)->mutex
);
321 ret
= nouveau_object_inc(object
->engine
);
322 mutex_unlock(&nv_subdev(object
->engine
)->mutex
);
324 nv_error(object
, "engine failed, %d\n", ret
);
329 ret
= nv_ofuncs(object
)->init(object
);
331 nv_error(object
, "init failed, %d\n", ret
);
335 nv_debug(object
, "initialised\n");
339 if (object
->engine
) {
340 mutex_lock(&nv_subdev(object
->engine
)->mutex
);
341 nouveau_object_dec(object
->engine
, false);
342 mutex_unlock(&nv_subdev(object
->engine
)->mutex
);
346 nouveau_object_dec(object
->parent
, false);
348 atomic_dec(&object
->usecount
);
353 nouveau_object_decf(struct nouveau_object
*object
)
357 nv_trace(object
, "stopping...\n");
359 ret
= nv_ofuncs(object
)->fini(object
, false);
361 nv_warn(object
, "failed fini, %d\n", ret
);
363 if (object
->engine
) {
364 mutex_lock(&nv_subdev(object
->engine
)->mutex
);
365 nouveau_object_dec(object
->engine
, false);
366 mutex_unlock(&nv_subdev(object
->engine
)->mutex
);
370 nouveau_object_dec(object
->parent
, false);
372 nv_debug(object
, "stopped\n");
377 nouveau_object_decs(struct nouveau_object
*object
)
381 nv_trace(object
, "suspending...\n");
383 ret
= nv_ofuncs(object
)->fini(object
, true);
385 nv_error(object
, "failed suspend, %d\n", ret
);
389 if (object
->engine
) {
390 mutex_lock(&nv_subdev(object
->engine
)->mutex
);
391 ret
= nouveau_object_dec(object
->engine
, true);
392 mutex_unlock(&nv_subdev(object
->engine
)->mutex
);
394 nv_warn(object
, "engine failed suspend, %d\n", ret
);
399 if (object
->parent
) {
400 ret
= nouveau_object_dec(object
->parent
, true);
402 nv_warn(object
, "parent failed suspend, %d\n", ret
);
407 nv_debug(object
, "suspended\n");
411 if (object
->engine
) {
412 mutex_lock(&nv_subdev(object
->engine
)->mutex
);
413 rret
= nouveau_object_inc(object
->engine
);
414 mutex_unlock(&nv_subdev(object
->engine
)->mutex
);
416 nv_fatal(object
, "engine failed to reinit, %d\n", rret
);
420 rret
= nv_ofuncs(object
)->init(object
);
422 nv_fatal(object
, "failed to reinit, %d\n", rret
);
428 nouveau_object_dec(struct nouveau_object
*object
, bool suspend
)
430 int ref
= atomic_add_return(-1, &object
->usecount
);
433 nv_trace(object
, "use(-1) == %d\n", atomic_read(&object
->usecount
));
437 ret
= nouveau_object_decs(object
);
439 ret
= nouveau_object_decf(object
);
442 atomic_inc(&object
->usecount
);
451 nouveau_object_debug(void)
453 #ifdef NOUVEAU_OBJECT_MAGIC
454 struct nouveau_object
*object
;
455 if (!list_empty(&_objlist
)) {
456 nv_fatal(NULL
, "*******************************************\n");
457 nv_fatal(NULL
, "* AIIIII! object(s) still exist!!!\n");
458 nv_fatal(NULL
, "*******************************************\n");
459 list_for_each_entry(object
, &_objlist
, list
) {
460 nv_fatal(object
, "%p/%p/%d/%d\n",
461 object
->parent
, object
->engine
,
462 atomic_read(&object
->refcount
),
463 atomic_read(&object
->usecount
));