#include <core/client.h>
#include <core/option.h>
-#include <core/parent.h>
#include <nvif/class.h>
#include <nvif/ioctl.h>
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++) {
}
kfree(ctr);
}
- nvkm_object_destroy(&dom->base);
+
+ return dom;
}
static int
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;
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;
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;
}
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);
}
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;
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_child_new(const struct nvkm_oclass *oclass, void *data, u32 size,
+ struct nvkm_object **pobject)
+{
+ struct nvkm_perfmon *perfmon = nvkm_perfmon(oclass->parent);
+ return nvkm_perfdom_new_(perfmon, oclass, data, size, pobject);
+}
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_get(struct nvkm_object *base, int index,
+ struct nvkm_oclass *oclass)
{
- 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;
+ 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;
+ }
+ return -EINVAL;
}
-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,
-};
+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;
+}
-struct nvkm_oclass
-nvkm_pm_sclass[] = {
- {
- .handle = NVIF_IOCTL_NEW_V0_PERFMON,
- .ofuncs = &nvkm_perfmon_ofuncs,
- },
- {},
+static struct nvkm_object_func
+nvkm_perfmon = {
+ .dtor = nvkm_perfmon_dtor,
+ .mthd = nvkm_perfmon_mthd,
+ .sclass = nvkm_perfmon_child_get,
};
-/*******************************************************************************
- * PPM context
- ******************************************************************************/
-static void
-nvkm_perfctx_dtor(struct nvkm_object *object)
+static int
+nvkm_perfmon_new(struct nvkm_pm *pm, const struct nvkm_oclass *oclass,
+ void *data, u32 size, struct nvkm_object **pobject)
{
- struct nvkm_pm *pm = (void *)object->engine;
- struct nvkm_perfctx *ctx = (void *)object;
+ struct nvkm_perfmon *perfmon;
- nvkm_gpuobj_destroy(&ctx->base);
- mutex_lock(&nv_subdev(pm)->mutex);
- if (pm->context == ctx)
- pm->context = NULL;
- mutex_unlock(&nv_subdev(pm)->mutex);
+ 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_perfctx_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
- struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
+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 = (void *)engine;
- struct nvkm_perfctx *ctx;
+ struct nvkm_pm *pm = nvkm_pm(oclass->engine);
int ret;
- /* no context needed for perfdom objects... */
- if (parent->parent != &nvkm_client(parent)->object) {
- atomic_inc(&parent->refcount);
- *pobject = parent;
- return 1;
- }
-
- ret = nvkm_gpuobj_create(parent, engine, oclass, 0, NULL, 0, 0, 0, &ctx);
- *pobject = nv_object(ctx);
+ ret = nvkm_perfmon_new(pm, oclass, data, size, pobject);
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);
-
+ 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;
}
-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 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,
};
-/*******************************************************************************
- * PPM engine/subdev functions
- ******************************************************************************/
+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)
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)
if (ret)
return ret;
+ pm->engine.func = &nvkm_pm;
+
INIT_LIST_HEAD(&pm->domains);
INIT_LIST_HEAD(&pm->sources);
return 0;