All of lore.kernel.org
 help / color / mirror / Atom feed
* [Intel-gfx] [PATCH i-g-t 1/3] intel_gpu_top: Support exiting the tool by pressing 'q'
@ 2020-12-17 10:38 ` Tvrtko Ursulin
  0 siblings, 0 replies; 6+ messages in thread
From: Tvrtko Ursulin @ 2020-12-17 10:38 UTC (permalink / raw)
  To: igt-dev; +Cc: Intel-gfx

From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

Analoguous to top(1) we can enable the user to exit from the tool by
pressing 'q' on the console.

v2:
 * Fix sleep period with closed stdin. (Chris)

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
 man/intel_gpu_top.rst |  6 ++++
 tools/intel_gpu_top.c | 80 ++++++++++++++++++++++++++++++++++++-------
 2 files changed, 73 insertions(+), 13 deletions(-)

diff --git a/man/intel_gpu_top.rst b/man/intel_gpu_top.rst
index 5552e9699d26..2e0c3a05acc1 100644
--- a/man/intel_gpu_top.rst
+++ b/man/intel_gpu_top.rst
@@ -48,6 +48,12 @@ OPTIONS
 -d
     Select a specific GPU using supported filter.
 
+RUNTIME CONTROL
+===============
+
+Supported keys:
+
+    'q'    Exit from the tool.
 
 DEVICE SELECTION
 ================
diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
index dbd353673e55..46221c9543eb 100644
--- a/tools/intel_gpu_top.c
+++ b/tools/intel_gpu_top.c
@@ -23,24 +23,26 @@
 
 #include "igt_device_scan.h"
 
-#include <stdio.h>
-#include <sys/types.h>
-#include <dirent.h>
-#include <stdint.h>
 #include <assert.h>
-#include <string.h>
 #include <ctype.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/stat.h>
+#include <dirent.h>
+#include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-#include <math.h>
-#include <locale.h>
 #include <limits.h>
+#include <locale.h>
+#include <math.h>
+#include <poll.h>
 #include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <termios.h>
 
 #include "igt_perf.h"
 
@@ -1246,6 +1248,54 @@ static char *tr_pmu_name(struct igt_device_card *card)
 	return device;
 }
 
+static void interactive_stdin(void)
+{
+	struct termios termios = { };
+	int ret;
+
+	ret = fcntl(0, F_GETFL, NULL);
+	ret |= O_NONBLOCK;
+	ret = fcntl(0, F_SETFL, ret);
+	assert(ret == 0);
+
+	ret = tcgetattr(0, &termios);
+	assert(ret == 0);
+
+	termios.c_lflag &= ~ICANON;
+	termios.c_cc[VMIN] = 1;
+	termios.c_cc[VTIME] = 0; /* Deciseconds only - we'll use poll. */
+
+	ret = tcsetattr(0, TCSAFLUSH, &termios);
+	assert(ret == 0);
+}
+
+static void process_stdin(unsigned int timeout_us)
+{
+	struct pollfd p = { .fd = 0, .events = POLLIN };
+	int ret;
+
+	ret = poll(&p, 1, timeout_us / 1000);
+	if (ret <= 0) {
+		if (ret < 0)
+			stop_top = true;
+		return;
+	}
+
+	for (;;) {
+		char c;
+
+		ret = read(0, &c, 1);
+		if (ret <= 0)
+			break;
+
+		switch (c) {
+		case 'q':
+			stop_top = true;
+			break;
+		};
+	}
+}
+
 int main(int argc, char **argv)
 {
 	unsigned int period_us = DEFAULT_PERIOD_MS * 1000;
@@ -1315,6 +1365,7 @@ int main(int argc, char **argv)
 	switch (output_mode) {
 	case INTERACTIVE:
 		pops = &term_pops;
+		interactive_stdin();
 		break;
 	case STDOUT:
 		pops = &stdout_pops;
@@ -1427,7 +1478,10 @@ int main(int argc, char **argv)
 		if (stop_top)
 			break;
 
-		usleep(period_us);
+		if (output_mode == INTERACTIVE)
+			process_stdin(period_us);
+		else
+			usleep(period_us);
 	}
 
 	free(codename);
-- 
2.25.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [igt-dev] [PATCH i-g-t 1/3] intel_gpu_top: Support exiting the tool by pressing 'q'
@ 2020-12-17 10:38 ` Tvrtko Ursulin
  0 siblings, 0 replies; 6+ messages in thread
