diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2015-08-20 14:54:16 +1000 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2015-08-28 12:37:38 +1000 |
commit | 395156e3e0283a68aef23341d26b42c7362a27d0 (patch) | |
tree | 9674ef1a25372fcaecc2a559b34f674ec21618dc /drm/nouveau/nvkm | |
parent | 4759e64523d65e88dd9f1a980583ad5b46cc828c (diff) | |
download | nouveau-395156e3e0283a68aef23341d26b42c7362a27d0.tar.gz |
engine: implement support for new-style nvkm_engine
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drm/nouveau/nvkm')
-rw-r--r-- | drm/nouveau/nvkm/core/engine.c | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/drm/nouveau/nvkm/core/engine.c b/drm/nouveau/nvkm/core/engine.c index a6294e86d..07559e7c4 100644 --- a/drm/nouveau/nvkm/core/engine.c +++ b/drm/nouveau/nvkm/core/engine.c @@ -25,6 +25,133 @@ #include <core/device.h> #include <core/option.h> +void +nvkm_engine_unref(struct nvkm_engine **pengine) +{ + struct nvkm_engine *engine = *pengine; + if (engine) { + mutex_lock(&engine->subdev.mutex); + if (--engine->usecount == 0) + nvkm_subdev_fini(&engine->subdev, false); + mutex_unlock(&engine->subdev.mutex); + *pengine = NULL; + } +} + +struct nvkm_engine * +nvkm_engine_ref(struct nvkm_engine *engine) +{ + if (engine) { + mutex_lock(&engine->subdev.mutex); + if (++engine->usecount == 1) { + int ret = nvkm_subdev_init(&engine->subdev); + if (ret) { + engine->usecount--; + mutex_unlock(&engine->subdev.mutex); + return ERR_PTR(ret); + } + } + mutex_unlock(&engine->subdev.mutex); + } + return engine; +} + +static void +nvkm_engine_intr(struct nvkm_subdev *obj) +{ + struct nvkm_engine *engine = container_of(obj, typeof(*engine), subdev); + if (engine->func->intr) + engine->func->intr(engine); +} + +static int +nvkm_engine_fini(struct nvkm_subdev *obj, bool suspend) +{ + struct nvkm_engine *engine = container_of(obj, typeof(*engine), subdev); + if (engine->func->fini) + return engine->func->fini(engine, suspend); + return 0; +} + +static int +nvkm_engine_init(struct nvkm_subdev *obj) +{ + struct nvkm_engine *engine = container_of(obj, typeof(*engine), subdev); + struct nvkm_subdev *subdev = &engine->subdev; + int ret = 0; + s64 time; + + if (!engine->usecount) { + nvkm_trace(subdev, "init skipped, engine has no users\n"); + return ret; + } + + if (engine->func->oneinit && !engine->subdev.oneinit) { + nvkm_trace(subdev, "one-time init running...\n"); + time = ktime_to_us(ktime_get()); + ret = engine->func->oneinit(engine); + if (ret) { + nvkm_trace(subdev, "one-time init failed, %d\n", ret); + return ret; + } + + engine->subdev.oneinit = true; + time = ktime_to_us(ktime_get()) - time; + nvkm_trace(subdev, "one-time init completed in %lldus\n", time); + } + + if (engine->func->init) + ret = engine->func->init(engine); + + return ret; +} + +static void * +nvkm_engine_dtor(struct nvkm_subdev *obj) +{ + struct nvkm_engine *engine = container_of(obj, typeof(*engine), subdev); + if (engine->func->dtor) + return engine->func->dtor(engine); + return engine; +} + +static const struct nvkm_subdev_func +nvkm_engine_func = { + .dtor = nvkm_engine_dtor, + .init = nvkm_engine_init, + .fini = nvkm_engine_fini, + .intr = nvkm_engine_intr, +}; + +int +nvkm_engine_ctor(const struct nvkm_engine_func *func, + struct nvkm_device *device, int index, u32 pmc_enable, + bool enable, struct nvkm_engine *engine) +{ + nvkm_subdev_ctor(&nvkm_engine_func, device, index, + pmc_enable, &engine->subdev); + engine->func = func; + + if (!nvkm_boolopt(device->cfgopt, nvkm_subdev_name[index], enable)) { + nvkm_debug(&engine->subdev, "disabled\n"); + return -ENODEV; + } + + spin_lock_init(&engine->lock); + return 0; +} + +int +nvkm_engine_new_(const struct nvkm_engine_func *func, + struct nvkm_device *device, int index, u32 pmc_enable, + bool enable, struct nvkm_engine **pengine) +{ + if (!(*pengine = kzalloc(sizeof(**pengine), GFP_KERNEL))) + return -ENOMEM; + return nvkm_engine_ctor(func, device, index, pmc_enable, + enable, *pengine); +} + struct nvkm_engine * nvkm_engine(void *obj, int idx) { |