summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau/nvkm/engine/pm
diff options
context:
space:
mode:
authorSamuel Pitoiset <samuel.pitoiset@gmail.com>2015-06-07 22:40:17 +0200
committerBen Skeggs <bskeggs@redhat.com>2015-08-28 12:39:58 +1000
commit45f0f94db285009a41a94e069618ea9bb269af84 (patch)
tree172c5850acba1ddd9f570bcbfed97c01a1587cba /drivers/gpu/drm/nouveau/nvkm/engine/pm
parent44d9de58ea5633e4f2d062e718016383b28b4eed (diff)
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.c86
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: