summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau/nvkm/core
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/core')
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/engine.c10
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/ioctl.c25
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/object.c48
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/subdev.c39
4 files changed, 66 insertions, 56 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/engine.c b/drivers/gpu/drm/nouveau/nvkm/core/engine.c
index 07559e7c4c4c..eabd271f68b3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/engine.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/engine.c
@@ -68,6 +68,8 @@ static int
nvkm_engine_fini(struct nvkm_subdev *obj, bool suspend)
{
struct nvkm_engine *engine = container_of(obj, typeof(*engine), subdev);
+ if (engine->subdev.object.oclass)
+ return engine->subdev.object.oclass->ofuncs->fini(&engine->subdev.object, suspend);
if (engine->func->fini)
return engine->func->fini(engine, suspend);
return 0;
@@ -86,6 +88,9 @@ nvkm_engine_init(struct nvkm_subdev *obj)
return ret;
}
+ if (engine->subdev.object.oclass)
+ return engine->subdev.object.oclass->ofuncs->init(&engine->subdev.object);
+
if (engine->func->oneinit && !engine->subdev.oneinit) {
nvkm_trace(subdev, "one-time init running...\n");
time = ktime_to_us(ktime_get());
@@ -110,6 +115,10 @@ static void *
nvkm_engine_dtor(struct nvkm_subdev *obj)
{
struct nvkm_engine *engine = container_of(obj, typeof(*engine), subdev);
+ if (engine->subdev.object.oclass) {
+ engine->subdev.object.oclass->ofuncs->dtor(&engine->subdev.object);
+ return NULL;
+ }
if (engine->func->dtor)
return engine->func->dtor(engine);
return engine;
@@ -201,5 +210,6 @@ nvkm_engine_create_(struct nvkm_object *parent, struct nvkm_object *engobj,
INIT_LIST_HEAD(&engine->contexts);
spin_lock_init(&engine->lock);
+ engine->subdev.func = &nvkm_engine_func;
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c b/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c
index 6e5ff942a6da..d9c26e40ae32 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c
@@ -91,7 +91,7 @@ nvkm_ioctl_new(struct nvkm_handle *handle, void *data, u32 size)
struct nvkm_object *engctx = NULL;
struct nvkm_object *object = NULL;
struct nvkm_parent *parent;
- struct nvkm_object *engine;
+ struct nvkm_engine *engine;
struct nvkm_oclass *oclass;
u32 _handle, _oclass;
int ret;
@@ -117,7 +117,8 @@ nvkm_ioctl_new(struct nvkm_handle *handle, void *data, u32 size)
parent = nv_parent(handle->object);
/* check that parent supports the requested subclass */
- ret = nvkm_parent_sclass(&parent->object, _oclass, &engine, &oclass);
+ ret = nvkm_parent_sclass(&parent->object, _oclass,
+ (struct nvkm_object **)&engine, &oclass);
if (ret) {
nvif_debug(&parent->object, "illegal class 0x%04x\n", _oclass);
goto fail_class;
@@ -128,18 +129,20 @@ nvkm_ioctl_new(struct nvkm_handle *handle, void *data, u32 size)
* state calculated at init (ie. default context construction)
*/
if (engine) {
- ret = nvkm_object_inc(engine);
- if (ret)
+ engine = nvkm_engine_ref(engine);
+ if (IS_ERR(engine)) {
+ ret = PTR_ERR(engine);
+ engine = NULL;
goto fail_class;
+ }
}
/* if engine requires it, create a context object to insert
* between the parent and its children (eg. PGRAPH context)
*/
- if (engine && nv_engine(engine)->cclass) {
- ret = nvkm_object_old(&parent->object, engine,
- nv_engine(engine)->cclass,
- data, size, &engctx);
+ if (engine && engine->cclass) {
+ ret = nvkm_object_old(&parent->object, &engine->subdev.object,
+ engine->cclass, data, size, &engctx);
if (ret)
goto fail_engctx;
} else {
@@ -147,7 +150,8 @@ nvkm_ioctl_new(struct nvkm_handle *handle, void *data, u32 size)
}
/* finally, create new object and bind it to its handle */
- ret = nvkm_object_old(engctx, engine, oclass, data, size, &object);
+ ret = nvkm_object_old(engctx, &engine->subdev.object, oclass,
+ data, size, &object);
client->data = object;
if (ret)
goto fail_ctor;
@@ -178,8 +182,7 @@ fail_init:
fail_ctor:
nvkm_object_ref(NULL, &engctx);
fail_engctx:
- if (engine)
- nvkm_object_dec(engine, false);
+ nvkm_engine_unref(&engine);
fail_class:
return ret;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/object.c b/drivers/gpu/drm/nouveau/nvkm/core/object.c
index 0abee7816874..0680eae072cf 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/object.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/object.c
@@ -201,6 +201,7 @@ nvkm_object_del(struct nvkm_object **pobject)
if (object && !WARN_ON(!object->func)) {
if (object->func->dtor)
*pobject = object->func->dtor(object);
+ nvkm_engine_unref(&object->engine);
kfree(*pobject);
*pobject = NULL;
}
@@ -212,7 +213,7 @@ nvkm_object_ctor(const struct nvkm_object_func *func,
{
object->func = func;
object->client = oclass->client;
- object->engine = oclass->engine;
+ object->engine = nvkm_engine_ref(oclass->engine);
object->oclass_name = oclass->base.oclass;
object->handle = oclass->handle;
object->parent = oclass->parent;
@@ -251,10 +252,11 @@ nvkm_object_new(const struct nvkm_oclass *oclass, void *data, u32 size,
}
int
-nvkm_object_create_(struct nvkm_object *parent, struct nvkm_object *engine,
+nvkm_object_create_(struct nvkm_object *parent, struct nvkm_object *engobj,
struct nvkm_oclass *oclass, u32 pclass,
int size, void **pobject)
{
+ struct nvkm_engine *engine = engobj ? nv_engine(engobj) : NULL;
struct nvkm_object *object;
object = *pobject = kzalloc(size, GFP_KERNEL);
@@ -262,7 +264,7 @@ nvkm_object_create_(struct nvkm_object *parent, struct nvkm_object *engine,
return -ENOMEM;
nvkm_object_ref(parent, &object->parent);
- nvkm_object_ref(engine, (struct nvkm_object **)&object->engine);
+ object->engine = nvkm_engine_ref(engine);
object->oclass = oclass;
object->pclass = pclass;
atomic_set(&object->refcount, 1);
@@ -287,7 +289,7 @@ _nvkm_object_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
void
nvkm_object_destroy(struct nvkm_object *object)
{
- nvkm_object_ref(NULL, (struct nvkm_object **)&object->engine);
+ nvkm_engine_unref(&object->engine);
nvkm_object_ref(NULL, &object->parent);
kfree(object);
}
@@ -333,7 +335,8 @@ nvkm_object_old(struct nvkm_object *parent, struct nvkm_object *engine,
}
if (ret == 0) {
- atomic_set(&object->refcount, 1);
+ if (!nv_iclass(object, NV_SUBDEV_CLASS))
+ atomic_set(&object->refcount, 1);
}
return 0;
@@ -370,14 +373,6 @@ nvkm_object_inc(struct nvkm_object *object)
goto fail_parent;
}
- 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);
- if (ret)
- goto fail_engine;
- }
-
ret = nvkm_object_init(object);
atomic_set(&object->usecount, 1);
if (ret)
@@ -386,12 +381,6 @@ nvkm_object_inc(struct nvkm_object *object)
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_engine:
if (object->parent)
nvkm_object_dec(object->parent, false);
fail_parent:
@@ -405,12 +394,6 @@ nvkm_object_decf(struct nvkm_object *object)
nvkm_object_fini(object, false);
atomic_set(&object->usecount, 0);
- 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);
- }
-
if (object->parent)
nvkm_object_dec(object->parent, false);
@@ -427,14 +410,6 @@ nvkm_object_decs(struct nvkm_object *object)
if (ret)
return ret;
- 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)
- goto fail_engine;
- }
-
if (object->parent) {
ret = nvkm_object_dec(object->parent, true);
if (ret)
@@ -444,13 +419,6 @@ nvkm_object_decs(struct nvkm_object *object)
return 0;
fail_parent:
- if (object->engine) {
- mutex_lock(&nv_subdev(object->engine)->mutex);
- nvkm_object_inc(&object->engine->subdev.object);
- mutex_unlock(&nv_subdev(object->engine)->mutex);
- }
-
-fail_engine:
nvkm_object_init(object);
return ret;
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/subdev.c b/drivers/gpu/drm/nouveau/nvkm/core/subdev.c
index 5af13d8be2f5..b0647c233478 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/subdev.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/subdev.c
@@ -74,6 +74,12 @@ nvkm_subdev_name[64] = {
void
nvkm_subdev_intr(struct nvkm_subdev *subdev)
{
+ if (subdev->object.oclass) {
+ if (subdev->intr)
+ subdev->intr(subdev);
+ return;
+ }
+
if (subdev->func->intr)
subdev->func->intr(subdev);
}
@@ -85,10 +91,18 @@ nvkm_subdev_fini(struct nvkm_subdev *subdev, bool suspend)
const char *action = suspend ? "suspend" : "fini";
u32 pmc_enable = subdev->pmc_enable;
s64 time;
+ int ret;
nvkm_trace(subdev, "%s running...\n", action);
time = ktime_to_us(ktime_get());
+ if (!subdev->func) {
+ ret = subdev->object.oclass->ofuncs->fini(&subdev->object, suspend);
+ if (ret)
+ return ret;
+ goto done;
+ }
+
if (subdev->func->fini) {
int ret = subdev->func->fini(subdev, suspend);
if (ret) {
@@ -104,6 +118,7 @@ nvkm_subdev_fini(struct nvkm_subdev *subdev, bool suspend)
nvkm_rd32(device, 0x000200);
}
+done:
time = ktime_to_us(ktime_get()) - time;
nvkm_trace(subdev, "%s completed in %lldus\n", action, time);
return 0;
@@ -117,7 +132,7 @@ nvkm_subdev_preinit(struct nvkm_subdev *subdev)
nvkm_trace(subdev, "preinit running...\n");
time = ktime_to_us(ktime_get());
- if (subdev->func->preinit) {
+ if (!subdev->object.oclass && subdev->func->preinit) {
int ret = subdev->func->preinit(subdev);
if (ret) {
nvkm_error(subdev, "preinit failed, %d\n", ret);
@@ -139,6 +154,13 @@ nvkm_subdev_init(struct nvkm_subdev *subdev)
nvkm_trace(subdev, "init running...\n");
time = ktime_to_us(ktime_get());
+ if (!subdev->func) {
+ ret = subdev->object.oclass->ofuncs->init(&subdev->object);
+ if (ret)
+ return ret;
+ goto done;
+ }
+
if (subdev->func->oneinit && !subdev->oneinit) {
s64 time;
nvkm_trace(subdev, "one-time init running...\n");
@@ -162,6 +184,7 @@ nvkm_subdev_init(struct nvkm_subdev *subdev)
}
}
+done:
time = ktime_to_us(ktime_get()) - time;
nvkm_trace(subdev, "init completed in %lldus\n", time);
return 0;
@@ -172,6 +195,12 @@ nvkm_subdev_del(struct nvkm_subdev **psubdev)
{
struct nvkm_subdev *subdev = *psubdev;
s64 time;
+
+ if (subdev && subdev->object.oclass) {
+ subdev->object.oclass->ofuncs->dtor(&subdev->object);
+ return;
+ }
+
if (subdev && !WARN_ON(!subdev->func)) {
nvkm_trace(subdev, "destroy running...\n");
time = ktime_to_us(ktime_get());
@@ -211,8 +240,10 @@ nvkm_subdev(void *obj, int idx)
struct nvkm_object *object = nv_object(obj);
while (object && !nv_iclass(object, NV_SUBDEV_CLASS))
object = object->parent;
- if (object == NULL || !object->parent || nv_subidx(nv_subdev(object)) != idx)
- object = nv_device(obj)->subdev[idx];
+ if (object == NULL || !object->parent || nv_subidx(nv_subdev(object)) != idx) {
+ struct nvkm_device *device = nv_device(obj);
+ return nvkm_device_subdev(device, idx);
+ }
return object ? nv_subdev(object) : NULL;
}
@@ -266,8 +297,6 @@ _nvkm_subdev_fini(struct nvkm_object *object, bool suspend)
void
nvkm_subdev_destroy(struct nvkm_subdev *subdev)
{
- int subidx = nv_hclass(subdev) & 0xff;
- nv_device(subdev)->subdev[subidx] = NULL;
nvkm_object_destroy(&subdev->object);
}