drm/nouveau/pm: convert user classes to new-style nvkm_object

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/pm.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/pm.h
index f13f8e6..c67cea6 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/pm.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/pm.h
@@ -1,5 +1,6 @@
 #ifndef __NVKM_PM_H__
 #define __NVKM_PM_H__
+#define nvkm_pm(p) container_of((p), struct nvkm_pm, engine)
 #include <core/engine.h>
 
 struct nvkm_perfdom;
@@ -7,20 +8,13 @@
 struct nvkm_pm {
 	struct nvkm_engine engine;
 
-	struct nvkm_perfctx *context;
-	void *profile_data;
+	struct nvkm_object *perfmon;
 
 	struct list_head domains;
 	struct list_head sources;
 	u32 sequence;
 };
 
-static inline struct nvkm_pm *
-nvkm_pm(void *obj)
-{
-	return (void *)nvkm_engine(obj, NVDEV_ENGINE_PM);
-}
-
 extern struct nvkm_oclass *nv40_pm_oclass;
 extern struct nvkm_oclass *nv50_pm_oclass;
 extern struct nvkm_oclass *g84_pm_oclass;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c
index 90a7d89..5b4ab63 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c
@@ -25,7 +25,6 @@
 
 #include <core/client.h>
 #include <core/option.h>
-#include <core/parent.h>
 
 #include <nvif/class.h>
 #include <nvif/ioctl.h>
@@ -304,11 +303,11 @@
 	return -EINVAL;
 }
 
-static void
-nvkm_perfdom_dtor(struct nvkm_object *object)
+static void *
+nvkm_perfdom_dtor(struct nvkm_object *base)
 {
-	struct nvkm_pm *pm = (void *)object->engine;
-	struct nvkm_perfdom *dom = (void *)object;
+	struct nvkm_perfdom *dom = nvkm_perfdom(base);
+	struct nvkm_pm *pm = dom->perfmon->pm;
 	int i;
 
 	for (i = 0; i < 4; i++) {
@@ -320,7 +319,8 @@
 		}
 		kfree(ctr);
 	}
-	nvkm_object_destroy(&dom->base);
+
+	return dom;
 }
 
 static int
@@ -353,15 +353,22 @@
 	return 0;
 }
 
+static const struct nvkm_object_func
+nvkm_perfdom = {
+	.dtor = nvkm_perfdom_dtor,
+	.mthd = nvkm_perfdom_mthd,
+};
+
 static int
-nvkm_perfdom_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
-		  struct nvkm_oclass *oclass, void *data, u32 size,
+nvkm_perfdom_new_(struct nvkm_perfmon *perfmon,
+		  const struct nvkm_oclass *oclass, void *data, u32 size,
 		  struct nvkm_object **pobject)
 {
 	union {
 		struct nvif_perfdom_v0 v0;
 	} *args = data;
-	struct nvkm_pm *pm = (void *)engine;
+	struct nvkm_pm *pm = perfmon->pm;
+	struct nvkm_object *parent = oclass->parent;
 	struct nvkm_perfdom *sdom = NULL;
 	struct nvkm_perfctr *ctr[4] = {};
 	struct nvkm_perfdom *dom;
@@ -403,10 +410,11 @@
 	if (!sdom)
 		return -EINVAL;
 
-	ret = nvkm_object_create(parent, engine, oclass, 0, &dom);
-	*pobject = nv_object(dom);
-	if (ret)
-		return ret;
+	if (!(dom = kzalloc(sizeof(*dom), GFP_KERNEL)))
+		return -ENOMEM;
+	nvkm_object_ctor(&nvkm_perfdom, oclass, &dom->object);
+	dom->perfmon = perfmon;
+	*pobject = &dom->object;
 
 	dom->func = sdom->func;
 	dom->addr = sdom->addr;
@@ -416,25 +424,18 @@
 	return 0;
 }
 
-static struct nvkm_ofuncs
-nvkm_perfdom_ofuncs = {
-	.ctor = nvkm_perfdom_ctor,
-	.dtor = nvkm_perfdom_dtor,
-	.init = _nvkm_object_init,
-	.fini = _nvkm_object_fini,
-	.mthd = nvkm_perfdom_mthd,
-};
-
 /*******************************************************************************
  * Perfmon object classes
  ******************************************************************************/
 static int
