From 168c2e213d3a9b605856d3676d9e93733c8b37d3 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 20 Aug 2015 14:54:16 +1000 Subject: [PATCH] drm/nouveau/engine: implement support for new-style nvkm_engine Signed-off-by: Ben Skeggs --- .../drm/nouveau/include/nvkm/core/engine.h | 37 +++++ drivers/gpu/drm/nouveau/nvkm/core/engine.c | 127 ++++++++++++++++++ 2 files changed, 164 insertions(+) diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h b/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h index f98980e15f26..8c67d755e5c1 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h @@ -1,12 +1,18 @@ #ifndef __NVKM_ENGINE_H__ #define __NVKM_ENGINE_H__ #include +struct nvkm_device_oclass; /*XXX: DEV!ENG */ +struct nvkm_fifo_chan; #define NV_ENGINE_(eng,var) (((var) << 8) | (eng)) #define NV_ENGINE(name,var) NV_ENGINE_(NVDEV_ENGINE_##name, (var)) struct nvkm_engine { struct nvkm_subdev subdev; + const struct nvkm_engine_func *func; + + int usecount; + struct nvkm_oclass *cclass; struct nvkm_oclass *sclass; @@ -17,6 +23,37 @@ struct nvkm_engine { int (*tlb_flush)(struct nvkm_engine *); }; +struct nvkm_engine_func { + void *(*dtor)(struct nvkm_engine *); + int (*oneinit)(struct nvkm_engine *); + int (*init)(struct nvkm_engine *); + int (*fini)(struct nvkm_engine *, bool suspend); + void (*intr)(struct nvkm_engine *); + + struct { + int (*sclass)(struct nvkm_oclass *, int index, + const struct nvkm_device_oclass **); + } base; + + struct { + int (*cclass)(struct nvkm_fifo_chan *, + const struct nvkm_oclass *, + struct nvkm_object **); + int (*sclass)(struct nvkm_oclass *, int index); + } fifo; + + struct nvkm_sclass sclass[]; +}; + +int nvkm_engine_ctor(const struct nvkm_engine_func *, struct nvkm_device *, + int index, u32 pmc_enable, bool enable, + struct nvkm_engine *); +int nvkm_engine_new_(const struct nvkm_engine_func *, struct nvkm_device *, + int index, u32 pmc_enable, bool enable, + struct nvkm_engine **); +struct nvkm_engine *nvkm_engine_ref(struct nvkm_engine *); +void nvkm_engine_unref(struct nvkm_engine **); + static inline struct nvkm_engine * nv_engine(void *obj) { diff --git a/drivers/gpu/drm/nouveau/nvkm/core/engine.c b/drivers/gpu/drm/nouveau/nvkm/core/engine.c index a6294e86d467..07559e7c4c4c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/engine.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/engine.c @@ -25,6 +25,133 @@ #include #include +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) { -- 2.39.2