19274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs/* 29274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs * Copyright 2012 Red Hat Inc. 39274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs * 49274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs * Permission is hereby granted, free of charge, to any person obtaining a 59274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs * copy of this software and associated documentation files (the "Software"), 69274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs * to deal in the Software without restriction, including without limitation 79274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs * the rights to use, copy, modify, merge, publish, distribute, sublicense, 89274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs * and/or sell copies of the Software, and to permit persons to whom the 99274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs * Software is furnished to do so, subject to the following conditions: 109274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs * 119274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs * The above copyright notice and this permission notice shall be included in 129274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs * all copies or substantial portions of the Software. 139274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs * 149274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 159274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 169274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 179274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 189274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 199274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 209274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs * OTHER DEALINGS IN THE SOFTWARE. 219274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs * 229274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs * Authors: Ben Skeggs 239274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs */ 249274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 259274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs#include <core/object.h> 269274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs#include <core/engine.h> 279274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 289274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs#ifdef NOUVEAU_OBJECT_MAGIC 299274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsstatic struct list_head _objlist = LIST_HEAD_INIT(_objlist); 309274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsstatic DEFINE_SPINLOCK(_objlist_lock); 319274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs#endif 329274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 339274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsint 349274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsnouveau_object_create_(struct nouveau_object *parent, 359274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs struct nouveau_object *engine, 369274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs struct nouveau_oclass *oclass, u32 pclass, 379274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs int size, void **pobject) 389274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs{ 399274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs struct nouveau_object *object; 409274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 419274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs object = *pobject = kzalloc(size, GFP_KERNEL); 429274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs if (!object) 439274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs return -ENOMEM; 449274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 459274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs nouveau_object_ref(parent, &object->parent); 469274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs nouveau_object_ref(engine, &object->engine); 479274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs object->oclass = oclass; 489274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs object->oclass->handle |= pclass; 499274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs atomic_set(&object->refcount, 1); 509274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs atomic_set(&object->usecount, 0); 519274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 529274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs#ifdef NOUVEAU_OBJECT_MAGIC 539274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs object->_magic = NOUVEAU_OBJECT_MAGIC; 549274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs spin_lock(&_objlist_lock); 559274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs list_add(&object->list, &_objlist); 569274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs spin_unlock(&_objlist_lock); 579274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs#endif 589274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs return 0; 599274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs} 609274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 61a532da976f17234375d3b34633ff5d48f71f62bcBen Skeggsint 629274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs_nouveau_object_ctor(struct nouveau_object *parent, 639274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs struct nouveau_object *engine, 649274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs struct nouveau_oclass *oclass, void *data, u32 size, 659274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs struct nouveau_object **pobject) 669274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs{ 67f5ee92f085376859d5c31743262350f8e344689aBen Skeggs if (size != 0) 68f5ee92f085376859d5c31743262350f8e344689aBen Skeggs return -ENOSYS; 69f5ee92f085376859d5c31743262350f8e344689aBen Skeggs return nouveau_object_create(parent, engine, oclass, 0, pobject); 709274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs} 719274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 729274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsvoid 739274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsnouveau_object_destroy(struct nouveau_object *object) 749274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs{ 759274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs#ifdef NOUVEAU_OBJECT_MAGIC 769274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs spin_lock(&_objlist_lock); 779274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs list_del(&object->list); 789274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs spin_unlock(&_objlist_lock); 799274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs#endif 809274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs nouveau_object_ref(NULL, &object->engine); 819274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs nouveau_object_ref(NULL, &object->parent); 829274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs kfree(object); 839274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs} 849274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 859274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsint 869274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsnouveau_object_init(struct nouveau_object *object) 879274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs{ 889274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs return 0; 899274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs} 909274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 919274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsint 929274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsnouveau_object_fini(struct nouveau_object *object, bool suspend) 939274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs{ 949274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs return 0; 959274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs} 969274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 979274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsstruct nouveau_ofuncs 989274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsnouveau_object_ofuncs = { 999274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs .ctor = _nouveau_object_ctor, 100f5ee92f085376859d5c31743262350f8e344689aBen Skeggs .dtor = nouveau_object_destroy, 101f5ee92f085376859d5c31743262350f8e344689aBen Skeggs .init = nouveau_object_init, 102f5ee92f085376859d5c31743262350f8e344689aBen Skeggs .fini = nouveau_object_fini, 1039274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs}; 1049274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 1059274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsint 1069274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsnouveau_object_ctor(struct nouveau_object *parent, 1079274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs struct nouveau_object *engine, 1089274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs struct nouveau_oclass *oclass, void *data, u32 size, 1099274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs struct nouveau_object **pobject) 1109274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs{ 1119274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs struct nouveau_ofuncs *ofuncs = oclass->ofuncs; 112db91d68c9b5ca22e1fa25569bbde4895ade9dac0Ben Skeggs struct nouveau_object *object = NULL; 1139274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs int ret; 1149274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 115db91d68c9b5ca22e1fa25569bbde4895ade9dac0Ben Skeggs ret = ofuncs->ctor(parent, engine, oclass, data, size, &object); 116db91d68c9b5ca22e1fa25569bbde4895ade9dac0Ben Skeggs *pobject = object; 1179274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs if (ret < 0) { 1189274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs if (ret != -ENODEV) { 1199274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs nv_error(parent, "failed to create 0x%08x, %d\n", 1209274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs oclass->handle, ret); 1219274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs } 1229274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 123db91d68c9b5ca22e1fa25569bbde4895ade9dac0Ben Skeggs if (object) { 124db91d68c9b5ca22e1fa25569bbde4895ade9dac0Ben Skeggs ofuncs->dtor(object); 1259274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs *pobject = NULL; 1269274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs } 1279274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 1289274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs return ret; 1299274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs } 1309274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 131db91d68c9b5ca22e1fa25569bbde4895ade9dac0Ben Skeggs if (ret == 0) { 132964f85ec51c860c813858a9950c5eda9311410d5Ben Skeggs nv_trace(object, "created\n"); 133db91d68c9b5ca22e1fa25569bbde4895ade9dac0Ben Skeggs atomic_set(&object->refcount, 1); 134db91d68c9b5ca22e1fa25569bbde4895ade9dac0Ben Skeggs } 135db91d68c9b5ca22e1fa25569bbde4895ade9dac0Ben Skeggs 1369274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs return 0; 1379274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs} 1389274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 1399274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsstatic void 1409274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsnouveau_object_dtor(struct nouveau_object *object) 1419274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs{ 142964f85ec51c860c813858a9950c5eda9311410d5Ben Skeggs nv_trace(object, "destroying\n"); 1439274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs nv_ofuncs(object)->dtor(object); 1449274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs} 1459274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 1469274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsvoid 1479274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsnouveau_object_ref(struct nouveau_object *obj, struct nouveau_object **ref) 1489274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs{ 1499274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs if (obj) { 1509274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs atomic_inc(&obj->refcount); 1519274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs nv_trace(obj, "inc() == %d\n", atomic_read(&obj->refcount)); 1529274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs } 1539274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 1549274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs if (*ref) { 1559274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs int dead = atomic_dec_and_test(&(*ref)->refcount); 1569274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs nv_trace(*ref, "dec() == %d\n", atomic_read(&(*ref)->refcount)); 1579274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs if (dead) 1589274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs nouveau_object_dtor(*ref); 1599274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs } 1609274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 1619274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs *ref = obj; 1629274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs} 1639274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 1649274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsint 1659274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsnouveau_object_inc(struct nouveau_object *object) 1669274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs{ 1679274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs int ref = atomic_add_return(1, &object->usecount); 1689274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs int ret; 1699274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 1709274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs nv_trace(object, "use(+1) == %d\n", atomic_read(&object->usecount)); 1719274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs if (ref != 1) 1729274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs return 0; 1739274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 1749274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs nv_trace(object, "initialising...\n"); 1759274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs if (object->parent) { 1769274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs ret = nouveau_object_inc(object->parent); 1779274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs if (ret) { 1789274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs nv_error(object, "parent failed, %d\n", ret); 1799274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs goto fail_parent; 1809274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs } 1819274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs } 1829274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 1839274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs if (object->engine) { 1849274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs mutex_lock(&nv_subdev(object->engine)->mutex); 1859274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs ret = nouveau_object_inc(object->engine); 1869274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs mutex_unlock(&nv_subdev(object->engine)->mutex); 1879274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs if (ret) { 1889274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs nv_error(object, "engine failed, %d\n", ret); 1899274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs goto fail_engine; 1909274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs } 1919274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs } 1929274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 1939274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs ret = nv_ofuncs(object)->init(object); 194db91d68c9b5ca22e1fa25569bbde4895ade9dac0Ben Skeggs atomic_set(&object->usecount, 1); 1959274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs if (ret) { 1969274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs nv_error(object, "init failed, %d\n", ret); 1979274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs goto fail_self; 1989274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs } 1999274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 200964f85ec51c860c813858a9950c5eda9311410d5Ben Skeggs nv_trace(object, "initialised\n"); 2019274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs return 0; 2029274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 2039274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsfail_self: 2049274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs if (object->engine) { 2059274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs mutex_lock(&nv_subdev(object->engine)->mutex); 2069274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs nouveau_object_dec(object->engine, false); 2079274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs mutex_unlock(&nv_subdev(object->engine)->mutex); 2089274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs } 2099274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsfail_engine: 2109274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs if (object->parent) 2119274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs nouveau_object_dec(object->parent, false); 2129274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsfail_parent: 2139274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs atomic_dec(&object->usecount); 2149274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs return ret; 2159274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs} 2169274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 2179274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsstatic int 2189274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsnouveau_object_decf(struct nouveau_object *object) 2199274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs{ 2209274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs int ret; 2219274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 2229274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs nv_trace(object, "stopping...\n"); 2239274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 2249274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs ret = nv_ofuncs(object)->fini(object, false); 225db91d68c9b5ca22e1fa25569bbde4895ade9dac0Ben Skeggs atomic_set(&object->usecount, 0); 2269274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs if (ret) 2279274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs nv_warn(object, "failed fini, %d\n", ret); 2289274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 2299274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs if (object->engine) { 2309274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs mutex_lock(&nv_subdev(object->engine)->mutex); 2319274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs nouveau_object_dec(object->engine, false); 2329274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs mutex_unlock(&nv_subdev(object->engine)->mutex); 2339274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs } 2349274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 2359274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs if (object->parent) 2369274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs nouveau_object_dec(object->parent, false); 2379274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 238964f85ec51c860c813858a9950c5eda9311410d5Ben Skeggs nv_trace(object, "stopped\n"); 2399274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs return 0; 2409274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs} 2419274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 2429274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsstatic int 2439274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsnouveau_object_decs(struct nouveau_object *object) 2449274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs{ 2459274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs int ret, rret; 2469274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 2479274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs nv_trace(object, "suspending...\n"); 2489274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 2499274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs ret = nv_ofuncs(object)->fini(object, true); 250db91d68c9b5ca22e1fa25569bbde4895ade9dac0Ben Skeggs atomic_set(&object->usecount, 0); 2519274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs if (ret) { 2529274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs nv_error(object, "failed suspend, %d\n", ret); 2539274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs return ret; 2549274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs } 2559274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 2569274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs if (object->engine) { 2579274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs mutex_lock(&nv_subdev(object->engine)->mutex); 2589274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs ret = nouveau_object_dec(object->engine, true); 2599274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs mutex_unlock(&nv_subdev(object->engine)->mutex); 2609274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs if (ret) { 2619274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs nv_warn(object, "engine failed suspend, %d\n", ret); 2629274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs goto fail_engine; 2639274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs } 2649274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs } 2659274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 2669274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs if (object->parent) { 2679274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs ret = nouveau_object_dec(object->parent, true); 2689274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs if (ret) { 2699274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs nv_warn(object, "parent failed suspend, %d\n", ret); 2709274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs goto fail_parent; 2719274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs } 2729274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs } 2739274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 274964f85ec51c860c813858a9950c5eda9311410d5Ben Skeggs nv_trace(object, "suspended\n"); 2759274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs return 0; 2769274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 2779274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsfail_parent: 2789274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs if (object->engine) { 2799274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs mutex_lock(&nv_subdev(object->engine)->mutex); 2809274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs rret = nouveau_object_inc(object->engine); 2819274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs mutex_unlock(&nv_subdev(object->engine)->mutex); 2829274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs if (rret) 2839274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs nv_fatal(object, "engine failed to reinit, %d\n", rret); 2849274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs } 2859274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 2869274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsfail_engine: 2879274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs rret = nv_ofuncs(object)->init(object); 2889274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs if (rret) 2899274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs nv_fatal(object, "failed to reinit, %d\n", rret); 2909274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 2919274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs return ret; 2929274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs} 2939274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 2949274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsint 2959274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsnouveau_object_dec(struct nouveau_object *object, bool suspend) 2969274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs{ 2979274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs int ref = atomic_add_return(-1, &object->usecount); 2989274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs int ret; 2999274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 3009274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs nv_trace(object, "use(-1) == %d\n", atomic_read(&object->usecount)); 3019274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 3029274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs if (ref == 0) { 3039274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs if (suspend) 3049274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs ret = nouveau_object_decs(object); 3059274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs else 3069274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs ret = nouveau_object_decf(object); 3079274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 3089274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs if (ret) { 3099274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs atomic_inc(&object->usecount); 3109274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs return ret; 3119274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs } 3129274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs } 3139274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 3149274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs return 0; 3159274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs} 3169274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs 3179274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsvoid 3189274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggsnouveau_object_debug(void) 3199274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs{ 3209274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs#ifdef NOUVEAU_OBJECT_MAGIC 3219274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs struct nouveau_object *object; 3229274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs if (!list_empty(&_objlist)) { 3239274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs nv_fatal(NULL, "*******************************************\n"); 3249274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs nv_fatal(NULL, "* AIIIII! object(s) still exist!!!\n"); 3259274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs nv_fatal(NULL, "*******************************************\n"); 3269274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs list_for_each_entry(object, &_objlist, list) { 3279274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs nv_fatal(object, "%p/%p/%d/%d\n", 3289274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs object->parent, object->engine, 3299274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs atomic_read(&object->refcount), 3309274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs atomic_read(&object->usecount)); 3319274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs } 3329274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs } 3339274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs#endif 3349274f4a9ba7e70d1770e237fca16d52f27f0c728Ben Skeggs} 335