summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Pitoiset <samuel.pitoiset@gmail.com>2015-06-07 22:40:24 +0200
committerBen Skeggs <bskeggs@redhat.com>2015-07-28 17:22:39 +1000
commit2e70447ac4ea4d1e10cfafea7fcec22e3e4db454 (patch)
tree02d48b76180a73314eff104ec333bf0969732c7a
parent51db44d6f4db8e011f7f146cc50e18caf912e2f6 (diff)
downloadnouveau-2e70447ac4ea4d1e10cfafea7fcec22e3e4db454.tar.gz
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 <samuel.pitoiset@gmail.com> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drm/nouveau/include/nvif/class.h12
-rw-r--r--drm/nouveau/nvkm/engine/pm/base.c77
2 files changed, 89 insertions, 0 deletions
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
******************************************************************************/
@@ -204,6 +229,56 @@ nvkm_perfmon_mthd_query_signal(struct nvkm_object *object, void *data, u32 size)
}
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) {
@@ -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;
}