aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nvkm/core/object.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/core/object.c')
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/object.c400
1 files changed, 167 insertions, 233 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/object.c b/drivers/gpu/drm/nouveau/nvkm/core/object.c
index 979f3627d395..67aa7223dcd7 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/object.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/object.c
@@ -22,309 +22,243 @@
* Authors: Ben Skeggs
*/
#include <core/object.h>
+#include <core/client.h>
#include <core/engine.h>
-#ifdef NVKM_OBJECT_MAGIC
-static struct list_head _objlist = LIST_HEAD_INIT(_objlist);
-static DEFINE_SPINLOCK(_objlist_lock);
-#endif
-
int
-nvkm_object_create_(struct nvkm_object *parent, struct nvkm_object *engine,
- struct nvkm_oclass *oclass, u32 pclass,
- int size, void **pobject)
+nvkm_object_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
{
- struct nvkm_object *object;
-
- object = *pobject = kzalloc(size, GFP_KERNEL);
- if (!object)
- return -ENOMEM;
-
- nvkm_object_ref(parent, &object->parent);
- nvkm_object_ref(engine, (struct nvkm_object **)&object->engine);
- object->oclass = oclass;
- object->oclass->handle |= pclass;
- atomic_set(&object->refcount, 1);
- atomic_set(&object->usecount, 0);
-
-#ifdef NVKM_OBJECT_MAGIC
- object->_magic = NVKM_OBJECT_MAGIC;
- spin_lock(&_objlist_lock);
- list_add(&object->list, &_objlist);
- spin_unlock(&_objlist_lock);
-#endif
- return 0;
+ if (likely(object->func->mthd))
+ return object->func->mthd(object, mthd, data, size);
+ return -ENODEV;
}
int
-_nvkm_object_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
- struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
+nvkm_object_ntfy(struct nvkm_object *object, u32 mthd,
+ struct nvkm_event **pevent)
{
- if (size != 0)
- return -ENOSYS;
- return nvkm_object_create(parent, engine, oclass, 0, pobject);
+ if (likely(object->func->ntfy))
+ return object->func->ntfy(object, mthd, pevent);
+ return -ENODEV;
}
-void
-nvkm_object_destroy(struct nvkm_object *object)
+int
+nvkm_object_map(struct nvkm_object *object, u64 *addr, u32 *size)
{
-#ifdef NVKM_OBJECT_MAGIC
- spin_lock(&_objlist_lock);
- list_del(&object->list);
- spin_unlock(&_objlist_lock);
-#endif
- nvkm_object_ref(NULL, (struct nvkm_object **)&object->engine);
- nvkm_object_ref(NULL, &object->parent);
- kfree(object);
+ if (likely(object->func->map))
+ return object->func->map(object, addr, size);
+ return -ENODEV;
}
int
-nvkm_object_init(struct nvkm_object *object)
+nvkm_object_rd08(struct nvkm_object *object, u64 addr, u8 *data)
{
- return 0;
+ if (likely(object->func->rd08))
+ return object->func->rd08(object, addr, data);
+ return -ENODEV;
}
int
-nvkm_object_fini(struct nvkm_object *object, bool suspend)
+nvkm_object_rd16(struct nvkm_object *object, u64 addr, u16 *data)
{
- return 0;
+ if (likely(object->func->rd16))
+ return object->func->rd16(object, addr, data);
+ return -ENODEV;
}
-struct nvkm_ofuncs
-nvkm_object_ofuncs = {
- .ctor = _nvkm_object_ctor,
- .dtor = nvkm_object_destroy,
- .init = nvkm_object_init,
- .fini = nvkm_object_fini,
-};
-
int
-nvkm_object_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
- struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
+nvkm_object_rd32(struct nvkm_object *object, u64 addr, u32 *data)
{
- struct nvkm_ofuncs *ofuncs = oclass->ofuncs;
- struct nvkm_object *object = NULL;
- int ret;
-
- ret = ofuncs->ctor(parent, engine, oclass, data, size, &object);
- *pobject = object;
- if (ret < 0) {
- if (ret != -ENODEV) {
- nv_error(parent, "failed to create 0x%08x, %d\n",
- oclass->handle, ret);
- }
-
- if (object) {
- ofuncs->dtor(object);
- *pobject = NULL;
- }
-
- return ret;
- }
-
- if (ret == 0) {
- nv_trace(object, "created\n");
- atomic_set(&object->refcount, 1);
- }
-
- return 0;
+ if (likely(object->func->rd32))
+ return object->func->rd32(object, addr, data);
+ return -ENODEV;
}
-static void
-nvkm_object_dtor(struct nvkm_object *object)
+int
+nvkm_object_wr08(struct nvkm_object *object, u64 addr, u8 data)
{
- nv_trace(object, "destroying\n");
- nv_ofuncs(object)->dtor(object);
+ if (likely(object->func->wr08))
+ return object->func->wr08(object, addr, data);
+ return -ENODEV;
}
-void
-nvkm_object_ref(struct nvkm_object *obj, struct nvkm_object **ref)
+int
+nvkm_object_wr16(struct nvkm_object *object, u64 addr, u16 data)
{
- if (obj) {
- atomic_inc(&obj->refcount);
- nv_trace(obj, "inc() == %d\n", atomic_read(&obj->refcount));
- }
+ if (likely(object->func->wr16))
+ return object->func->wr16(object, addr, data);
+ return -ENODEV;
+}
- if (*ref) {
- int dead = atomic_dec_and_test(&(*ref)->refcount);
- nv_trace(*ref, "dec() == %d\n", atomic_read(&(*ref)->refcount));
- if (dead)
- nvkm_object_dtor(*ref);
- }
+int
+nvkm_object_wr32(struct nvkm_object *object, u64 addr, u32 data)
+{
+ if (likely(object->func->wr32))
+ return object->func->wr32(object, addr, data);
+ return -ENODEV;
+}
- *ref = obj;
+int
+nvkm_object_bind(struct nvkm_object *object, struct nvkm_gpuobj *gpuobj,
+ int align, struct nvkm_gpuobj **pgpuobj)
+{
+ if (object->func->bind)
+ return object->func->bind(object, gpuobj, align, pgpuobj);
+ return -ENODEV;
}
int
-nvkm_object_inc(struct nvkm_object *object)
+nvkm_object_fini(struct nvkm_object *object, bool suspend)
{
- int ref = atomic_add_return(1, &object->usecount);
+ const char *action = suspend ? "suspend" : "fini";
+ struct nvkm_object *child;
+ s64 time;
int ret;
- nv_trace(object, "use(+1) == %d\n", atomic_read(&object->usecount));
- if (ref != 1)
- return 0;
-
- nv_trace(object, "initialising...\n");
- if (object->parent) {
- ret = nvkm_object_inc(object->parent);
- if (ret) {
- nv_error(object, "parent failed, %d\n", ret);
- goto fail_parent;
- }
+ nvif_debug(object, "%s children...\n", action);
+ time = ktime_to_us(ktime_get());
+ list_for_each_entry(child, &object->tree, head) {
+ ret = nvkm_object_fini(child, suspend);
+ if (ret && suspend)
+ goto fail_child;
}
- if (object->engine) {
- mutex_lock(&nv_subdev(object->engine)->mutex);
- ret = nvkm_object_inc(&object->engine->subdev.object);
- mutex_unlock(&nv_subdev(object->engine)->mutex);
+ nvif_debug(object, "%s running...\n", action);
+ if (object->func->fini) {
+ ret = object->func->fini(object, suspend);
if (ret) {
- nv_error(object, "engine failed, %d\n", ret);
- goto fail_engine;
+ nvif_error(object, "%s failed with %d\n", action, ret);
+ if (suspend)
+ goto fail;
}
}
- ret = nv_ofuncs(object)->init(object);
- atomic_set(&object->usecount, 1);
- if (ret) {
- nv_error(object, "init failed, %d\n", ret);
- goto fail_self;
- }
-
- nv_trace(object, "initialised\n");
+ time = ktime_to_us(ktime_get()) - time;
+ nvif_debug(object, "%s completed in %lldus\n", action, time);
return 0;
-fail_self:
- if (object->engine) {
- mutex_lock(&nv_subdev(object->engine)->mutex);
- nvkm_object_dec(&object->engine->subdev.object, false);
- mutex_unlock(&nv_subdev(object->engine)->mutex);
+fail:
+ if (object->func->init) {
+ int rret = object->func->init(object);
+ if (rret)
+ nvif_fatal(object, "failed to restart, %d\n", rret);
+ }
+fail_child:
+ list_for_each_entry_continue_reverse(child, &object->tree, head) {
+ nvkm_object_init(child);
}
-fail_engine:
- if (object->parent)
- nvkm_object_dec(object->parent, false);
-fail_parent:
- atomic_dec(&object->usecount);
return ret;
}
-static int
-nvkm_object_decf(struct nvkm_object *object)
+int
+nvkm_object_init(struct nvkm_object *object)
{
+ struct nvkm_object *child;
+ s64 time;
int ret;
- nv_trace(object, "stopping...\n");
-
- ret = nv_ofuncs(object)->fini(object, false);
- atomic_set(&object->usecount, 0);
- if (ret)
- nv_warn(object, "failed fini, %d\n", ret);
-
- if (object->engine) {
- mutex_lock(&nv_subdev(object->engine)->mutex);
- nvkm_object_dec(&object->engine->subdev.object, false);
- mutex_unlock(&nv_subdev(object->engine)->mutex);
+ nvif_debug(object, "init running...\n");
+ time = ktime_to_us(ktime_get());
+ if (object->func->init) {
+ ret = object->func->init(object);
+ if (ret)
+ goto fail;
}
- if (object->parent)
- nvkm_object_dec(object->parent, false);
+ nvif_debug(object, "init children...\n");
+ list_for_each_entry(child, &object->tree, head) {
+ ret = nvkm_object_init(child);
+ if (ret)
+ goto fail_child;
+ }
- nv_trace(object, "stopped\n");
+ time = ktime_to_us(ktime_get()) - time;
+ nvif_debug(object, "init completed in %lldus\n", time);
return 0;
+
+fail_child:
+ list_for_each_entry_continue_reverse(child, &object->tree, head)
+ nvkm_object_fini(child, false);
+fail:
+ nvif_error(object, "init failed with %d\n", ret);
+ if (object->func->fini)
+ object->func->fini(object, false);
+ return ret;
}
-static int
-nvkm_object_decs(struct nvkm_object *object)
+void *
+nvkm_object_dtor(struct nvkm_object *object)
{
- int ret, rret;
-
- nv_trace(object, "suspending...\n");
-
- ret = nv_ofuncs(object)->fini(object, true);
- atomic_set(&object->usecount, 0);
- if (ret) {
- nv_error(object, "failed suspend, %d\n", ret);
- return ret;
+ struct nvkm_object *child, *ctemp;
+ void *data = object;
+ s64 time;
+
+ nvif_debug(object, "destroy children...\n");
+ time = ktime_to_us(ktime_get());
+ list_for_each_entry_safe(child, ctemp, &object->tree, head) {
+ nvkm_object_del(&child);
}
- if (object->engine) {
- mutex_lock(&nv_subdev(object->engine)->mutex);
- ret = nvkm_object_dec(&object->engine->subdev.object, true);
- mutex_unlock(&nv_subdev(object->engine)->mutex);
- if (ret) {
- nv_warn(object, "engine failed suspend, %d\n", ret);
- goto fail_engine;
- }
- }
-
- if (object->parent) {
- ret = nvkm_object_dec(object->parent, true);
- if (ret) {
- nv_warn(object, "parent failed suspend, %d\n", ret);
- goto fail_parent;
- }
- }
-
- nv_trace(object, "suspended\n");
- return 0;
+ nvif_debug(object, "destroy running...\n");
+ if (object->func->dtor)
+ data = object->func->dtor(object);
+ nvkm_engine_unref(&object->engine);
+ time = ktime_to_us(ktime_get()) - time;
+ nvif_debug(object, "destroy completed in %lldus...\n", time);
+ return data;
+}
-fail_parent:
- if (object->engine) {
- mutex_lock(&nv_subdev(object->engine)->mutex);
- rret = nvkm_object_inc(&object->engine->subdev.object);
- mutex_unlock(&nv_subdev(object->engine)->mutex);
- if (rret)
- nv_fatal(object, "engine failed to reinit, %d\n", rret);
+void
+nvkm_object_del(struct nvkm_object **pobject)
+{
+ struct nvkm_object *object = *pobject;
+ if (object && !WARN_ON(!object->func)) {
+ *pobject = nvkm_object_dtor(object);
+ nvkm_client_remove(object->client, object);
+ list_del(&object->head);
+ kfree(*pobject);
+ *pobject = NULL;
}
+}
-fail_engine:
- rret = nv_ofuncs(object)->init(object);
- if (rret)
- nv_fatal(object, "failed to reinit, %d\n", rret);
-
- return ret;
+void
+nvkm_object_ctor(const struct nvkm_object_func *func,
+ const struct nvkm_oclass *oclass, struct nvkm_object *object)
+{
+ object->func = func;
+ object->client = oclass->client;
+ object->engine = nvkm_engine_ref(oclass->engine);
+ object->oclass = oclass->base.oclass;
+ object->handle = oclass->handle;
+ INIT_LIST_HEAD(&object->head);
+ INIT_LIST_HEAD(&object->tree);
+ RB_CLEAR_NODE(&object->node);
+ WARN_ON(oclass->engine && !object->engine);
}
int
-nvkm_object_dec(struct nvkm_object *object, bool suspend)
+nvkm_object_new_(const struct nvkm_object_func *func,
+ const struct nvkm_oclass *oclass, void *data, u32 size,
+ struct nvkm_object **pobject)
{
- int ref = atomic_add_return(-1, &object->usecount);
- int ret;
-
- nv_trace(object, "use(-1) == %d\n", atomic_read(&object->usecount));
-
- if (ref == 0) {
- if (suspend)
- ret = nvkm_object_decs(object);
- else
- ret = nvkm_object_decf(object);
-
- if (ret) {
- atomic_inc(&object->usecount);
- return ret;
- }
+ if (size == 0) {
+ if (!(*pobject = kzalloc(sizeof(**pobject), GFP_KERNEL)))
+ return -ENOMEM;
+ nvkm_object_ctor(func, oclass, *pobject);
+ return 0;
}
-
- return 0;
+ return -ENOSYS;
}
-void
-nvkm_object_debug(void)
+static const struct nvkm_object_func
+nvkm_object_func = {
+};
+
+int
+nvkm_object_new(const struct nvkm_oclass *oclass, void *data, u32 size,
+ struct nvkm_object **pobject)
{
-#ifdef NVKM_OBJECT_MAGIC
- struct nvkm_object *object;
- if (!list_empty(&_objlist)) {
- nv_fatal(NULL, "*******************************************\n");
- nv_fatal(NULL, "* AIIIII! object(s) still exist!!!\n");
- nv_fatal(NULL, "*******************************************\n");
- list_for_each_entry(object, &_objlist, list) {
- nv_fatal(object, "%p/%p/%d/%d\n",
- object->parent, object->engine,
- atomic_read(&object->refcount),
- atomic_read(&object->usecount));
- }
- }
-#endif
+ const struct nvkm_object_func *func =
+ oclass->base.func ? oclass->base.func : &nvkm_object_func;
+ return nvkm_object_new_(func, oclass, data, size, pobject);
}