|
@@ -185,181 +185,6 @@ nvkm_perfsrc_disable(struct nvkm_pm *ppm, struct nvkm_perfctr *ctr)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-/*******************************************************************************
|
|
|
- * Perfmon object classes
|
|
|
- ******************************************************************************/
|
|
|
-static int
|
|
|
-nvkm_perfmon_mthd_query_domain(struct nvkm_object *object, void *data, u32 size)
|
|
|
-{
|
|
|
- union {
|
|
|
- struct nvif_perfmon_query_domain_v0 v0;
|
|
|
- } *args = data;
|
|
|
- struct nvkm_pm *ppm = (void *)object->engine;
|
|
|
- struct nvkm_perfdom *dom;
|
|
|
- u8 domain_nr;
|
|
|
- int di, ret;
|
|
|
-
|
|
|
- nv_ioctl(object, "perfmon query domain size %d\n", size);
|
|
|
- if (nvif_unpack(args->v0, 0, 0, false)) {
|
|
|
- nv_ioctl(object, "perfmon domain vers %d iter %02x\n",
|
|
|
- args->v0.version, args->v0.iter);
|
|
|
- di = (args->v0.iter & 0xff) - 1;
|
|
|
- } else
|
|
|
- return ret;
|
|
|
-
|
|
|
- domain_nr = nvkm_pm_count_perfdom(ppm);
|
|
|
- if (di >= (int)domain_nr)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- if (di >= 0) {
|
|
|
- dom = nvkm_perfdom_find(ppm, di);
|
|
|
- if (dom == NULL)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- args->v0.id = di;
|
|
|
- args->v0.signal_nr = nvkm_perfdom_count_perfsig(dom);
|
|
|
-
|
|
|
- /* Currently only global counters (PCOUNTER) are implemented
|
|
|
- * but this will be different for local counters (MP). */
|
|
|
- args->v0.counter_nr = 4;
|
|
|
- }
|
|
|
-
|
|
|
- if (++di < domain_nr) {
|
|
|
- args->v0.iter = ++di;
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- args->v0.iter = 0xff;
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int
|
|
|
-nvkm_perfmon_mthd_query_signal(struct nvkm_object *object, void *data, u32 size)
|
|
|
-{
|
|
|
- union {
|
|
|
- struct nvif_perfmon_query_signal_v0 v0;
|
|
|
- } *args = data;
|
|
|
- struct nvkm_device *device = nv_device(object);
|
|
|
- struct nvkm_pm *ppm = (void *)object->engine;
|
|
|
- struct nvkm_perfdom *dom;
|
|
|
- struct nvkm_perfsig *sig;
|
|
|
- const bool all = nvkm_boolopt(device->cfgopt, "NvPmShowAll", false);
|
|
|
- const bool raw = nvkm_boolopt(device->cfgopt, "NvPmUnnamed", all);
|
|
|
- int ret, si;
|
|
|
-
|
|
|
- nv_ioctl(object, "perfmon query signal size %d\n", size);
|
|
|
- if (nvif_unpack(args->v0, 0, 0, false)) {
|
|
|
- nv_ioctl(object,
|
|
|
- "perfmon query signal vers %d dom %d iter %04x\n",
|
|
|
- args->v0.version, args->v0.domain, args->v0.iter);
|
|
|
- si = (args->v0.iter & 0xffff) - 1;
|
|
|
- } else
|
|
|
- return ret;
|
|
|
-
|
|
|
- dom = nvkm_perfdom_find(ppm, args->v0.domain);
|
|
|
- if (dom == NULL || si >= (int)dom->signal_nr)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- if (si >= 0) {
|
|
|
- sig = &dom->signal[si];
|
|
|
- if (raw || !sig->name) {
|
|
|
- snprintf(args->v0.name, sizeof(args->v0.name),
|
|
|
- "/%s/%02x", dom->name, si);
|
|
|
- } else {
|
|
|
- strncpy(args->v0.name, sig->name,
|
|
|
- sizeof(args->v0.name));
|
|
|
- }
|
|
|
-
|
|
|
- args->v0.signal = si;
|
|
|
- args->v0.source_nr = nvkm_perfsig_count_perfsrc(sig);
|
|
|
- }
|
|
|
-
|
|
|
- while (++si < dom->signal_nr) {
|
|
|
- if (all || dom->signal[si].name) {
|
|
|
- args->v0.iter = ++si;
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- args->v0.iter = 0xffff;
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int
|
|
|
-nvkm_perfmon_mthd_query_source(struct nvkm_object *object, void *data, u32 size)
|
|
|
-{
|
|
|
- union {
|
|
|
- struct nvif_perfmon_query_source_v0 v0;
|
|
|
- } *args = data;
|
|
|
- struct nvkm_pm *ppm = (void *)object->engine;
|
|
|
- struct nvkm_perfdom *dom = NULL;
|
|
|
- struct nvkm_perfsig *sig;
|
|
|
- struct nvkm_perfsrc *src;
|
|
|
- u8 source_nr = 0;
|
|
|
- int si, ret;
|
|
|
-
|
|
|
- nv_ioctl(object, "perfmon query source size %d\n", size);
|
|
|
- if (nvif_unpack(args->v0, 0, 0, false)) {
|
|
|
- nv_ioctl(object,
|
|
|
- "perfmon source vers %d dom %d sig %02x iter %02x\n",
|
|
|
- args->v0.version, args->v0.domain, args->v0.signal,
|
|
|
- args->v0.iter);
|
|
|
- si = (args->v0.iter & 0xff) - 1;
|
|
|
- } else
|
|
|
- return ret;
|
|
|
-
|
|
|
- sig = nvkm_perfsig_find(ppm, args->v0.domain, args->v0.signal, &dom);
|
|
|
- if (!sig)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- source_nr = nvkm_perfsig_count_perfsrc(sig);
|
|
|
- if (si >= (int)source_nr)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- if (si >= 0) {
|
|
|
- src = nvkm_perfsrc_find(ppm, sig, sig->source[si]);
|
|
|
- if (!src)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- args->v0.source = sig->source[si];
|
|
|
- args->v0.mask = src->mask;
|
|
|
- strncpy(args->v0.name, src->name, sizeof(args->v0.name));
|
|
|
- }
|
|
|
-
|
|
|
- if (++si < source_nr) {
|
|
|
- args->v0.iter = ++si;
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- args->v0.iter = 0xff;
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int
|
|
|
-nvkm_perfmon_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
|
|
|
-{
|
|
|
- switch (mthd) {
|
|
|
- case NVIF_PERFMON_V0_QUERY_DOMAIN:
|
|
|
- return nvkm_perfmon_mthd_query_domain(object, data, size);
|
|
|
- case NVIF_PERFMON_V0_QUERY_SIGNAL:
|
|
|
- return nvkm_perfmon_mthd_query_signal(object, data, size);
|
|
|
- case NVIF_PERFMON_V0_QUERY_SOURCE:
|
|
|
- return nvkm_perfmon_mthd_query_source(object, data, size);
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
- return -EINVAL;
|
|
|
-}
|
|
|
-
|
|
|
-static struct nvkm_ofuncs
|
|
|
-nvkm_perfmon_ofuncs = {
|
|
|
- .ctor = _nvkm_object_ctor,
|
|
|
- .dtor = nvkm_object_destroy,
|
|
|
- .init = nvkm_object_init,
|
|
|
- .fini = nvkm_object_fini,
|
|
|
- .mthd = nvkm_perfmon_mthd,
|
|
|
-};
|
|
|
-
|
|
|
/*******************************************************************************
|
|
|
* Perfdom object classes
|
|
|
******************************************************************************/
|
|
@@ -585,6 +410,181 @@ nvkm_perfdom_ofuncs = {
|
|
|
.mthd = nvkm_perfdom_mthd,
|
|
|
};
|
|
|
|
|
|
+/*******************************************************************************
|
|
|
+ * Perfmon object classes
|
|
|
+ ******************************************************************************/
|
|
|
+static int
|
|
|
+nvkm_perfmon_mthd_query_domain(struct nvkm_object *object, void *data, u32 size)
|
|
|
+{
|
|
|
+ union {
|
|
|
+ struct nvif_perfmon_query_domain_v0 v0;
|
|
|
+ } *args = data;
|
|
|
+ struct nvkm_pm *ppm = (void *)object->engine;
|
|
|
+ struct nvkm_perfdom *dom;
|
|
|
+ u8 domain_nr;
|
|
|
+ int di, ret;
|
|
|
+
|
|
|
+ nv_ioctl(object, "perfmon query domain size %d\n", size);
|
|
|
+ if (nvif_unpack(args->v0, 0, 0, false)) {
|
|
|
+ nv_ioctl(object, "perfmon domain vers %d iter %02x\n",
|
|
|
+ args->v0.version, args->v0.iter);
|
|
|
+ di = (args->v0.iter & 0xff) - 1;
|
|
|
+ } else
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ domain_nr = nvkm_pm_count_perfdom(ppm);
|
|
|
+ if (di >= (int)domain_nr)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ if (di >= 0) {
|
|
|
+ dom = nvkm_perfdom_find(ppm, di);
|
|
|
+ if (dom == NULL)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ args->v0.id = di;
|
|
|
+ args->v0.signal_nr = nvkm_perfdom_count_perfsig(dom);
|
|
|
+
|
|
|
+ /* Currently only global counters (PCOUNTER) are implemented
|
|
|
+ * but this will be different for local counters (MP). */
|
|
|
+ args->v0.counter_nr = 4;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (++di < domain_nr) {
|
|
|
+ args->v0.iter = ++di;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ args->v0.iter = 0xff;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+nvkm_perfmon_mthd_query_signal(struct nvkm_object *object, void *data, u32 size)
|
|
|
+{
|
|
|
+ union {
|
|
|
+ struct nvif_perfmon_query_signal_v0 v0;
|
|
|
+ } *args = data;
|
|
|
+ struct nvkm_device *device = nv_device(object);
|
|
|
+ struct nvkm_pm *ppm = (void *)object->engine;
|
|
|
+ struct nvkm_perfdom *dom;
|
|
|
+ struct nvkm_perfsig *sig;
|
|
|
+ const bool all = nvkm_boolopt(device->cfgopt, "NvPmShowAll", false);
|
|
|
+ const bool raw = nvkm_boolopt(device->cfgopt, "NvPmUnnamed", all);
|
|
|
+ int ret, si;
|
|
|
+
|
|
|
+ nv_ioctl(object, "perfmon query signal size %d\n", size);
|
|
|
+ if (nvif_unpack(args->v0, 0, 0, false)) {
|
|
|
+ nv_ioctl(object,
|
|
|
+ "perfmon query signal vers %d dom %d iter %04x\n",
|
|
|
+ args->v0.version, args->v0.domain, args->v0.iter);
|
|
|
+ si = (args->v0.iter & 0xffff) - 1;
|
|
|
+ } else
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ dom = nvkm_perfdom_find(ppm, args->v0.domain);
|
|
|
+ if (dom == NULL || si >= (int)dom->signal_nr)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ if (si >= 0) {
|
|
|
+ sig = &dom->signal[si];
|
|
|
+ if (raw || !sig->name) {
|
|
|
+ snprintf(args->v0.name, sizeof(args->v0.name),
|
|
|
+ "/%s/%02x", dom->name, si);
|
|
|
+ } else {
|
|
|
+ strncpy(args->v0.name, sig->name,
|
|
|
+ sizeof(args->v0.name));
|
|
|
+ }
|
|
|
+
|
|
|
+ args->v0.signal = si;
|
|
|
+ args->v0.source_nr = nvkm_perfsig_count_perfsrc(sig);
|
|
|
+ }
|
|
|
+
|
|
|
+ while (++si < dom->signal_nr) {
|
|
|
+ if (all || dom->signal[si].name) {
|
|
|
+ args->v0.iter = ++si;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ args->v0.iter = 0xffff;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+nvkm_perfmon_mthd_query_source(struct nvkm_object *object, void *data, u32 size)
|
|
|
+{
|
|
|
+ union {
|
|
|
+ struct nvif_perfmon_query_source_v0 v0;
|
|
|
+ } *args = data;
|
|
|
+ struct nvkm_pm *ppm = (void *)object->engine;
|
|
|
+ struct nvkm_perfdom *dom = NULL;
|
|
|
+ struct nvkm_perfsig *sig;
|
|
|
+ struct nvkm_perfsrc *src;
|
|
|
+ u8 source_nr = 0;
|
|
|
+ int si, ret;
|
|
|
+
|
|
|
+ nv_ioctl(object, "perfmon query source size %d\n", size);
|
|
|
+ if (nvif_unpack(args->v0, 0, 0, false)) {
|
|
|
+ nv_ioctl(object,
|
|
|
+ "perfmon source vers %d dom %d sig %02x iter %02x\n",
|
|
|
+ args->v0.version, args->v0.domain, args->v0.signal,
|
|
|
+ args->v0.iter);
|
|
|
+ si = (args->v0.iter & 0xff) - 1;
|
|
|
+ } else
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ sig = nvkm_perfsig_find(ppm, args->v0.domain, args->v0.signal, &dom);
|
|
|
+ if (!sig)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ source_nr = nvkm_perfsig_count_perfsrc(sig);
|
|
|
+ if (si >= (int)source_nr)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ if (si >= 0) {
|
|
|
+ src = nvkm_perfsrc_find(ppm, sig, sig->source[si]);
|
|
|
+ if (!src)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ args->v0.source = sig->source[si];
|
|
|
+ args->v0.mask = src->mask;
|
|
|
+ strncpy(args->v0.name, src->name, sizeof(args->v0.name));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (++si < source_nr) {
|
|
|
+ args->v0.iter = ++si;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ args->v0.iter = 0xff;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+nvkm_perfmon_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
|
|
|
+{
|
|
|
+ switch (mthd) {
|
|
|
+ case NVIF_PERFMON_V0_QUERY_DOMAIN:
|
|
|
+ return nvkm_perfmon_mthd_query_domain(object, data, size);
|
|
|
+ case NVIF_PERFMON_V0_QUERY_SIGNAL:
|
|
|
+ return nvkm_perfmon_mthd_query_signal(object, data, size);
|
|
|
+ case NVIF_PERFMON_V0_QUERY_SOURCE:
|
|
|
+ return nvkm_perfmon_mthd_query_source(object, data, size);
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return -EINVAL;
|
|
|
+}
|
|
|
+
|
|
|
+static struct nvkm_ofuncs
|
|
|
+nvkm_perfmon_ofuncs = {
|
|
|
+ .ctor = _nvkm_object_ctor,
|
|
|
+ .dtor = nvkm_object_destroy,
|
|
|
+ .init = nvkm_object_init,
|
|
|
+ .fini = nvkm_object_fini,
|
|
|
+ .mthd = nvkm_perfmon_mthd,
|
|
|
+};
|
|
|
+
|
|
|
struct nvkm_oclass
|
|
|
nvkm_pm_sclass[] = {
|
|
|
{
|