From: Tvrtko Ursulin @ 2020-12-17 10:38 UTC (permalink / raw)
  To: igt-dev; +Cc: Intel-gfx, Tvrtko Ursulin

From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

Analoguous to top(1) we can enable the user to exit from the tool by
pressing 'q' on the console.

v2:
 * Fix sleep period with closed stdin. (Chris)

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
 man/intel_gpu_top.rst |  6 ++++
 tools/intel_gpu_top.c | 80 ++++++++++++++++++++++++++++++++++++-------
 2 files changed, 73 insertions(+), 13 deletions(-)

diff --git a/man/intel_gpu_top.rst b/man/intel_gpu_top.rst
index 5552e9699d26..2e0c3a05acc1 100644
--- a/man/intel_gpu_top.rst
+++ b/man/intel_gpu_top.rst
@@ -48,6 +48,12 @@ OPTIONS
 -d
     Select a specific GPU using supported filter.
 
+RUNTIME CONTROL
+===============
+
+Supported keys:
+
+    'q'    Exit from the tool.
 
 DEVICE SELECTION
 ================
diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
index dbd353673e55..46221c9543eb 100644
--- a/tools/intel_gpu_top.c
+++ b/tools/intel_gpu_top.c
@@ -23,24 +23,26 @@
 
 #include "igt_device_scan.h"
 
-#include <stdio.h>
-#include <sys/types.h>
-#include <dirent.h>
-#include <stdint.h>
 #include <assert.h>
-#include <string.h>
 #include <ctype.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/stat.h>
+#include <dirent.h>
+#include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-#include <math.h>
-#include <locale.h>
 #include <limits.h>
+#include <locale.h>
+#include <math.h>
+#include <poll.h>
 #include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <termios.h>
 
 #include "igt_perf.h"
 
@@ -1246,6 +1248,54 @@ static char *tr_pmu_name(struct igt_device_card *card)
 	return device;
 }
 
