drm/nouveau/pm: implement NVIF_PERFMON_V0_QUERY_DOMAIN method
authorSamuel Pitoiset <samuel.pitoiset@gmail.com>
Sun, 7 Jun 2015 20:40:17 +0000 (22:40 +0200)
committerBen Skeggs <bskeggs@redhat.com>
Fri, 28 Aug 2015 02:39:58 +0000 (12:39 +1000)
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>
drivers/gpu/drm/nouveau/include/nvif/class.h
drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c

index 11935a048744ca9eaeb41fe0a707f38638f6fe84..0b28929f5be6c9d4f73829478acdd6a6177dc503 100644 (file)
@@ -251,7 +251,16 @@ struct gf110_dma_v0 {
  * perfmon
  ******************************************************************************/
 
-#define NVIF_PERFMON_V0_QUERY_SIGNAL                                       0x00
+#define NVIF_PERFMON_V0_QUERY_DOMAIN                                       0x00
+#define NVIF_PERFMON_V0_QUERY_SIGNAL                                       0x01
+
+struct nvif_perfmon_query_domain_v0 {
+       __u8  version;
+       __u8  id;
+       __u8  counter_nr;
+       __u8  iter;
+       __u32 signal_nr;
+};
 
 struct nvif_perfmon_query_signal_v0 {
        __u8  version;
index 2f851473cecfd1d107dcfa4d6ef8980b20eee976..3d9bcbc1064c50c53993aee761b01a6d08d8e6ef 100644 (file)
 #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)
 {
@@ -82,6 +121,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)
 {
@@ -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: