diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2015-08-20 14:54:17 +1000 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2015-08-28 12:40:35 +1000 |
commit | 6cf813fb26640ef539051fb7f965af8c9ff10d92 (patch) | |
tree | cbb7d8fa7199ad86a1b4b26458c17cb54136736c /drivers/gpu/drm/nouveau/nvkm/core | |
parent | 7974dd1bdb43aaf5b45a915c6b439d11733450fc (diff) |
drm/nouveau/device: prepare for new-style subdevs
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/core')
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/core/engine.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/core/ioctl.c | 25 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/core/object.c | 48 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/core/subdev.c | 39 |
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); } |