[Nouveau] [PATCH RFC 08/20] pm: allow to query signals by domain
Samuel Pitoiset
samuel.pitoiset at gmail.com
Sun Jun 7 13:40:18 PDT 2015
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.pitoiset at 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
More information about the Nouveau
mailing list