+static void interactive_stdin(void)
+{
+	struct termios termios = { };
+	int ret;
+
+	ret = fcntl(0, F_GETFL, NULL);
+	ret |= O_NONBLOCK;
+	ret = fcntl(0, F_SETFL, ret);
+	assert(ret == 0);
+
+	ret = tcgetattr(0, &termios);
+	assert(ret == 0);
+
+	termios.c_lflag &= ~ICANON;
+	termios.c_cc[VMIN] = 1;
+	termios.c_cc[VTIME] = 0; /* Deciseconds only - we'll use poll. */
+
+	ret = tcsetattr(0, TCSAFLUSH, &termios);
+	assert(ret == 0);
+}
+
+static void process_stdin(unsigned int timeout_us)
+{
+	struct pollfd p = { .fd = 0, .events = POLLIN };
+	int ret;
+
+	ret = poll(&p, 1, timeout_us / 1000);
+	if (ret <= 0) {
+		if (ret < 0)
+			stop_top = true;
+		return;
+	}
+
+	for (;;) {
+		char c;
+
+		ret = read(0, &c, 1);
+		if (ret <= 0)
+			break;
+
+		switch (c) {
+		case 'q':
+			stop_top = true;
+			break;
+		};
+	}
+}
+
 int main(int argc, char **argv)
 {
 	unsigned int period_us = DEFAULT_PERIOD_MS * 1000;
@@ -1315,6 +1365,7 @@ int main(int argc, char **argv)
 	switch (output_mode) {
 	case INTERACTIVE:
 		pops = &term_pops;
+		interactive_stdin();
 		break;
 	case STDOUT:
 		pops = &stdout_pops;
@@ -1427,7 +1478,10 @@ int main(int argc, char **argv)
 		if (stop_top)
 			break;
 
-		usleep(period_us);
+		if (output_mode == INTERACTIVE)
+			process_stdin(period_us);
+		else
+			usleep(period_us);
 	}
 
 	free(codename);
-- 
2.25.1

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [Intel-gfx] [PATCH i-g-t 2/3] intel_gpu_top: Aggregate engine busyness per class
  2020-12-17 10:38 ` [igt-dev] " Tvrtko Ursulin
@ 2020-12-17 10:38   ` Tvrtko Ursulin
  -1 siblings, 0 replies; 6+ messages in thread
From: Tvrtko Ursulin @ 2020-12-17 10:38 UTC (permalink / raw)
  To: igt-dev; +Cc: Intel-gfx

From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

Similarly to how top(1) handles SMP, we can default to showing engines of
a same class as a single bar graph entry.

To achieve this a little bit of hackery is employed. PMU sampling is left
as is and only at the presentation layer we create a fake set of engines,
one for each class, summing and normalizing the load respectively.

v2:
 * Fix building the aggregated engines.
 * Tidy static variable handling.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
 man/intel_gpu_top.rst |   1 +
 tools/intel_gpu_top.c | 209 +++++++++++++++++++++++++++++++++++++++---
 2 files changed, 197 insertions(+), 13 deletions(-)

diff --git a/man/intel_gpu_top.rst b/man/intel_gpu_top.rst
index 2e0c3a05acc1..35ab10da9bb4 100644
--- a/man/intel_gpu_top.rst
+++ b/man/intel_gpu_top.rst
@@ -54,6 +54,7 @@ RUNTIME CONTROL
 Supported keys:
 
     'q'    Exit from the tool.
+    '1'    Toggle between aggregated engine class and physical engine mode.
 
 DEVICE SELECTION
 ================
diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
index 46221c9543eb..d1149eb8e14d 100644
--- a/tools/intel_gpu_top.c
+++ b/tools/intel_gpu_top.c
@@ -76,8 +76,16 @@ struct engine {
 	struct pmu_counter sema;
 };
 
+struct engine_class {
+	unsigned int class;
+	const char *name;
+	unsigned int num_engines;
+};
+
 struct engines {
 	unsigned int num_engines;
+	unsigned int num_classes;
+	struct engine_class *class;
 	unsigned int num_counters;
 	DIR *root;
 	int fd;
@@ -1118,6 +1126,8 @@ print_imc(struct engines *engines, double t, int lines, int con_w, int con_h)
 	return lines;
 }
 
+static bool class_view;
+
 static int
 print_engines_header(struct engines *engines, double t,
 		     int lines, int con_w, int con_h)
@@ -1133,8 +1143,13 @@ print_engines_header(struct engines *engines, double t,
 		pops->open_struct("engines");
 
 		if (output_mode == INTERACTIVE) {
-			const char *a = "          ENGINE      BUSY ";
 			const char *b = " MI_SEMA MI_WAIT";
+			const char *a;
+
+			if (class_view)
+				a = "         ENGINES     BUSY  ";
+			else
+				a = "          ENGINE     BUSY  ";
 
 			printf("\033[7m%s%*s%s\033[0m\n",
 			       a, (int)(con_w - 1 - strlen(a) - strlen(b)),
@@ -1214,6 +1229,181 @@ print_engines_footer(struct engines *engines, double t,
 	return lines;
 }
 
+static int class_cmp(const void *_a, const void *_b)
+{
+	const struct engine_class *a = _a;
+	const struct engine_class *b = _b;
+
+	return a->class - b->class;
+}
+
+static void init_engine_classes(struct engines *engines)
+{
+	struct engine_class *classes;
+	unsigned int i, num;
+	int max = -1;
+
+	for (i = 0; i < engines->num_engines; i++) {
+		struct engine *engine = engine_ptr(engines, i);
+
+		if ((int)engine->class > max)
+			max = engine->class;
+	}
+	assert(max >= 0);
+
+	num = max + 1;
+
+	classes = calloc(num, sizeof(*classes));
+	assert(classes);
+
+	for (i = 0; i < engines->num_engines; i++) {
+		struct engine *engine = engine_ptr(engines, i);
+
+		classes[engine->class].num_engines++;
+	}
+
+	for (i = 0; i < num; i++) {
+		classes[i].class = i;
+		classes[i].name = class_display_name(i);
+	}
+
+	qsort(classes, num, sizeof(*classes), class_cmp);
+
+	engines->num_classes = num;
+	engines->class = classes;
+}
+
+static void __pmu_sum(struct pmu_pair *dst, struct pmu_pair *src)
+{
+	dst->prev += src->prev;
+	dst->cur += src->cur;
+}
+
+static void __pmu_normalize(struct pmu_pair *val, unsigned int n)
+{
+	val->prev /= n;
+	val->cur /= n;
+}
+
+static struct engines *init_class_engines(struct engines *engines)
+{
+	unsigned int num_present;
+	struct engines *classes;
+	unsigned int i, j, k;
+
+	init_engine_classes(engines);
+
+	num_present = 0; /* Classes with engines. */
+	for (i = 0; i < engines->num_classes; i++) {
+		if (engines->class[i].num_engines)
+			num_present++;
+	}
+
+	classes = calloc(1, sizeof(struct engines) +
+			    num_present * sizeof(struct engine));
+	assert(classes);
+
+	classes->num_engines = num_present;
+	classes->num_classes = engines->num_classes;
+	classes->class = engines->class;
+
+	j = 0;
+	for (i = 0; i < engines->num_classes; i++) {
+		struct engine *engine = engine_ptr(classes, j);
+
+		/* Skip classes with no engines. */
+		if (!engines->class[i].num_engines)
+			continue;
+
+		assert(j < num_present);
+
+		engine->class = i;
+		engine->instance = -1;
+
+		engine->display_name = strdup(class_display_name(i));
+		assert(engine->display_name);
+		engine->short_name = strdup(class_short_name(i));
+		assert(engine->short_name);
+
+		/*
+		 * Copy over pmu metadata from one real engine of the same
+		 * class.
+		 */
+		for (k = 0; k < engines->num_engines; k++) {
+			struct engine *e = engine_ptr(engines, k);
+
+			if (e->class == i) {
+				engine->num_counters = e->num_counters;
+				engine->busy = e->busy;
+				engine->sema = e->sema;
+				engine->wait = e->wait;
+				break;
+			}
+		}
+
+		j++; /* Next "class engine" to populate. */
+	}
+
+	return classes;
+}
+
+static struct engines *update_class_engines(struct engines *engines)
+{
+	static struct engines *classes;
+	unsigned int i, j;
+
+	if (!classes)
+		classes = init_class_engines(engines);
+
+	for (i = 0; i < classes->num_engines; i++) {
+		struct engine *engine = engine_ptr(classes, i);
+		unsigned int num_engines =
+			classes->class[engine->class].num_engines;
+
+		assert(num_engines);
+
+		memset(&engine->busy.val, 0, sizeof(engine->busy.val));
+		memset(&engine->sema.val, 0, sizeof(engine->sema.val));
+		memset(&engine->wait.val, 0, sizeof(engine->wait.val));
+
+		for (j = 0; j < engines->num_engines; j++) {
+			struct engine *e = engine_ptr(engines, j);
+
+			if (e->class == engine->class) {
+				__pmu_sum(&engine->busy.val, &e->busy.val);
+				__pmu_sum(&engine->sema.val, &e->sema.val);
+				__pmu_sum(&engine->wait.val, &e->wait.val);
+			}
+		}
+
+		__pmu_normalize(&engine->busy.val, num_engines);
+		__pmu_normalize(&engine->sema.val, num_engines);
+		__pmu_normalize(&engine->wait.val, num_engines);
+	}
+
+	return classes;
+}
+
+static int
+print_engines(struct engines *engines, double t, int lines, int w, int h)
+{
+	struct engines *show;
+
+	if (class_view)
+		show = update_class_engines(engines);
+	else
+		show = engines;
+
+	lines = print_engines_header(show, t, lines, w,  h);
+
+	for (unsigned int i = 0; i < show->num_engines && lines < h; i++)
+		lines = print_engine(show, i, t, lines, w, h);
+
+	lines = print_engines_footer(show, t, lines, w, h);
+
+	return lines;
+}
+
 static bool stop_top;
 
 static void sigint_handler(int  sig)
@@ -1292,6 +1482,9 @@ static void process_stdin(unsigned int timeout_us)
 		case 'q':
 			stop_top = true;
 			break;
+		case '1':
+			class_view ^= true;
+			break;
 		};
 	}
 }
@@ -1302,7 +1495,6 @@ int main(int argc, char **argv)
 	int con_w = -1, con_h = -1;
 	char *output_path = NULL;
 	struct engines *engines;
-	unsigned int i;
 	int ret = 0, ch;
 	bool list_device = false;
 	char *pmu_device, *opt_device = NULL;
@@ -1366,6 +1558,7 @@ int main(int argc, char **argv)
 	case INTERACTIVE:
 		pops = &term_pops;
 		interactive_stdin();
+		class_view = true;
 		break;
 	case STDOUT:
 		pops = &stdout_pops;
@@ -1462,17 +1655,7 @@ int main(int argc, char **argv)
 
 			lines = print_imc(engines, t, lines, con_w, con_h);
 
-			lines = print_engines_header(engines, t, lines, con_w,
-						     con_h);
-
-			for (i = 0;
-			     i < engines->num_engines && lines < con_h;
-			     i++)
-				lines = print_engine(engines, i, t, lines,
-						     con_w, con_h);
-
-			lines = print_engines_footer(engines, t, lines, con_w,
-						     con_h);
+			lines = print_engines(engines, t, lines, con_w, con_h);
 		}
 
 		if (stop_top)
