From 2e70447ac4ea4d1e10cfafea7fcec22e3e4db454 Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Sun, 7 Jun 2015 22:40:24 +0200 Subject: pm: implement NVIF_PERFMON_V0_QUERY_SOURCE method This allows to query the ID, the mask and the user-readable name of sources for each signal. Signed-off-by: Samuel Pitoiset Signed-off-by: Ben Skeggs --- drm/nouveau/include/nvif/class.h | 12 ++++++ drm/nouveau/nvkm/engine/pm/base.c | 77 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/drm/nouveau/include/nvif/class.h b/drm/nouveau/include/nvif/class.h index caae193f3..d85fb0d94 100644 --- a/drm/nouveau/include/nvif/class.h +++ b/drm/nouveau/include/nvif/class.h @@ -253,6 +253,7 @@ struct gf110_dma_v0 { #define NVIF_PERFMON_V0_QUERY_DOMAIN 0x00 #define NVIF_PERFMON_V0_QUERY_SIGNAL 0x01 +#define NVIF_PERFMON_V0_QUERY_SOURCE 0x02 struct nvif_perfmon_query_domain_v0 { __u8 version; @@ -273,6 +274,17 @@ struct nvif_perfmon_query_signal_v0 { char name[64]; }; +struct nvif_perfmon_query_source_v0 { + __u8 version; + __u8 domain; + __u8 signal; + __u8 iter; + __u8 pad04[4]; + __u32 source; + __u32 mask; + char name[64]; +}; + /******************************************************************************* * perfctr diff --git a/drm/nouveau/nvkm/engine/pm/base.c b/drm/nouveau/nvkm/engine/pm/base.c index a9c57a201..ec02abfd8 100644 --- a/drm/nouveau/nvkm/engine/pm/base.c +++ b/drm/nouveau/nvkm/engine/pm/base.c @@ -103,6 +103,31 @@ nvkm_perfsig_count_perfsrc(struct nvkm_perfsig *sig) return source_nr; } +static struct nvkm_perfsrc * +nvkm_perfsrc_find(struct nvkm_pm *ppm, struct nvkm_perfsig *sig, int si) +{ + struct nvkm_perfsrc *src; + bool found = false; + int tmp = 1; /* Sources ID start from 1 */ + u8 i; + + for (i = 0; i < ARRAY_SIZE(sig->source) && sig->source[i]; i++) { + if (sig->source[i] == si) { + found = true; + break; + } + } + + if (found) { + list_for_each_entry(src, &ppm->sources, head) { + if (tmp++ == si) + return src; + } + } + + return NULL; +} + /******************************************************************************* * Perfmon object classes ******************************************************************************/ @@ -203,6 +228,56 @@ nvkm_perfmon_mthd_query_signal(struct nvkm_object *object, void *data, u32 size) 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) { @@ -211,6 +286,8 @@ nvkm_perfmon_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) 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; } -- cgit v1.2.1