This will allow to configure performance counters with hardware signal
indexes instead of user-readable names in an upcoming patch.

Signed-off-by: Samuel Pitoiset <samuel.pitoi...@gmail.com>
---
 bin/nv_perfmon.c                  | 185 ++++++++++++++++++++++++++++----------
 drm/nouveau/include/nvif/class.h  |   3 +-
 drm/nouveau/nvkm/engine/pm/base.c |  36 +++-----
 3 files changed, 150 insertions(+), 74 deletions(-)

diff --git a/bin/nv_perfmon.c b/bin/nv_perfmon.c
index 30a3138..958520e 100644
--- a/bin/nv_perfmon.c
+++ b/bin/nv_perfmon.c
@@ -36,8 +36,7 @@
 #include <sys/time.h>
 
 static struct nvif_device *device;
-static char **signals;
-static int nr_signals;
+static int nr_signals; /* number of signals for all domains */
 
 #define SEC_US  1000000
 #define REFRESH_PERIOD SEC_US
@@ -247,6 +246,17 @@ ui_menu_win = {
  *
  
******************************************************************************/
 
+struct ui_perfmon_dom {
+       struct list_head head;
+       struct list_head list;
+       u8 id;
+};
+
+struct ui_perfmon_sig {
+       struct list_head head;
+       char *name;
+};
+
 struct ui_main {
        struct list_head head;
        u32 handle;
@@ -258,6 +268,7 @@ struct ui_main {
 };
 
 static struct list_head ui_main_list = LIST_HEAD_INIT(ui_main_list);
+static struct list_head ui_doms_list = LIST_HEAD_INIT(ui_doms_list);
 static u32 ui_main_handle = 0xc0000000;
 
 static void
@@ -269,32 +280,134 @@ ui_main_remove(struct ui_main *item)
 }
 
 static void
+ui_perfmon_query_signals(struct nvif_object *perfmon,
+                        struct ui_perfmon_dom *dom)
+{
+       struct nvif_perfmon_query_signal_v0 args = {};
+       struct ui_perfmon_sig *sig;
+       int ret;
+
+       args.domain = dom->id;
+       do {
+               u32 prev_iter = args.iter;
+
+               args.name[0] = '\0';
+               ret = nvif_mthd(perfmon, NVIF_PERFMON_V0_QUERY_SIGNAL,
+                               &args, sizeof(args));
+               assert(ret == 0);
+
+               if (prev_iter) {
+                       nr_signals++;
+                       sig = calloc(1, sizeof(*sig));
+                       sig->name = malloc(sizeof(args.name));
+                       strncpy(sig->name, args.name, sizeof(args.name));
+                       list_add_tail(&sig->head, &dom->list);
+
+                       args.iter = prev_iter;
+                       ret = nvif_mthd(perfmon, NVIF_PERFMON_V0_QUERY_SIGNAL,
+                                       &args, sizeof(args));
+                       assert(ret == 0);
+               }
+       } while (args.iter != 0xffffffff);
+}
+
+static void
+ui_perfmon_query_domains(struct nvif_object *perfmon)
+{
+       struct nvif_perfmon_query_domain_v0 args = {};
+       struct ui_perfmon_dom *dom;
+       int ret;
+
+       assert(ret == 0);
+       do {
+               u8 prev_iter = args.iter;
+
+               ret = nvif_mthd(perfmon, NVIF_PERFMON_V0_QUERY_DOMAIN,
+                               &args, sizeof(args));
+               assert(ret == 0);
+
+               if (prev_iter) {
+                       dom = calloc(1, sizeof(*dom));
+                       dom->id = args.id;
+                       INIT_LIST_HEAD(&dom->list);
+                       list_add_tail(&dom->head, &ui_doms_list);
+
+                       args.iter = prev_iter;
+                       ret = nvif_mthd(perfmon, NVIF_PERFMON_V0_QUERY_DOMAIN,
+                                       &args, sizeof(args));
+                       assert(ret == 0);
+
+                       /* query available signals for the domain */
+                       ui_perfmon_query_signals(perfmon, dom);
+               }
+       } while (args.iter != 0xff);
+}
+
+static void
+ui_perfmon_init(void)
+{
+       struct nvif_object perfmon;
+       int ret;
+
+       ret = nvif_object_init(nvif_object(device), NULL, 0xdeadbeef,
+                              NVIF_IOCTL_NEW_V0_PERFMON, NULL, 0, &perfmon);
+       assert(ret == 0);
+
+       /* query available domains for the device */
+       ui_perfmon_query_domains(&perfmon);
+
+       nvif_object_fini(&perfmon);
+}
+
+static void
+ui_perfmon_fini(void)
+{
+       struct ui_perfmon_dom *dom, *next_dom;
+       struct ui_perfmon_sig *sig, *next_sig;
+
+       list_for_each_entry_safe(dom, next_dom, &ui_doms_list, head) {
+               list_for_each_entry_safe(sig, next_sig, &dom->list, head) {
+                       list_del(&sig->head);
+                       free(sig->name);
+                       free(sig);
+               }
+               list_del(&dom->head);
+               free(dom);
+       }
+}
+
+static void
 ui_main_select(void)
 {
        struct ui_main *item, *temp;
-       int ret, i;
+       struct ui_perfmon_dom *dom;
+       struct ui_perfmon_sig *sig;
+       int ret;
 
        list_for_each_entry_safe(item, temp, &ui_main_list, head) {
                ui_main_remove(item);
        }
 
-       for (i = 0; i < nr_signals; i++) {
-               struct nvif_perfctr_v0 args = {
-                       .logic_op = 0xaaaa,
-               };
+       list_for_each_entry(dom, &ui_doms_list, head) {
+               list_for_each_entry(sig, &dom->list, head) {
+                       struct nvif_perfctr_v0 args = {
+                               .logic_op = 0xaaaa,
+                       };
 
-               item = calloc(1, sizeof(*item));
-               item->handle = ui_main_handle++;
-               item->name = signals[i];
-               item->incr = 0;
+                       item = calloc(1, sizeof(*item));
+                       item->handle = ui_main_handle++;
+                       item->name = sig->name;
 
-               strncpy(args.name[0], item->name, sizeof(args.name[0]));
+                       strncpy(args.name[0], item->name, sizeof(args.name[0]));
 
-               ret = nvif_object_init(nvif_object(device), NULL, item->handle,
-                                      NVIF_IOCTL_NEW_V0_PERFCTR, &args,
-                                      sizeof(args), &item->object);
-               assert(ret == 0);
-               list_add_tail(&item->head, &ui_main_list);
+                       ret = nvif_object_init(nvif_object(device), NULL,
+                                              item->handle,
+                                              NVIF_IOCTL_NEW_V0_PERFCTR,
+                                              &args, sizeof(args),
+                                              &item->object);
+                       assert(ret == 0);
+                       list_add_tail(&item->head, &ui_main_list);
+               }
        }
 }
 
@@ -314,12 +427,14 @@ ui_main_alarm_handler(int signal)
                if (!sampled) {
                        struct nvif_perfctr_sample args = {};
 
-                       ret = nvif_mthd(&item->object, NVIF_PERFCTR_V0_SAMPLE, 
&args, sizeof(args));
+                       ret = nvif_mthd(&item->object, NVIF_PERFCTR_V0_SAMPLE,
+                                       &args, sizeof(args));
                        assert(ret == 0);
                        sampled = true;
                }
 
-               ret = nvif_mthd(&item->object, NVIF_PERFCTR_V0_READ, &args, 
sizeof(args));
+               ret = nvif_mthd(&item->object, NVIF_PERFCTR_V0_READ,
+                               &args, sizeof(args));
                assert(ret == 0 || ret == -EAGAIN);
 
                if (ret == 0) {
@@ -600,9 +715,7 @@ main(int argc, char **argv)
        const char *cfg = NULL;
        const char *dbg = "error";
        u64 dev = ~0ULL;
-       struct nvif_perfmon_query_signal_v0 args = {};
        struct nvif_client *client;
-       struct nvif_object object;
        int ret, c, k;
        int scan = 0;
 
@@ -643,31 +756,7 @@ main(int argc, char **argv)
                return 1;
        }
 
-       ret = nvif_object_init(nvif_object(device), NULL, 0xdeadbeef,
-                              NVIF_IOCTL_NEW_V0_PERFMON, NULL, 0, &object);
-       assert(ret == 0);
-       do {
-               u32 prev_iter = args.iter;
-
-               args.name[0] = '\0';
-               ret = nvif_mthd(&object, NVIF_PERFMON_V0_QUERY_SIGNAL,
-                               &args, sizeof(args));
-               assert(ret == 0);
-
-               if (prev_iter) {
-                       nr_signals++;
-                       signals = realloc(signals, nr_signals * sizeof(char*));
-                       signals[nr_signals - 1] = malloc(sizeof(args.name));
-
-                       args.iter = prev_iter;
-                       strncpy(signals[nr_signals - 1], args.name,
-                               sizeof(args.name));
-                       ret = nvif_mthd(&object, NVIF_PERFMON_V0_QUERY_SIGNAL,
-                                       &args, sizeof(args));
-                       assert(ret == 0);
-               }
-       } while (args.iter != 0xffffffff);
-       nvif_object_fini(&object);
+       ui_perfmon_init();
 
        initscr();
        keypad(stdscr, TRUE);
@@ -696,10 +785,8 @@ main(int argc, char **argv)
 
        ui_destroy();
        endwin();
+       ui_perfmon_fini();
 
-       while (nr_signals--)
-               free(signals[nr_signals]);
-       free(signals);
        nvif_device_ref(NULL, &device);
        return 0;
 }
diff --git a/drm/nouveau/include/nvif/class.h b/drm/nouveau/include/nvif/class.h
index 0b28929..cf2af89 100644
--- a/drm/nouveau/include/nvif/class.h
+++ b/drm/nouveau/include/nvif/class.h
@@ -264,7 +264,8 @@ struct nvif_perfmon_query_domain_v0 {
 
 struct nvif_perfmon_query_signal_v0 {
        __u8  version;
-       __u8  pad01[3];
+       __u8  domain;
+       __u8  pad02[2];
        __u32 iter;
        char  name[64];
 };
diff --git a/drm/nouveau/nvkm/engine/pm/base.c 
b/drm/nouveau/nvkm/engine/pm/base.c
index 3d9bcbc..d61beff 100644
--- a/drm/nouveau/nvkm/engine/pm/base.c
+++ b/drm/nouveau/nvkm/engine/pm/base.c
@@ -174,29 +174,22 @@ nvkm_perfmon_mthd_query_signal(struct nvkm_object 
*object, void *data, u32 size)
        } *args = data;
        struct nvkm_device *device = nv_device(object);
        struct nvkm_pm *ppm = (void *)object->engine;
-       struct nvkm_perfdom *dom = NULL, *chk;
+       struct nvkm_perfdom *dom;
        const bool all = nvkm_boolopt(device->cfgopt, "NvPmShowAll", false);
        const bool raw = nvkm_boolopt(device->cfgopt, "NvPmUnnamed", all);
        const char *name;
-       int tmp = 0, di, si;
-       int ret;
+       int ret, si;
 
        nv_ioctl(object, "perfmon query signal size %d\n", size);
        if (nvif_unpack(args->v0, 0, 0, false)) {
-               nv_ioctl(object, "perfmon query signal vers %d iter %08x\n",
-                        args->v0.version, args->v0.iter);
-               di = (args->v0.iter & 0xff000000) >> 24;
-               si = (args->v0.iter & 0x00ffffff) - 1;
+               nv_ioctl(object,
+                        "perfmon query signal vers %d dom %d iter %08x\n",
+                        args->v0.version, args->v0.domain, args->v0.iter);
+               si = (args->v0.iter & 0xffffffff) - 1;
        } else
                return ret;
 
-       list_for_each_entry(chk, &ppm->domains, head) {
-               if (tmp++ == di) {
-                       dom = chk;
-                       break;
-               }
-       }
-
+       dom = nvkm_perfdom_find(ppm, args->v0.domain);
        if (dom == NULL || si >= (int)dom->signal_nr)
                return -EINVAL;
 
@@ -209,17 +202,12 @@ nvkm_perfmon_mthd_query_signal(struct nvkm_object 
*object, void *data, u32 size)
                }
        }
 
-       do {
-               while (++si < dom->signal_nr) {
-                       if (all || dom->signal[si].name) {
-                               args->v0.iter = (di << 24) | ++si;
-                               return 0;
-                       }
+       while (++si < dom->signal_nr) {
+               if (all || dom->signal[si].name) {
+                       args->v0.iter = ++si;
+                       return 0;
                }
-               si = -1;
-               di = di + 1;
-               dom = list_entry(dom->head.next, typeof(*dom), head);
-       } while (&dom->head != &ppm->domains);
+       }
 
        args->v0.iter = 0xffffffff;
        return 0;
-- 
2.4.2

_______________________________________________
Nouveau mailing list
Nouveau@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/nouveau

Reply via email to