-- 
2.25.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [igt-dev] [PATCH i-g-t 2/3] intel_gpu_top: Aggregate engine busyness per class
@ 2020-12-17 10:38   ` Tvrtko Ursulin
  0 siblings, 0 replies; 6+ messages in thread
From: Tvrtko Ursulin @ 2020-12-17 10:38 UTC (permalink / raw)
  To: igt-dev; +Cc: Intel-gfx, Tvrtko Ursulin

From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

Similarly to how top(1) handles SMP, we can default to showing engines of
a same class as a single bar graph entry.

To achieve this a little bit of hackery is employed. PMU sampling is left
as is and only at the presentation layer we create a fake set of engines,
one for each class, summing and normalizing the load respectively.

v2:
 * Fix building the aggregated engines.
 * Tidy static variable handling.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
 man/intel_gpu_top.rst |   1 +
 tools/intel_gpu_top.c | 209 +++++++++++++++++++++++++++++++++++++++---
 2 files changed, 197 insertions(+), 13 deletions(-)

diff --git a/man/intel_gpu_top.rst b/man/intel_gpu_top.rst
index 2e0c3a05acc1..35ab10da9bb4 100644
--- a/man/intel_gpu_top.rst
+++ b/man/intel_gpu_top.rst
@@ -54,6 +54,7 @@ RUNTIME CONTROL
 Supported keys:
 
     'q'    Exit from the tool.
+    '1'    Toggle between aggregated engine class and physical engine mode.
 
 DEVICE SELECTION
 ================
diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
index 46221c9543eb..d1149eb8e14d 100644
--- a/tools/intel_gpu_top.c
+++ b/tools/intel_gpu_top.c
@@ -76,8 +76,16 @@ struct engine {
 	struct pmu_counter sema;
 };
 
+struct engine_class {
+	unsigned int class;
+	const char *name;
+	unsigned int num_engines;
+};
+
 struct engines {
 	unsigned int num_engines;
+	unsigned int num_classes;
+	struct engine_class *class;
 	unsigned int num_counters;
 	DIR *root;
 	int fd;
@@ -1118,6 +1126,8 @@ print_imc(struct engines *engines, double t, int lines, int con_w, int con_h)
 	return lines;
 }
 
+static bool class_view;
+
 static int
 print_engines_header(struct engines *engines, double t,
 		     int lines, int con_w, int con_h)
@@ -1133,8 +1143,13 @@ print_engines_header(struct engines *engines, double t,
 		pops->open_struct("engines");
 
 		if (output_mode == INTERACTIVE) {
-			const char *a = "          ENGINE      BUSY ";
 			const char *b = " MI_SEMA MI_WAIT";
+			const char *a;
+
+			if (class_view)
+				a = "         ENGINES     BUSY  ";
+			else
+				a = "          ENGINE     BUSY  ";
 
 			printf("\033[7m%s%*s%s\033[0m\n",
 			       a, (int)(con_w - 1 - strlen(a) - strlen(b)),
@@ -1214,6 +1229,181 @@ print_engines_footer(struct engines *engines, double t,
 	return lines;
 }
 
+static int class_cmp(const void *_a, const void *_b)
+{
+	const struct engine_class *a = _a;
+	const struct engine_class *b = _b;
+
+	return a->class - b->class;
+}
+
+static void init_engine_classes(struct engines *engines)
+{
+	struct engine_class *classes;
+	unsigned int i, num;
+	int max = -1;
+
+	for (i = 0; i < engines->num_engines; i++) {
+		struct engine *engine = engine_ptr(engines, i);
+
+		if ((int)engine->class > max)
+			max = engine->class;
+	}
+	assert(max >= 0);
+
+	num = max + 1;
+
+	classes = calloc(num, sizeof(*classes));
+	assert(classes);
+
+	for (i = 0; i < engines->num_engines; i++) {
+		struct engine *engine = engine_ptr(engines, i);
+
+		classes[engine->class].num_engines++;
+	}
+
+	for (i = 0; i < num; i++) {
+		classes[i].class = i;
+		classes[i].name = class_display_name(i);
+	}
+
+	qsort(classes, num, sizeof(*classes), class_cmp);
+
+	engines->num_classes = num;
+	engines->class = classes;
+}
+
+static void __pmu_sum(struct pmu_pair *dst, struct pmu_pair *src)
+{
+	dst->prev += src->prev;
+	dst->cur += src->cur;
+}
+
+static void __pmu_normalize(struct pmu_pair *val, unsigned int n)
+{
+	val->prev /= n;
+	val->cur /= n;
+}
+
+static struct engines *init_class_engines(struct engines *engines)
+{
+	unsigned int num_present;
+	struct engines *classes;
+	unsigned int i, j, k;
+
+	init_engine_classes(engines);
+
+	num_present = 0; /* Classes with engines. */
+	for (i = 0; i < engines->num_classes; i++) {
+		if (engines->class[i].num_engines)
+			num_present++;
+	}
+
+	classes = calloc(1, sizeof(struct engines) +
+			    num_present * sizeof(struct engine));
+	assert(classes);
+
+	classes->num_engines = num_present;
+	classes->num_classes = engines->num_classes;
+	classes->class = engines->class;
+
+	j = 0;
+	for (i = 0; i < engines->num_classes; i++) {
+		struct engine *engine = engine_ptr(classes, j);
+
+		/* Skip classes with no engines. */
+		if (!engines->class[i].num_engines)
+			continue;
+
+		assert(j < num_present);
+
+		engine->class = i;
+		engine->instance = -1;
+
+		engine->display_name = strdup(class_display_name(i));
+		assert(engine->display_name);
+		engine->short_name = strdup(class_short_name(i));
+		assert(engine->short_name);
+
+		/*
+		 * Copy over pmu metadata from one real engine of the same
+		 * class.
+		 */
+		for (k = 0; k < engines->num_engines; k++) {
+			struct engine *e = engine_ptr(engines, k);
+
+			if (e->class == i) {
+				engine->num_counters = e->num_counters;
+				engine->busy = e->busy;
+				engine->sema = e->sema;
+				engine->wait = e->wait;
+				break;
+			}
+		}
+
+		j++; /* Next "class engine" to populate. */
+	}
+
+	return classes;
+}
+
+static struct engines *update_class_engines(struct engines *engines)
+{
+	static struct engines *classes;
+	unsigned int i, j;
+
+	if (!classes)
+		classes = init_class_engines(engines);
+
+	for (i = 0; i < classes->num_engines; i++) {
+		struct engine *engine = engine_ptr(classes, i);
+		unsigned int num_engines =
+			classes->class[engine->class].num_engines;
+
+		assert(num_engines);
+
+		memset(&engine->busy.val, 0, sizeof(engine->busy.val));
+		memset(&engine->sema.val, 0, sizeof(engine->sema.val));
+		memset(&engine->wait.val, 0, sizeof(engine->wait.val));
+
+		for (j = 0; j < engines->num_engines; j++) {
+			struct engine *e = engine_ptr(engines, j);
+
+			if (e->class == engine->class) {
+				__pmu_sum(&engine->busy.val, &e->busy.val);
+				__pmu_sum(&engine->sema.val, &e->sema.val);
+				__pmu_sum(&engine->wait.val, &e->wait.val);
+			}
+		}
+
+		__pmu_normalize(&engine->busy.val, num_engines);
+		__pmu_normalize(&engine->sema.val, num_engines);
+		__pmu_normalize(&engine->wait.val, num_engines);
+	}
+
+	return classes;
+}
+
+static int
+print_engines(struct engines *engines, double t, int lines, int w, int h)
+{
+	struct engines *show;
+
+	if (class_view)
+		show = update_class_engines(engines);
+	else
+		show = engines;
+
+	lines = print_engines_header(show, t, lines, w,  h);
+
+	for (unsigned int i = 0; i < show->num_engines && lines < h; i++)
+		lines = print_engine(show, i, t, lines, w, h);
+
+	lines = print_engines_footer(show, t, lines, w, h);
+
+	return lines;
+}
+
 static bool stop_top;
 
 static void sigint_handler(int  sig)
@@ -1292,6 +1482,9 @@ static void process_stdin(unsigned int timeout_us)
 		case 'q':
 			stop_top = true;
 			break;
+		case '1':
+			class_view ^= true;
+			break;
 		};
 	}
 }
@@ -1302,7 +1495,6 @@ int main(int argc, char **argv)
 	int con_w = -1, con_h = -1;
 	char *output_path = NULL;
 	struct engines *engines;
-	unsigned int i;
 	int ret = 0, ch;
 	bool list_device = false;
 	char *pmu_device, *opt_device = NULL;
@@ -1366,6 +1558,7 @@ int main(int argc, char **argv)
 	case INTERACTIVE:
 		pops = &term_pops;
 		interactive_stdin();
+		class_view = true;
 		break;
 	case STDOUT:
 		pops = &stdout_pops;
@@ -1462,17 +1655,7 @@ int main(int argc, char **argv)
 
 			lines = print_imc(engines, t, lines, con_w, con_h);
 
-			lines = print_engines_header(engines, t, lines, con_w,
-						     con_h);
-
-			for (i = 0;
-			     i < engines->num_engines && lines < con_h;
-			     i++)
-				lines = print_engine(engines, i, t, lines,
-						     con_w, con_h);
-
-			lines = print_engines_footer(engines, t, lines, con_w,
-						     con_h);
+			lines = print_engines(engines, t, lines, con_w, con_h);
 		}
 
 		if (stop_top)
-- 
2.25.1

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [Intel-gfx] [PATCH i-g-t 3/3] intel_gpu_top: Fix interactive mode on serial console
  2020-12-17 10:38 ` [igt-dev] " Tvrtko Ursulin
  (?)
  (?)
@ 2020-12-17 10:38 ` Tvrtko Ursulin
  -1 siblings, 0 replies; 6+ messages in thread
From: Tvrtko Ursulin @ 2020-12-17 10:38 UTC (permalink / raw)
  To: igt-dev; +Cc: Intel-gfx

From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

TIOCGWINSZ returns zero columns and rows on serial so lets assume 80x24.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
 tools/intel_gpu_top.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
index d1149eb8e14d..72ad7cbe9a8c 100644
--- a/tools/intel_gpu_top.c
+++ b/tools/intel_gpu_top.c
@@ -1640,6 +1640,11 @@ int main(int argc, char **argv)
 		} else if (ioctl(0, TIOCGWINSZ, &ws) != -1) {
 			con_w = ws.ws_col;
 			con_h = ws.ws_row;
+			if (con_w == 0 && con_h == 0) {
+				/* Serial console. */
+				con_w = 80;
+				con_h = 24;
+			}
 		}
 
 		pmu_sample(engines);
-- 
2.25.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [igt-dev] ✗ Fi.CI.BAT: failure for series starting with [i-g-t,1/3] intel_gpu_top: Support exiting the tool by pressing 'q'
  2020-12-17 10:38 ` [igt-dev] " Tvrtko Ursulin
                   ` (2 preceding siblings ...)
  (?)
@ 2020-12-17 12:14 ` Patchwork
  -1 siblings, 0 replies; 6+ messages in thread