-nvkm_perfmon_mthd_query_domain(struct nvkm_object *object, void *data, u32 size)
+nvkm_perfmon_mthd_query_domain(struct nvkm_perfmon *perfmon,
+			       void *data, u32 size)
 {
 	union {
 		struct nvif_perfmon_query_domain_v0 v0;
 	} *args = data;
-	struct nvkm_pm *pm = (void *)object->engine;
+	struct nvkm_object *object = &perfmon->object;
+	struct nvkm_pm *pm = perfmon->pm;
 	struct nvkm_perfdom *dom;
 	u8 domain_nr;
 	int di, ret;
@@ -475,13 +476,15 @@
 }
 
 static int
-nvkm_perfmon_mthd_query_signal(struct nvkm_object *object, void *data, u32 size)
+nvkm_perfmon_mthd_query_signal(struct nvkm_perfmon *perfmon,
+			       void *data, u32 size)
 {
 	union {
 		struct nvif_perfmon_query_signal_v0 v0;
 	} *args = data;
-	struct nvkm_device *device = nv_device(object);
-	struct nvkm_pm *pm = (void *)object->engine;
+	struct nvkm_object *object = &perfmon->object;
+	struct nvkm_pm *pm = perfmon->pm;
+	struct nvkm_device *device = pm->engine.subdev.device;
 	struct nvkm_perfdom *dom;
 	struct nvkm_perfsig *sig;
 	const bool all = nvkm_boolopt(device->cfgopt, "NvPmShowAll", false);
@@ -527,12 +530,14 @@
 }
 
 static int
-nvkm_perfmon_mthd_query_source(struct nvkm_object *object, void *data, u32 size)
+nvkm_perfmon_mthd_query_source(struct nvkm_perfmon *perfmon,
+			       void *data, u32 size)
 {
 	union {
 		struct nvif_perfmon_query_source_v0 v0;
 	} *args = data;
-	struct nvkm_pm *pm = (void *)object->engine;
+	struct nvkm_object *object = &perfmon->object;
+	struct nvkm_pm *pm = perfmon->pm;
 	struct nvkm_perfdom *dom = NULL;
 	struct nvkm_perfsig *sig;
 	struct nvkm_perfsrc *src;
@@ -579,117 +584,118 @@
 static int
 nvkm_perfmon_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
 {
+	struct nvkm_perfmon *perfmon = nvkm_perfmon(object);
 	switch (mthd) {
 	case NVIF_PERFMON_V0_QUERY_DOMAIN:
-		return nvkm_perfmon_mthd_query_domain(object, data, size);
+		return nvkm_perfmon_mthd_query_domain(perfmon, data, size);
 	case NVIF_PERFMON_V0_QUERY_SIGNAL:
-		return nvkm_perfmon_mthd_query_signal(object, data, size);
+		return nvkm_perfmon_mthd_query_signal(perfmon, data, size);
 	case NVIF_PERFMON_V0_QUERY_SOURCE:
-		return nvkm_perfmon_mthd_query_source(object, data, size);
+		return nvkm_perfmon_mthd_query_source(perfmon, data, size);
 	default:
 		break;
 	}
 	return -EINVAL;
 }
 
-static struct nvkm_oclass
-nvkm_perfmon_sclass[] = {
-	{ .handle = NVIF_IOCTL_NEW_V0_PERFDOM,
-	  .ofuncs = &nvkm_perfdom_ofuncs,
-	},
-	{}
-};
-
 static int
-nvkm_perfmon_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
-		  struct nvkm_oclass *oclass, void *data, u32 size,
-		  struct nvkm_object **pobject)
+nvkm_perfmon_child_new(const struct nvkm_oclass *oclass, void *data, u32 size,
+		       struct nvkm_object **pobject)
 {
-	struct nvkm_parent *perfmon;
-	int ret = nvkm_parent_create(parent, engine, oclass, 0,
-				     nvkm_perfmon_sclass, 0, &perfmon);
-	*pobject = perfmon ? &perfmon->object : NULL;
-	return ret;
-}
-
-static struct nvkm_ofuncs
-nvkm_perfmon_ofuncs = {
-	.ctor = nvkm_perfmon_ctor,
-	.dtor = _nvkm_parent_dtor,
-	.init = _nvkm_parent_init,
-	.fini = _nvkm_parent_fini,
-	.mthd = nvkm_perfmon_mthd,
-};
-
-struct nvkm_oclass
-nvkm_pm_sclass[] = {
-	{
-	  .handle = NVIF_IOCTL_NEW_V0_PERFMON,
-	  .ofuncs = &nvkm_perfmon_ofuncs,
-	},
-	{},
-};
-
-/*******************************************************************************
- * PPM context
- ******************************************************************************/
-static void
-nvkm_perfctx_dtor(struct nvkm_object *object)
-{
-	struct nvkm_pm *pm = (void *)object->engine;
-	struct nvkm_perfctx *ctx = (void *)object;
-
-	nvkm_gpuobj_destroy(&ctx->base);
-	mutex_lock(&nv_subdev(pm)->mutex);
-	if (pm->context == ctx)
-		pm->context = NULL;
-	mutex_unlock(&nv_subdev(pm)->mutex);
+	struct nvkm_perfmon *perfmon = nvkm_perfmon(oclass->parent);
+	return nvkm_perfdom_new_(perfmon, oclass, data, size, pobject);
 }
 
 static int
-nvkm_perfctx_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
-		  struct nvkm_oclass *oclass, void *data, u32 size,
-		  struct nvkm_object **pobject)
+nvkm_perfmon_child_get(struct nvkm_object *base, int index,
+		       struct nvkm_oclass *oclass)
 {
-	struct nvkm_pm *pm = (void *)engine;
-	struct nvkm_perfctx *ctx;
-	int ret;
-
-	/* no context needed for perfdom objects... */
-	if (parent->parent != &nvkm_client(parent)->object) {
-		atomic_inc(&parent->refcount);
-		*pobject = parent;
-		return 1;
+	if (index == 0) {
+		oclass->base.oclass = NVIF_IOCTL_NEW_V0_PERFDOM;
+		oclass->base.minver = 0;
+		oclass->base.maxver = 0;
+		oclass->ctor = nvkm_perfmon_child_new;
+		return 0;
 	}
-
-	ret = nvkm_gpuobj_create(parent, engine, oclass, 0, NULL, 0, 0, 0, &ctx);
-	*pobject = nv_object(ctx);
-	if (ret)
-		return ret;
-
-	mutex_lock(&nv_subdev(pm)->mutex);
-	if (pm->context == NULL)
-		pm->context = ctx;
-	if (ctx != pm->context)
-		ret = -EBUSY;
-	mutex_unlock(&nv_subdev(pm)->mutex);
-
-	return ret;
+	return -EINVAL;
 }
 
-struct nvkm_oclass
-nvkm_pm_cclass = {
-	.ofuncs = &(struct nvkm_ofuncs) {
-		.ctor = nvkm_perfctx_ctor,
-		.dtor = nvkm_perfctx_dtor,
-		.init = _nvkm_gpuobj_init,
-		.fini = _nvkm_gpuobj_fini,
-	},
+static void *
+nvkm_perfmon_dtor(struct nvkm_object *base)
+{
+	struct nvkm_perfmon *perfmon = nvkm_perfmon(base);
+	struct nvkm_pm *pm = perfmon->pm;
+	mutex_lock(&pm->engine.subdev.mutex);
+	if (pm->perfmon == &perfmon->object)
+		pm->perfmon = NULL;
+	mutex_unlock(&pm->engine.subdev.mutex);
+	return perfmon;
+}
+
+static struct nvkm_object_func
+nvkm_perfmon = {
+	.dtor = nvkm_perfmon_dtor,
+	.mthd = nvkm_perfmon_mthd,
+	.sclass = nvkm_perfmon_child_get,
 };
 
+static int
+nvkm_perfmon_new(struct nvkm_pm *pm, const struct nvkm_oclass *oclass,
+		 void *data, u32 size, struct nvkm_object **pobject)
+{
+	struct nvkm_perfmon *perfmon;
+
+	if (!(perfmon = kzalloc(sizeof(*perfmon), GFP_KERNEL)))
+		return -ENOMEM;
+	nvkm_object_ctor(&nvkm_perfmon, oclass, &perfmon->object);
+	perfmon->pm = pm;
+	*pobject = &perfmon->object;
+	return 0;
+}
+
 /*******************************************************************************
  * PPM engine/subdev functions
  ******************************************************************************/
+
+static int
+nvkm_pm_oclass_new(struct nvkm_device *device, const struct nvkm_oclass *oclass,
+		   void *data, u32 size, struct nvkm_object **pobject)
+{
+	struct nvkm_pm *pm = nvkm_pm(oclass->engine);
+	int ret;
+
+	ret = nvkm_perfmon_new(pm, oclass, data, size, pobject);
+	if (ret)
+		return ret;
+
+	mutex_lock(&pm->engine.subdev.mutex);
+	if (pm->perfmon == NULL)
+		pm->perfmon = *pobject;
+	ret = (pm->perfmon == *pobject) ? 0 : -EBUSY;
+	mutex_unlock(&pm->engine.subdev.mutex);
+	return ret;
+}
+
+static const struct nvkm_device_oclass
+nvkm_pm_oclass = {
+	.base.oclass = NVIF_IOCTL_NEW_V0_PERFMON,
+	.base.minver = -1,
+	.base.maxver = -1,
+	.ctor = nvkm_pm_oclass_new,
+};
+
+static int
+nvkm_pm_oclass_get(struct nvkm_oclass *oclass, int index,
+		   const struct nvkm_device_oclass **class)
+{
+	if (index == 0) {
+		oclass->base = nvkm_pm_oclass.base;
+		*class = &nvkm_pm_oclass;
+		return index;
+	}
+	return 1;
+}
+
 int
 nvkm_perfsrc_new(struct nvkm_pm *pm, struct nvkm_perfsig *sig,
 		 const struct nvkm_specsrc *spec)
@@ -845,6 +851,11 @@
 	nvkm_engine_destroy(&pm->engine);
 }
 
+static const struct nvkm_engine_func
+nvkm_pm = {
+	.base.sclass = nvkm_pm_oclass_get,
+};
+
 int
 nvkm_pm_create_(struct nvkm_object *parent, struct nvkm_object *engine,
 		struct nvkm_oclass *oclass, int length, void **pobject)
@@ -858,6 +869,8 @@
 	if (ret)
 		return ret;
 
+	pm->engine.func = &nvkm_pm;
+
 	INIT_LIST_HEAD(&pm->domains);
 	INIT_LIST_HEAD(&pm->sources);
 	return 0;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.c
index 75a9e62..18e0ed5 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.c
@@ -226,8 +226,6 @@
 	if (ret)
 		return ret;
 
-	nv_engine(pm)->cclass = &nvkm_pm_cclass;
-	nv_engine(pm)->sclass =  nvkm_pm_sclass;
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/pm/gk110.c
index 3177ba4..44df8d3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/gk110.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/pm/gk110.c
@@ -36,8 +36,6 @@
 	if (ret)
 		return ret;
 
-	nv_engine(pm)->cclass = &nvkm_pm_cclass;
-	nv_engine(pm)->sclass =  nvkm_pm_sclass;
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv40.c
index b37c024f..a4660dc 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv40.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/pm/nv40.c
@@ -112,8 +112,6 @@
 	if (ret)
 		return ret;
 
-	nv_engine(pm)->cclass = &nvkm_pm_cclass;
-	nv_engine(pm)->sclass =  nvkm_pm_sclass;
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/pm/priv.h
index 2af3a50..889dca2 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/pm/priv.h
@@ -12,16 +12,6 @@
 	u32 ctr;
 };
 
