diff options
author | Samuel Pitoiset <samuel.pitoiset@gmail.com> | 2015-06-07 23:40:17 +0300 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2015-08-28 05:39:58 +0300 |
commit | 45f0f94db285009a41a94e069618ea9bb269af84 (patch) | |
tree | 172c5850acba1ddd9f570bcbfed97c01a1587cba /drivers/gpu/drm/nouveau/nvkm/engine/pm | |
parent | 44d9de58ea5633e4f2d062e718016383b28b4eed (diff) | |
download | linux-45f0f94db285009a41a94e069618ea9bb269af84.tar.xz |
drm/nouveau/pm: implement NVIF_PERFMON_V0_QUERY_DOMAIN method
This allows to query the number of available domains, including the
number of hardware counter and the number of signals per domain.
Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/engine/pm')
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c index 2f851473cecf..3d9bcbc1064c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c @@ -34,6 +34,45 @@ #define QUAD_MASK 0x0f #define QUAD_FREE 0x01 +static u8 +nvkm_pm_count_perfdom(struct nvkm_pm *ppm) +{ + struct nvkm_perfdom *dom; + u8 domain_nr = 0; + + list_for_each_entry(dom, &ppm->domains, head) + domain_nr++; + return domain_nr; +} + +static u32 +nvkm_perfdom_count_perfsig(struct nvkm_perfdom *dom) +{ + u32 signal_nr = 0; + int i; + + if (dom) { + for (i = 0; i < dom->signal_nr; i++) { + if (dom->signal[i].name) + signal_nr++; + } + } + return signal_nr; +} + +static struct nvkm_perfdom * +nvkm_perfdom_find(struct nvkm_pm *ppm, int di) +{ + struct nvkm_perfdom *dom; + int tmp = 0; + + list_for_each_entry(dom, &ppm->domains, head) { + if (tmp++ == di) + return dom; + } + return NULL; +} + static struct nvkm_perfsig * nvkm_perfsig_find_(struct nvkm_perfdom *dom, const char *name, u32 size) { @@ -83,6 +122,51 @@ nvkm_perfsig_find(struct nvkm_pm *ppm, const char *name, u32 size, * 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 { @@ -145,6 +229,8 @@ 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); default: |