From: Patchwork @ 2020-12-17 12:14 UTC (permalink / raw)
  To: Tvrtko Ursulin; +Cc: igt-dev


[-- Attachment #1.1: Type: text/plain, Size: 5288 bytes --]

== Series Details ==

Series: series starting with [i-g-t,1/3] intel_gpu_top: Support exiting the tool by pressing 'q'
URL   : https://patchwork.freedesktop.org/series/85039/
State : failure

== Summary ==

CI Bug Log - changes from IGT_5906 -> IGTPW_5305
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with IGTPW_5305 absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in IGTPW_5305, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_5305/index.html

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in IGTPW_5305:

### IGT changes ###

#### Possible regressions ####

  * igt@i915_selftest@live@gtt:
    - fi-bsw-kefka:       [PASS][1] -> [DMESG-WARN][2]
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_5906/fi-bsw-kefka/igt@i915_selftest@live@gtt.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_5305/fi-bsw-kefka/igt@i915_selftest@live@gtt.html

  
Known issues
------------

  Here are the changes found in IGTPW_5305 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@amdgpu/amd_cs_nop@nop-gfx0:
    - fi-apl-guc:         NOTRUN -> [SKIP][3] ([fdo#109271]) +17 similar issues
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_5305/fi-apl-guc/igt@amdgpu/amd_cs_nop@nop-gfx0.html

  * igt@i915_getparams_basic@basic-subslice-total:
    - fi-tgl-y:           [PASS][4] -> [DMESG-WARN][5] ([i915#402]) +1 similar issue
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_5906/fi-tgl-y/igt@i915_getparams_basic@basic-subslice-total.html
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_5305/fi-tgl-y/igt@i915_getparams_basic@basic-subslice-total.html

  * igt@i915_selftest@live@gt_heartbeat:
    - fi-tgl-y:           [PASS][6] -> [DMESG-FAIL][7] ([i915#2601])
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_5906/fi-tgl-y/igt@i915_selftest@live@gt_heartbeat.html
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_5305/fi-tgl-y/igt@i915_selftest@live@gt_heartbeat.html

  
#### Possible fixes ####

  * igt@gem_mmap_gtt@basic:
    - fi-tgl-y:           [DMESG-WARN][8] ([i915#402]) -> [PASS][9] +1 similar issue
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_5906/fi-tgl-y/igt@gem_mmap_gtt@basic.html
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_5305/fi-tgl-y/igt@gem_mmap_gtt@basic.html

  * igt@i915_pm_rpm@module-reload:
    - fi-kbl-guc:         [FAIL][10] ([i915#579]) -> [PASS][11]
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_5906/fi-kbl-guc/igt@i915_pm_rpm@module-reload.html
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_5305/fi-kbl-guc/igt@i915_pm_rpm@module-reload.html

  * igt@i915_selftest@live@gt_timelines:
    - fi-apl-guc:         [INCOMPLETE][12] ([i915#2750]) -> [PASS][13]
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_5906/fi-apl-guc/igt@i915_selftest@live@gt_timelines.html
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_5305/fi-apl-guc/igt@i915_selftest@live@gt_timelines.html

  * igt@i915_selftest@live@hugepages:
    - fi-bsw-kefka:       [DMESG-WARN][14] -> [PASS][15]
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_5906/fi-bsw-kefka/igt@i915_selftest@live@hugepages.html
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_5305/fi-bsw-kefka/igt@i915_selftest@live@hugepages.html

  * igt@kms_chamelium@hdmi-edid-read:
    - fi-kbl-7500u:       [DMESG-FAIL][16] ([i915#165]) -> [PASS][17]
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_5906/fi-kbl-7500u/igt@kms_chamelium@hdmi-edid-read.html
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_5305/fi-kbl-7500u/igt@kms_chamelium@hdmi-edid-read.html

  
#### Warnings ####

  * igt@i915_pm_rpm@basic-rte:
    - fi-kbl-guc:         [SKIP][18] ([fdo#109271]) -> [FAIL][19] ([i915#579])
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/IGT_5906/fi-kbl-guc/igt@i915_pm_rpm@basic-rte.html
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_5305/fi-kbl-guc/igt@i915_pm_rpm@basic-rte.html

  
  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [i915#165]: https://gitlab.freedesktop.org/drm/intel/issues/165
  [i915#2601]: https://gitlab.freedesktop.org/drm/intel/issues/2601
  [i915#2750]: https://gitlab.freedesktop.org/drm/intel/issues/2750
  [i915#402]: https://gitlab.freedesktop.org/drm/intel/issues/402
  [i915#579]: https://gitlab.freedesktop.org/drm/intel/issues/579


Participating hosts (42 -> 38)
------------------------------

  Missing    (4): fi-dg1-1 fi-bsw-cyan fi-bdw-samus fi-hsw-4200u 


Build changes
-------------

  * CI: CI-20190529 -> None
  * IGT: IGT_5906 -> IGTPW_5305

  CI-20190529: 20190529
  CI_DRM_9496: c1bf99ceda83bcdd33f05515deb9efc3649d449e @ git://anongit.freedesktop.org/gfx-ci/linux
  IGTPW_5305: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_5305/index.html
  IGT_5906: f5b022a2e5054ee7e335d7856344807308db6d6f @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_5305/index.html

[-- Attachment #1.2: Type: text/html, Size: 6347 bytes --]

[-- Attachment #2: Type: text/plain, Size: 154 bytes --]

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2020-12-17 12:14 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-17 10:38 [Intel-gfx] [PATCH i-g-t 1/3] intel_gpu_top: Support exiting the tool by pressing 'q' Tvrtko Ursulin
2020-12-17 10:38 ` [igt-dev] " Tvrtko Ursulin
2020-12-17 10:38 ` [Intel-gfx] [PATCH i-g-t 2/3] intel_gpu_top: Aggregate engine busyness per class Tvrtko Ursulin
2020-12-17 10:38   ` [igt-dev] " Tvrtko Ursulin
2020-12-17 10:38 ` [Intel-gfx] [PATCH i-g-t 3/3] intel_gpu_top: Fix interactive mode on serial console Tvrtko Ursulin
2020-12-17 12:14 ` [igt-dev] ✗ Fi.CI.BAT: failure for series starting with [i-g-t,1/3] intel_gpu_top: Support exiting the tool by pressing 'q' Patchwork

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.