-extern struct nvkm_oclass nvkm_pm_sclass[];
-
-#include <core/gpuobj.h>
-
-struct nvkm_perfctx {
-	struct nvkm_gpuobj base;
-};
-
-extern struct nvkm_oclass nvkm_pm_cclass;
-
 struct nvkm_specmux {
 	u32 mask;
 	u8 shift;
@@ -68,8 +58,11 @@
 	const struct nvkm_funcdom *func;
 };
 
+#define nvkm_perfdom(p) container_of((p), struct nvkm_perfdom, object)
+
 struct nvkm_perfdom {
-	struct nvkm_object base;
+	struct nvkm_object object;
+	struct nvkm_perfmon *perfmon;
 	struct list_head head;
 	struct list_head list;
 	const struct nvkm_funcdom *func;
@@ -93,6 +86,13 @@
 int nvkm_perfdom_new(struct nvkm_pm *, const char *, u32, u32, u32, u32,
 		     const struct nvkm_specdom *);
 
+#define nvkm_perfmon(p) container_of((p), struct nvkm_perfmon, object)
+
+struct nvkm_perfmon {
+	struct nvkm_object object;
+	struct nvkm_pm *pm;
+};
+
 #define nvkm_pm_create(p,e,o,d)                                        \
 	nvkm_pm_create_((p), (e), (o), sizeof(**d), (void **)d)
 #define nvkm_pm_dtor(p) ({                                             \