All of lore.kernel.org
 help / color / mirror / Atom feed
* [igt-dev] [PATCH i-g-t v2 00/11] Resurrect GuC Relay Logging
@ 2022-12-06  8:58 Alan Previn
  2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 01/11] tools/intel_guc_logger: Re-enable basic functionality Alan Previn
                   ` (12 more replies)
  0 siblings, 13 replies; 19+ messages in thread
From: Alan Previn @ 2022-12-06  8:58 UTC (permalink / raw)
  To: igt-dev

This series brings GuC relay logging back to life by
re-aligning the (previously implicit, now query-able)
guc-log-relay subbuffer-specs, debugfs file handle names
and usages between intel_guc_logger tool and i915.

This series depends on fixes and updates on the
kernel side via this series:
https://patchwork.freedesktop.org/series/103767/

Changes from prio revs:
   v1: - With MTL and multi-tile, add support for GT-ID
         selection for GuC logging.
       - Add new design changes to flusher thread to do
         decoding of the GuC log buffer header data and
         unwrap all head-->tail regions into a linear
         sequence so we can concatenate the GuC log outoput
         file to make it look like a single large contiguous
         GuC Log buffer (as it it came direct from memory).
         This was a design miss from original code and is
         needed to ensure internal tools can decode the logs. 


Alan Previn (11):
  tools/intel_guc_logger: Re-enable basic functionality
  tools/intel_guc_logger: Refactor intel_guc_logger globals into structs
  tools/intel_guc_logger: Add GT-ID selection for intel_guc_logger
  tools/intel_guc_logger: Add helper function for flusher code
  tools/intel_guc_logger: Add GuC Log header structure definition
  tools/intel_guc_logger: Concatenate log samples into a contiguous
    file.
  tools/intel_guc_logger: Add overflow awareness.
  tools/intel_guc_logger: Limit relay logging output file to 4GB.
  tools/intel_guc_logger: By default don't change GuC log verbosity
  tools/intel_guc_logger: On exit, save any leftover GuC log data
  tools/intel_guc_logger: Add useful debug messages

 tools/intel_guc_logger.c | 851 +++++++++++++++++++++++++++++++--------
 1 file changed, 674 insertions(+), 177 deletions(-)


base-commit: c001793d5f22deb01918b6ba52af829794582df1
-- 
2.34.1

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

* [igt-dev] [PATCH i-g-t v2 01/11] tools/intel_guc_logger: Re-enable basic functionality
  2022-12-06  8:58 [igt-dev] [PATCH i-g-t v2 00/11] Resurrect GuC Relay Logging Alan Previn
@ 2022-12-06  8:58 ` Alan Previn
  2023-01-20 20:26   ` [igt-dev] [i-g-t, v2, " Dong, Zhanjun
  2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 02/11] tools/intel_guc_logger: Refactor intel_guc_logger globals into structs Alan Previn
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 19+ messages in thread
From: Alan Previn @ 2022-12-06  8:58 UTC (permalink / raw)
  To: igt-dev

Fix these multiple issues to get basic functionality up
and running on GuC using:
1. Start using the updated debugfs path for all GuC relay-logging
   file names.
2. Use the updated debugfs names for the relay-logging control
   and channel files to match kernel changes.
3. Start querrying the relay sub-buffer info (buffer size and
   number of sub-buffers) from kernel's new debugfs files.
4. Separate the control enabling from the log-level-setting and
   keep the control handle open while collecting the logs.

Signed-off-by: Alan Previn <alan.previn.teres.alexis@intel.com>
---
 tools/intel_guc_logger.c | 179 ++++++++++++++++++++++++++++-----------
 1 file changed, 129 insertions(+), 50 deletions(-)

diff --git a/tools/intel_guc_logger.c b/tools/intel_guc_logger.c
index 5f1de8db..4a991127 100644
--- a/tools/intel_guc_logger.c
+++ b/tools/intel_guc_logger.c
@@ -42,24 +42,30 @@
 
 #include "igt.h"
 
+#define KB(x) ((uint64_t)(x) * 1024)
 #define MB(x) ((uint64_t)(x) * 1024 * 1024)
 #ifndef PAGE_SIZE
   #define PAGE_SIZE 4096
 #endif
-/* Currently the size of GuC log buffer is 19 pages & so is the size of relay
- * subbuffer. If the size changes in future, then this define also needs to be
- * updated accordingly.
- */
-#define SUBBUF_SIZE (19*PAGE_SIZE)
-/* Need large buffering from logger side to hide the DISK IO latency, Driver
- * can only store 8 snapshots of GuC log buffer in relay.
- */
-#define NUM_SUBBUFS 100
 
-#define RELAY_FILE_NAME  "guc_log"
 #define DEFAULT_OUTPUT_FILE_NAME  "guc_log_dump.dat"
-#define CONTROL_FILE_NAME "i915_guc_log_control"
 
+#define GLR_LOGLEVEL_NAME         "guc_log_level"
+#define GLR_CTL_NAME              "guc_log_relay_ctl"
+#define GLR_CHANNEL_NAME          "guc_log_relay_chan0"
+
+#define DEFAULT_SUBBUF_COUNT         (4 * 8)
+					/* default to kernel built-in:   *
+					 *   4 x 8 subbuf regions        *
+					 */
+#define DEFAULT_SUBBUF_SIZE          (KB(4 + 8 + 64))
+					/* default to kernel built-ins : *
+					 *   4K -> buffer states array   *
+					 *   8K -> GuC crash dump        *
+					 *  64K -> log events buffer     *
+					 */
+
+int drm_fd;
 char *read_buffer;
 char *out_filename;
 int poll_timeout = 2; /* by default 2ms timeout */
@@ -68,23 +74,53 @@ pthread_t flush_thread;
 int verbosity_level = 3; /* by default capture logs at max verbosity */
 uint32_t produced, consumed;
 uint64_t total_bytes_written;
-int num_buffers = NUM_SUBBUFS;
-int relay_fd, outfile_fd = -1;
+int subbuf_count;
+int subbuf_size;
+int ctl_fd, relay_fd, outfile_fd = -1;
 uint32_t test_duration, max_filesize;
 pthread_cond_t underflow_cond, overflow_cond;
 bool stop_logging, discard_oldlogs, capturing_stopped;
+char *gucfspath;
 
-static void guc_log_control(bool enable, uint32_t log_level)
+static void get_guc_subbuf_info(void)
+{
+	int fd, ret, j;
+	char *path;
+	const char *dbg_fs_names[2] = {"guc_log_relay_buf_size\0",
+					"guc_log_relay_subbuf_count\0"};
+	char outstr[128];
+	uint64_t tmp[2] = {DEFAULT_SUBBUF_SIZE, DEFAULT_SUBBUF_COUNT};
+
+	for (j = 0; j < 2; j++) {
+		igt_assert_neq(asprintf(&path, "%s/%s", gucfspath, dbg_fs_names[j]), -1);
+		igt_info("Opening subbuf path %s\n", path);
+		fd = igt_debugfs_open(drm_fd, path, O_RDONLY);
+		free(path);
+		igt_assert_f(fd >= 0, "couldn't open the GuC log relay-subbuf file\n");
+		ret = read(fd, outstr, sizeof(outstr) - 1);
+		igt_assert(ret > 0);
+		outstr[ret] = '\0';
+		tmp[j] = atoll(outstr);
+		close(fd);
+	}
+	subbuf_size = tmp[0];
+	subbuf_count = tmp[1];
+	igt_info("Debugfs retrieved subbuf info: size=%d, count=%d\n",
+		 subbuf_size, subbuf_count);
+}
+
+static void guc_log_verbosity(bool enable, int log_level)
 {
-	int control_fd;
-	char data[19];
+	char *str;
+	int loglevelfd;
 	uint64_t val;
 	int ret;
 
-	igt_assert_lte(log_level, 3);
-
-	control_fd = igt_debugfs_open(-1, CONTROL_FILE_NAME, O_WRONLY);
-	igt_assert_f(control_fd >= 0, "couldn't open the guc log control file\n");
+	igt_assert_neq(asprintf(&str, "%s/%s", gucfspath, GLR_LOGLEVEL_NAME), -1);
+	igt_info("Opening log level -> %s\n", str);
+	loglevelfd = igt_debugfs_open(drm_fd, str, O_WRONLY);
+	free(str);
+	igt_assert_f(loglevelfd >= 0, "couldn't open the GuC log level file\n");
 
 	/*
 	 * i915 expects GuC log level to be specified as:
@@ -96,13 +132,51 @@ static void guc_log_control(bool enable, uint32_t log_level)
 	 */
 	val = enable ? log_level + 1 : 0;
 
-	ret = snprintf(data, sizeof(data), "0x%" PRIx64, val);
-	igt_assert(ret > 2 && ret < sizeof(data));
+	ret = asprintf(&str, "0x%" PRIx64, val);
+	igt_assert_neq(ret, -1);
+	ret = write(loglevelfd, str, ret);
+	free(str);
+	igt_assert_f(ret > 0, "couldn't write verbosity to log level file\n");
+	igt_info("Set GuC log level = %d\n", (int)val);
+
+	close(loglevelfd);
+}
 
-	ret = write(control_fd, data, ret);
-	igt_assert_f(ret > 0, "couldn't write to the log control file\n");
+static void guc_log_control(bool enable, uint32_t log_level)
+{
+	char *str;
+	uint64_t val = 0;
+	int ret;
 
-	close(control_fd);
+	if (enable) {
+		igt_assert_neq(asprintf(&str, "%s/%s", gucfspath, GLR_CTL_NAME), -1);
+		igt_info("Opening control file -> %s\n", str);
+		ctl_fd = igt_debugfs_open(drm_fd, str, O_WRONLY);
+		free(str);
+		igt_assert_f(ctl_fd >= 0, "couldn't open the GuC log relay-ctl file\n");
+		val = 1;
+	}
+
+	/*
+	 * i915 expects relay logging controls:
+	 * 1    : open + enable relay logging
+	 * 2    : flush
+	 * 0    : disable relay logging + close
+	 */
+	if (ctl_fd) {
+		ret = asprintf(&str, "0x%" PRIx64, val);
+		igt_assert_neq(ret, -1);
+		ret = write(ctl_fd, str, ret);
+		free(str);
+		igt_assert_f(ret > 0, "couldn't write to the log control file\n");
+	}
+
+	guc_log_verbosity(enable, log_level);
+
+	if (!enable) {
+		igt_info("Closing control file\n");
+		close(ctl_fd);
+	}
 }
 
 static void int_sig_handler(int sig)
@@ -119,18 +193,18 @@ static void pull_leftover_data(void)
 
 	do {
 		/* Read the logs from relay buffer */
-		ret = read(relay_fd, read_buffer, SUBBUF_SIZE);
+		ret = read(relay_fd, read_buffer, subbuf_size);
 		if (!ret)
 			break;
 
-		igt_assert_f(ret > 0, "failed to read from the guc log file\n");
-		igt_assert_f(ret == SUBBUF_SIZE, "invalid read from relay file\n");
+		igt_assert_f(ret > 0, "failed to read from the GuC log file\n");
+		igt_assert_f(ret == subbuf_size, "invalid read from relay file\n");
 
 		bytes_read += ret;
 
 		if (outfile_fd >= 0) {
-			ret = write(outfile_fd, read_buffer, SUBBUF_SIZE);
-			igt_assert_f(ret == SUBBUF_SIZE, "couldn't dump the logs in a file\n");
+			ret = write(outfile_fd, read_buffer, subbuf_size);
+			igt_assert_f(ret == subbuf_size, "couldn't dump the logs in a file\n");
 			total_bytes_written += ret;
 		}
 	} while(1);
@@ -149,7 +223,7 @@ static void pull_data(void)
 	int ret;
 
 	pthread_mutex_lock(&mutex);
-	while (num_filled_bufs() >= num_buffers) {
+	while (num_filled_bufs() >= subbuf_count) {
 		igt_debug("overflow, will wait, produced %u, consumed %u\n", produced, consumed);
 		/* Stall the main thread in case of overflow, as there are no
 		 * buffers available to store the new logs, otherwise there
@@ -159,12 +233,12 @@ static void pull_data(void)
 	};
 	pthread_mutex_unlock(&mutex);
 
-	ptr = read_buffer + (produced % num_buffers) * SUBBUF_SIZE;
+	ptr = read_buffer + (produced % subbuf_count) * subbuf_size;
 
 	/* Read the logs from relay buffer */
-	ret = read(relay_fd, ptr, SUBBUF_SIZE);
-	igt_assert_f(ret >= 0, "failed to read from the guc log file\n");
-	igt_assert_f(!ret || ret == SUBBUF_SIZE, "invalid read from relay file\n");
+	ret = read(relay_fd, ptr, subbuf_size);
+	igt_assert_f(ret >= 0, "failed to read from the GuC log file\n");
+	igt_assert_f(!ret || ret == subbuf_size, "invalid read from relay file\n");
 
 	if (ret) {
 		pthread_mutex_lock(&mutex);
@@ -204,10 +278,10 @@ static void *flusher(void *arg)
 		};
 		pthread_mutex_unlock(&mutex);
 
-		ptr = read_buffer + (consumed % num_buffers) * SUBBUF_SIZE;
+		ptr = read_buffer + (consumed % subbuf_count) * subbuf_size;
 
-		ret = write(outfile_fd, ptr, SUBBUF_SIZE);
-		igt_assert_f(ret == SUBBUF_SIZE, "couldn't dump the logs in a file\n");
+		ret = write(outfile_fd, ptr, subbuf_size);
+		igt_assert_f(ret == subbuf_size, "couldn't dump the logs in a file\n");
 
 		total_bytes_written += ret;
 		if (max_filesize && (total_bytes_written > MB(max_filesize))) {
@@ -260,8 +334,13 @@ static void init_flusher_thread(void)
 
 static void open_relay_file(void)
 {
-	relay_fd = igt_debugfs_open(-1, RELAY_FILE_NAME, O_RDONLY);
-	igt_assert_f(relay_fd >= 0, "couldn't open the guc log file\n");
+	char *path;
+
+	igt_assert_neq(asprintf(&path, "%s/%s", gucfspath, GLR_CHANNEL_NAME), -1);
+	igt_info("Opening this path -> %s\n", path);
+	relay_fd = igt_debugfs_open(drm_fd, path, O_RDONLY);
+	free(path);
+	igt_assert_f(relay_fd >= 0, "couldn't open the GuC log relay-channel file\n");
 
 	/* Purge the old/boot-time logs from the relay buffer.
 	 * This is more for Val team's requirement, where they have to first
@@ -292,7 +371,7 @@ static void open_output_file(void)
 
 static void init_main_thread(void)
 {
-	struct sched_param	thread_sched;
+	struct sched_param thread_sched;
 	int ret;
 
 	/* Run the main thread at highest priority to ensure that it always
@@ -311,11 +390,11 @@ static void init_main_thread(void)
 		igt_assert_f(0, "SIGALRM handler registration failed\n");
 
 	/* Need an aligned pointer for direct IO */
-	ret = posix_memalign((void **)&read_buffer, PAGE_SIZE, num_buffers * SUBBUF_SIZE);
+	ret = posix_memalign((void **)&read_buffer, PAGE_SIZE, subbuf_count * subbuf_size);
 	igt_assert_f(ret == 0, "couldn't allocate the read buffer\n");
 
 	/* Keep the pages locked in RAM, avoid page fault overhead */
-	ret = mlock(read_buffer, num_buffers * SUBBUF_SIZE);
+	ret = mlock(read_buffer, subbuf_count * subbuf_size);
 	igt_assert_f(ret == 0, "failed to lock memory\n");
 
 	/* Enable the logging, it may not have been enabled from boot and so
@@ -342,11 +421,6 @@ static int parse_options(int opt, int opt_index, void *data)
 		igt_assert_f(out_filename, "Couldn't allocate the o/p filename\n");
 		igt_debug("logs to be stored in file %s\n", out_filename);
 		break;
-	case 'b':
-		num_buffers = atoi(optarg);
-		igt_assert_f(num_buffers > 0, "invalid input for -b option\n");
-		igt_debug("number of buffers to be used is %d\n", num_buffers);
-		break;
 	case 't':
 		test_duration = atoi(optarg);
 		igt_assert_f(test_duration > 0, "invalid input for -t option\n");
@@ -377,7 +451,6 @@ static void process_command_line(int argc, char **argv)
 	static struct option long_options[] = {
 		{"verbosity", required_argument, 0, 'v'},
 		{"outputfile", required_argument, 0, 'o'},
-		{"buffers", required_argument, 0, 'b'},
 		{"testduration", required_argument, 0, 't'},
 		{"polltimeout", required_argument, 0, 'p'},
 		{"size", required_argument, 0, 's'},
@@ -388,7 +461,6 @@ static void process_command_line(int argc, char **argv)
 	const char *help =
 		"  -v --verbosity=level   verbosity level of GuC logging (0-3)\n"
 		"  -o --outputfile=name   name of the output file, including the location, where logs will be stored\n"
-		"  -b --buffers=num       number of buffers to be maintained on logger side for storing logs\n"
 		"  -t --testduration=sec  max duration in seconds for which the logger should run\n"
 		"  -p --polltimeout=ms    polling timeout in ms, -1 == indefinite wait for the new data\n"
 		"  -s --size=MB           max size of output file in MBs after which logging will be stopped\n"
@@ -404,6 +476,11 @@ int main(int argc, char **argv)
 	int nfds;
 	int ret;
 
+	drm_fd = drm_open_driver(DRIVER_INTEL);
+	igt_assert(drm_fd != -1);
+	igt_assert_neq(asprintf(&gucfspath, "gt0/uc"), -1);
+
+	get_guc_subbuf_info();
 	process_command_line(argc, argv);
 
 	init_main_thread();
@@ -466,5 +543,7 @@ int main(int argc, char **argv)
 	free(read_buffer);
 	close(relay_fd);
 	close(outfile_fd);
+	free(gucfspath);
+	close(drm_fd);
 	igt_exit();
 }
-- 
2.34.1

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

* [igt-dev] [PATCH i-g-t v2 02/11] tools/intel_guc_logger: Refactor intel_guc_logger globals into structs
  2022-12-06  8:58 [igt-dev] [PATCH i-g-t v2 00/11] Resurrect GuC Relay Logging Alan Previn
  2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 01/11] tools/intel_guc_logger: Re-enable basic functionality Alan Previn
@ 2022-12-06  8:58 ` Alan Previn
  2023-02-01  0:04   ` [igt-dev] [i-g-t, v2, " Dong, Zhanjun
  2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 03/11] tools/intel_guc_logger: Add GT-ID selection for intel_guc_logger Alan Previn
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 19+ messages in thread
From: Alan Previn @ 2022-12-06  8:58 UTC (permalink / raw)
  To: igt-dev

Refactor all of the global variables used in intel_guc_logger
into abstractions of structures at thread level, GuC-GT level
and global level.

While at it, remove asserts from the non primary thread to ensure
process cleanup doesn't get stuck.

Signed-off-by: Alan Previn <alan.previn.teres.alexis@intel.com>
---
 tools/intel_guc_logger.c | 458 ++++++++++++++++++++++++---------------
 1 file changed, 279 insertions(+), 179 deletions(-)

diff --git a/tools/intel_guc_logger.c b/tools/intel_guc_logger.c
index 4a991127..356cde59 100644
--- a/tools/intel_guc_logger.c
+++ b/tools/intel_guc_logger.c
@@ -48,12 +48,12 @@
   #define PAGE_SIZE 4096
 #endif
 
-#define DEFAULT_OUTPUT_FILE_NAME  "guc_log_dump.dat"
-
 #define GLR_LOGLEVEL_NAME         "guc_log_level"
 #define GLR_CTL_NAME              "guc_log_relay_ctl"
 #define GLR_CHANNEL_NAME          "guc_log_relay_chan0"
 
+#define DEFAULT_OUTPUT_FILE_NAME     "guc_log_dump" /*.dat suffic added later*/
+#define DEFAULT_GUCLOG_VERBOSITY     3 /* by default capture logs at max verbosity */
 #define DEFAULT_SUBBUF_COUNT         (4 * 8)
 					/* default to kernel built-in:   *
 					 *   4 x 8 subbuf regions        *
@@ -64,25 +64,54 @@
 					 *   8K -> GuC crash dump        *
 					 *  64K -> log events buffer     *
 					 */
-
-int drm_fd;
-char *read_buffer;
-char *out_filename;
-int poll_timeout = 2; /* by default 2ms timeout */
-pthread_mutex_t mutex;
-pthread_t flush_thread;
-int verbosity_level = 3; /* by default capture logs at max verbosity */
-uint32_t produced, consumed;
-uint64_t total_bytes_written;
-int subbuf_count;
-int subbuf_size;
-int ctl_fd, relay_fd, outfile_fd = -1;
-uint32_t test_duration, max_filesize;
-pthread_cond_t underflow_cond, overflow_cond;
-bool stop_logging, discard_oldlogs, capturing_stopped;
-char *gucfspath;
-
-static void get_guc_subbuf_info(void)
+#define DEFAULT_POLL_TIMEOUT         2 /* default timeout of 2ms */
+#define DEFAULT_MAX_OUTPUT_SIZE      MB(4 * 1024) /* default to 4 GB max file size */
+
+enum relay_cmd {
+	RELAY_CMD_DISABLE = 0,
+	RELAY_CMD_ENABLE = 1,
+	RELAY_CMD_FLUSH = 2,
+};
+
+struct guc_t {
+	int gt_id;
+	char *fspath;
+	int control_fd;
+	int relaychan;
+	int outfd;
+	char *readbuf;
+	int subbuf_count;
+	int subbuf_size;
+	uint64_t total_bytes_written;
+	pthread_mutex_t mutex;
+	pthread_t flush_thread;
+	pthread_cond_t underflow_cond;
+	pthread_cond_t overflow_cond;
+	int64_t produced;
+	int64_t consumed;
+	bool stop_logging;
+	bool capturing_stopped;
+};
+
+struct global_t {
+	int drmfd;
+	int verbosity;
+	char *out_filename;
+	uint64_t max_filesize;
+	uint32_t test_duration;
+	int poll_timeout;
+	bool discard_oldlogs;
+};
+
+struct thread_t {
+	struct global_t *global;
+	struct guc_t *guc;
+};
+
+/* only global instance needed for killing threads from main's signal handler */
+struct thread_t *gbl_thread_handle;
+
+static void get_guc_subbuf_info(struct thread_t *tdata)
 {
 	int fd, ret, j;
 	char *path;
@@ -92,9 +121,9 @@ static void get_guc_subbuf_info(void)
 	uint64_t tmp[2] = {DEFAULT_SUBBUF_SIZE, DEFAULT_SUBBUF_COUNT};
 
 	for (j = 0; j < 2; j++) {
-		igt_assert_neq(asprintf(&path, "%s/%s", gucfspath, dbg_fs_names[j]), -1);
+		igt_assert_neq(asprintf(&path, "%s/%s", tdata->guc->fspath, dbg_fs_names[j]), -1);
 		igt_info("Opening subbuf path %s\n", path);
-		fd = igt_debugfs_open(drm_fd, path, O_RDONLY);
+		fd = igt_debugfs_open(tdata->global->drmfd, path, O_RDONLY);
 		free(path);
 		igt_assert_f(fd >= 0, "couldn't open the GuC log relay-subbuf file\n");
 		ret = read(fd, outstr, sizeof(outstr) - 1);
@@ -103,35 +132,36 @@ static void get_guc_subbuf_info(void)
 		tmp[j] = atoll(outstr);
 		close(fd);
 	}
-	subbuf_size = tmp[0];
-	subbuf_count = tmp[1];
+	tdata->guc->subbuf_size = tmp[0];
+	tdata->guc->subbuf_count = tmp[1];
 	igt_info("Debugfs retrieved subbuf info: size=%d, count=%d\n",
-		 subbuf_size, subbuf_count);
+		 tdata->guc->subbuf_size, tdata->guc->subbuf_count);
 }
 
-static void guc_log_verbosity(bool enable, int log_level)
+static void guc_log_verbosity(struct thread_t *tdata, bool enable)
 {
 	char *str;
 	int loglevelfd;
 	uint64_t val;
 	int ret;
 
-	igt_assert_neq(asprintf(&str, "%s/%s", gucfspath, GLR_LOGLEVEL_NAME), -1);
+	igt_assert_neq(asprintf(&str, "%s/%s", tdata->guc->fspath, GLR_LOGLEVEL_NAME), -1);
 	igt_info("Opening log level -> %s\n", str);
-	loglevelfd = igt_debugfs_open(drm_fd, str, O_WRONLY);
+	loglevelfd = igt_debugfs_open(tdata->global->drmfd, str, O_WRONLY);
 	free(str);
 	igt_assert_f(loglevelfd >= 0, "couldn't open the GuC log level file\n");
 
 	/*
 	 * i915 expects GuC log level to be specified as:
 	 * 0: disabled
-	 * 1: enabled (verbosity level 0 = min)
-	 * 2: enabled (verbosity level 1)
-	 * 3: enabled (verbosity level 2)
-	 * 4: enabled (verbosity level 3 = max)
+	 * 1: enabled (non-verbose mode)
+	 * 2: GuC verbosity level 0
+	 * 3: GuC verbosity level 1
+	 * 4: GuC verbosity level 2
+	 * 5: GuC verbosity level 3
+	 * intel_guc_logger takes input range of 0..3 that maps to 2..5 above.
 	 */
-	val = enable ? log_level + 1 : 0;
-
+	val = enable ? tdata->global->verbosity + 2 : 0;
 	ret = asprintf(&str, "0x%" PRIx64, val);
 	igt_assert_neq(ret, -1);
 	ret = write(loglevelfd, str, ret);
@@ -142,40 +172,37 @@ static void guc_log_verbosity(bool enable, int log_level)
 	close(loglevelfd);
 }
 
-static void guc_log_control(bool enable, uint32_t log_level)
+static void guc_log_control(struct thread_t *tdata, enum relay_cmd cmd)
 {
 	char *str;
-	uint64_t val = 0;
 	int ret;
 
-	if (enable) {
-		igt_assert_neq(asprintf(&str, "%s/%s", gucfspath, GLR_CTL_NAME), -1);
+	igt_assert_f((cmd >= 0 && cmd <= 2), "Invalid GuC-log-control cmd!\n");
+
+	if (cmd == RELAY_CMD_ENABLE) {
+		igt_assert_neq(asprintf(&str, "%s/%s", tdata->guc->fspath, GLR_CTL_NAME), -1);
 		igt_info("Opening control file -> %s\n", str);
-		ctl_fd = igt_debugfs_open(drm_fd, str, O_WRONLY);
+		tdata->guc->control_fd = igt_debugfs_open(tdata->global->drmfd, str, O_WRONLY);
 		free(str);
-		igt_assert_f(ctl_fd >= 0, "couldn't open the GuC log relay-ctl file\n");
-		val = 1;
+		igt_assert_f(tdata->guc->control_fd >= 0, "Can't open GuC log relay-ctl file\n");
 	}
 
-	/*
-	 * i915 expects relay logging controls:
-	 * 1    : open + enable relay logging
-	 * 2    : flush
-	 * 0    : disable relay logging + close
-	 */
-	if (ctl_fd) {
-		ret = asprintf(&str, "0x%" PRIx64, val);
+	if (tdata->guc->control_fd) {
+		ret = asprintf(&str, "0x%" PRIx64, (unsigned long)cmd);
 		igt_assert_neq(ret, -1);
-		ret = write(ctl_fd, str, ret);
+		ret = write(tdata->guc->control_fd, str, ret);
 		free(str);
-		igt_assert_f(ret > 0, "couldn't write to the log control file\n");
-	}
+		igt_assert_f(ret > 0, "couldn't set cmd-%u on log control file\n", cmd);
 
-	guc_log_verbosity(enable, log_level);
+		if (cmd == RELAY_CMD_ENABLE)
+			guc_log_verbosity(tdata, true);
+	}
 
-	if (!enable) {
+	if (cmd == RELAY_CMD_DISABLE) {
 		igt_info("Closing control file\n");
-		close(ctl_fd);
+		guc_log_verbosity(tdata, false);
+		close(tdata->guc->control_fd);
+		tdata->guc->control_fd = 0;
 	}
 }
 
@@ -183,68 +210,82 @@ static void int_sig_handler(int sig)
 {
 	igt_info("received signal %d\n", sig);
 
-	stop_logging = true;
+	if (!gbl_thread_handle)
+		return;
+
+	if (gbl_thread_handle[0].guc)
+		gbl_thread_handle[0].guc->stop_logging = true;
 }
 
-static void pull_leftover_data(void)
+static void pull_leftover_data(struct thread_t *tdata)
 {
+	struct guc_t *guc = tdata->guc;
 	unsigned int bytes_read = 0;
+	int subbuf_size = guc->subbuf_size;
 	int ret;
 
 	do {
-		/* Read the logs from relay buffer */
-		ret = read(relay_fd, read_buffer, subbuf_size);
+		/* Read the logs from relay channel buffer */
+		ret = read(guc->relaychan, guc->readbuf, subbuf_size);
 		if (!ret)
 			break;
-
-		igt_assert_f(ret > 0, "failed to read from the GuC log file\n");
-		igt_assert_f(ret == subbuf_size, "invalid read from relay file\n");
-
+		if (ret < 0) {
+			igt_warn("failed leftover-read from GuC GT-%d relay-channel\n",
+				 guc->gt_id);
+			break;
+		}
+		if (ret != subbuf_size)
+			igt_warn("invalid leftover-size from GuC GT-%d relay-channel\n",
+				 guc->gt_id);
 		bytes_read += ret;
-
-		if (outfile_fd >= 0) {
-			ret = write(outfile_fd, read_buffer, subbuf_size);
-			igt_assert_f(ret == subbuf_size, "couldn't dump the logs in a file\n");
-			total_bytes_written += ret;
+		if (guc->outfd >= 0) {
+			ret = write(guc->outfd, guc->readbuf, subbuf_size);
+			if (ret != subbuf_size)
+				igt_warn("Couldn't dump leftover logs to file\n");
+			guc->total_bytes_written += ret;
 		}
 	} while(1);
 
-	igt_debug("%u bytes flushed\n", bytes_read);
+	igt_debug("%u bytes flushed from GuC GT-%d\n", bytes_read, guc->gt_id);
 }
 
-static int num_filled_bufs(void)
+static int num_filled_bufs(struct guc_t *guc)
 {
-	return (produced - consumed);
+	return (guc->produced - guc->consumed);
 }
 
-static void pull_data(void)
+static void pull_data(struct thread_t *tdata)
 {
 	char *ptr;
 	int ret;
+	struct guc_t *guc = tdata->guc;
+	int subbuf_size = guc->subbuf_size;
 
-	pthread_mutex_lock(&mutex);
-	while (num_filled_bufs() >= subbuf_count) {
-		igt_debug("overflow, will wait, produced %u, consumed %u\n", produced, consumed);
+	pthread_mutex_lock(&guc->mutex);
+	while (num_filled_bufs(guc) >= guc->subbuf_count) {
+		igt_debug("overflow, will wait, produced %ld, consumed %ld\n",
+			  guc->produced, guc->consumed);
 		/* Stall the main thread in case of overflow, as there are no
 		 * buffers available to store the new logs, otherwise there
 		 * could be corruption if both threads work on the same buffer.
 		 */
-		pthread_cond_wait(&overflow_cond, &mutex);
+		pthread_cond_wait(&guc->overflow_cond, &guc->mutex);
 	};
-	pthread_mutex_unlock(&mutex);
+	pthread_mutex_unlock(&guc->mutex);
 
-	ptr = read_buffer + (produced % subbuf_count) * subbuf_size;
+	ptr = guc->readbuf + (guc->produced % guc->subbuf_count) * subbuf_size;
 
-	/* Read the logs from relay buffer */
-	ret = read(relay_fd, ptr, subbuf_size);
+	/* Read the logs from relay channel buffer */
+	ret = read(guc->relaychan, ptr, subbuf_size);
 	igt_assert_f(ret >= 0, "failed to read from the GuC log file\n");
-	igt_assert_f(!ret || ret == subbuf_size, "invalid read from relay file\n");
+	igt_assert_f(!ret || ret <= subbuf_size, "invalid read from relay file\n");
 
 	if (ret) {
-		pthread_mutex_lock(&mutex);
-		produced++;
-		pthread_cond_signal(&underflow_cond);
-		pthread_mutex_unlock(&mutex);
+		pthread_mutex_lock(&guc->mutex);
+		guc->produced++;
+		pthread_cond_signal(&guc->underflow_cond);
+		pthread_mutex_unlock(&guc->mutex);
+		igt_info("read %d KB from relay file\n", (ret / 1024));
 	} else {
 		/* Occasionally (very rare) read from the relay file returns no
 		 * data, albeit the polling done prior to read call indicated
@@ -257,56 +298,74 @@ static void pull_data(void)
 static void *flusher(void *arg)
 {
 	char *ptr;
-	int ret;
+	int ret, subbuf_size;
+	struct thread_t *tdata = (struct thread_t *)arg;
+	struct global_t *gbl;
+	struct guc_t *guc;
+
+	igt_assert_f(tdata, "Flusher didn't receive thread context ptr!\n");
+	gbl = tdata->global;
+	guc = tdata->guc;
+	subbuf_size = guc->subbuf_size;
 
 	igt_debug("execution started of flusher thread\n");
 
 	do {
-		pthread_mutex_lock(&mutex);
-		while (!num_filled_bufs()) {
+		pthread_mutex_lock(&guc->mutex);
+		while (!num_filled_bufs(guc)) {
 			/* Exit only after completing the flush of all the filled
 			 * buffers as User would expect that all logs captured up
 			 * till the point of interruption/exit are written out to
 			 * the disk file.
 			 */
-			if (capturing_stopped) {
+			if (guc->capturing_stopped) {
 				igt_debug("flusher to exit now\n");
-				pthread_mutex_unlock(&mutex);
+				pthread_mutex_unlock(&guc->mutex);
 				return NULL;
 			}
-			pthread_cond_wait(&underflow_cond, &mutex);
+			pthread_cond_wait(&guc->underflow_cond, &guc->mutex);
 		};
-		pthread_mutex_unlock(&mutex);
-
-		ptr = read_buffer + (consumed % subbuf_count) * subbuf_size;
+		pthread_mutex_unlock(&guc->mutex);
 
-		ret = write(outfile_fd, ptr, subbuf_size);
-		igt_assert_f(ret == subbuf_size, "couldn't dump the logs in a file\n");
+		ptr = guc->readbuf + (guc->consumed % guc->subbuf_count) * subbuf_size;
 
-		total_bytes_written += ret;
-		if (max_filesize && (total_bytes_written > MB(max_filesize))) {
-			igt_debug("reached the target of %" PRIu64 " bytes\n", MB(max_filesize));
-			stop_logging = true;
+		ret = write(guc->outfd, ptr, subbuf_size);
+		if (ret < 0) {
+			igt_warn("Dump to file failed with err %d, stopping!\n", ret);
+			guc->stop_logging = true;
+		} else if (!ret) {
+			igt_warn("Dump to file flushed zero bytes!\n");
+		} else {
+			if (ret != subbuf_size)
+				igt_warn("Dump size mismatch = %d!\n", ret);
+			guc->total_bytes_written += ret;
+			igt_info("wrote %d KB out to dat file\n", (ret / 1024));
+			if (gbl->max_filesize && guc->total_bytes_written >
+			    MB(gbl->max_filesize)) {
+				igt_debug("reached the target of %" PRIu64 " bytes\n",
+					  MB(gbl->max_filesize));
+				guc->stop_logging = true;
+			}
+			pthread_mutex_lock(&guc->mutex);
+			guc->consumed++;
+			pthread_cond_signal(&guc->overflow_cond);
+			pthread_mutex_unlock(&guc->mutex);
 		}
-
-		pthread_mutex_lock(&mutex);
-		consumed++;
-		pthread_cond_signal(&overflow_cond);
-		pthread_mutex_unlock(&mutex);
 	} while(1);
 
 	return NULL;
 }
 
-static void init_flusher_thread(void)
+static void init_flusher_thread(struct thread_t *tdata)
 {
-	struct sched_param	thread_sched;
-	pthread_attr_t		p_attr;
+	struct sched_param thread_sched;
+	pthread_attr_t p_attr;
+	struct guc_t *guc = tdata->guc;
 	int ret;
 
-	pthread_cond_init(&underflow_cond, NULL);
-	pthread_cond_init(&overflow_cond, NULL);
-	pthread_mutex_init(&mutex, NULL);
+	pthread_cond_init(&guc->underflow_cond, NULL);
+	pthread_cond_init(&guc->overflow_cond, NULL);
+	pthread_mutex_init(&guc->mutex, NULL);
 
 	ret = pthread_attr_init(&p_attr);
 	igt_assert_f(ret == 0, "error obtaining default thread attributes\n");
@@ -325,22 +384,22 @@ static void init_flusher_thread(void)
 	ret = pthread_attr_setschedparam(&p_attr, &thread_sched);
 	igt_assert_f(ret == 0, "couldn't set thread priority\n");
 
-	ret = pthread_create(&flush_thread, &p_attr, flusher, NULL);
+	ret = pthread_create(&guc->flush_thread, &p_attr, flusher, tdata);
 	igt_assert_f(ret == 0, "thread creation failed\n");
 
 	ret = pthread_attr_destroy(&p_attr);
 	igt_assert_f(ret == 0, "error destroying thread attributes\n");
 }
 
-static void open_relay_file(void)
+static void open_relay_file(struct thread_t *tdata)
 {
 	char *path;
 
-	igt_assert_neq(asprintf(&path, "%s/%s", gucfspath, GLR_CHANNEL_NAME), -1);
+	igt_assert_neq(asprintf(&path, "%s/%s", tdata->guc->fspath, GLR_CHANNEL_NAME), -1);
 	igt_info("Opening this path -> %s\n", path);
-	relay_fd = igt_debugfs_open(drm_fd, path, O_RDONLY);
+	tdata->guc->relaychan = igt_debugfs_open(tdata->global->drmfd, path, O_RDONLY);
 	free(path);
-	igt_assert_f(relay_fd >= 0, "couldn't open the GuC log relay-channel file\n");
+	igt_assert_f(tdata->guc->relaychan >= 0, "couldn't open the GuC log relay-channel file\n");
 
 	/* Purge the old/boot-time logs from the relay buffer.
 	 * This is more for Val team's requirement, where they have to first
@@ -349,29 +408,39 @@ static void open_relay_file(void)
 	 * wait for the new data, at that point benchmark can be launched from
 	 * a different shell.
 	 */
-	if (discard_oldlogs)
-		pull_leftover_data();
+	if (tdata->global->discard_oldlogs)
+		pull_leftover_data(tdata);
 }
 
-static void open_output_file(void)
+static void open_output_file(struct thread_t *tdata)
 {
+	char *path;
+
 	/* Use Direct IO mode for the output file, as the data written is not
 	 * supposed to be accessed again, this saves a copy of data from App's
 	 * buffer to kernel buffer (Page cache). Due to no buffering on kernel
 	 * side, data is flushed out to disk faster and more buffering can be
 	 * done on the logger side to hide the disk IO latency.
 	 */
-	outfile_fd = open(out_filename ? : DEFAULT_OUTPUT_FILE_NAME,
-			  O_CREAT | O_WRONLY | O_TRUNC | O_DIRECT,
-			  0440);
-	igt_assert_f(outfile_fd >= 0, "couldn't open the output file\n");
+	if (tdata->global->out_filename) {
+		igt_assert_neq(asprintf(&path, "%s_GT%d.dat", tdata->global->out_filename,
+					tdata->guc->gt_id), -1);
+	} else {
+		igt_assert_neq(asprintf(&path, "%s_GT%d.dat", DEFAULT_OUTPUT_FILE_NAME,
+					tdata->guc->gt_id), -1);
+	}
+
+	tdata->guc->outfd = open(path, O_CREAT | O_WRONLY | O_TRUNC | O_DIRECT, 0440);
+	igt_assert_f(tdata->guc->outfd >= 0, "couldn't open the output file\n");
 
-	free(out_filename);
+	igt_info("Creating output GuC-log-file: %s\n", path);
+	free(path);
 }
 
-static void init_main_thread(void)
+static void init_main_thread(struct thread_t *tdata)
 {
 	struct sched_param thread_sched;
+	struct guc_t *guc = tdata->guc;
 	int ret;
 
 	/* Run the main thread at highest priority to ensure that it always
@@ -390,55 +459,60 @@ static void init_main_thread(void)
 		igt_assert_f(0, "SIGALRM handler registration failed\n");
 
 	/* Need an aligned pointer for direct IO */
-	ret = posix_memalign((void **)&read_buffer, PAGE_SIZE, subbuf_count * subbuf_size);
+	ret = posix_memalign((void **)&guc->readbuf, PAGE_SIZE,
+			     (guc->subbuf_count * guc->subbuf_size));
 	igt_assert_f(ret == 0, "couldn't allocate the read buffer\n");
 
 	/* Keep the pages locked in RAM, avoid page fault overhead */
-	ret = mlock(read_buffer, subbuf_count * subbuf_size);
+	ret = mlock(guc->readbuf, (guc->subbuf_count * guc->subbuf_size));
 	igt_assert_f(ret == 0, "failed to lock memory\n");
 
 	/* Enable the logging, it may not have been enabled from boot and so
 	 * the relay file also wouldn't have been created.
 	 */
-	guc_log_control(true, verbosity_level);
-
-	open_relay_file();
-	open_output_file();
+	guc_log_control(tdata, RELAY_CMD_ENABLE);
+	open_relay_file(tdata);
+	open_output_file(tdata);
 }
 
-static int parse_options(int opt, int opt_index, void *data)
+static int parse_options(int opt, int opt_index, void *ptr)
 {
+	struct global_t *data = (struct global_t *)ptr;
+
+	igt_assert(data);
 	igt_debug("opt %c optarg %s\n", opt, optarg);
 
 	switch(opt) {
 	case 'v':
-		verbosity_level = atoi(optarg);
-		igt_assert_f(verbosity_level >= 0 && verbosity_level <= 3, "invalid input for -v option\n");
-		igt_debug("verbosity level to be used is %d\n", verbosity_level);
+		data->verbosity = atoi(optarg);
+		igt_assert_f(data->verbosity >= 0 && data->verbosity <= 3,
+			     "invalid input for -v option\n");
+		igt_debug("verbosity level to be used is %d\n", data->verbosity);
 		break;
 	case 'o':
-		out_filename = strdup(optarg);
-		igt_assert_f(out_filename, "Couldn't allocate the o/p filename\n");
-		igt_debug("logs to be stored in file %s\n", out_filename);
+		data->out_filename = strdup(optarg);
+		igt_assert_f(data->out_filename, "Couldn't allocate the o/p filename\n");
+		igt_debug("logs to be stored in file %s_G[GuC-ID]\n", data->out_filename);
 		break;
 	case 't':
-		test_duration = atoi(optarg);
-		igt_assert_f(test_duration > 0, "invalid input for -t option\n");
-		igt_debug("logger to run for %d second\n", test_duration);
+		data->test_duration = atoi(optarg);
+		igt_assert_f(data->test_duration > 0, "invalid input for -t option\n");
+		igt_debug("logger to run for %d second\n", data->test_duration);
 		break;
 	case 'p':
-		poll_timeout = atoi(optarg);
-		igt_assert_f(poll_timeout != 0, "invalid input for -p option\n");
-		if (poll_timeout > 0)
-			igt_debug("polling to be done with %d millisecond timeout\n", poll_timeout);
+		data->poll_timeout = atoi(optarg);
+		igt_assert_f(data->poll_timeout != 0, "invalid input for -p option\n");
+		if (data->poll_timeout > 0)
+			igt_debug("polling to be done with %d millisecond timeout\n",
+				  data->poll_timeout);
 		break;
 	case 's':
-		max_filesize = atoi(optarg);
-		igt_assert_f(max_filesize > 0, "invalid input for -s option\n");
-		igt_debug("max allowed size of the output file is %d MB\n", max_filesize);
+		data->max_filesize = atoll(optarg);
+		igt_assert_f(data->max_filesize > 0, "invalid input for -s option\n");
+		igt_debug("max allowed size of the output file is %lu MB\n", data->max_filesize);
 		break;
 	case 'd':
-		discard_oldlogs = true;
+		data->discard_oldlogs = true;
 		igt_debug("old/boot-time logs will be discarded\n");
 		break;
 	}
@@ -446,7 +520,7 @@ static int parse_options(int opt, int opt_index, void *data)
 	return 0;
 }
 
-static void process_command_line(int argc, char **argv)
+static void process_command_line(int argc, char **argv, struct global_t *data)
 {
 	static struct option long_options[] = {
 		{"verbosity", required_argument, 0, 'v'},
@@ -467,23 +541,39 @@ static void process_command_line(int argc, char **argv)
 		"  -d --discard           discard the old/boot-time logs before entering into the capture loop\n";
 
 	igt_simple_init_parse_opts(&argc, argv, "v:o:b:t:p:s:d", long_options,
-				   help, parse_options, NULL);
+				   help, parse_options, data);
 }
 
 int main(int argc, char **argv)
 {
+	struct global_t gbldata;
+	/* For now, just one thread collecting logs from any single GuC source */
+	struct guc_t gucdata[1];  /* only GT0 for now */
+	struct thread_t thread[1];
 	struct pollfd relay_poll_fd;
-	int nfds;
-	int ret;
+	int nfds, ret;
 
-	drm_fd = drm_open_driver(DRIVER_INTEL);
-	igt_assert(drm_fd != -1);
-	igt_assert_neq(asprintf(&gucfspath, "gt0/uc"), -1);
+	/* setup global context */
+	memset(&gbldata, 0, sizeof(gbldata));
+	gbldata.verbosity    = DEFAULT_GUCLOG_VERBOSITY;
+	gbldata.poll_timeout = DEFAULT_POLL_TIMEOUT;
+	gbldata.drmfd        = drm_open_driver_render(DRIVER_INTEL);
+	igt_assert(gbldata.drmfd != -1);
 
-	get_guc_subbuf_info();
-	process_command_line(argc, argv);
+	memset(&gucdata[0], 0, sizeof(struct guc_t));
+	gucdata[0].gt_id = 0;
+	igt_assert_neq(asprintf(&gucdata[0].fspath, "gt/uc"), -1);
+	gucdata[0].outfd = -1;
 
-	init_main_thread();
+	thread[0].global = &gbldata;
+	thread[0].guc = &gucdata[0];
+	get_guc_subbuf_info(&thread[0]);
+
+	process_command_line(argc, argv, &gbldata);
+
+	gbl_thread_handle = thread;
+
+	init_main_thread(&thread[0]);
 
 	/* Use a separate thread for flushing the logs to a file on disk.
 	 * Main thread will buffer the data from relay file in its pool of
@@ -493,15 +583,15 @@ int main(int argc, char **argv)
 	 * (/proc/sys/vm/dirty_ratio), kernel starts blocking the processes
 	 * doing the file writes.
 	 */
-	init_flusher_thread();
+	init_flusher_thread(&thread[0]);
 
-	relay_poll_fd.fd = relay_fd;
+	relay_poll_fd.fd = thread[0].guc->relaychan;
 	relay_poll_fd.events = POLLIN;
 	relay_poll_fd.revents = 0;
 
 	nfds = 1; /* only one fd to poll */
 
-	alarm(test_duration); /* Start the alarm */
+	alarm(gbldata.test_duration); /* Start the alarm */
 
 	do {
 		/* Wait/poll for the new data to be available, relay doesn't
@@ -515,7 +605,7 @@ int main(int argc, char **argv)
 		 * succession (less than a jiffy gap between 2 flush interrupts)
 		 * causing relay to run out of sub buffers to store new logs.
 		 */
-		ret = poll(&relay_poll_fd, nfds, poll_timeout);
+		ret = poll(&relay_poll_fd, nfds, gbldata.poll_timeout);
 		if (ret < 0) {
 			if (errno == EINTR)
 				break;
@@ -526,24 +616,34 @@ int main(int argc, char **argv)
 		if (!relay_poll_fd.revents)
 			continue;
 
-		pull_data();
-	} while (!stop_logging);
+		pull_data(&thread[0]);
+	} while (!thread[0].guc->stop_logging);
 
 	/* Pause logging on the GuC side */
-	guc_log_control(false, 0);
+	guc_log_control(&thread[0], RELAY_CMD_FLUSH);
+	guc_log_control(&thread[0], RELAY_CMD_DISABLE);
 
 	/* Signal flusher thread to make an exit */
-	capturing_stopped = 1;
-	pthread_cond_signal(&underflow_cond);
-	pthread_join(flush_thread, NULL);
-
-	pull_leftover_data();
-	igt_info("total bytes written %" PRIu64 "\n", total_bytes_written);
-
-	free(read_buffer);
-	close(relay_fd);
-	close(outfile_fd);
-	free(gucfspath);
-	close(drm_fd);
+	thread[0].guc->capturing_stopped = 1;
+	pthread_cond_signal(&thread[0].guc->underflow_cond);
+	pthread_join(thread[0].guc->flush_thread, NULL);
+	pull_leftover_data(&thread[0]);
+	igt_info("total bytes written %" PRIu64 "\n", thread[0].guc->total_bytes_written);
+
+	if (gucdata[0].outfd)
+		close(gucdata[0].outfd);
+	if (gucdata[0].relaychan > 0)
+		close(gucdata[0].relaychan);
+	if (gucdata[0].control_fd > 0)
+		close(gucdata[0].control_fd);
+	if (gucdata[0].readbuf)
+		free(gucdata[0].readbuf);
+	if (gucdata[0].fspath)
+		free(gucdata[0].fspath);
+
+	if (gbldata.out_filename)
+		free(gbldata.out_filename);
+	close(gbldata.drmfd);
+
 	igt_exit();
 }
-- 
2.34.1

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

* [igt-dev] [PATCH i-g-t v2 03/11] tools/intel_guc_logger: Add GT-ID selection for intel_guc_logger
  2022-12-06  8:58 [igt-dev] [PATCH i-g-t v2 00/11] Resurrect GuC Relay Logging Alan Previn
  2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 01/11] tools/intel_guc_logger: Re-enable basic functionality Alan Previn
  2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 02/11] tools/intel_guc_logger: Refactor intel_guc_logger globals into structs Alan Previn
@ 2022-12-06  8:58 ` Alan Previn
  2023-03-14 21:54   ` Teres Alexis, Alan Previn
  2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 04/11] tools/intel_guc_logger: Add helper function for flusher code Alan Previn
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 19+ messages in thread
From: Alan Previn @ 2022-12-06  8:58 UTC (permalink / raw)
  To: igt-dev

With the introduction of MTL and multi-tile products, add a new
cmd line param for users to select which GT to collect GuC relay
logs from.

Signed-off-by: Alan Previn <alan.previn.teres.alexis@intel.com>
---
 tools/intel_guc_logger.c | 58 +++++++++++++++++++++++++++++++++++-----
 1 file changed, 51 insertions(+), 7 deletions(-)

diff --git a/tools/intel_guc_logger.c b/tools/intel_guc_logger.c
index 356cde59..f694ff18 100644
--- a/tools/intel_guc_logger.c
+++ b/tools/intel_guc_logger.c
@@ -48,9 +48,12 @@
   #define PAGE_SIZE 4096
 #endif
 
-#define GLR_LOGLEVEL_NAME         "guc_log_level"
-#define GLR_CTL_NAME              "guc_log_relay_ctl"
-#define GLR_CHANNEL_NAME          "guc_log_relay_chan0"
+#define MAX_GTS                      4
+#define DEFAULT_GT_ID                0 /* default logging from GuC GT-0 */
+
+#define GLR_LOGLEVEL_NAME            "guc_log_level"
+#define GLR_CTL_NAME                 "guc_log_relay_ctl"
+#define GLR_CHANNEL_NAME             "guc_log_relay_chan0"
 
 #define DEFAULT_OUTPUT_FILE_NAME     "guc_log_dump" /*.dat suffic added later*/
 #define DEFAULT_GUCLOG_VERBOSITY     3 /* by default capture logs at max verbosity */
@@ -96,6 +99,8 @@ struct guc_t {
 struct global_t {
 	int drmfd;
 	int verbosity;
+	uint32_t usr_gt_id;
+	uint32_t avail_guc_mask;
 	char *out_filename;
 	uint64_t max_filesize;
 	uint32_t test_duration;
@@ -111,6 +116,23 @@ struct thread_t {
 /* only global instance needed for killing threads from main's signal handler */
 struct thread_t *gbl_thread_handle;
 
+static void get_avail_guc_mask(struct global_t *gbl)
+{
+	int i, fd;
+	char path[20];
+
+	/* Query the number of GTs with GuC based on debugfs paths */
+	for (i = 0; i < MAX_GTS; i++) {
+		sprintf(path, "gt%d/uc/guc_info", i);
+		fd = igt_debugfs_open(gbl->drmfd, path, O_RDONLY);
+		if (fd > 0) {
+			igt_debug("Found GUC at GT-ID-%d\n", i);
+			gbl->avail_guc_mask |= (1 << i);
+			close(fd);
+		}
+	}
+}
+
 static void get_guc_subbuf_info(struct thread_t *tdata)
 {
 	int fd, ret, j;
@@ -492,7 +514,7 @@ static int parse_options(int opt, int opt_index, void *ptr)
 	case 'o':
 		data->out_filename = strdup(optarg);
 		igt_assert_f(data->out_filename, "Couldn't allocate the o/p filename\n");
-		igt_debug("logs to be stored in file %s_G[GuC-ID]\n", data->out_filename);
+		igt_debug("logs to be stored in file %s_G[GT-ID]\n", data->out_filename);
 		break;
 	case 't':
 		data->test_duration = atoi(optarg);
@@ -515,6 +537,14 @@ static int parse_options(int opt, int opt_index, void *ptr)
 		data->discard_oldlogs = true;
 		igt_debug("old/boot-time logs will be discarded\n");
 		break;
+	case 'i':
+		data->usr_gt_id = atoi(optarg);
+		igt_assert_f((data->usr_gt_id >= 0) && (data->usr_gt_id < MAX_GTS),
+			     "invalid input for -i (GT-ID) option\n");
+		igt_assert_f((data->avail_guc_mask & BIT(data->usr_gt_id)),
+			     "Requested GT-ID-%d unavailable, avail-mask = 0x%08x\n",
+			     data->usr_gt_id, data->avail_guc_mask);
+		break;
 	}
 
 	return 0;
@@ -529,6 +559,7 @@ static void process_command_line(int argc, char **argv, struct global_t *data)
 		{"polltimeout", required_argument, 0, 'p'},
 		{"size", required_argument, 0, 's'},
 		{"discard", no_argument, 0, 'd'},
+		{"gt_id", required_argument, 0, 'i'},
 		{ 0, 0, 0, 0 }
 	};
 
@@ -538,9 +569,10 @@ static void process_command_line(int argc, char **argv, struct global_t *data)
 		"  -t --testduration=sec  max duration in seconds for which the logger should run\n"
 		"  -p --polltimeout=ms    polling timeout in ms, -1 == indefinite wait for the new data\n"
 		"  -s --size=MB           max size of output file in MBs after which logging will be stopped\n"
-		"  -d --discard           discard the old/boot-time logs before entering into the capture loop\n";
+		"  -d --discard           discard the old/boot-time logs before entering into the capture loop\n"
+		"  -i --gt_id             GT-ID of GuC to capture from, defaults to capture from gt0\n";
 
-	igt_simple_init_parse_opts(&argc, argv, "v:o:b:t:p:s:d", long_options,
+	igt_simple_init_parse_opts(&argc, argv, "v:o:b:t:p:s:d:i", long_options,
 				   help, parse_options, data);
 }
 
@@ -556,6 +588,7 @@ int main(int argc, char **argv)
 	/* setup global context */
 	memset(&gbldata, 0, sizeof(gbldata));
 	gbldata.verbosity    = DEFAULT_GUCLOG_VERBOSITY;
+	gbldata.usr_gt_id    = DEFAULT_GT_ID;
 	gbldata.poll_timeout = DEFAULT_POLL_TIMEOUT;
 	gbldata.drmfd        = drm_open_driver_render(DRIVER_INTEL);
 	igt_assert(gbldata.drmfd != -1);
@@ -567,10 +600,21 @@ int main(int argc, char **argv)
 
 	thread[0].global = &gbldata;
 	thread[0].guc = &gucdata[0];
-	get_guc_subbuf_info(&thread[0]);
 
+	get_avail_guc_mask(&gbldata);
+	igt_assert_f(gbldata.avail_guc_mask, "Can't detect any available GuC's");
+
+	get_guc_subbuf_info(&thread[0]);
 	process_command_line(argc, argv, &gbldata);
 
+	igt_assert_f((gbldata.avail_guc_mask & BIT(gbldata.usr_gt_id)),
+		     "GuC of GT-ID-%d not avail. Avail-Mask = 0x%08x. Use '-i' option!\n",
+		     gbldata.usr_gt_id, gbldata.avail_guc_mask);
+
+	gucdata[0].gt_id = gbldata.usr_gt_id;
+	sprintf(gucdata[0].fspath, "gt%d/uc", gbldata.usr_gt_id);
+	igt_info("Logging on GuC of GT_ID-%d\n", gbldata.usr_gt_id);
+
 	gbl_thread_handle = thread;
 
 	init_main_thread(&thread[0]);
-- 
2.34.1

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

* [igt-dev] [PATCH i-g-t v2 04/11] tools/intel_guc_logger: Add helper function for flusher code
  2022-12-06  8:58 [igt-dev] [PATCH i-g-t v2 00/11] Resurrect GuC Relay Logging Alan Previn
                   ` (2 preceding siblings ...)
  2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 03/11] tools/intel_guc_logger: Add GT-ID selection for intel_guc_logger Alan Previn
@ 2022-12-06  8:58 ` Alan Previn
  2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 05/11] tools/intel_guc_logger: Add GuC Log header structure definition Alan Previn
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 19+ messages in thread
From: Alan Previn @ 2022-12-06  8:58 UTC (permalink / raw)
  To: igt-dev

Add an abstraction for the flusher-thread's code that writes
the log buffer data to file. This prepares us for future
patches that requires calling the same helper for different
types of data flushing.

Signed-off-by: Alan Previn <alan.previn.teres.alexis@intel.com>
---
 tools/intel_guc_logger.c | 53 +++++++++++++++++++++++++++-------------
 1 file changed, 36 insertions(+), 17 deletions(-)

diff --git a/tools/intel_guc_logger.c b/tools/intel_guc_logger.c
index f694ff18..ce4d1bc5 100644
--- a/tools/intel_guc_logger.c
+++ b/tools/intel_guc_logger.c
@@ -317,6 +317,40 @@ static void pull_data(struct thread_t *tdata)
 	}
 }
 
+static bool file_reached_maxsize(struct global_t *gbl, struct guc_t *guc)
+{
+	if (gbl->max_filesize && MB(gbl->max_filesize) - guc->total_bytes_written <= 0)
+		return true;
+
+	return false;
+}
+
+static int _write(struct global_t *gbl, struct guc_t *guc,
+		  char *inptr, int copy_size)
+{
+	int ret = 0;
+
+	ret = write(guc->outfd, inptr, copy_size);
+	if (ret < 0) {
+		igt_warn("Copy to file failed with err %d, stopping!\n", ret);
+		guc->stop_logging = true;
+	} else if (!ret) {
+		igt_warn("Copy to file flushed zero bytes!\n");
+	} else {
+		if (ret != copy_size)
+			igt_warn("File write size err: ask = %d, copied = %d!\n",
+				 copy_size, ret);
+		guc->total_bytes_written += ret;
+		igt_info("wrote %d KB out to dat file\n", (ret / 1024));
+		if (file_reached_maxsize(gbl, guc)) {
+			igt_info("Reached target filesize of %" PRIu64 " bytes\n",
+				 MB(gbl->max_filesize));
+			guc->stop_logging = true;
+		}
+	}
+	return ret;
+}
+
 static void *flusher(void *arg)
 {
 	char *ptr;
@@ -351,23 +385,8 @@ static void *flusher(void *arg)
 
 		ptr = guc->readbuf + (guc->consumed % guc->subbuf_count) * subbuf_size;
 
-		ret = write(guc->outfd, ptr, subbuf_size);
-		if (ret < 0) {
-			igt_warn("Dump to file failed with err %d, stopping!\n", ret);
-			guc->stop_logging = true;
-		} else if (!ret) {
-			igt_warn("Dump to file flushed zero bytes!\n");
-		} else {
-			if (ret != subbuf_size)
-				igt_warn("Dump size mismatch = %d!\n", ret);
-			guc->total_bytes_written += ret;
-			igt_info("wrote %d KB out to dat file\n", (ret / 1024));
-			if (gbl->max_filesize && guc->total_bytes_written >
-			    MB(gbl->max_filesize)) {
-				igt_debug("reached the target of %" PRIu64 " bytes\n",
-					  MB(gbl->max_filesize));
-				guc->stop_logging = true;
-			}
+		ret = _write(gbl, guc, ptr, subbuf_size);
+		if (ret > 0) {
 			pthread_mutex_lock(&guc->mutex);
 			guc->consumed++;
 			pthread_cond_signal(&guc->overflow_cond);
-- 
2.34.1

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

* [igt-dev] [PATCH i-g-t v2 05/11] tools/intel_guc_logger: Add GuC Log header structure definition
  2022-12-06  8:58 [igt-dev] [PATCH i-g-t v2 00/11] Resurrect GuC Relay Logging Alan Previn
                   ` (3 preceding siblings ...)
  2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 04/11] tools/intel_guc_logger: Add helper function for flusher code Alan Previn
@ 2022-12-06  8:58 ` Alan Previn
  2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 06/11] tools/intel_guc_logger: Concatenate log samples into a contiguous file Alan Previn
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 19+ messages in thread
From: Alan Previn @ 2022-12-06  8:58 UTC (permalink / raw)
  To: igt-dev

We need to redesign the logger to generate an output file that's formatted
as a single log buffer. It needs to continuously concatenate new GuC Log
buffer samnples provided by the kernel. To do this, the logger needs the
header structure of GuC log buffers as per the definition of the GuC
firmware.

Add this header structure that will be used in upcoming patches to extract
GuC Log debug entries.

Signed-off-by: Alan Previn <alan.previn.teres.alexis@intel.com>
---
 tools/intel_guc_logger.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/tools/intel_guc_logger.c b/tools/intel_guc_logger.c
index ce4d1bc5..fdef4622 100644
--- a/tools/intel_guc_logger.c
+++ b/tools/intel_guc_logger.c
@@ -317,6 +317,38 @@ static void pull_data(struct thread_t *tdata)
 	}
 }
 
+/**
+ * struct guc_log_buffer_state_format_2_0 - GuC log buffer state
+ * It includes snippet from i915 guc-log-relay code:
+ *
+ * Below state structure is used for describing the location of new GuC firmware
+ * log data. This includes the read_offset that points to the location where i915
+ * read last in log buffer (the last data we already wrote to file) as well as the
+ * write_offset which is incremented by GuC with the number new bytes of log data.
+ * When the log buffer becomes half full, GuC sends a flush interrupt to i915.
+ * GuC firmware expects that while it is writing to second half of the buffer,
+ * first half would get consumed by i915 and then get a flush completed
+ * acknowledgment from Host. Thus, we would expect to see the size of new incoming
+ * data being about half the size of the buffer state size member variable.
+ * If the read and write pointers are equal, it means that the buffer is full
+ */
+
+#define GUCLOGEVT_2_0_START_OFFSET      PAGE_SIZE
+
+struct guc_log_buffer_state_2_0 {
+	uint32_t marker[2]; /* we should find GUCLOG_LOGEVENTHEADER_MAGIC */
+#define GUCLOGEVT_2_0_HEADER_MAGIC_DW0 0XCABBA9E6
+#define GUCLOGEVT_2_0_HEADER_MAGIC_DW1 0XDEADFEED
+	uint32_t read_offset; /* start offset inclusive of new data */
+	uint32_t write_offset;  /* GuC in midst of writing new data, ignore this */
+	uint32_t size; /* the buffer size that driver and GuC shares */
+	uint32_t sampled_write_offset; /* end-offset exclusive of new data */
+	uint32_t wrap_offset; /* end-offset exclusive when data wraps */
+	uint32_t flags; /* GuC uses to update driver of events like overflows */
+	uint32_t version; /* we currently recognize version 2 */
+#define GUCLOGEVT_2_0_VERSION          0x0002
+};
+
 static bool file_reached_maxsize(struct global_t *gbl, struct guc_t *guc)
 {
 	if (gbl->max_filesize && MB(gbl->max_filesize) - guc->total_bytes_written <= 0)
-- 
2.34.1

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

* [igt-dev] [PATCH i-g-t v2 06/11] tools/intel_guc_logger: Concatenate log samples into a contiguous file.
  2022-12-06  8:58 [igt-dev] [PATCH i-g-t v2 00/11] Resurrect GuC Relay Logging Alan Previn
                   ` (4 preceding siblings ...)
  2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 05/11] tools/intel_guc_logger: Add GuC Log header structure definition Alan Previn
@ 2022-12-06  8:58 ` Alan Previn
  2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 07/11] tools/intel_guc_logger: Add overflow awareness Alan Previn
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 19+ messages in thread
From: Alan Previn @ 2022-12-06  8:58 UTC (permalink / raw)
  To: igt-dev

On the first log sample flushed from kernel, copy the GuC Log-events
header structure once at start of file.

With every new subbuffer flush, use the latest header's head and
tail pointers to extract only new valid data. Concatenate this
new set of debug logs into the output file.

Ensure the logger reorders content when dealing with wraparound of
the read and write pointers received log samples.

When ending, before closing the output file handle, go back to the
single header struct at start of file and update the read, write and
size offsets to make the valid buffer range take up the entire
output file contents.

Signed-off-by: Alan Previn <alan.previn.teres.alexis@intel.com>
---
 tools/intel_guc_logger.c | 179 +++++++++++++++++++++++++++++++++++----
 1 file changed, 164 insertions(+), 15 deletions(-)

diff --git a/tools/intel_guc_logger.c b/tools/intel_guc_logger.c
index fdef4622..57657e66 100644
--- a/tools/intel_guc_logger.c
+++ b/tools/intel_guc_logger.c
@@ -92,6 +92,7 @@ struct guc_t {
 	pthread_cond_t overflow_cond;
 	int64_t produced;
 	int64_t consumed;
+	bool header_stored;
 	bool stop_logging;
 	bool capturing_stopped;
 };
@@ -357,36 +358,145 @@ static bool file_reached_maxsize(struct global_t *gbl, struct guc_t *guc)
 	return false;
 }
 
+static void _write_header(struct global_t *gbl, struct guc_t *guc,
+			  struct guc_log_buffer_state_2_0 *header)
+{
+	int ret;
+	struct guc_log_buffer_state_2_0 fakecrashdump = {0};
+
+	ret = write(guc->outfd, header, sizeof(struct guc_log_buffer_state_2_0));
+	if (ret < 0) {
+		igt_warn("Header to file failed err %d, stopping!\n", -errno);
+		guc->stop_logging = true;
+	} else if (!ret) {
+		igt_debug("Header to file flushed zero bytes!\n");
+	} else {
+		/*
+		 * Offline decoding tools expect to find another header structure
+		 * describing the guc-crash-dump region before the debug-logs
+		 * lets add that here. Make sure it looks valid but empty.
+		 */
+#define GUCCRASHDUMP_2_0_HEADER_MAGIC_DW0 0XCABBA9E6
+#define GUCCRASHDUMP_2_0_HEADER_MAGIC_DW1 0x8086DEAD
+		fakecrashdump.marker[0] = GUCCRASHDUMP_2_0_HEADER_MAGIC_DW0;
+		fakecrashdump.marker[1] = GUCCRASHDUMP_2_0_HEADER_MAGIC_DW1;
+		fakecrashdump.size = KB(4);
+		fakecrashdump.wrap_offset = KB(4) - 4;
+		write(guc->outfd, &fakecrashdump, sizeof(fakecrashdump));
+
+		/*
+		 * Offline decoding tools expect to find the start of log-event
+		 * entries at GUCLOGEVT_2_0_START_OFFSET, so lets add zeros to fill
+		 * up to that point.
+		 */
+		lseek(guc->outfd, GUCLOGEVT_2_0_START_OFFSET - 1, SEEK_SET);
+		write(guc->outfd, "", 1);
+	}
+}
+
 static int _write(struct global_t *gbl, struct guc_t *guc,
-		  char *inptr, int copy_size)
+		  struct guc_log_buffer_state_2_0 *header, char *inptr, int bytes_to_copy)
 {
-	int ret = 0;
+	int ret = 0, max_copy_size = 0;
 
-	ret = write(guc->outfd, inptr, copy_size);
+	max_copy_size = header->size - header->read_offset;
+	if (bytes_to_copy > max_copy_size) {
+		igt_warn("Copy data size (%d) larger than max_copy_size (%d) so clip!\n",
+			 bytes_to_copy, max_copy_size);
+		bytes_to_copy = max_copy_size;
+	}
+	ret = write(guc->outfd, inptr + header->read_offset, bytes_to_copy);
 	if (ret < 0) {
-		igt_warn("Copy to file failed with err %d, stopping!\n", ret);
+		igt_warn("Copy to file failed with err %d, stopping!\n", -errno);
 		guc->stop_logging = true;
 	} else if (!ret) {
 		igt_warn("Copy to file flushed zero bytes!\n");
 	} else {
-		if (ret != copy_size)
-			igt_warn("File write size err: ask = %d, copied = %d!\n",
-				 copy_size, ret);
-		guc->total_bytes_written += ret;
-		igt_info("wrote %d KB out to dat file\n", (ret / 1024));
+		if (ret != bytes_to_copy)
+			igt_warn("File write size warn: ask = %d, copied = %d!\n",
+				 bytes_to_copy, ret);
+	}
+	return ret;
+}
+
+static bool write_extracted_data(struct global_t *gbl, struct guc_t *guc,
+				 char *inptr, int subbuf_size)
+{
+	struct guc_log_buffer_state_2_0 header = {0};
+	int bytes_to_copy = 0, copied = 0, ret = 0, tmp;
+	bool first_header = !guc->header_stored;
+
+	memcpy(&header, inptr, sizeof(header));
+
+	/* verify we have a valid header info */
+	if (header.marker[0] != GUCLOGEVT_2_0_HEADER_MAGIC_DW0 ||
+	    header.marker[1] != GUCLOGEVT_2_0_HEADER_MAGIC_DW1) {
+		igt_warn("Can't find GuC log buffer header magic, skip to next channel.\n");
+		return true;
+	} else if (header.version != GUCLOGEVT_2_0_VERSION) {
+		igt_warn("Mismatch on GuC log buffer header version 0x%08x, ignoring.\n",
+			 header.version);
+	}
+
+	inptr += GUCLOGEVT_2_0_START_OFFSET;
+
+	/*
+	 * If we just begun relay logging, copy the header just once, else
+	 * copy only the new data from relay subbuf but ensure the output
+	 * file contens is populated in a contiguous stream
+	 */
+	if (!guc->header_stored) {
+		_write_header(gbl, guc, &header);
+		if (guc->stop_logging) {
+			igt_warn("Bailing from failed header-write!\n");
+			return false;
+		}
+		guc->header_stored = true;
+	}
+
+	/* In case of wrap-around, copy data in chronological order, i.e. spatial end first*/
+	if (header.read_offset > header.sampled_write_offset) {
+		tmp = header.wrap_offset ? : header.size;
+		bytes_to_copy = tmp - header.read_offset;
+		ret = _write(gbl, guc, &header, inptr + header.read_offset, bytes_to_copy);
+		if (ret > 0)
+			copied = ret;
+		header.read_offset = 0;
+	}
+
+	/* Now copy the rest after wraparound or non-wraparound content from head */
+	if (ret >= 0) {
+		bytes_to_copy = header.sampled_write_offset - header.read_offset;
+		if (bytes_to_copy) {
+			ret = _write(gbl, guc, &header, inptr + header.read_offset, bytes_to_copy);
+			if (ret > 0)
+				copied += ret;
+		}
+	}
+
+	if (copied || first_header) {
+		guc->total_bytes_written += copied;
+		if (first_header)
+			igt_info("first parse found %d KB of data\n", (copied / 1024));
+		else
+			igt_info("wrote %d KB out to dat file\n", (copied / 1024));
 		if (file_reached_maxsize(gbl, guc)) {
 			igt_info("Reached target filesize of %" PRIu64 " bytes\n",
 				 MB(gbl->max_filesize));
 			guc->stop_logging = true;
 		}
+		return true;
 	}
-	return ret;
+	if (ret < 0)
+		guc->stop_logging = true;
+
+	return false;
 }
 
 static void *flusher(void *arg)
 {
 	char *ptr;
-	int ret, subbuf_size;
+	int subbuf_size;
 	struct thread_t *tdata = (struct thread_t *)arg;
 	struct global_t *gbl;
 	struct guc_t *guc;
@@ -416,9 +526,7 @@ static void *flusher(void *arg)
 		pthread_mutex_unlock(&guc->mutex);
 
 		ptr = guc->readbuf + (guc->consumed % guc->subbuf_count) * subbuf_size;
-
-		ret = _write(gbl, guc, ptr, subbuf_size);
-		if (ret > 0) {
+		if (write_extracted_data(gbl, guc, ptr, subbuf_size)) {
 			pthread_mutex_lock(&guc->mutex);
 			guc->consumed++;
 			pthread_cond_signal(&guc->overflow_cond);
@@ -503,13 +611,53 @@ static void open_output_file(struct thread_t *tdata)
 					tdata->guc->gt_id), -1);
 	}
 
-	tdata->guc->outfd = open(path, O_CREAT | O_WRONLY | O_TRUNC | O_DIRECT, 0440);
+	tdata->guc->outfd = open(path, O_CREAT | O_RDWR | O_TRUNC, 0440);
 	igt_assert_f(tdata->guc->outfd >= 0, "couldn't open the output file\n");
 
 	igt_info("Creating output GuC-log-file: %s\n", path);
 	free(path);
 }
 
+static void update_outfile_header(struct thread_t *tdata)
+{
+	struct guc_t *guc = tdata->guc;
+	struct guc_log_buffer_state_2_0 tmphdr = {0};
+
+	if (guc->outfd > 0 && guc->consumed && guc->total_bytes_written) {
+		/*
+		 * Offline decoder tool expects the 4KB crash dump buffer after
+		 * the debug-log-events we've been writing. Create an empty one.
+		 */
+		lseek(guc->outfd, KB(4) - 1, SEEK_CUR);
+		write(guc->outfd, "", 1);
+
+		/*
+		 * Go back to top of the file and update the debug-log-events
+		 * header structure with new head + tail ptrs and size so the
+		 * file appears as a gigantic log buffer as it were in mem.
+		 */
+		if (lseek(guc->outfd, 0, SEEK_SET) == 0) {
+			read(guc->outfd, &tmphdr, sizeof(tmphdr));
+
+			tmphdr.size = guc->total_bytes_written;
+			tmphdr.read_offset = 0;
+			tmphdr.sampled_write_offset = guc->total_bytes_written;
+			tmphdr.write_offset = guc->total_bytes_written;
+			tmphdr.wrap_offset = guc->total_bytes_written;
+
+			if (lseek(guc->outfd, 0, SEEK_SET) == 0)
+				write(guc->outfd, &tmphdr, sizeof(tmphdr));
+		} else {
+			igt_warn("Failed seek for header (errno=%d) on GT-%d after %ldKB\n",
+				 guc->gt_id, errno, (guc->total_bytes_written / 1024));
+		}
+
+	} else {
+		igt_debug("Skip final header: GT-%d, consume-subbufs-%ld, wrote-bytes-%ld\n",
+			  guc->gt_id, guc->consumed, guc->total_bytes_written);
+	}
+}
+
 static void init_main_thread(struct thread_t *tdata)
 {
 	struct sched_param thread_sched;
@@ -723,6 +871,7 @@ int main(int argc, char **argv)
 	pthread_cond_signal(&thread[0].guc->underflow_cond);
 	pthread_join(thread[0].guc->flush_thread, NULL);
 	pull_leftover_data(&thread[0]);
+	update_outfile_header(&thread[0]);
 	igt_info("total bytes written %" PRIu64 "\n", thread[0].guc->total_bytes_written);
 
 	if (gucdata[0].outfd)
-- 
2.34.1

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

* [igt-dev] [PATCH i-g-t v2 07/11] tools/intel_guc_logger: Add overflow awareness.
  2022-12-06  8:58 [igt-dev] [PATCH i-g-t v2 00/11] Resurrect GuC Relay Logging Alan Previn
                   ` (5 preceding siblings ...)
  2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 06/11] tools/intel_guc_logger: Concatenate log samples into a contiguous file Alan Previn
@ 2022-12-06  8:58 ` Alan Previn
  2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 08/11] tools/intel_guc_logger: Limit relay logging output file to 4GB Alan Previn
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 19+ messages in thread
From: Alan Previn @ 2022-12-06  8:58 UTC (permalink / raw)
  To: igt-dev

Update header structure definition and make logger
aware of the fw overflow flag so that it can warn the
end user of possible decode issue at that point in the
file. Also, copy the entire buffer irrespective of the
head and tail ptrs when overflow occurs.

Signed-off-by: Alan Previn <alan.previn.teres.alexis@intel.com>
---
 tools/intel_guc_logger.c | 30 +++++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/tools/intel_guc_logger.c b/tools/intel_guc_logger.c
index 57657e66..38c50598 100644
--- a/tools/intel_guc_logger.c
+++ b/tools/intel_guc_logger.c
@@ -95,6 +95,7 @@ struct guc_t {
 	bool header_stored;
 	bool stop_logging;
 	bool capturing_stopped;
+	uint32_t fw_overflows;
 };
 
 struct global_t {
@@ -345,7 +346,15 @@ struct guc_log_buffer_state_2_0 {
 	uint32_t size; /* the buffer size that driver and GuC shares */
 	uint32_t sampled_write_offset; /* end-offset exclusive of new data */
 	uint32_t wrap_offset; /* end-offset exclusive when data wraps */
-	uint32_t flags; /* GuC uses to update driver of events like overflows */
+	union {
+		/* GuC uses to update driver of events like overflows */
+		struct {
+			uint32_t midflushing:1;
+			uint32_t overflow_count:4;
+			uint32_t reserved:27;
+		};
+		uint32_t flags;
+	};
 	uint32_t version; /* we currently recognize version 2 */
 #define GUCLOGEVT_2_0_VERSION          0x0002
 };
@@ -425,6 +434,7 @@ static bool write_extracted_data(struct global_t *gbl, struct guc_t *guc,
 	struct guc_log_buffer_state_2_0 header = {0};
 	int bytes_to_copy = 0, copied = 0, ret = 0, tmp;
 	bool first_header = !guc->header_stored;
+	bool is_overflowing = false;
 
 	memcpy(&header, inptr, sizeof(header));
 
@@ -440,6 +450,17 @@ static bool write_extracted_data(struct global_t *gbl, struct guc_t *guc,
 
 	inptr += GUCLOGEVT_2_0_START_OFFSET;
 
+	if (guc->fw_overflows == 0xFFFFFFFF) {
+		guc->fw_overflows = header.overflow_count;
+	} else if (header.overflow_count != (guc->fw_overflows & 0x000F)) {
+		if (header.overflow_count < (guc->fw_overflows & 0x000F))
+			guc->fw_overflows += 16;
+		guc->fw_overflows = (guc->fw_overflows & ~0x000F) + header.overflow_count;
+		is_overflowing = true;
+		igt_info("GuC FW Log Overflow #%d - possible decode kaput after offset %ld\n",
+			 guc->fw_overflows, guc->consumed);
+	}
+
 	/*
 	 * If we just begun relay logging, copy the header just once, else
 	 * copy only the new data from relay subbuf but ensure the output
@@ -454,6 +475,12 @@ static bool write_extracted_data(struct global_t *gbl, struct guc_t *guc,
 		guc->header_stored = true;
 	}
 
+	/* head == tail means we are empty unless overflowing, else augment ptrs for full copy*/
+	if (is_overflowing) {
+		header.read_offset = 0;
+		header.sampled_write_offset = header.wrap_offset ? : header.size;
+	}
+
 	/* In case of wrap-around, copy data in chronological order, i.e. spatial end first*/
 	if (header.read_offset > header.sampled_write_offset) {
 		tmp = header.wrap_offset ? : header.size;
@@ -794,6 +821,7 @@ int main(int argc, char **argv)
 
 	memset(&gucdata[0], 0, sizeof(struct guc_t));
 	gucdata[0].gt_id = 0;
+	gucdata[0].fw_overflows = 0xFFFFFFFF;
 	igt_assert_neq(asprintf(&gucdata[0].fspath, "gt/uc"), -1);
 	gucdata[0].outfd = -1;
 
-- 
2.34.1

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

* [igt-dev] [PATCH i-g-t v2 08/11] tools/intel_guc_logger: Limit relay logging output file to 4GB.
  2022-12-06  8:58 [igt-dev] [PATCH i-g-t v2 00/11] Resurrect GuC Relay Logging Alan Previn
                   ` (6 preceding siblings ...)
  2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 07/11] tools/intel_guc_logger: Add overflow awareness Alan Previn
@ 2022-12-06  8:58 ` Alan Previn
  2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 09/11] tools/intel_guc_logger: By default don't change GuC log verbosity Alan Previn
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 19+ messages in thread
From: Alan Previn @ 2022-12-06  8:58 UTC (permalink / raw)
  To: igt-dev

Because the GuC Log buffer header structure has a buffer-size
data type of 32 bits, let's make the output file size limit
a total of 4GB.

Signed-off-by: Alan Previn <alan.previn.teres.alexis@intel.com>
---
 tools/intel_guc_logger.c | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/tools/intel_guc_logger.c b/tools/intel_guc_logger.c
index 38c50598..be09190c 100644
--- a/tools/intel_guc_logger.c
+++ b/tools/intel_guc_logger.c
@@ -68,7 +68,7 @@
 					 *  64K -> log events buffer     *
 					 */
 #define DEFAULT_POLL_TIMEOUT         2 /* default timeout of 2ms */
-#define DEFAULT_MAX_OUTPUT_SIZE      MB(4 * 1024) /* default to 4 GB max file size */
+#define DEFAULT_MAX_OUTPUT_SIZE_MB   (4 * 1024) /* default to 4 GB max file size */
 
 enum relay_cmd {
 	RELAY_CMD_DISABLE = 0,
@@ -104,7 +104,7 @@ struct global_t {
 	uint32_t usr_gt_id;
 	uint32_t avail_guc_mask;
 	char *out_filename;
-	uint64_t max_filesize;
+	long long max_filesize;
 	uint32_t test_duration;
 	int poll_timeout;
 	bool discard_oldlogs;
@@ -361,7 +361,7 @@ struct guc_log_buffer_state_2_0 {
 
 static bool file_reached_maxsize(struct global_t *gbl, struct guc_t *guc)
 {
-	if (gbl->max_filesize && MB(gbl->max_filesize) - guc->total_bytes_written <= 0)
+	if (gbl->max_filesize && (gbl->max_filesize - guc->total_bytes_written <= 0))
 		return true;
 
 	return false;
@@ -508,8 +508,7 @@ static bool write_extracted_data(struct global_t *gbl, struct guc_t *guc,
 		else
 			igt_info("wrote %d KB out to dat file\n", (copied / 1024));
 		if (file_reached_maxsize(gbl, guc)) {
-			igt_info("Reached target filesize of %" PRIu64 " bytes\n",
-				 MB(gbl->max_filesize));
+			igt_info("Reached target filesize of %lld bytes\n", gbl->max_filesize);
 			guc->stop_logging = true;
 		}
 		return true;
@@ -757,7 +756,10 @@ static int parse_options(int opt, int opt_index, void *ptr)
 	case 's':
 		data->max_filesize = atoll(optarg);
 		igt_assert_f(data->max_filesize > 0, "invalid input for -s option\n");
-		igt_debug("max allowed size of the output file is %lu MB\n", data->max_filesize);
+		if (data->max_filesize >= DEFAULT_MAX_OUTPUT_SIZE_MB)
+			data->max_filesize = DEFAULT_MAX_OUTPUT_SIZE_MB;
+		igt_debug("max allowed size of the output file is %lld MB\n", data->max_filesize);
+		data->max_filesize *= MB(1);
 		break;
 	case 'd':
 		data->discard_oldlogs = true;
@@ -794,7 +796,7 @@ static void process_command_line(int argc, char **argv, struct global_t *data)
 		"  -o --outputfile=name   name of the output file, including the location, where logs will be stored\n"
 		"  -t --testduration=sec  max duration in seconds for which the logger should run\n"
 		"  -p --polltimeout=ms    polling timeout in ms, -1 == indefinite wait for the new data\n"
-		"  -s --size=MB           max size of output file in MBs after which logging will be stopped\n"
+		"  -s --size=MB           max size of output file in MBs after which logging stops, default is 4GB\n"
 		"  -d --discard           discard the old/boot-time logs before entering into the capture loop\n"
 		"  -i --gt_id             GT-ID of GuC to capture from, defaults to capture from gt0\n";
 
@@ -816,6 +818,7 @@ int main(int argc, char **argv)
 	gbldata.verbosity    = DEFAULT_GUCLOG_VERBOSITY;
 	gbldata.usr_gt_id    = DEFAULT_GT_ID;
 	gbldata.poll_timeout = DEFAULT_POLL_TIMEOUT;
+	gbldata.max_filesize = DEFAULT_MAX_OUTPUT_SIZE_MB * MB(1);
 	gbldata.drmfd        = drm_open_driver_render(DRIVER_INTEL);
 	igt_assert(gbldata.drmfd != -1);
 
-- 
2.34.1

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

* [igt-dev] [PATCH i-g-t v2 09/11] tools/intel_guc_logger: By default don't change GuC log verbosity
  2022-12-06  8:58 [igt-dev] [PATCH i-g-t v2 00/11] Resurrect GuC Relay Logging Alan Previn
                   ` (7 preceding siblings ...)
  2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 08/11] tools/intel_guc_logger: Limit relay logging output file to 4GB Alan Previn
@ 2022-12-06  8:58 ` Alan Previn
  2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 10/11] tools/intel_guc_logger: On exit, save any leftover GuC log data Alan Previn
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 19+ messages in thread
From: Alan Previn @ 2022-12-06  8:58 UTC (permalink / raw)
  To: igt-dev

By default, don't change the verbosity if the user hasn't explicitly
requested to change it. Also, don't allow users to set the GuC log
verbosity to level of 0 (i.e. disabled) else the logger will not
receive any data.

Also, fix a bug where we set the verbosity at the end of logging
to zero. Instead, save the original GuC log verbosity when we start
the logger and then restore that value.

Signed-off-by: Alan Previn <alan.previn.teres.alexis@intel.com>
---
 tools/intel_guc_logger.c | 33 +++++++++++++++++++++++----------
 1 file changed, 23 insertions(+), 10 deletions(-)

diff --git a/tools/intel_guc_logger.c b/tools/intel_guc_logger.c
index be09190c..7243ad43 100644
--- a/tools/intel_guc_logger.c
+++ b/tools/intel_guc_logger.c
@@ -56,7 +56,7 @@
 #define GLR_CHANNEL_NAME             "guc_log_relay_chan0"
 
 #define DEFAULT_OUTPUT_FILE_NAME     "guc_log_dump" /*.dat suffic added later*/
-#define DEFAULT_GUCLOG_VERBOSITY     3 /* by default capture logs at max verbosity */
+#define DEFAULT_GUCLOG_VERBOSITY     0 /* by default don't change GuC verbosity */
 #define DEFAULT_SUBBUF_COUNT         (4 * 8)
 					/* default to kernel built-in:   *
 					 *   4 x 8 subbuf regions        *
@@ -96,6 +96,7 @@ struct guc_t {
 	bool stop_logging;
 	bool capturing_stopped;
 	uint32_t fw_overflows;
+	uint64_t ori_loglevel;
 };
 
 struct global_t {
@@ -167,17 +168,18 @@ static void guc_log_verbosity(struct thread_t *tdata, bool enable)
 	char *str;
 	int loglevelfd;
 	uint64_t val;
+	char outstr[128];
 	int ret;
 
 	igt_assert_neq(asprintf(&str, "%s/%s", tdata->guc->fspath, GLR_LOGLEVEL_NAME), -1);
 	igt_info("Opening log level -> %s\n", str);
-	loglevelfd = igt_debugfs_open(tdata->global->drmfd, str, O_WRONLY);
+	loglevelfd = igt_debugfs_open(tdata->global->drmfd, str, O_RDWR);
 	free(str);
 	igt_assert_f(loglevelfd >= 0, "couldn't open the GuC log level file\n");
 
 	/*
 	 * i915 expects GuC log level to be specified as:
-	 * 0: disabled
+	 * 0: [dont modify verbosity]
 	 * 1: enabled (non-verbose mode)
 	 * 2: GuC verbosity level 0
 	 * 3: GuC verbosity level 1
@@ -185,13 +187,24 @@ static void guc_log_verbosity(struct thread_t *tdata, bool enable)
 	 * 5: GuC verbosity level 3
 	 * intel_guc_logger takes input range of 0..3 that maps to 2..5 above.
 	 */
-	val = enable ? tdata->global->verbosity + 2 : 0;
-	ret = asprintf(&str, "0x%" PRIx64, val);
-	igt_assert_neq(ret, -1);
-	ret = write(loglevelfd, str, ret);
-	free(str);
-	igt_assert_f(ret > 0, "couldn't write verbosity to log level file\n");
-	igt_info("Set GuC log level = %d\n", (int)val);
+	if (enable) {
+		ret = read(loglevelfd, outstr, sizeof(outstr) - 1);
+		igt_assert(ret > 0);
+		outstr[ret] = '\0';
+		tdata->guc->ori_loglevel = atoll(outstr);
+		igt_info("Current GuC log level = %d\n",
+			 (int)tdata->guc->ori_loglevel);
+	}
+	/* Treat the lowest verbosity level as no change to verbosity  */
+	if (tdata->global->verbosity) {
+		val = enable ? tdata->global->verbosity + 2 : tdata->guc->ori_loglevel;
+		ret = asprintf(&str, "0x%" PRIx64, val);
+		igt_assert_neq(ret, -1);
+		ret = write(loglevelfd, str, ret);
+		free(str);
+		igt_assert_f(ret > 0, "couldn't write verbosity to log level file\n");
+		igt_info("Setting GuC log level = %d\n", (int)val);
+	}
 
 	close(loglevelfd);
 }
-- 
2.34.1

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

* [igt-dev] [PATCH i-g-t v2 10/11] tools/intel_guc_logger: On exit, save any leftover GuC log data
  2022-12-06  8:58 [igt-dev] [PATCH i-g-t v2 00/11] Resurrect GuC Relay Logging Alan Previn
                   ` (8 preceding siblings ...)
  2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 09/11] tools/intel_guc_logger: By default don't change GuC log verbosity Alan Previn
@ 2022-12-06  8:58 ` Alan Previn
  2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 11/11] tools/intel_guc_logger: Add useful debug messages Alan Previn
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 19+ messages in thread
From: Alan Previn @ 2022-12-06  8:58 UTC (permalink / raw)
  To: igt-dev

On exit, trigger the kernel, via debugfs, to flush any leftover GuC
log data so we can receive and save that into the end of the
output file using existing helper function.

Signed-off-by: Alan Previn <alan.previn.teres.alexis@intel.com>
---
 tools/intel_guc_logger.c | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/tools/intel_guc_logger.c b/tools/intel_guc_logger.c
index 7243ad43..8bea2b4b 100644
--- a/tools/intel_guc_logger.c
+++ b/tools/intel_guc_logger.c
@@ -224,7 +224,7 @@ static void guc_log_control(struct thread_t *tdata, enum relay_cmd cmd)
 		igt_assert_f(tdata->guc->control_fd >= 0, "Can't open GuC log relay-ctl file\n");
 	}
 
-	if (tdata->guc->control_fd) {
+	if (tdata->guc->control_fd && cmd > RELAY_CMD_DISABLE) {
 		ret = asprintf(&str, "0x%" PRIx64, (unsigned long)cmd);
 		igt_assert_neq(ret, -1);
 		ret = write(tdata->guc->control_fd, str, ret);
@@ -254,7 +254,10 @@ static void int_sig_handler(int sig)
 		gbl_thread_handle[0].guc->stop_logging = true;
 }
 
-static void pull_leftover_data(struct thread_t *tdata)
+static bool write_extracted_data(struct global_t *gbl, struct guc_t *guc,
+				 char *inptr, int subbuf_size);
+
+static void pull_leftover_data(struct thread_t *tdata, bool save_it)
 {
 	struct guc_t *guc = tdata->guc;
 	unsigned int bytes_read = 0;
@@ -275,12 +278,8 @@ static void pull_leftover_data(struct thread_t *tdata)
 			igt_warn("invalid leftover-size from GuC GT-%d relay-channel\n",
 				 guc->gt_id);
 		bytes_read += ret;
-		if (guc->outfd >= 0) {
-			ret = write(guc->outfd, guc->readbuf, subbuf_size);
-			if (ret != subbuf_size)
-				igt_warn("Couldn't dump leftover logs to file\n");
-			guc->total_bytes_written += ret;
-		}
+		if (guc->outfd >= 0 && save_it)
+			write_extracted_data(tdata->global, guc, guc->readbuf, subbuf_size);
 	} while(1);
 
 	igt_debug("%u bytes flushed from GuC GT-%d\n", bytes_read, guc->gt_id);
@@ -629,7 +628,7 @@ static void open_relay_file(struct thread_t *tdata)
 	 * a different shell.
 	 */
 	if (tdata->global->discard_oldlogs)
-		pull_leftover_data(tdata);
+		pull_leftover_data(tdata, false);
 }
 
 static void open_output_file(struct thread_t *tdata)
@@ -914,7 +913,7 @@ int main(int argc, char **argv)
 	thread[0].guc->capturing_stopped = 1;
 	pthread_cond_signal(&thread[0].guc->underflow_cond);
 	pthread_join(thread[0].guc->flush_thread, NULL);
-	pull_leftover_data(&thread[0]);
+	pull_leftover_data(&thread[0], true);
 	update_outfile_header(&thread[0]);
 	igt_info("total bytes written %" PRIu64 "\n", thread[0].guc->total_bytes_written);
 
-- 
2.34.1

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

* [igt-dev] [PATCH i-g-t v2 11/11] tools/intel_guc_logger: Add useful debug messages
  2022-12-06  8:58 [igt-dev] [PATCH i-g-t v2 00/11] Resurrect GuC Relay Logging Alan Previn
                   ` (9 preceding siblings ...)
  2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 10/11] tools/intel_guc_logger: On exit, save any leftover GuC log data Alan Previn
@ 2022-12-06  8:58 ` Alan Previn
  2022-12-06  9:41 ` [igt-dev] ✓ Fi.CI.BAT: success for Resurrect GuC Relay Logging (rev2) Patchwork
  2022-12-06 11:27 ` [igt-dev] ✓ Fi.CI.IGT: " Patchwork
  12 siblings, 0 replies; 19+ messages in thread
From: Alan Previn @ 2022-12-06  8:58 UTC (permalink / raw)
  To: igt-dev

Add useful debug messages for verbose logging progress so that
errors or warnings are not lost while capturing data.

Signed-off-by: Alan Previn <alan.previn.teres.alexis@intel.com>
---
 tools/intel_guc_logger.c | 33 ++++++++++++++++++++++++++++++++-
 1 file changed, 32 insertions(+), 1 deletion(-)

diff --git a/tools/intel_guc_logger.c b/tools/intel_guc_logger.c
index 8bea2b4b..008bee50 100644
--- a/tools/intel_guc_logger.c
+++ b/tools/intel_guc_logger.c
@@ -450,6 +450,16 @@ static bool write_extracted_data(struct global_t *gbl, struct guc_t *guc,
 
 	memcpy(&header, inptr, sizeof(header));
 
+	igt_debug("header->marker[0] = 0x%08x\n", header.marker[0]);
+	igt_debug("header->marker[1] = 0x%08x\n", header.marker[1]);
+	igt_debug("header->read_offset = 0x%08x\n", header.read_offset);
+	igt_debug("header->write_offset = 0x%08x\n", header.write_offset);
+	igt_debug("header->size = 0x%08x\n", header.size);
+	igt_debug("header->sampled_write_offset = 0x%08x\n", header.sampled_write_offset);
+	igt_debug("header->wrap_offset = 0x%08x\n", header.wrap_offset);
+	igt_debug("header->flags = 0x%08x\n", header.flags);
+	igt_debug("header->counts = 0x%08x\n", header.version);
+
 	/* verify we have a valid header info */
 	if (header.marker[0] != GUCLOGEVT_2_0_HEADER_MAGIC_DW0 ||
 	    header.marker[1] != GUCLOGEVT_2_0_HEADER_MAGIC_DW1) {
@@ -555,14 +565,16 @@ static void *flusher(void *arg)
 			 * the disk file.
 			 */
 			if (guc->capturing_stopped) {
-				igt_debug("flusher to exit now\n");
+				igt_debug("Write-flush exiting\n");
 				pthread_mutex_unlock(&guc->mutex);
 				return NULL;
 			}
+			igt_debug("Write-flush waiting\n");
 			pthread_cond_wait(&guc->underflow_cond, &guc->mutex);
 		};
 		pthread_mutex_unlock(&guc->mutex);
 
+		igt_debug("Write-flush extracting\n");
 		ptr = guc->readbuf + (guc->consumed % guc->subbuf_count) * subbuf_size;
 		if (write_extracted_data(gbl, guc, ptr, subbuf_size)) {
 			pthread_mutex_lock(&guc->mutex);
@@ -669,6 +681,8 @@ static void update_outfile_header(struct thread_t *tdata)
 		lseek(guc->outfd, KB(4) - 1, SEEK_CUR);
 		write(guc->outfd, "", 1);
 
+		igt_debug("Finalizing header data of GT-%d to buffer-size = %ld\n",
+			  guc->gt_id, guc->total_bytes_written);
 		/*
 		 * Go back to top of the file and update the debug-log-events
 		 * header structure with new head + tail ptrs and size so the
@@ -683,6 +697,17 @@ static void update_outfile_header(struct thread_t *tdata)
 			tmphdr.write_offset = guc->total_bytes_written;
 			tmphdr.wrap_offset = guc->total_bytes_written;
 
+			igt_debug("Final header->marker[0] = 0x%08x\n", tmphdr.marker[0]);
+			igt_debug("Final header->marker[1] = 0x%08x\n", tmphdr.marker[1]);
+			igt_debug("Final header->read_offset = 0x%08x\n", tmphdr.read_offset);
+			igt_debug("Final header->write_offset = 0x%08x\n", tmphdr.write_offset);
+			igt_debug("Final header->size = 0x%08x\n", tmphdr.size);
+			igt_debug("Final header->sampled_write_offset = 0x%08x\n",
+				  tmphdr.sampled_write_offset);
+			igt_debug("Final header->wrap_offset = 0x%08x\n", tmphdr.wrap_offset);
+			igt_debug("Final header->flags = 0x%08x\n", tmphdr.flags);
+			igt_debug("Final header->counts = 0x%08x\n", tmphdr.version);
+
 			if (lseek(guc->outfd, 0, SEEK_SET) == 0)
 				write(guc->outfd, &tmphdr, sizeof(tmphdr));
 		} else {
@@ -824,6 +849,7 @@ int main(int argc, char **argv)
 	struct thread_t thread[1];
 	struct pollfd relay_poll_fd;
 	int nfds, ret;
+	int poll_msg_count = 0;
 
 	/* setup global context */
 	memset(&gbldata, 0, sizeof(gbldata));
@@ -891,6 +917,8 @@ int main(int argc, char **argv)
 		 * succession (less than a jiffy gap between 2 flush interrupts)
 		 * causing relay to run out of sub buffers to store new logs.
 		 */
+		if (++poll_msg_count % 200 == 0)
+			igt_debug("Read-pull waited %d\n", poll_msg_count);
 		ret = poll(&relay_poll_fd, nfds, gbldata.poll_timeout);
 		if (ret < 0) {
 			if (errno == EINTR)
@@ -902,8 +930,11 @@ int main(int argc, char **argv)
 		if (!relay_poll_fd.revents)
 			continue;
 
+		igt_debug("Read-pull copying data after %d polls\n", poll_msg_count);
+		poll_msg_count = 0;
 		pull_data(&thread[0]);
 	} while (!thread[0].guc->stop_logging);
+	igt_debug("Read-pull exiting\n");
 
 	/* Pause logging on the GuC side */
 	guc_log_control(&thread[0], RELAY_CMD_FLUSH);
-- 
2.34.1

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

* [igt-dev] ✓ Fi.CI.BAT: success for Resurrect GuC Relay Logging (rev2)
  2022-12-06  8:58 [igt-dev] [PATCH i-g-t v2 00/11] Resurrect GuC Relay Logging Alan Previn
                   ` (10 preceding siblings ...)
  2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 11/11] tools/intel_guc_logger: Add useful debug messages Alan Previn
@ 2022-12-06  9:41 ` Patchwork
  2022-12-06 11:27 ` [igt-dev] ✓ Fi.CI.IGT: " Patchwork
  12 siblings, 0 replies; 19+ messages in thread
From: Patchwork @ 2022-12-06  9:41 UTC (permalink / raw)
  To: Alan Previn; +Cc: igt-dev

[-- Attachment #1: Type: text/plain, Size: 5343 bytes --]

== Series Details ==

Series: Resurrect GuC Relay Logging (rev2)
URL   : https://patchwork.freedesktop.org/series/103768/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_12471 -> IGTPW_8201
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

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

Participating hosts (44 -> 43)
------------------------------

  Additional (1): fi-hsw-4770 
  Missing    (2): fi-tgl-dsi fi-apl-guc 

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

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

### IGT changes ###

#### Issues hit ####

  * igt@gem_softpin@allocator-basic-reserve:
    - fi-hsw-4770:        NOTRUN -> [SKIP][1] ([fdo#109271]) +11 similar issues
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/fi-hsw-4770/igt@gem_softpin@allocator-basic-reserve.html

  * igt@i915_selftest@live@hangcheck:
    - fi-hsw-4770:        NOTRUN -> [INCOMPLETE][2] ([i915#4785])
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/fi-hsw-4770/igt@i915_selftest@live@hangcheck.html
    - fi-ivb-3770:        [PASS][3] -> [INCOMPLETE][4] ([i915#3303] / [i915#7122])
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12471/fi-ivb-3770/igt@i915_selftest@live@hangcheck.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/fi-ivb-3770/igt@i915_selftest@live@hangcheck.html

  * igt@kms_chamelium@dp-crc-fast:
    - fi-hsw-4770:        NOTRUN -> [SKIP][5] ([fdo#109271] / [fdo#111827]) +7 similar issues
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/fi-hsw-4770/igt@kms_chamelium@dp-crc-fast.html

  * igt@kms_cursor_legacy@basic-busy-flip-before-cursor@atomic-transitions-varying-size:
    - fi-bsw-kefka:       [PASS][6] -> [FAIL][7] ([i915#6298])
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12471/fi-bsw-kefka/igt@kms_cursor_legacy@basic-busy-flip-before-cursor@atomic-transitions-varying-size.html
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/fi-bsw-kefka/igt@kms_cursor_legacy@basic-busy-flip-before-cursor@atomic-transitions-varying-size.html

  * igt@kms_pipe_crc_basic@suspend-read-crc@pipe-c-dp-2:
    - fi-icl-u2:          [PASS][8] -> [DMESG-WARN][9] ([i915#2867])
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12471/fi-icl-u2/igt@kms_pipe_crc_basic@suspend-read-crc@pipe-c-dp-2.html
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/fi-icl-u2/igt@kms_pipe_crc_basic@suspend-read-crc@pipe-c-dp-2.html

  * igt@kms_psr@sprite_plane_onoff:
    - fi-hsw-4770:        NOTRUN -> [SKIP][10] ([fdo#109271] / [i915#1072]) +3 similar issues
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/fi-hsw-4770/igt@kms_psr@sprite_plane_onoff.html

  * igt@runner@aborted:
    - fi-hsw-4770:        NOTRUN -> [FAIL][11] ([fdo#109271] / [i915#4312] / [i915#5594])
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/fi-hsw-4770/igt@runner@aborted.html
    - fi-ivb-3770:        NOTRUN -> [FAIL][12] ([fdo#109271] / [i915#4312])
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/fi-ivb-3770/igt@runner@aborted.html

  
#### Possible fixes ####

  * igt@gem_exec_suspend@basic-s0@smem:
    - {bat-rplp-1}:       [DMESG-WARN][13] ([i915#2867]) -> [PASS][14] +1 similar issue
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12471/bat-rplp-1/igt@gem_exec_suspend@basic-s0@smem.html
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/bat-rplp-1/igt@gem_exec_suspend@basic-s0@smem.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [fdo#111827]: https://bugs.freedesktop.org/show_bug.cgi?id=111827
  [i915#1072]: https://gitlab.freedesktop.org/drm/intel/issues/1072
  [i915#2867]: https://gitlab.freedesktop.org/drm/intel/issues/2867
  [i915#3303]: https://gitlab.freedesktop.org/drm/intel/issues/3303
  [i915#4312]: https://gitlab.freedesktop.org/drm/intel/issues/4312
  [i915#4785]: https://gitlab.freedesktop.org/drm/intel/issues/4785
  [i915#4983]: https://gitlab.freedesktop.org/drm/intel/issues/4983
  [i915#5594]: https://gitlab.freedesktop.org/drm/intel/issues/5594
  [i915#6257]: https://gitlab.freedesktop.org/drm/intel/issues/6257
  [i915#6298]: https://gitlab.freedesktop.org/drm/intel/issues/6298
  [i915#6434]: https://gitlab.freedesktop.org/drm/intel/issues/6434
  [i915#7122]: https://gitlab.freedesktop.org/drm/intel/issues/7122
  [i915#7346]: https://gitlab.freedesktop.org/drm/intel/issues/7346


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

  * CI: CI-20190529 -> None
  * IGT: IGT_7083 -> IGTPW_8201

  CI-20190529: 20190529
  CI_DRM_12471: 7f8dc69dce0e934751fe31c01a6b6baa0c65bf23 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGTPW_8201: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/index.html
  IGT_7083: c001793d5f22deb01918b6ba52af829794582df1 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git


Testlist changes
----------------

+igt@drm_import_export@flink
+igt@drm_import_export@import-close-race-flink
+igt@drm_import_export@import-close-race-prime
+igt@drm_import_export@prime

== Logs ==

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

[-- Attachment #2: Type: text/html, Size: 6310 bytes --]

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

* [igt-dev] ✓ Fi.CI.IGT: success for Resurrect GuC Relay Logging (rev2)
  2022-12-06  8:58 [igt-dev] [PATCH i-g-t v2 00/11] Resurrect GuC Relay Logging Alan Previn
                   ` (11 preceding siblings ...)
  2022-12-06  9:41 ` [igt-dev] ✓ Fi.CI.BAT: success for Resurrect GuC Relay Logging (rev2) Patchwork
@ 2022-12-06 11:27 ` Patchwork
  12 siblings, 0 replies; 19+ messages in thread
From: Patchwork @ 2022-12-06 11:27 UTC (permalink / raw)
  To: Alan Previn; +Cc: igt-dev

[-- Attachment #1: Type: text/plain, Size: 34255 bytes --]

== Series Details ==

Series: Resurrect GuC Relay Logging (rev2)
URL   : https://patchwork.freedesktop.org/series/103768/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_12471_full -> IGTPW_8201_full
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

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

Participating hosts (9 -> 8)
------------------------------

  Additional (2): shard-rkl shard-dg1 
  Missing    (3): pig-skl-6260u pig-kbl-iris pig-glk-j5005 

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

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

### IGT changes ###

#### Suppressed ####

  The following results come from untrusted machines, tests, or statuses.
  They do not affect the overall result.

  * igt@i915_hangman@gt-engine-hang@rcs0:
    - {shard-rkl}:        NOTRUN -> [FAIL][1]
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-rkl-5/igt@i915_hangman@gt-engine-hang@rcs0.html

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

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

### IGT changes ###

#### Issues hit ####

  * igt@gem_ctx_persistence@many-contexts:
    - shard-tglb:         NOTRUN -> [FAIL][2] ([i915#2410])
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-tglb3/igt@gem_ctx_persistence@many-contexts.html

  * igt@gem_exec_balancer@parallel-keep-in-fence:
    - shard-iclb:         [PASS][3] -> [SKIP][4] ([i915#4525]) +1 similar issue
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12471/shard-iclb2/igt@gem_exec_balancer@parallel-keep-in-fence.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-iclb3/igt@gem_exec_balancer@parallel-keep-in-fence.html

  * igt@gem_exec_fair@basic-flow@rcs0:
    - shard-tglb:         [PASS][5] -> [FAIL][6] ([i915#2842]) +1 similar issue
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12471/shard-tglb6/igt@gem_exec_fair@basic-flow@rcs0.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-tglb7/igt@gem_exec_fair@basic-flow@rcs0.html

  * igt@gem_exec_fair@basic-pace-solo@rcs0:
    - shard-iclb:         NOTRUN -> [FAIL][7] ([i915#2842]) +1 similar issue
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-iclb8/igt@gem_exec_fair@basic-pace-solo@rcs0.html
    - shard-tglb:         NOTRUN -> [FAIL][8] ([i915#2842])
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-tglb3/igt@gem_exec_fair@basic-pace-solo@rcs0.html

  * igt@gem_lmem_swapping@heavy-verify-random:
    - shard-apl:          NOTRUN -> [SKIP][9] ([fdo#109271] / [i915#4613]) +2 similar issues
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-apl3/igt@gem_lmem_swapping@heavy-verify-random.html

  * igt@gem_lmem_swapping@parallel-random-engines:
    - shard-iclb:         NOTRUN -> [SKIP][10] ([i915#4613]) +1 similar issue
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-iclb3/igt@gem_lmem_swapping@parallel-random-engines.html
    - shard-tglb:         NOTRUN -> [SKIP][11] ([i915#4613]) +1 similar issue
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-tglb5/igt@gem_lmem_swapping@parallel-random-engines.html

  * igt@gem_render_copy@y-tiled-mc-ccs-to-vebox-yf-tiled:
    - shard-iclb:         NOTRUN -> [SKIP][12] ([i915#768])
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-iclb8/igt@gem_render_copy@y-tiled-mc-ccs-to-vebox-yf-tiled.html

  * igt@gem_vm_create@invalid-create:
    - shard-snb:          NOTRUN -> [SKIP][13] ([fdo#109271]) +64 similar issues
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-snb4/igt@gem_vm_create@invalid-create.html

  * igt@gen9_exec_parse@bb-chained:
    - shard-tglb:         NOTRUN -> [SKIP][14] ([i915#2527] / [i915#2856])
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-tglb6/igt@gen9_exec_parse@bb-chained.html
    - shard-iclb:         NOTRUN -> [SKIP][15] ([i915#2856])
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-iclb3/igt@gen9_exec_parse@bb-chained.html

  * igt@i915_module_load@reload-with-fault-injection:
    - shard-snb:          [PASS][16] -> [DMESG-WARN][17] ([i915#4528])
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12471/shard-snb5/igt@i915_module_load@reload-with-fault-injection.html
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-snb7/igt@i915_module_load@reload-with-fault-injection.html

  * igt@i915_pm_dc@dc9-dpms:
    - shard-tglb:         NOTRUN -> [SKIP][18] ([i915#4281])
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-tglb1/igt@i915_pm_dc@dc9-dpms.html

  * igt@i915_query@test-query-geometry-subslices:
    - shard-iclb:         NOTRUN -> [SKIP][19] ([i915#5723])
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-iclb5/igt@i915_query@test-query-geometry-subslices.html
    - shard-tglb:         NOTRUN -> [SKIP][20] ([i915#5723])
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-tglb7/igt@i915_query@test-query-geometry-subslices.html

  * igt@i915_selftest@live@hangcheck:
    - shard-tglb:         [PASS][21] -> [DMESG-WARN][22] ([i915#5591])
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12471/shard-tglb2/igt@i915_selftest@live@hangcheck.html
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-tglb2/igt@i915_selftest@live@hangcheck.html

  * igt@kms_atomic@atomic_plane_damage:
    - shard-iclb:         NOTRUN -> [SKIP][23] ([i915#4765])
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-iclb2/igt@kms_atomic@atomic_plane_damage.html

  * igt@kms_atomic@plane-primary-overlay-mutable-zpos:
    - shard-iclb:         NOTRUN -> [SKIP][24] ([i915#404])
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-iclb7/igt@kms_atomic@plane-primary-overlay-mutable-zpos.html
    - shard-tglb:         NOTRUN -> [SKIP][25] ([i915#404])
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-tglb1/igt@kms_atomic@plane-primary-overlay-mutable-zpos.html

  * igt@kms_big_fb@linear-32bpp-rotate-270:
    - shard-apl:          NOTRUN -> [SKIP][26] ([fdo#109271]) +46 similar issues
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-apl6/igt@kms_big_fb@linear-32bpp-rotate-270.html
    - shard-tglb:         NOTRUN -> [SKIP][27] ([fdo#111614]) +1 similar issue
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-tglb7/igt@kms_big_fb@linear-32bpp-rotate-270.html

  * igt@kms_big_fb@y-tiled-8bpp-rotate-90:
    - shard-iclb:         NOTRUN -> [SKIP][28] ([fdo#110725] / [fdo#111614]) +1 similar issue
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-iclb8/igt@kms_big_fb@y-tiled-8bpp-rotate-90.html

  * igt@kms_ccs@pipe-a-random-ccs-data-y_tiled_gen12_rc_ccs:
    - shard-iclb:         NOTRUN -> [SKIP][29] ([fdo#109278]) +6 similar issues
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-iclb5/igt@kms_ccs@pipe-a-random-ccs-data-y_tiled_gen12_rc_ccs.html

  * igt@kms_ccs@pipe-b-bad-pixel-format-4_tiled_dg2_rc_ccs:
    - shard-tglb:         NOTRUN -> [SKIP][30] ([i915#3689] / [i915#6095]) +1 similar issue
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-tglb3/igt@kms_ccs@pipe-b-bad-pixel-format-4_tiled_dg2_rc_ccs.html

  * igt@kms_ccs@pipe-c-crc-sprite-planes-basic-y_tiled_gen12_rc_ccs_cc:
    - shard-apl:          NOTRUN -> [SKIP][31] ([fdo#109271] / [i915#3886])
   [31]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-apl3/igt@kms_ccs@pipe-c-crc-sprite-planes-basic-y_tiled_gen12_rc_ccs_cc.html

  * igt@kms_ccs@pipe-c-missing-ccs-buffer-yf_tiled_ccs:
    - shard-tglb:         NOTRUN -> [SKIP][32] ([fdo#111615] / [i915#3689])
   [32]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-tglb2/igt@kms_ccs@pipe-c-missing-ccs-buffer-yf_tiled_ccs.html

  * igt@kms_ccs@pipe-c-random-ccs-data-4_tiled_dg2_rc_ccs_cc:
    - shard-tglb:         NOTRUN -> [SKIP][33] ([i915#6095])
   [33]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-tglb6/igt@kms_ccs@pipe-c-random-ccs-data-4_tiled_dg2_rc_ccs_cc.html

  * igt@kms_ccs@pipe-d-bad-rotation-90-4_tiled_dg2_rc_ccs_cc:
    - shard-tglb:         NOTRUN -> [SKIP][34] ([i915#3689])
   [34]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-tglb2/igt@kms_ccs@pipe-d-bad-rotation-90-4_tiled_dg2_rc_ccs_cc.html

  * igt@kms_chamelium@dp-crc-fast:
    - shard-iclb:         NOTRUN -> [SKIP][35] ([fdo#109284] / [fdo#111827]) +2 similar issues
   [35]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-iclb2/igt@kms_chamelium@dp-crc-fast.html

  * igt@kms_chamelium@dp-frame-dump:
    - shard-apl:          NOTRUN -> [SKIP][36] ([fdo#109271] / [fdo#111827]) +4 similar issues
   [36]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-apl8/igt@kms_chamelium@dp-frame-dump.html
    - shard-snb:          NOTRUN -> [SKIP][37] ([fdo#109271] / [fdo#111827]) +2 similar issues
   [37]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-snb5/igt@kms_chamelium@dp-frame-dump.html

  * igt@kms_chamelium@hdmi-audio-edid:
    - shard-tglb:         NOTRUN -> [SKIP][38] ([fdo#109284] / [fdo#111827]) +2 similar issues
   [38]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-tglb2/igt@kms_chamelium@hdmi-audio-edid.html

  * igt@kms_content_protection@lic@pipe-a-dp-1:
    - shard-apl:          NOTRUN -> [TIMEOUT][39] ([i915#7173])
   [39]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-apl6/igt@kms_content_protection@lic@pipe-a-dp-1.html

  * igt@kms_content_protection@mei_interface:
    - shard-tglb:         NOTRUN -> [SKIP][40] ([i915#7118])
   [40]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-tglb3/igt@kms_content_protection@mei_interface.html
    - shard-iclb:         NOTRUN -> [SKIP][41] ([i915#7118])
   [41]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-iclb1/igt@kms_content_protection@mei_interface.html

  * igt@kms_cursor_crc@cursor-offscreen-512x170:
    - shard-iclb:         NOTRUN -> [SKIP][42] ([fdo#109279] / [i915#3359])
   [42]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-iclb7/igt@kms_cursor_crc@cursor-offscreen-512x170.html
    - shard-tglb:         NOTRUN -> [SKIP][43] ([fdo#109279] / [i915#3359])
   [43]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-tglb1/igt@kms_cursor_crc@cursor-offscreen-512x170.html

  * igt@kms_dither@fb-8bpc-vs-panel-8bpc:
    - shard-tglb:         NOTRUN -> [SKIP][44] ([i915#1769] / [i915#3555])
   [44]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-tglb6/igt@kms_dither@fb-8bpc-vs-panel-8bpc.html

  * igt@kms_flip@flip-vs-suspend@c-dp1:
    - shard-apl:          [PASS][45] -> [DMESG-WARN][46] ([i915#180])
   [45]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12471/shard-apl2/igt@kms_flip@flip-vs-suspend@c-dp1.html
   [46]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-apl8/igt@kms_flip@flip-vs-suspend@c-dp1.html

  * igt@kms_flip_scaled_crc@flip-32bpp-4tile-to-32bpp-4tiledg2rcccs-downscaling@pipe-a-valid-mode:
    - shard-iclb:         NOTRUN -> [SKIP][47] ([i915#2587] / [i915#2672]) +2 similar issues
   [47]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-iclb8/igt@kms_flip_scaled_crc@flip-32bpp-4tile-to-32bpp-4tiledg2rcccs-downscaling@pipe-a-valid-mode.html

  * igt@kms_flip_scaled_crc@flip-32bpp-yftile-to-32bpp-yftileccs-downscaling@pipe-a-default-mode:
    - shard-iclb:         NOTRUN -> [SKIP][48] ([i915#6375])
   [48]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-iclb2/igt@kms_flip_scaled_crc@flip-32bpp-yftile-to-32bpp-yftileccs-downscaling@pipe-a-default-mode.html

  * igt@kms_flip_scaled_crc@flip-64bpp-4tile-to-16bpp-4tile-upscaling@pipe-a-default-mode:
    - shard-iclb:         NOTRUN -> [SKIP][49] ([i915#2672]) +6 similar issues
   [49]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-iclb3/igt@kms_flip_scaled_crc@flip-64bpp-4tile-to-16bpp-4tile-upscaling@pipe-a-default-mode.html

  * igt@kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-downscaling@pipe-a-default-mode:
    - shard-iclb:         NOTRUN -> [SKIP][50] ([i915#3555]) +1 similar issue
   [50]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-iclb2/igt@kms_flip_scaled_crc@flip-64bpp-xtile-to-16bpp-xtile-downscaling@pipe-a-default-mode.html

  * igt@kms_frontbuffer_tracking@fbcpsr-1p-primscrn-shrfb-pgflip-blt:
    - shard-tglb:         NOTRUN -> [SKIP][51] ([i915#6497]) +2 similar issues
   [51]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-tglb3/igt@kms_frontbuffer_tracking@fbcpsr-1p-primscrn-shrfb-pgflip-blt.html

  * igt@kms_frontbuffer_tracking@psr-2p-primscrn-spr-indfb-draw-render:
    - shard-tglb:         NOTRUN -> [SKIP][52] ([fdo#109280] / [fdo#111825]) +7 similar issues
   [52]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-tglb5/igt@kms_frontbuffer_tracking@psr-2p-primscrn-spr-indfb-draw-render.html

  * igt@kms_frontbuffer_tracking@psr-2p-scndscrn-spr-indfb-draw-mmap-wc:
    - shard-iclb:         NOTRUN -> [SKIP][53] ([fdo#109280]) +6 similar issues
   [53]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-iclb8/igt@kms_frontbuffer_tracking@psr-2p-scndscrn-spr-indfb-draw-mmap-wc.html

  * igt@kms_plane_alpha_blend@alpha-basic@pipe-a-dp-1:
    - shard-apl:          NOTRUN -> [FAIL][54] ([i915#4573])
   [54]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-apl2/igt@kms_plane_alpha_blend@alpha-basic@pipe-a-dp-1.html

  * igt@kms_plane_alpha_blend@alpha-basic@pipe-c-dp-1:
    - shard-apl:          NOTRUN -> [DMESG-FAIL][55] ([IGT#6]) +1 similar issue
   [55]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-apl2/igt@kms_plane_alpha_blend@alpha-basic@pipe-c-dp-1.html

  * igt@kms_plane_scaling@planes-unity-scaling-downscale-factor-0-5@pipe-c-edp-1:
    - shard-iclb:         [PASS][56] -> [SKIP][57] ([i915#5235]) +2 similar issues
   [56]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12471/shard-iclb5/igt@kms_plane_scaling@planes-unity-scaling-downscale-factor-0-5@pipe-c-edp-1.html
   [57]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-iclb2/igt@kms_plane_scaling@planes-unity-scaling-downscale-factor-0-5@pipe-c-edp-1.html

  * igt@kms_psr2_sf@overlay-plane-update-continuous-sf:
    - shard-tglb:         NOTRUN -> [SKIP][58] ([i915#2920])
   [58]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-tglb3/igt@kms_psr2_sf@overlay-plane-update-continuous-sf.html
    - shard-iclb:         NOTRUN -> [SKIP][59] ([fdo#111068] / [i915#658])
   [59]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-iclb1/igt@kms_psr2_sf@overlay-plane-update-continuous-sf.html

  * igt@kms_psr@psr2_sprite_mmap_gtt:
    - shard-iclb:         [PASS][60] -> [SKIP][61] ([fdo#109441]) +2 similar issues
   [60]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12471/shard-iclb2/igt@kms_psr@psr2_sprite_mmap_gtt.html
   [61]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-iclb5/igt@kms_psr@psr2_sprite_mmap_gtt.html

  * igt@kms_psr_stress_test@invalidate-primary-flip-overlay:
    - shard-iclb:         [PASS][62] -> [SKIP][63] ([i915#5519])
   [62]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12471/shard-iclb7/igt@kms_psr_stress_test@invalidate-primary-flip-overlay.html
   [63]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-iclb5/igt@kms_psr_stress_test@invalidate-primary-flip-overlay.html

  * igt@perf@gen12-oa-tlb-invalidate:
    - shard-iclb:         NOTRUN -> [SKIP][64] ([fdo#109289])
   [64]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-iclb2/igt@perf@gen12-oa-tlb-invalidate.html

  
#### Possible fixes ####

  * igt@gem_exec_balancer@parallel-contexts:
    - shard-iclb:         [SKIP][65] ([i915#4525]) -> [PASS][66]
   [65]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12471/shard-iclb5/igt@gem_exec_balancer@parallel-contexts.html
   [66]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-iclb2/igt@gem_exec_balancer@parallel-contexts.html

  * igt@i915_pm_dc@dc6-psr:
    - shard-iclb:         [FAIL][67] ([i915#3989] / [i915#454]) -> [PASS][68]
   [67]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12471/shard-iclb3/igt@i915_pm_dc@dc6-psr.html
   [68]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-iclb1/igt@i915_pm_dc@dc6-psr.html

  * igt@i915_pm_rps@engine-order:
    - shard-apl:          [FAIL][69] ([i915#6537]) -> [PASS][70]
   [69]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12471/shard-apl7/igt@i915_pm_rps@engine-order.html
   [70]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-apl7/igt@i915_pm_rps@engine-order.html

  * igt@kms_flip@flip-vs-suspend-interruptible@a-dp1:
    - shard-apl:          [DMESG-WARN][71] ([i915#180]) -> [PASS][72]
   [71]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12471/shard-apl2/igt@kms_flip@flip-vs-suspend-interruptible@a-dp1.html
   [72]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-apl3/igt@kms_flip@flip-vs-suspend-interruptible@a-dp1.html

  * igt@kms_hdmi_inject@inject-audio:
    - shard-tglb:         [SKIP][73] ([i915#433]) -> [PASS][74]
   [73]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12471/shard-tglb1/igt@kms_hdmi_inject@inject-audio.html
   [74]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-tglb3/igt@kms_hdmi_inject@inject-audio.html

  * igt@kms_psr@psr2_cursor_mmap_gtt:
    - shard-iclb:         [SKIP][75] ([fdo#109441]) -> [PASS][76] +3 similar issues
   [75]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12471/shard-iclb7/igt@kms_psr@psr2_cursor_mmap_gtt.html
   [76]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-iclb2/igt@kms_psr@psr2_cursor_mmap_gtt.html

  * igt@kms_psr_stress_test@flip-primary-invalidate-overlay:
    - shard-tglb:         [SKIP][77] ([i915#5519]) -> [PASS][78]
   [77]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12471/shard-tglb7/igt@kms_psr_stress_test@flip-primary-invalidate-overlay.html
   [78]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-tglb3/igt@kms_psr_stress_test@flip-primary-invalidate-overlay.html

  * igt@kms_vblank@pipe-b-wait-idle-hang:
    - shard-apl:          [SKIP][79] ([fdo#109271]) -> [PASS][80]
   [79]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12471/shard-apl8/igt@kms_vblank@pipe-b-wait-idle-hang.html
   [80]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-apl8/igt@kms_vblank@pipe-b-wait-idle-hang.html

  
#### Warnings ####

  * igt@gem_exec_balancer@parallel-ordering:
    - shard-iclb:         [SKIP][81] ([i915#4525]) -> [FAIL][82] ([i915#6117])
   [81]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12471/shard-iclb6/igt@gem_exec_balancer@parallel-ordering.html
   [82]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-iclb1/igt@gem_exec_balancer@parallel-ordering.html

  * igt@i915_pm_rc6_residency@rc6-idle@rcs0:
    - shard-iclb:         [WARN][83] ([i915#2684]) -> [FAIL][84] ([i915#2684] / [i915#3591])
   [83]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12471/shard-iclb7/igt@i915_pm_rc6_residency@rc6-idle@rcs0.html
   [84]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-iclb7/igt@i915_pm_rc6_residency@rc6-idle@rcs0.html

  * igt@kms_psr2_sf@overlay-plane-move-continuous-sf:
    - shard-iclb:         [SKIP][85] ([i915#2920]) -> [SKIP][86] ([i915#658])
   [85]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12471/shard-iclb2/igt@kms_psr2_sf@overlay-plane-move-continuous-sf.html
   [86]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-iclb3/igt@kms_psr2_sf@overlay-plane-move-continuous-sf.html

  * igt@kms_psr2_sf@plane-move-sf-dmg-area:
    - shard-iclb:         [SKIP][87] ([i915#2920]) -> [SKIP][88] ([fdo#111068] / [i915#658])
   [87]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12471/shard-iclb2/igt@kms_psr2_sf@plane-move-sf-dmg-area.html
   [88]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-iclb8/igt@kms_psr2_sf@plane-move-sf-dmg-area.html

  * igt@kms_psr2_sf@primary-plane-update-sf-dmg-area:
    - shard-iclb:         [SKIP][89] ([fdo#111068] / [i915#658]) -> [SKIP][90] ([i915#2920]) +1 similar issue
   [89]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_12471/shard-iclb3/igt@kms_psr2_sf@primary-plane-update-sf-dmg-area.html
   [90]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/shard-iclb2/igt@kms_psr2_sf@primary-plane-update-sf-dmg-area.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [IGT#6]: https://gitlab.freedesktop.org/drm/igt-gpu-tools/issues/6
  [fdo#103375]: https://bugs.freedesktop.org/show_bug.cgi?id=103375
  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [fdo#109274]: https://bugs.freedesktop.org/show_bug.cgi?id=109274
  [fdo#109278]: https://bugs.freedesktop.org/show_bug.cgi?id=109278
  [fdo#109279]: https://bugs.freedesktop.org/show_bug.cgi?id=109279
  [fdo#109280]: https://bugs.freedesktop.org/show_bug.cgi?id=109280
  [fdo#109283]: https://bugs.freedesktop.org/show_bug.cgi?id=109283
  [fdo#109284]: https://bugs.freedesktop.org/show_bug.cgi?id=109284
  [fdo#109285]: https://bugs.freedesktop.org/show_bug.cgi?id=109285
  [fdo#109289]: https://bugs.freedesktop.org/show_bug.cgi?id=109289
  [fdo#109295]: https://bugs.freedesktop.org/show_bug.cgi?id=109295
  [fdo#109302]: https://bugs.freedesktop.org/show_bug.cgi?id=109302
  [fdo#109303]: https://bugs.freedesktop.org/show_bug.cgi?id=109303
  [fdo#109307]: https://bugs.freedesktop.org/show_bug.cgi?id=109307
  [fdo#109308]: https://bugs.freedesktop.org/show_bug.cgi?id=109308
  [fdo#109309]: https://bugs.freedesktop.org/show_bug.cgi?id=109309
  [fdo#109312]: https://bugs.freedesktop.org/show_bug.cgi?id=109312
  [fdo#109314]: https://bugs.freedesktop.org/show_bug.cgi?id=109314
  [fdo#109315]: https://bugs.freedesktop.org/show_bug.cgi?id=109315
  [fdo#109441]: https://bugs.freedesktop.org/show_bug.cgi?id=109441
  [fdo#109506]: https://bugs.freedesktop.org/show_bug.cgi?id=109506
  [fdo#110189]: https://bugs.freedesktop.org/show_bug.cgi?id=110189
  [fdo#110542]: https://bugs.freedesktop.org/show_bug.cgi?id=110542
  [fdo#110723]: https://bugs.freedesktop.org/show_bug.cgi?id=110723
  [fdo#110725]: https://bugs.freedesktop.org/show_bug.cgi?id=110725
  [fdo#111068]: https://bugs.freedesktop.org/show_bug.cgi?id=111068
  [fdo#111614]: https://bugs.freedesktop.org/show_bug.cgi?id=111614
  [fdo#111615]: https://bugs.freedesktop.org/show_bug.cgi?id=111615
  [fdo#111656]: https://bugs.freedesktop.org/show_bug.cgi?id=111656
  [fdo#111825]: https://bugs.freedesktop.org/show_bug.cgi?id=111825
  [fdo#111827]: https://bugs.freedesktop.org/show_bug.cgi?id=111827
  [fdo#112054]: https://bugs.freedesktop.org/show_bug.cgi?id=112054
  [fdo#112283]: https://bugs.freedesktop.org/show_bug.cgi?id=112283
  [i915#1072]: https://gitlab.freedesktop.org/drm/intel/issues/1072
  [i915#1257]: https://gitlab.freedesktop.org/drm/intel/issues/1257
  [i915#132]: https://gitlab.freedesktop.org/drm/intel/issues/132
  [i915#1397]: https://gitlab.freedesktop.org/drm/intel/issues/1397
  [i915#1722]: https://gitlab.freedesktop.org/drm/intel/issues/1722
  [i915#1755]: https://gitlab.freedesktop.org/drm/intel/issues/1755
  [i915#1769]: https://gitlab.freedesktop.org/drm/intel/issues/1769
  [i915#180]: https://gitlab.freedesktop.org/drm/intel/issues/180
  [i915#1825]: https://gitlab.freedesktop.org/drm/intel/issues/1825
  [i915#1839]: https://gitlab.freedesktop.org/drm/intel/issues/1839
  [i915#1845]: https://gitlab.freedesktop.org/drm/intel/issues/1845
  [i915#1849]: https://gitlab.freedesktop.org/drm/intel/issues/1849
  [i915#1850]: https://gitlab.freedesktop.org/drm/intel/issues/1850
  [i915#1902]: https://gitlab.freedesktop.org/drm/intel/issues/1902
  [i915#2190]: https://gitlab.freedesktop.org/drm/intel/issues/2190
  [i915#2410]: https://gitlab.freedesktop.org/drm/intel/issues/2410
  [i915#2433]: https://gitlab.freedesktop.org/drm/intel/issues/2433
  [i915#2434]: https://gitlab.freedesktop.org/drm/intel/issues/2434
  [i915#2435]: https://gitlab.freedesktop.org/drm/intel/issues/2435
  [i915#2436]: https://gitlab.freedesktop.org/drm/intel/issues/2436
  [i915#2437]: https://gitlab.freedesktop.org/drm/intel/issues/2437
  [i915#2527]: https://gitlab.freedesktop.org/drm/intel/issues/2527
  [i915#2575]: https://gitlab.freedesktop.org/drm/intel/issues/2575
  [i915#2582]: https://gitlab.freedesktop.org/drm/intel/issues/2582
  [i915#2587]: https://gitlab.freedesktop.org/drm/intel/issues/2587
  [i915#2672]: https://gitlab.freedesktop.org/drm/intel/issues/2672
  [i915#2684]: https://gitlab.freedesktop.org/drm/intel/issues/2684
  [i915#2705]: https://gitlab.freedesktop.org/drm/intel/issues/2705
  [i915#280]: https://gitlab.freedesktop.org/drm/intel/issues/280
  [i915#284]: https://gitlab.freedesktop.org/drm/intel/issues/284
  [i915#2842]: https://gitlab.freedesktop.org/drm/intel/issues/2842
  [i915#2846]: https://gitlab.freedesktop.org/drm/intel/issues/2846
  [i915#2856]: https://gitlab.freedesktop.org/drm/intel/issues/2856
  [i915#2920]: https://gitlab.freedesktop.org/drm/intel/issues/2920
  [i915#2994]: https://gitlab.freedesktop.org/drm/intel/issues/2994
  [i915#3002]: https://gitlab.freedesktop.org/drm/intel/issues/3002
  [i915#3281]: https://gitlab.freedesktop.org/drm/intel/issues/3281
  [i915#3282]: https://gitlab.freedesktop.org/drm/intel/issues/3282
  [i915#3291]: https://gitlab.freedesktop.org/drm/intel/issues/3291
  [i915#3297]: https://gitlab.freedesktop.org/drm/intel/issues/3297
  [i915#3299]: https://gitlab.freedesktop.org/drm/intel/issues/3299
  [i915#3301]: https://gitlab.freedesktop.org/drm/intel/issues/3301
  [i915#3318]: https://gitlab.freedesktop.org/drm/intel/issues/3318
  [i915#3323]: https://gitlab.freedesktop.org/drm/intel/issues/3323
  [i915#3359]: https://gitlab.freedesktop.org/drm/intel/issues/3359
  [i915#3458]: https://gitlab.freedesktop.org/drm/intel/issues/3458
  [i915#3469]: https://gitlab.freedesktop.org/drm/intel/issues/3469
  [i915#3528]: https://gitlab.freedesktop.org/drm/intel/issues/3528
  [i915#3539]: https://gitlab.freedesktop.org/drm/intel/issues/3539
  [i915#3546]: https://gitlab.freedesktop.org/drm/intel/issues/3546
  [i915#3555]: https://gitlab.freedesktop.org/drm/intel/issues/3555
  [i915#3558]: https://gitlab.freedesktop.org/drm/intel/issues/3558
  [i915#3591]: https://gitlab.freedesktop.org/drm/intel/issues/3591
  [i915#3637]: https://gitlab.freedesktop.org/drm/intel/issues/3637
  [i915#3638]: https://gitlab.freedesktop.org/drm/intel/issues/3638
  [i915#3639]: https://gitlab.freedesktop.org/drm/intel/issues/3639
  [i915#3689]: https://gitlab.freedesktop.org/drm/intel/issues/3689
  [i915#3708]: https://gitlab.freedesktop.org/drm/intel/issues/3708
  [i915#3734]: https://gitlab.freedesktop.org/drm/intel/issues/3734
  [i915#3742]: https://gitlab.freedesktop.org/drm/intel/issues/3742
  [i915#3826]: https://gitlab.freedesktop.org/drm/intel/issues/3826
  [i915#3840]: https://gitlab.freedesktop.org/drm/intel/issues/3840
  [i915#3886]: https://gitlab.freedesktop.org/drm/intel/issues/3886
  [i915#3936]: https://gitlab.freedesktop.org/drm/intel/issues/3936
  [i915#3938]: https://gitlab.freedesktop.org/drm/intel/issues/3938
  [i915#3952]: https://gitlab.freedesktop.org/drm/intel/issues/3952
  [i915#3955]: https://gitlab.freedesktop.org/drm/intel/issues/3955
  [i915#3989]: https://gitlab.freedesktop.org/drm/intel/issues/3989
  [i915#4036]: https://gitlab.freedesktop.org/drm/intel/issues/4036
  [i915#404]: https://gitlab.freedesktop.org/drm/intel/issues/404
  [i915#4070]: https://gitlab.freedesktop.org/drm/intel/issues/4070
  [i915#4077]: https://gitlab.freedesktop.org/drm/intel/issues/4077
  [i915#4078]: https://gitlab.freedesktop.org/drm/intel/issues/4078
  [i915#4079]: https://gitlab.freedesktop.org/drm/intel/issues/4079
  [i915#4083]: https://gitlab.freedesktop.org/drm/intel/issues/4083
  [i915#4098]: https://gitlab.freedesktop.org/drm/intel/issues/4098
  [i915#4103]: https://gitlab.freedesktop.org/drm/intel/issues/4103
  [i915#4212]: https://gitlab.freedesktop.org/drm/intel/issues/4212
  [i915#4213]: https://gitlab.freedesktop.org/drm/intel/issues/4213
  [i915#426]: https://gitlab.freedesktop.org/drm/intel/issues/426
  [i915#4270]: https://gitlab.freedesktop.org/drm/intel/issues/4270
  [i915#4281]: https://gitlab.freedesktop.org/drm/intel/issues/4281
  [i915#4312]: https://gitlab.freedesktop.org/drm/intel/issues/4312
  [i915#433]: https://gitlab.freedesktop.org/drm/intel/issues/433
  [i915#4387]: https://gitlab.freedesktop.org/drm/intel/issues/4387
  [i915#4391]: https://gitlab.freedesktop.org/drm/intel/issues/4391
  [i915#4525]: https://gitlab.freedesktop.org/drm/intel/issues/4525
  [i915#4528]: https://gitlab.freedesktop.org/drm/intel/issues/4528
  [i915#4538]: https://gitlab.freedesktop.org/drm/intel/issues/4538
  [i915#454]: https://gitlab.freedesktop.org/drm/intel/issues/454
  [i915#4565]: https://gitlab.freedesktop.org/drm/intel/issues/4565
  [i915#4573]: https://gitlab.freedesktop.org/drm/intel/issues/4573
  [i915#4613]: https://gitlab.freedesktop.org/drm/intel/issues/4613
  [i915#4765]: https://gitlab.freedesktop.org/drm/intel/issues/4765
  [i915#4767]: https://gitlab.freedesktop.org/drm/intel/issues/4767
  [i915#4771]: https://gitlab.freedesktop.org/drm/intel/issues/4771
  [i915#4812]: https://gitlab.freedesktop.org/drm/intel/issues/4812
  [i915#4818]: https://gitlab.freedesktop.org/drm/intel/issues/4818
  [i915#4833]: https://gitlab.freedesktop.org/drm/intel/issues/4833
  [i915#4852]: https://gitlab.freedesktop.org/drm/intel/issues/4852
  [i915#4854]: https://gitlab.freedesktop.org/drm/intel/issues/4854
  [i915#4855]: https://gitlab.freedesktop.org/drm/intel/issues/4855
  [i915#4859]: https://gitlab.freedesktop.org/drm/intel/issues/4859
  [i915#4860]: https://gitlab.freedesktop.org/drm/intel/issues/4860
  [i915#4874]: https://gitlab.freedesktop.org/drm/intel/issues/4874
  [i915#4877]: https://gitlab.freedesktop.org/drm/intel/issues/4877
  [i915#4879]: https://gitlab.freedesktop.org/drm/intel/issues/4879
  [i915#4880]: https://gitlab.freedesktop.org/drm/intel/issues/4880
  [i915#4884]: https://gitlab.freedesktop.org/drm/intel/issues/4884
  [i915#4885]: https://gitlab.freedesktop.org/drm/intel/issues/4885
  [i915#4958]: https://gitlab.freedesktop.org/drm/intel/issues/4958
  [i915#4991]: https://gitlab.freedesktop.org/drm/intel/issues/4991
  [i915#5176]: https://gitlab.freedesktop.org/drm/intel/issues/5176
  [i915#5235]: https://gitlab.freedesktop.org/drm/intel/issues/5235
  [i915#5286]: https://gitlab.freedesktop.org/drm/intel/issues/5286
  [i915#5288]: https://gitlab.freedesktop.org/drm/intel/issues/5288
  [i915#5289]: https://gitlab.freedesktop.org/drm/intel/issues/5289
  [i915#5325]: https://gitlab.freedesktop.org/drm/intel/issues/5325
  [i915#5327]: https://gitlab.freedesktop.org/drm/intel/issues/5327
  [i915#533]: https://gitlab.freedesktop.org/drm/intel/issues/533
  [i915#5439]: https://gitlab.freedesktop.org/drm/intel/issues/5439
  [i915#5461]: https://gitlab.freedesktop.org/drm/intel/issues/5461
  [i915#5519]: https://gitlab.freedesktop.org/drm/intel/issues/5519
  [i915#5563]: https://gitlab.freedesktop.org/drm/intel/issues/5563
  [i915#5591]: https://gitlab.freedesktop.org/drm/intel/issues/5591
  [i915#5723]: https://gitlab.freedesktop.org/drm/intel/issues/5723
  [i915#6095]: https://gitlab.freedesktop.org/drm/intel/issues/6095
  [i915#6117]: https://gitlab.freedesktop.org/drm/intel/issues/6117
  [i915#6227]: https://gitlab.freedesktop.org/drm/intel/issues/6227
  [i915#6245]: https://gitlab.freedesktop.org/drm/intel/issues/6245
  [i915#6248]: https://gitlab.freedesktop.org/drm/intel/issues/6248
  [i915#6252]: https://gitlab.freedesktop.org/drm/intel/issues/6252
  [i915#6301]: https://gitlab.freedesktop.org/drm/intel/issues/6301
  [i915#6334]: https://gitlab.freedesktop.org/drm/intel/issues/6334
  [i915#6335]: https://gitlab.freedesktop.org/drm/intel/issues/6335
  [i915#6344]: https://gitlab.freedesktop.org/drm/intel/issues/6344
  [i915#6375]: https://gitlab.freedesktop.org/drm/intel/issues/6375
  [i915#6412]: https://gitlab.freedesktop.org/drm/intel/issues/6412
  [i915#6433]: https://gitlab.freedesktop.org/drm/intel/issues/6433
  [i915#6493]: https://gitlab.freedesktop.org/drm/intel/issues/6493
  [i915#6497]: https://gitlab.freedesktop.org/drm/intel/issues/6497
  [i915#6524]: https://gitlab.freedesktop.org/drm/intel/issues/6524
  [i915#6537]: https://gitlab.freedesktop.org/drm/intel/issues/6537
  [i915#658]: https://gitlab.freedesktop.org/drm/intel/issues/658
  [i915#6590]: https://gitlab.freedesktop.org/drm/intel/issues/6590
  [i915#6621]: https://gitlab.freedesktop.org/drm/intel/issues/6621
  [i915#6768]: https://gitlab.freedesktop.org/drm/intel/issues/6768
  [i915#7052]: https://gitlab.freedesktop.org/drm/intel/issues/7052
  [i915#7116]: https://gitlab.freedesktop.org/drm/intel/issues/7116
  [i915#7118]: https://gitlab.freedesktop.org/drm/intel/issues/7118
  [i915#7173]: https://gitlab.freedesktop.org/drm/intel/issues/7173
  [i915#7178]: https://gitlab.freedesktop.org/drm/intel/issues/7178
  [i915#7276]: https://gitlab.freedesktop.org/drm/intel/issues/7276
  [i915#7397]: https://gitlab.freedesktop.org/drm/intel/issues/7397
  [i915#7456]: https://gitlab.freedesktop.org/drm/intel/issues/7456
  [i915#7561]: https://gitlab.freedesktop.org/drm/intel/issues/7561
  [i915#7582]: https://gitlab.freedesktop.org/drm/intel/issues/7582
  [i915#768]: https://gitlab.freedesktop.org/drm/intel/issues/768


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

  * CI: CI-20190529 -> None
  * IGT: IGT_7083 -> IGTPW_8201
  * Piglit: piglit_4509 -> None

  CI-20190529: 20190529
  CI_DRM_12471: 7f8dc69dce0e934751fe31c01a6b6baa0c65bf23 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGTPW_8201: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_8201/index.html
  IGT_7083: c001793d5f22deb01918b6ba52af829794582df1 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  piglit_4509: fdc5a4ca11124ab8413c7988896eec4c97336694 @ git://anongit.freedesktop.org/piglit

== Logs ==

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

[-- Attachment #2: Type: text/html, Size: 29775 bytes --]

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

* Re: [igt-dev] [i-g-t, v2, 01/11] tools/intel_guc_logger: Re-enable basic functionality
  2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 01/11] tools/intel_guc_logger: Re-enable basic functionality Alan Previn
@ 2023-01-20 20:26   ` Dong, Zhanjun
  2023-03-14 21:46     ` Teres Alexis, Alan Previn
  0 siblings, 1 reply; 19+ messages in thread
From: Dong, Zhanjun @ 2023-01-20 20:26 UTC (permalink / raw)
  To: Alan Previn, igt-dev

See my comments inline below.


Regards,

Zhanjun Dong


On 2022-12-06 3:58 a.m., Alan Previn wrote:
> Fix these multiple issues to get basic functionality up
> and running on GuC using:
> 1. Start using the updated debugfs path for all GuC relay-logging
>     file names.
> 2. Use the updated debugfs names for the relay-logging control
>     and channel files to match kernel changes.
> 3. Start querrying the relay sub-buffer info (buffer size and
>     number of sub-buffers) from kernel's new debugfs files.
> 4. Separate the control enabling from the log-level-setting and
>     keep the control handle open while collecting the logs.
>
> Signed-off-by: Alan Previn <alan.previn.teres.alexis@intel.com>
> ---
>   tools/intel_guc_logger.c | 179 ++++++++++++++++++++++++++++-----------
>   1 file changed, 129 insertions(+), 50 deletions(-)
>
> diff --git a/tools/intel_guc_logger.c b/tools/intel_guc_logger.c
> index 5f1de8db..4a991127 100644
> --- a/tools/intel_guc_logger.c
> +++ b/tools/intel_guc_logger.c
> @@ -42,24 +42,30 @@
>   
>   #include "igt.h"
>   
> +#define KB(x) ((uint64_t)(x) * 1024)
>   #define MB(x) ((uint64_t)(x) * 1024 * 1024)
>   #ifndef PAGE_SIZE
>     #define PAGE_SIZE 4096
>   #endif
> -/* Currently the size of GuC log buffer is 19 pages & so is the size of relay
> - * subbuffer. If the size changes in future, then this define also needs to be
> - * updated accordingly.
> - */
> -#define SUBBUF_SIZE (19*PAGE_SIZE)
> -/* Need large buffering from logger side to hide the DISK IO latency, Driver
> - * can only store 8 snapshots of GuC log buffer in relay.
> - */
> -#define NUM_SUBBUFS 100
>   
> -#define RELAY_FILE_NAME  "guc_log"
>   #define DEFAULT_OUTPUT_FILE_NAME  "guc_log_dump.dat"
> -#define CONTROL_FILE_NAME "i915_guc_log_control"
>   
> +#define GLR_LOGLEVEL_NAME         "guc_log_level"
> +#define GLR_CTL_NAME              "guc_log_relay_ctl"
> +#define GLR_CHANNEL_NAME          "guc_log_relay_chan0"
> +
> +#define DEFAULT_SUBBUF_COUNT         (4 * 8)
> +					/* default to kernel built-in:   *
> +					 *   4 x 8 subbuf regions        *
> +					 */
> +#define DEFAULT_SUBBUF_SIZE          (KB(4 + 8 + 64))
> +					/* default to kernel built-ins : *
> +					 *   4K -> buffer states array   *
> +					 *   8K -> GuC crash dump        *
> +					 *  64K -> log events buffer     *
> +					 */
> +
> +int drm_fd;
>   char *read_buffer;
>   char *out_filename;
>   int poll_timeout = 2; /* by default 2ms timeout */
> @@ -68,23 +74,53 @@ pthread_t flush_thread;
>   int verbosity_level = 3; /* by default capture logs at max verbosity */
>   uint32_t produced, consumed;
>   uint64_t total_bytes_written;
> -int num_buffers = NUM_SUBBUFS;
> -int relay_fd, outfile_fd = -1;
> +int subbuf_count;
> +int subbuf_size;
> +int ctl_fd, relay_fd, outfile_fd = -1;
>   uint32_t test_duration, max_filesize;
>   pthread_cond_t underflow_cond, overflow_cond;
>   bool stop_logging, discard_oldlogs, capturing_stopped;
> +char *gucfspath;
>   
> -static void guc_log_control(bool enable, uint32_t log_level)
> +static void get_guc_subbuf_info(void)
> +{
> +	int fd, ret, j;
> +	char *path;
> +	const char *dbg_fs_names[2] = {"guc_log_relay_buf_size\0",
> +					"guc_log_relay_subbuf_count\0"};
> +	char outstr[128];
> +	uint64_t tmp[2] = {DEFAULT_SUBBUF_SIZE, DEFAULT_SUBBUF_COUNT};
> +
> +	for (j = 0; j < 2; j++) {
> +		igt_assert_neq(asprintf(&path, "%s/%s", gucfspath, dbg_fs_names[j]), -1);
> +		igt_info("Opening subbuf path %s\n", path);
> +		fd = igt_debugfs_open(drm_fd, path, O_RDONLY);
> +		free(path);
> +		igt_assert_f(fd >= 0, "couldn't open the GuC log relay-subbuf file\n");
> +		ret = read(fd, outstr, sizeof(outstr) - 1);
> +		igt_assert(ret > 0);
> +		outstr[ret] = '\0';
> +		tmp[j] = atoll(outstr);
> +		close(fd);
> +	}
> +	subbuf_size = tmp[0];
> +	subbuf_count = tmp[1];
How about define tmp[x] the same data type as subbuf_xxx to avoid type 
rang diff?
> +	igt_info("Debugfs retrieved subbuf info: size=%d, count=%d\n",
> +		 subbuf_size, subbuf_count);
> +}
> +
> +static void guc_log_verbosity(bool enable, int log_level)
>   {
> -	int control_fd;
> -	char data[19];
> +	char *str;
> +	int loglevelfd;
>   	uint64_t val;
>   	int ret;
>   
> -	igt_assert_lte(log_level, 3);
> -
> -	control_fd = igt_debugfs_open(-1, CONTROL_FILE_NAME, O_WRONLY);
> -	igt_assert_f(control_fd >= 0, "couldn't open the guc log control file\n");
> +	igt_assert_neq(asprintf(&str, "%s/%s", gucfspath, GLR_LOGLEVEL_NAME), -1);
> +	igt_info("Opening log level -> %s\n", str);
> +	loglevelfd = igt_debugfs_open(drm_fd, str, O_WRONLY);
> +	free(str);
> +	igt_assert_f(loglevelfd >= 0, "couldn't open the GuC log level file\n");
>   
>   	/*
>   	 * i915 expects GuC log level to be specified as:
> @@ -96,13 +132,51 @@ static void guc_log_control(bool enable, uint32_t log_level)
>   	 */
>   	val = enable ? log_level + 1 : 0;
>   
> -	ret = snprintf(data, sizeof(data), "0x%" PRIx64, val);
> -	igt_assert(ret > 2 && ret < sizeof(data));
> +	ret = asprintf(&str, "0x%" PRIx64, val);
> +	igt_assert_neq(ret, -1);
> +	ret = write(loglevelfd, str, ret);
> +	free(str);
> +	igt_assert_f(ret > 0, "couldn't write verbosity to log level file\n");
> +	igt_info("Set GuC log level = %d\n", (int)val);
> +
> +	close(loglevelfd);
> +}
>   
> -	ret = write(control_fd, data, ret);
> -	igt_assert_f(ret > 0, "couldn't write to the log control file\n");
> +static void guc_log_control(bool enable, uint32_t log_level)
How about to have the same log_level type among the file?
> +{
> +	char *str;
> +	uint64_t val = 0;
> +	int ret;
>   
> -	close(control_fd);
> +	if (enable) {
> +		igt_assert_neq(asprintf(&str, "%s/%s", gucfspath, GLR_CTL_NAME), -1);
> +		igt_info("Opening control file -> %s\n", str);
> +		ctl_fd = igt_debugfs_open(drm_fd, str, O_WRONLY);
> +		free(str);
> +		igt_assert_f(ctl_fd >= 0, "couldn't open the GuC log relay-ctl file\n");
> +		val = 1;
> +	}
> +
> +	/*
> +	 * i915 expects relay logging controls:
> +	 * 1    : open + enable relay logging
> +	 * 2    : flush
> +	 * 0    : disable relay logging + close
> +	 */
> +	if (ctl_fd) {
> +		ret = asprintf(&str, "0x%" PRIx64, val);

val could only be 0 or 1 in this function now, no uint64 needed, it 
could be something like:

     str = val? "0x1" : "0x0";

No string alloc/free needed.

> +		igt_assert_neq(ret, -1);
> +		ret = write(ctl_fd, str, ret);
> +		free(str);
> +		igt_assert_f(ret > 0, "couldn't write to the log control file\n");
> +	}
> +
> +	guc_log_verbosity(enable, log_level);
> +
> +	if (!enable) {
> +		igt_info("Closing control file\n");
> +		close(ctl_fd);
> +	}
>   }
>   
>   static void int_sig_handler(int sig)
> @@ -119,18 +193,18 @@ static void pull_leftover_data(void)
>   
>   	do {
>   		/* Read the logs from relay buffer */
> -		ret = read(relay_fd, read_buffer, SUBBUF_SIZE);
> +		ret = read(relay_fd, read_buffer, subbuf_size);
>   		if (!ret)
>   			break;
>   
> -		igt_assert_f(ret > 0, "failed to read from the guc log file\n");
> -		igt_assert_f(ret == SUBBUF_SIZE, "invalid read from relay file\n");
> +		igt_assert_f(ret > 0, "failed to read from the GuC log file\n");
> +		igt_assert_f(ret == subbuf_size, "invalid read from relay file\n");
>   
>   		bytes_read += ret;
>   
>   		if (outfile_fd >= 0) {
> -			ret = write(outfile_fd, read_buffer, SUBBUF_SIZE);
> -			igt_assert_f(ret == SUBBUF_SIZE, "couldn't dump the logs in a file\n");
> +			ret = write(outfile_fd, read_buffer, subbuf_size);
> +			igt_assert_f(ret == subbuf_size, "couldn't dump the logs in a file\n");
>   			total_bytes_written += ret;
>   		}
>   	} while(1);
> @@ -149,7 +223,7 @@ static void pull_data(void)
>   	int ret;
>   
>   	pthread_mutex_lock(&mutex);
> -	while (num_filled_bufs() >= num_buffers) {
> +	while (num_filled_bufs() >= subbuf_count) {
>   		igt_debug("overflow, will wait, produced %u, consumed %u\n", produced, consumed);
>   		/* Stall the main thread in case of overflow, as there are no
>   		 * buffers available to store the new logs, otherwise there
> @@ -159,12 +233,12 @@ static void pull_data(void)
>   	};
>   	pthread_mutex_unlock(&mutex);
>   
> -	ptr = read_buffer + (produced % num_buffers) * SUBBUF_SIZE;
> +	ptr = read_buffer + (produced % subbuf_count) * subbuf_size;
>   
>   	/* Read the logs from relay buffer */
> -	ret = read(relay_fd, ptr, SUBBUF_SIZE);
> -	igt_assert_f(ret >= 0, "failed to read from the guc log file\n");
> -	igt_assert_f(!ret || ret == SUBBUF_SIZE, "invalid read from relay file\n");
> +	ret = read(relay_fd, ptr, subbuf_size);
> +	igt_assert_f(ret >= 0, "failed to read from the GuC log file\n");
> +	igt_assert_f(!ret || ret == subbuf_size, "invalid read from relay file\n");
>   
>   	if (ret) {
>   		pthread_mutex_lock(&mutex);
> @@ -204,10 +278,10 @@ static void *flusher(void *arg)
>   		};
>   		pthread_mutex_unlock(&mutex);
>   
> -		ptr = read_buffer + (consumed % num_buffers) * SUBBUF_SIZE;
> +		ptr = read_buffer + (consumed % subbuf_count) * subbuf_size;
>   
> -		ret = write(outfile_fd, ptr, SUBBUF_SIZE);
> -		igt_assert_f(ret == SUBBUF_SIZE, "couldn't dump the logs in a file\n");
> +		ret = write(outfile_fd, ptr, subbuf_size);
> +		igt_assert_f(ret == subbuf_size, "couldn't dump the logs in a file\n");
>   
>   		total_bytes_written += ret;
>   		if (max_filesize && (total_bytes_written > MB(max_filesize))) {
> @@ -260,8 +334,13 @@ static void init_flusher_thread(void)
>   
>   static void open_relay_file(void)
>   {
> -	relay_fd = igt_debugfs_open(-1, RELAY_FILE_NAME, O_RDONLY);
> -	igt_assert_f(relay_fd >= 0, "couldn't open the guc log file\n");
> +	char *path;
> +
> +	igt_assert_neq(asprintf(&path, "%s/%s", gucfspath, GLR_CHANNEL_NAME), -1);
> +	igt_info("Opening this path -> %s\n", path);
> +	relay_fd = igt_debugfs_open(drm_fd, path, O_RDONLY);
> +	free(path);
> +	igt_assert_f(relay_fd >= 0, "couldn't open the GuC log relay-channel file\n");
>   
>   	/* Purge the old/boot-time logs from the relay buffer.
>   	 * This is more for Val team's requirement, where they have to first
> @@ -292,7 +371,7 @@ static void open_output_file(void)
>   
>   static void init_main_thread(void)
>   {
> -	struct sched_param	thread_sched;
> +	struct sched_param thread_sched;
>   	int ret;
>   
>   	/* Run the main thread at highest priority to ensure that it always
> @@ -311,11 +390,11 @@ static void init_main_thread(void)
>   		igt_assert_f(0, "SIGALRM handler registration failed\n");
>   
>   	/* Need an aligned pointer for direct IO */
> -	ret = posix_memalign((void **)&read_buffer, PAGE_SIZE, num_buffers * SUBBUF_SIZE);
> +	ret = posix_memalign((void **)&read_buffer, PAGE_SIZE, subbuf_count * subbuf_size);
>   	igt_assert_f(ret == 0, "couldn't allocate the read buffer\n");
>   
>   	/* Keep the pages locked in RAM, avoid page fault overhead */
> -	ret = mlock(read_buffer, num_buffers * SUBBUF_SIZE);
> +	ret = mlock(read_buffer, subbuf_count * subbuf_size);
>   	igt_assert_f(ret == 0, "failed to lock memory\n");
>   
>   	/* Enable the logging, it may not have been enabled from boot and so
> @@ -342,11 +421,6 @@ static int parse_options(int opt, int opt_index, void *data)
>   		igt_assert_f(out_filename, "Couldn't allocate the o/p filename\n");
>   		igt_debug("logs to be stored in file %s\n", out_filename);
>   		break;
> -	case 'b':
> -		num_buffers = atoi(optarg);
> -		igt_assert_f(num_buffers > 0, "invalid input for -b option\n");
> -		igt_debug("number of buffers to be used is %d\n", num_buffers);
> -		break;
>   	case 't':
>   		test_duration = atoi(optarg);
>   		igt_assert_f(test_duration > 0, "invalid input for -t option\n");
> @@ -377,7 +451,6 @@ static void process_command_line(int argc, char **argv)
>   	static struct option long_options[] = {
>   		{"verbosity", required_argument, 0, 'v'},
>   		{"outputfile", required_argument, 0, 'o'},
> -		{"buffers", required_argument, 0, 'b'},
>   		{"testduration", required_argument, 0, 't'},
>   		{"polltimeout", required_argument, 0, 'p'},
>   		{"size", required_argument, 0, 's'},
> @@ -388,7 +461,6 @@ static void process_command_line(int argc, char **argv)
>   	const char *help =
>   		"  -v --verbosity=level   verbosity level of GuC logging (0-3)\n"
>   		"  -o --outputfile=name   name of the output file, including the location, where logs will be stored\n"
> -		"  -b --buffers=num       number of buffers to be maintained on logger side for storing logs\n"
>   		"  -t --testduration=sec  max duration in seconds for which the logger should run\n"
>   		"  -p --polltimeout=ms    polling timeout in ms, -1 == indefinite wait for the new data\n"
>   		"  -s --size=MB           max size of output file in MBs after which logging will be stopped\n"
> @@ -404,6 +476,11 @@ int main(int argc, char **argv)
>   	int nfds;
>   	int ret;
>   
> +	drm_fd = drm_open_driver(DRIVER_INTEL);
> +	igt_assert(drm_fd != -1);
> +	igt_assert_neq(asprintf(&gucfspath, "gt0/uc"), -1);
> +
> +	get_guc_subbuf_info();
>   	process_command_line(argc, argv);
>   
Can we parse options before open driver? When run with -h, open driver 
is not expected.
>   	init_main_thread();
> @@ -466,5 +543,7 @@ int main(int argc, char **argv)
>   	free(read_buffer);
>   	close(relay_fd);
>   	close(outfile_fd);
> +	free(gucfspath);
> +	close(drm_fd);
>   	igt_exit();
>   }

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

* Re: [igt-dev] [i-g-t, v2, 02/11] tools/intel_guc_logger: Refactor intel_guc_logger globals into structs
  2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 02/11] tools/intel_guc_logger: Refactor intel_guc_logger globals into structs Alan Previn
@ 2023-02-01  0:04   ` Dong, Zhanjun
  2023-03-14 21:47     ` Teres Alexis, Alan Previn
  0 siblings, 1 reply; 19+ messages in thread
From: Dong, Zhanjun @ 2023-02-01  0:04 UTC (permalink / raw)
  To: Alan Previn, igt-dev

See my comments below.


Regards,

Zhanjun Dong

On 2022-12-06 3:58 a.m., Alan Previn wrote:
> Refactor all of the global variables used in intel_guc_logger
> into abstractions of structures at thread level, GuC-GT level
> and global level.
>
> While at it, remove asserts from the non primary thread to ensure
> process cleanup doesn't get stuck.
>
> Signed-off-by: Alan Previn<alan.previn.teres.alexis@intel.com>
> ---
>   tools/intel_guc_logger.c | 458 ++++++++++++++++++++++++---------------
>   1 file changed, 279 insertions(+), 179 deletions(-)
>
> diff --git a/tools/intel_guc_logger.c b/tools/intel_guc_logger.c
> index 4a991127..356cde59 100644
> --- a/tools/intel_guc_logger.c
> +++ b/tools/intel_guc_logger.c
> @@ -48,12 +48,12 @@
>     #define PAGE_SIZE 4096
>   #endif
>   
> -#define DEFAULT_OUTPUT_FILE_NAME  "guc_log_dump.dat"
> -
>   #define GLR_LOGLEVEL_NAME         "guc_log_level"
>   #define GLR_CTL_NAME              "guc_log_relay_ctl"
>   #define GLR_CHANNEL_NAME          "guc_log_relay_chan0"
>   
> +#define DEFAULT_OUTPUT_FILE_NAME     "guc_log_dump" /*.dat suffic added later*/
> +#define DEFAULT_GUCLOG_VERBOSITY     3 /* by default capture logs at max verbosity */
>   #define DEFAULT_SUBBUF_COUNT         (4 * 8)
>   					/* default to kernel built-in:   *
>   					 *   4 x 8 subbuf regions        *
> @@ -64,25 +64,54 @@
>   					 *   8K -> GuC crash dump        *
>   					 *  64K -> log events buffer     *
>   					 */
> -
> -int drm_fd;
> -char *read_buffer;
> -char *out_filename;
> -int poll_timeout = 2; /* by default 2ms timeout */
> -pthread_mutex_t mutex;
> -pthread_t flush_thread;
> -int verbosity_level = 3; /* by default capture logs at max verbosity */
> -uint32_t produced, consumed;
> -uint64_t total_bytes_written;
> -int subbuf_count;
> -int subbuf_size;
> -int ctl_fd, relay_fd, outfile_fd = -1;
> -uint32_t test_duration, max_filesize;
> -pthread_cond_t underflow_cond, overflow_cond;
> -bool stop_logging, discard_oldlogs, capturing_stopped;
> -char *gucfspath;
> -
> -static void get_guc_subbuf_info(void)
> +#define DEFAULT_POLL_TIMEOUT         2 /* default timeout of 2ms */
> +#define DEFAULT_MAX_OUTPUT_SIZE      MB(4 * 1024) /* default to 4 GB max file size */
> +
> +enum relay_cmd {
> +	RELAY_CMD_DISABLE = 0,
> +	RELAY_CMD_ENABLE = 1,
> +	RELAY_CMD_FLUSH = 2,
> +};
> +
> +struct guc_t {
> +	int gt_id;
> +	char *fspath;
> +	int control_fd;
> +	int relaychan;
> +	int outfd;
> +	char *readbuf;
> +	int subbuf_count;
> +	int subbuf_size;
> +	uint64_t total_bytes_written;
> +	pthread_mutex_t mutex;
> +	pthread_t flush_thread;
> +	pthread_cond_t underflow_cond;
> +	pthread_cond_t overflow_cond;
> +	int64_t produced;
> +	int64_t consumed;
> +	bool stop_logging;
> +	bool capturing_stopped;
> +};
> +
> +struct global_t {
> +	int drmfd;
> +	int verbosity;
> +	char *out_filename;
> +	uint64_t max_filesize;
> +	uint32_t test_duration;
> +	int poll_timeout;
> +	bool discard_oldlogs;
> +};
> +
> +struct thread_t {
> +	struct global_t *global;
> +	struct guc_t *guc;
> +};
> +
> +/* only global instance needed for killing threads from main's signal handler */
> +struct thread_t *gbl_thread_handle;
> +
> +static void get_guc_subbuf_info(struct thread_t *tdata)
>   {
>   	int fd, ret, j;
>   	char *path;
> @@ -92,9 +121,9 @@ static void get_guc_subbuf_info(void)
>   	uint64_t tmp[2] = {DEFAULT_SUBBUF_SIZE, DEFAULT_SUBBUF_COUNT};
>   
>   	for (j = 0; j < 2; j++) {
> -		igt_assert_neq(asprintf(&path, "%s/%s", gucfspath, dbg_fs_names[j]), -1);
> +		igt_assert_neq(asprintf(&path, "%s/%s", tdata->guc->fspath, dbg_fs_names[j]), -1);
>   		igt_info("Opening subbuf path %s\n", path);
> -		fd = igt_debugfs_open(drm_fd, path, O_RDONLY);
> +		fd = igt_debugfs_open(tdata->global->drmfd, path, O_RDONLY);
>   		free(path);
>   		igt_assert_f(fd >= 0, "couldn't open the GuC log relay-subbuf file\n");
>   		ret = read(fd, outstr, sizeof(outstr) - 1);
> @@ -103,35 +132,36 @@ static void get_guc_subbuf_info(void)
>   		tmp[j] = atoll(outstr);
>   		close(fd);
>   	}
> -	subbuf_size = tmp[0];
> -	subbuf_count = tmp[1];
> +	tdata->guc->subbuf_size = tmp[0];
> +	tdata->guc->subbuf_count = tmp[1];
>   	igt_info("Debugfs retrieved subbuf info: size=%d, count=%d\n",
> -		 subbuf_size, subbuf_count);
> +		 tdata->guc->subbuf_size, tdata->guc->subbuf_count);
>   }
>   
> -static void guc_log_verbosity(bool enable, int log_level)
> +static void guc_log_verbosity(struct thread_t *tdata, bool enable)
>   {
>   	char *str;
>   	int loglevelfd;
>   	uint64_t val;
>   	int ret;
>   
> -	igt_assert_neq(asprintf(&str, "%s/%s", gucfspath, GLR_LOGLEVEL_NAME), -1);
> +	igt_assert_neq(asprintf(&str, "%s/%s", tdata->guc->fspath, GLR_LOGLEVEL_NAME), -1);
>   	igt_info("Opening log level -> %s\n", str);
> -	loglevelfd = igt_debugfs_open(drm_fd, str, O_WRONLY);
> +	loglevelfd = igt_debugfs_open(tdata->global->drmfd, str, O_WRONLY);
>   	free(str);
>   	igt_assert_f(loglevelfd >= 0, "couldn't open the GuC log level file\n");
>   
>   	/*
>   	 * i915 expects GuC log level to be specified as:
>   	 * 0: disabled
> -	 * 1: enabled (verbosity level 0 = min)
> -	 * 2: enabled (verbosity level 1)
> -	 * 3: enabled (verbosity level 2)
> -	 * 4: enabled (verbosity level 3 = max)
> +	 * 1: enabled (non-verbose mode)
> +	 * 2: GuC verbosity level 0
> +	 * 3: GuC verbosity level 1
> +	 * 4: GuC verbosity level 2
> +	 * 5: GuC verbosity level 3
> +	 * intel_guc_logger takes input range of 0..3 that maps to 2..5 above.
>   	 */
> -	val = enable ? log_level + 1 : 0;
> -
> +	val = enable ? tdata->global->verbosity + 2 : 0;
>   	ret = asprintf(&str, "0x%" PRIx64, val);
>   	igt_assert_neq(ret, -1);
>   	ret = write(loglevelfd, str, ret);
> @@ -142,40 +172,37 @@ static void guc_log_verbosity(bool enable, int log_level)
>   	close(loglevelfd);
>   }
>   
> -static void guc_log_control(bool enable, uint32_t log_level)
> +static void guc_log_control(struct thread_t *tdata, enum relay_cmd cmd)
>   {
>   	char *str;
> -	uint64_t val = 0;
>   	int ret;
>   
> -	if (enable) {
> -		igt_assert_neq(asprintf(&str, "%s/%s", gucfspath, GLR_CTL_NAME), -1);
> +	igt_assert_f((cmd >= 0 && cmd <= 2), "Invalid GuC-log-control cmd!\n");
> +
> +	if (cmd == RELAY_CMD_ENABLE) {
> +		igt_assert_neq(asprintf(&str, "%s/%s", tdata->guc->fspath, GLR_CTL_NAME), -1);
>   		igt_info("Opening control file -> %s\n", str);
> -		ctl_fd = igt_debugfs_open(drm_fd, str, O_WRONLY);
> +		tdata->guc->control_fd = igt_debugfs_open(tdata->global->drmfd, str, O_WRONLY);
>   		free(str);
> -		igt_assert_f(ctl_fd >= 0, "couldn't open the GuC log relay-ctl file\n");
> -		val = 1;
> +		igt_assert_f(tdata->guc->control_fd >= 0, "Can't open GuC log relay-ctl file\n");
>   	}
>   
> -	/*
> -	 * i915 expects relay logging controls:
> -	 * 1    : open + enable relay logging
> -	 * 2    : flush
> -	 * 0    : disable relay logging + close
> -	 */
> -	if (ctl_fd) {
> -		ret = asprintf(&str, "0x%" PRIx64, val);
> +	if (tdata->guc->control_fd) {
> +		ret = asprintf(&str, "0x%" PRIx64, (unsigned long)cmd);
Why don't use typical int or unsigned int for max compatibility?
>   		igt_assert_neq(ret, -1);
> -		ret = write(ctl_fd, str, ret);
> +		ret = write(tdata->guc->control_fd, str, ret);
>   		free(str);
> -		igt_assert_f(ret > 0, "couldn't write to the log control file\n");
> -	}
> +		igt_assert_f(ret > 0, "couldn't set cmd-%u on log control file\n", cmd);
>   
> -	guc_log_verbosity(enable, log_level);
> +		if (cmd == RELAY_CMD_ENABLE)
> +			guc_log_verbosity(tdata, true);
> +	}
>   
> -	if (!enable) {
> +	if (cmd == RELAY_CMD_DISABLE) {
>   		igt_info("Closing control file\n");
> -		close(ctl_fd);
> +		guc_log_verbosity(tdata, false);
> +		close(tdata->guc->control_fd);
> +		tdata->guc->control_fd = 0;
>   	}
>   }
>   
> @@ -183,68 +210,82 @@ static void int_sig_handler(int sig)
>   {
>   	igt_info("received signal %d\n", sig);
>   
> -	stop_logging = true;
> +	if (!gbl_thread_handle)
> +		return;
> +
> +	if (gbl_thread_handle[0].guc)
> +		gbl_thread_handle[0].guc->stop_logging = true;
>   }
>   
> -static void pull_leftover_data(void)
> +static void pull_leftover_data(struct thread_t *tdata)
>   {
> +	struct guc_t *guc = tdata->guc;
>   	unsigned int bytes_read = 0;
> +	int subbuf_size = guc->subbuf_size;
>   	int ret;
>   
>   	do {
> -		/* Read the logs from relay buffer */
> -		ret = read(relay_fd, read_buffer, subbuf_size);
> +		/* Read the logs from relay channel buffer */
> +		ret = read(guc->relaychan, guc->readbuf, subbuf_size);
>   		if (!ret)
>   			break;
> -
> -		igt_assert_f(ret > 0, "failed to read from the GuC log file\n");
> -		igt_assert_f(ret == subbuf_size, "invalid read from relay file\n");
> -
> +		if (ret < 0) {
> +			igt_warn("failed leftover-read from GuC GT-%d relay-channel\n",
> +				 guc->gt_id);
> +			break;
> +		}
> +		if (ret != subbuf_size)
> +			igt_warn("invalid leftover-size from GuC GT-%d relay-channel\n",
> +				 guc->gt_id);
>   		bytes_read += ret;
> -
> -		if (outfile_fd >= 0) {
> -			ret = write(outfile_fd, read_buffer, subbuf_size);
> -			igt_assert_f(ret == subbuf_size, "couldn't dump the logs in a file\n");
> -			total_bytes_written += ret;
> +		if (guc->outfd >= 0) {
> +			ret = write(guc->outfd, guc->readbuf, subbuf_size);
> +			if (ret != subbuf_size)
> +				igt_warn("Couldn't dump leftover logs to file\n");
> +			guc->total_bytes_written += ret;
>   		}
>   	} while(1);
>   
> -	igt_debug("%u bytes flushed\n", bytes_read);
> +	igt_debug("%u bytes flushed from GuC GT-%d\n", bytes_read, guc->gt_id);
>   }
>   
> -static int num_filled_bufs(void)
> +static int num_filled_bufs(struct guc_t *guc)
>   {
> -	return (produced - consumed);
> +	return (guc->produced - guc->consumed);
>   }
>   
> -static void pull_data(void)
> +static void pull_data(struct thread_t *tdata)
>   {
>   	char *ptr;
>   	int ret;
> +	struct guc_t *guc = tdata->guc;
> +	int subbuf_size = guc->subbuf_size;
>   
> -	pthread_mutex_lock(&mutex);
> -	while (num_filled_bufs() >= subbuf_count) {
> -		igt_debug("overflow, will wait, produced %u, consumed %u\n", produced, consumed);
> +	pthread_mutex_lock(&guc->mutex);
> +	while (num_filled_bufs(guc) >= guc->subbuf_count) {
> +		igt_debug("overflow, will wait, produced %ld, consumed %ld\n",
> +			  guc->produced, guc->consumed);
>   		/* Stall the main thread in case of overflow, as there are no
>   		 * buffers available to store the new logs, otherwise there
>   		 * could be corruption if both threads work on the same buffer.
>   		 */
> -		pthread_cond_wait(&overflow_cond, &mutex);
> +		pthread_cond_wait(&guc->overflow_cond, &guc->mutex);
>   	};
> -	pthread_mutex_unlock(&mutex);
> +	pthread_mutex_unlock(&guc->mutex);
>   
> -	ptr = read_buffer + (produced % subbuf_count) * subbuf_size;
> +	ptr = guc->readbuf + (guc->produced % guc->subbuf_count) * subbuf_size;
>   
> -	/* Read the logs from relay buffer */
> -	ret = read(relay_fd, ptr, subbuf_size);
> +	/* Read the logs from relay channel buffer */
> +	ret = read(guc->relaychan, ptr, subbuf_size);
>   	igt_assert_f(ret >= 0, "failed to read from the GuC log file\n");
> -	igt_assert_f(!ret || ret == subbuf_size, "invalid read from relay file\n");
> +	igt_assert_f(!ret || ret <= subbuf_size, "invalid read from relay file\n");
>   
>   	if (ret) {
> -		pthread_mutex_lock(&mutex);
> -		produced++;
> -		pthread_cond_signal(&underflow_cond);
> -		pthread_mutex_unlock(&mutex);
> +		pthread_mutex_lock(&guc->mutex);
> +		guc->produced++;
> +		pthread_cond_signal(&guc->underflow_cond);
> +		pthread_mutex_unlock(&guc->mutex);
> +		igt_info("read %d KB from relay file\n", (ret / 1024));
>   	} else {
>   		/* Occasionally (very rare) read from the relay file returns no
>   		 * data, albeit the polling done prior to read call indicated
> @@ -257,56 +298,74 @@ static void pull_data(void)
>   static void *flusher(void *arg)
>   {
>   	char *ptr;
> -	int ret;
> +	int ret, subbuf_size;
> +	struct thread_t *tdata = (struct thread_t *)arg;
> +	struct global_t *gbl;
> +	struct guc_t *guc;
> +
> +	igt_assert_f(tdata, "Flusher didn't receive thread context ptr!\n");
> +	gbl = tdata->global;
> +	guc = tdata->guc;
> +	subbuf_size = guc->subbuf_size;
>   
>   	igt_debug("execution started of flusher thread\n");
>   
>   	do {
> -		pthread_mutex_lock(&mutex);
> -		while (!num_filled_bufs()) {
> +		pthread_mutex_lock(&guc->mutex);
> +		while (!num_filled_bufs(guc)) {
>   			/* Exit only after completing the flush of all the filled
>   			 * buffers as User would expect that all logs captured up
>   			 * till the point of interruption/exit are written out to
>   			 * the disk file.
>   			 */
> -			if (capturing_stopped) {
> +			if (guc->capturing_stopped) {
>   				igt_debug("flusher to exit now\n");
> -				pthread_mutex_unlock(&mutex);
> +				pthread_mutex_unlock(&guc->mutex);
>   				return NULL;
>   			}
> -			pthread_cond_wait(&underflow_cond, &mutex);
> +			pthread_cond_wait(&guc->underflow_cond, &guc->mutex);
>   		};
> -		pthread_mutex_unlock(&mutex);
> -
> -		ptr = read_buffer + (consumed % subbuf_count) * subbuf_size;
> +		pthread_mutex_unlock(&guc->mutex);
>   
> -		ret = write(outfile_fd, ptr, subbuf_size);
> -		igt_assert_f(ret == subbuf_size, "couldn't dump the logs in a file\n");
> +		ptr = guc->readbuf + (guc->consumed % guc->subbuf_count) * subbuf_size;
>   
> -		total_bytes_written += ret;
> -		if (max_filesize && (total_bytes_written > MB(max_filesize))) {
> -			igt_debug("reached the target of %" PRIu64 " bytes\n", MB(max_filesize));
> -			stop_logging = true;
> +		ret = write(guc->outfd, ptr, subbuf_size);
> +		if (ret < 0) {
> +			igt_warn("Dump to file failed with err %d, stopping!\n", ret);
> +			guc->stop_logging = true;
> +		} else if (!ret) {
> +			igt_warn("Dump to file flushed zero bytes!\n");
> +		} else {
> +			if (ret != subbuf_size)
> +				igt_warn("Dump size mismatch = %d!\n", ret);
> +			guc->total_bytes_written += ret;
> +			igt_info("wrote %d KB out to dat file\n", (ret / 1024));
> +			if (gbl->max_filesize && guc->total_bytes_written >
> +			    MB(gbl->max_filesize)) {
> +				igt_debug("reached the target of %" PRIu64 " bytes\n",
> +					  MB(gbl->max_filesize));
> +				guc->stop_logging = true;
> +			}
> +			pthread_mutex_lock(&guc->mutex);
> +			guc->consumed++;
> +			pthread_cond_signal(&guc->overflow_cond);
> +			pthread_mutex_unlock(&guc->mutex);
>   		}
> -
> -		pthread_mutex_lock(&mutex);
> -		consumed++;
> -		pthread_cond_signal(&overflow_cond);
> -		pthread_mutex_unlock(&mutex);
>   	} while(1);
>   
>   	return NULL;
>   }
>   
> -static void init_flusher_thread(void)
> +static void init_flusher_thread(struct thread_t *tdata)
>   {
> -	struct sched_param	thread_sched;
> -	pthread_attr_t		p_attr;
> +	struct sched_param thread_sched;
> +	pthread_attr_t p_attr;
> +	struct guc_t *guc = tdata->guc;
>   	int ret;
>   
> -	pthread_cond_init(&underflow_cond, NULL);
> -	pthread_cond_init(&overflow_cond, NULL);
> -	pthread_mutex_init(&mutex, NULL);
> +	pthread_cond_init(&guc->underflow_cond, NULL);
> +	pthread_cond_init(&guc->overflow_cond, NULL);
> +	pthread_mutex_init(&guc->mutex, NULL);
>   
>   	ret = pthread_attr_init(&p_attr);
>   	igt_assert_f(ret == 0, "error obtaining default thread attributes\n");
> @@ -325,22 +384,22 @@ static void init_flusher_thread(void)
>   	ret = pthread_attr_setschedparam(&p_attr, &thread_sched);
>   	igt_assert_f(ret == 0, "couldn't set thread priority\n");
>   
> -	ret = pthread_create(&flush_thread, &p_attr, flusher, NULL);
> +	ret = pthread_create(&guc->flush_thread, &p_attr, flusher, tdata);
>   	igt_assert_f(ret == 0, "thread creation failed\n");
>   
>   	ret = pthread_attr_destroy(&p_attr);
>   	igt_assert_f(ret == 0, "error destroying thread attributes\n");
>   }
>   
> -static void open_relay_file(void)
> +static void open_relay_file(struct thread_t *tdata)
>   {
>   	char *path;
>   
> -	igt_assert_neq(asprintf(&path, "%s/%s", gucfspath, GLR_CHANNEL_NAME), -1);
> +	igt_assert_neq(asprintf(&path, "%s/%s", tdata->guc->fspath, GLR_CHANNEL_NAME), -1);
>   	igt_info("Opening this path -> %s\n", path);
> -	relay_fd = igt_debugfs_open(drm_fd, path, O_RDONLY);
> +	tdata->guc->relaychan = igt_debugfs_open(tdata->global->drmfd, path, O_RDONLY);
>   	free(path);
> -	igt_assert_f(relay_fd >= 0, "couldn't open the GuC log relay-channel file\n");
> +	igt_assert_f(tdata->guc->relaychan >= 0, "couldn't open the GuC log relay-channel file\n");
>   
>   	/* Purge the old/boot-time logs from the relay buffer.
>   	 * This is more for Val team's requirement, where they have to first
> @@ -349,29 +408,39 @@ static void open_relay_file(void)
>   	 * wait for the new data, at that point benchmark can be launched from
>   	 * a different shell.
>   	 */
> -	if (discard_oldlogs)
> -		pull_leftover_data();
> +	if (tdata->global->discard_oldlogs)
> +		pull_leftover_data(tdata);
>   }
>   
> -static void open_output_file(void)
> +static void open_output_file(struct thread_t *tdata)
>   {
> +	char *path;
> +
>   	/* Use Direct IO mode for the output file, as the data written is not
>   	 * supposed to be accessed again, this saves a copy of data from App's
>   	 * buffer to kernel buffer (Page cache). Due to no buffering on kernel
>   	 * side, data is flushed out to disk faster and more buffering can be
>   	 * done on the logger side to hide the disk IO latency.
>   	 */
> -	outfile_fd = open(out_filename ? : DEFAULT_OUTPUT_FILE_NAME,
> -			  O_CREAT | O_WRONLY | O_TRUNC | O_DIRECT,
> -			  0440);
> -	igt_assert_f(outfile_fd >= 0, "couldn't open the output file\n");
> +	if (tdata->global->out_filename) {
> +		igt_assert_neq(asprintf(&path, "%s_GT%d.dat", tdata->global->out_filename,
> +					tdata->guc->gt_id), -1);
> +	} else {
> +		igt_assert_neq(asprintf(&path, "%s_GT%d.dat", DEFAULT_OUTPUT_FILE_NAME,
> +					tdata->guc->gt_id), -1);
> +	}
> +
> +	tdata->guc->outfd = open(path, O_CREAT | O_WRONLY | O_TRUNC | O_DIRECT, 0440);
> +	igt_assert_f(tdata->guc->outfd >= 0, "couldn't open the output file\n");
>   
> -	free(out_filename);
> +	igt_info("Creating output GuC-log-file: %s\n", path);
> +	free(path);
>   }
>   
> -static void init_main_thread(void)
> +static void init_main_thread(struct thread_t *tdata)
>   {
>   	struct sched_param thread_sched;
> +	struct guc_t *guc = tdata->guc;
>   	int ret;
>   
>   	/* Run the main thread at highest priority to ensure that it always
> @@ -390,55 +459,60 @@ static void init_main_thread(void)
>   		igt_assert_f(0, "SIGALRM handler registration failed\n");
>   
>   	/* Need an aligned pointer for direct IO */
> -	ret = posix_memalign((void **)&read_buffer, PAGE_SIZE, subbuf_count * subbuf_size);
> +	ret = posix_memalign((void **)&guc->readbuf, PAGE_SIZE,
> +			     (guc->subbuf_count * guc->subbuf_size));
>   	igt_assert_f(ret == 0, "couldn't allocate the read buffer\n");
>   
>   	/* Keep the pages locked in RAM, avoid page fault overhead */
> -	ret = mlock(read_buffer, subbuf_count * subbuf_size);
> +	ret = mlock(guc->readbuf, (guc->subbuf_count * guc->subbuf_size));
>   	igt_assert_f(ret == 0, "failed to lock memory\n");
>   
>   	/* Enable the logging, it may not have been enabled from boot and so
>   	 * the relay file also wouldn't have been created.
>   	 */
> -	guc_log_control(true, verbosity_level);
> -
> -	open_relay_file();
> -	open_output_file();
> +	guc_log_control(tdata, RELAY_CMD_ENABLE);
> +	open_relay_file(tdata);
> +	open_output_file(tdata);
>   }
>   
> -static int parse_options(int opt, int opt_index, void *data)
> +static int parse_options(int opt, int opt_index, void *ptr)
>   {
> +	struct global_t *data = (struct global_t *)ptr;
> +
> +	igt_assert(data);
>   	igt_debug("opt %c optarg %s\n", opt, optarg);
>   
>   	switch(opt) {
>   	case 'v':
> -		verbosity_level = atoi(optarg);
> -		igt_assert_f(verbosity_level >= 0 && verbosity_level <= 3, "invalid input for -v option\n");
> -		igt_debug("verbosity level to be used is %d\n", verbosity_level);
> +		data->verbosity = atoi(optarg);
> +		igt_assert_f(data->verbosity >= 0 && data->verbosity <= 3,
> +			     "invalid input for -v option\n");
> +		igt_debug("verbosity level to be used is %d\n", data->verbosity);
>   		break;
>   	case 'o':
> -		out_filename = strdup(optarg);
> -		igt_assert_f(out_filename, "Couldn't allocate the o/p filename\n");
> -		igt_debug("logs to be stored in file %s\n", out_filename);
> +		data->out_filename = strdup(optarg);
> +		igt_assert_f(data->out_filename, "Couldn't allocate the o/p filename\n");
> +		igt_debug("logs to be stored in file %s_G[GuC-ID]\n", data->out_filename);
>   		break;
>   	case 't':
> -		test_duration = atoi(optarg);
> -		igt_assert_f(test_duration > 0, "invalid input for -t option\n");
> -		igt_debug("logger to run for %d second\n", test_duration);
> +		data->test_duration = atoi(optarg);
> +		igt_assert_f(data->test_duration > 0, "invalid input for -t option\n");
> +		igt_debug("logger to run for %d second\n", data->test_duration);
>   		break;
>   	case 'p':
> -		poll_timeout = atoi(optarg);
> -		igt_assert_f(poll_timeout != 0, "invalid input for -p option\n");
> -		if (poll_timeout > 0)
> -			igt_debug("polling to be done with %d millisecond timeout\n", poll_timeout);
> +		data->poll_timeout = atoi(optarg);
> +		igt_assert_f(data->poll_timeout != 0, "invalid input for -p option\n");
> +		if (data->poll_timeout > 0)
> +			igt_debug("polling to be done with %d millisecond timeout\n",
> +				  data->poll_timeout);
>   		break;
>   	case 's':
> -		max_filesize = atoi(optarg);
> -		igt_assert_f(max_filesize > 0, "invalid input for -s option\n");
> -		igt_debug("max allowed size of the output file is %d MB\n", max_filesize);
> +		data->max_filesize = atoll(optarg);
> +		igt_assert_f(data->max_filesize > 0, "invalid input for -s option\n");
> +		igt_debug("max allowed size of the output file is %lu MB\n", data->max_filesize);
>   		break;
>   	case 'd':
> -		discard_oldlogs = true;
> +		data->discard_oldlogs = true;
>   		igt_debug("old/boot-time logs will be discarded\n");
>   		break;
How about unsupported option(s)?
>   	}
> @@ -446,7 +520,7 @@ static int parse_options(int opt, int opt_index, void *data)
>   	return 0;
>   }
>   
> -static void process_command_line(int argc, char **argv)
> +static void process_command_line(int argc, char **argv, struct global_t *data)
>   {
>   	static struct option long_options[] = {
>   		{"verbosity", required_argument, 0, 'v'},
> @@ -467,23 +541,39 @@ static void process_command_line(int argc, char **argv)
>   		"  -d --discard           discard the old/boot-time logs before entering into the capture loop\n";
>   
>   	igt_simple_init_parse_opts(&argc, argv, "v:o:b:t:p:s:d", long_options,
> -				   help, parse_options, NULL);
> +				   help, parse_options, data);
>   }
>   
>   int main(int argc, char **argv)
>   {
> +	struct global_t gbldata;
> +	/* For now, just one thread collecting logs from any single GuC source */
> +	struct guc_t gucdata[1];  /* only GT0 for now */
> +	struct thread_t thread[1];
>   	struct pollfd relay_poll_fd;
> -	int nfds;
> -	int ret;
> +	int nfds, ret;
>   
> -	drm_fd = drm_open_driver(DRIVER_INTEL);
> -	igt_assert(drm_fd != -1);
> -	igt_assert_neq(asprintf(&gucfspath, "gt0/uc"), -1);
> +	/* setup global context */
> +	memset(&gbldata, 0, sizeof(gbldata));
> +	gbldata.verbosity    = DEFAULT_GUCLOG_VERBOSITY;
> +	gbldata.poll_timeout = DEFAULT_POLL_TIMEOUT;
> +	gbldata.drmfd        = drm_open_driver_render(DRIVER_INTEL);
> +	igt_assert(gbldata.drmfd != -1);
>   
> -	get_guc_subbuf_info();
> -	process_command_line(argc, argv);
> +	memset(&gucdata[0], 0, sizeof(struct guc_t));
> +	gucdata[0].gt_id = 0;
> +	igt_assert_neq(asprintf(&gucdata[0].fspath, "gt/uc"), -1);
Depends on platform, name could be gt/uc or gt0/uc, gt1/uc
> +	gucdata[0].outfd = -1;
>   
> -	init_main_thread();
> +	thread[0].global = &gbldata;
> +	thread[0].guc = &gucdata[0];
> +	get_guc_subbuf_info(&thread[0]);
> +
> +	process_command_line(argc, argv, &gbldata);
> +
> +	gbl_thread_handle = thread;
> +
> +	init_main_thread(&thread[0]);
>   
>   	/* Use a separate thread for flushing the logs to a file on disk.
>   	 * Main thread will buffer the data from relay file in its pool of
> @@ -493,15 +583,15 @@ int main(int argc, char **argv)
>   	 * (/proc/sys/vm/dirty_ratio), kernel starts blocking the processes
>   	 * doing the file writes.
>   	 */
> -	init_flusher_thread();
> +	init_flusher_thread(&thread[0]);
>   
> -	relay_poll_fd.fd = relay_fd;
> +	relay_poll_fd.fd = thread[0].guc->relaychan;
>   	relay_poll_fd.events = POLLIN;
>   	relay_poll_fd.revents = 0;
>   
>   	nfds = 1; /* only one fd to poll */
>   
> -	alarm(test_duration); /* Start the alarm */
> +	alarm(gbldata.test_duration); /* Start the alarm */
>   
>   	do {
>   		/* Wait/poll for the new data to be available, relay doesn't
> @@ -515,7 +605,7 @@ int main(int argc, char **argv)
>   		 * succession (less than a jiffy gap between 2 flush interrupts)
>   		 * causing relay to run out of sub buffers to store new logs.
>   		 */
> -		ret = poll(&relay_poll_fd, nfds, poll_timeout);
> +		ret = poll(&relay_poll_fd, nfds, gbldata.poll_timeout);
>   		if (ret < 0) {
>   			if (errno == EINTR)
>   				break;
> @@ -526,24 +616,34 @@ int main(int argc, char **argv)
>   		if (!relay_poll_fd.revents)
>   			continue;
>   
> -		pull_data();
> -	} while (!stop_logging);
> +		pull_data(&thread[0]);
> +	} while (!thread[0].guc->stop_logging);
>   
>   	/* Pause logging on the GuC side */
> -	guc_log_control(false, 0);
> +	guc_log_control(&thread[0], RELAY_CMD_FLUSH);
> +	guc_log_control(&thread[0], RELAY_CMD_DISABLE);
>   
>   	/* Signal flusher thread to make an exit */
> -	capturing_stopped = 1;
> -	pthread_cond_signal(&underflow_cond);
> -	pthread_join(flush_thread, NULL);
> -
> -	pull_leftover_data();
> -	igt_info("total bytes written %" PRIu64 "\n", total_bytes_written);
> -
> -	free(read_buffer);
> -	close(relay_fd);
> -	close(outfile_fd);
> -	free(gucfspath);
> -	close(drm_fd);
> +	thread[0].guc->capturing_stopped = 1;
> +	pthread_cond_signal(&thread[0].guc->underflow_cond);
> +	pthread_join(thread[0].guc->flush_thread, NULL);
> +	pull_leftover_data(&thread[0]);
> +	igt_info("total bytes written %" PRIu64 "\n", thread[0].guc->total_bytes_written);
> +
> +	if (gucdata[0].outfd)
> +		close(gucdata[0].outfd);
> +	if (gucdata[0].relaychan > 0)
> +		close(gucdata[0].relaychan);
> +	if (gucdata[0].control_fd > 0)
> +		close(gucdata[0].control_fd);
> +	if (gucdata[0].readbuf)
> +		free(gucdata[0].readbuf);
> +	if (gucdata[0].fspath)
> +		free(gucdata[0].fspath);
> +
> +	if (gbldata.out_filename)
> +		free(gbldata.out_filename);
> +	close(gbldata.drmfd);
> +
>   	igt_exit();
>   }

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

* Re: [igt-dev] [i-g-t, v2, 01/11] tools/intel_guc_logger: Re-enable basic functionality
  2023-01-20 20:26   ` [igt-dev] [i-g-t, v2, " Dong, Zhanjun
@ 2023-03-14 21:46     ` Teres Alexis, Alan Previn
  0 siblings, 0 replies; 19+ messages in thread
From: Teres Alexis, Alan Previn @ 2023-03-14 21:46 UTC (permalink / raw)
  To: Dong, Zhanjun, igt-dev

thanks for reviewing - will rerev with below fixes

On Fri, 2023-01-20 at 15:26 -0500, Dong, Zhanjun wrote:
> See my comments inline below.
> 
> 
> Regards,
> 
> Zhanjun Dong
> 
> 
> On 2022-12-06 3:58 a.m., Alan Previn wrote:
> > Fix these multiple issues to get basic functionality up
> > and running on GuC using:
> > 
> > 
> > 
alan:snip
> > +	subbuf_size = tmp[0];
> > +	subbuf_count = tmp[1];
> How about define tmp[x] the same data type as subbuf_xxx to avoid type 
> rang diff?
> > 
> > 
sure - will fix

alan:snip
> > -	ret = write(control_fd, data, ret);
> > -	igt_assert_f(ret > 0, "couldn't write to the log control file\n");
> > +static void guc_log_control(bool enable, uint32_t log_level)
> How about to have the same log_level type among the file?

right - will fix this.

alan:snip
> > +
> 
> val could only be 0 or 1 in this function now, no uint64 needed, it 
> could be something like:
> 
>      str = val? "0x1" : "0x0";
> 
> No string alloc/free needed.

alan: actually in coming patches more we end up with 3 options "0x1", "0x2" or "0x3".
instead, i could add a local array of 'const char * array_strings = { "0x1", "0x2", "0x3" };'
and use string 'array_strings[val-1]' (after verifying val)?
since its a known short list, we dont need to use the asprintf

alan:snip
> > @@ -404,6 +476,11 @@ int main(int argc, char **argv)
> >   	int nfds;
> >   	int ret;
> >   
> > +	drm_fd = drm_open_driver(DRIVER_INTEL);
> > +	igt_assert(drm_fd != -1);
> > +	igt_assert_neq(asprintf(&gucfspath, "gt0/uc"), -1);
> > +
> > +	get_guc_subbuf_info();
> >   	process_command_line(argc, argv);
> >   
> Can we parse options before open driver? When run with -h, open driver 
> is not expected.

alan: as per our offline joint debug: yes definitely :)


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

* Re: [igt-dev] [i-g-t, v2, 02/11] tools/intel_guc_logger: Refactor intel_guc_logger globals into structs
  2023-02-01  0:04   ` [igt-dev] [i-g-t, v2, " Dong, Zhanjun
@ 2023-03-14 21:47     ` Teres Alexis, Alan Previn
  0 siblings, 0 replies; 19+ messages in thread
From: Teres Alexis, Alan Previn @ 2023-03-14 21:47 UTC (permalink / raw)
  To: Dong, Zhanjun, igt-dev

On Tue, 2023-01-31 at 19:04 -0500, Dong, Zhanjun wrote:
> See my comments below.
> 
> 
> Regards,
> 
> Zhanjun Dong
> 
> On 2022-12-06 3:58 a.m., Alan Previn wrote:
> > Refactor all of the global variables used in intel_guc_logger
> > into abstractions of structures at thread level, GuC-GT level
> > and global level.
> > 
> > While at it, remove asserts from the non primary thread to ensure
> > process cleanup doesn't get stuck.
> > 
alan:snip

> > -	if (ctl_fd) {
> > -		ret = asprintf(&str, "0x%" PRIx64, val);
> > +	if (tdata->guc->control_fd) {
> > +		ret = asprintf(&str, "0x%" PRIx64, (unsigned long)cmd);
> Why don't use typical int or unsigned int for max compatibility?
alan:sure will change to "int" like patch #1 direction and change the enum names to #defines.
side note: above code will look different, not using asprintf, not needing typecase after i fix
it as per your review comment of patch 1 anyway. I will change to int anyway.
alan:snip

> >   	case 'd':
> > -		discard_oldlogs = true;
> > +		data->discard_oldlogs = true;
> >   		igt_debug("old/boot-time logs will be discarded\n");
> >   		break;
> How about unsupported option(s)?
alan: i believe the igt helper takes care of that.
alan:snip

> >   -	get_guc_subbuf_info();
> > -	process_command_line(argc, argv);
> > +	memset(&gucdata[0], 0, sizeof(struct guc_t));
> > +	gucdata[0].gt_id = 0;
> > +	igt_assert_neq(asprintf(&gucdata[0].fspath, "gt/uc"), -1);
> Depends on platform, name could be gt/uc or gt0/uc, gt1/uc
alan: yeah thanks - this series last rev was published sometime back - but i will fix this
on the next patch that properly handles multi-gt platforms - for this patch #2, I'll
keept defaulting to single-gt product only as above. the next patch needs to be fixed for that.


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

* Re: [igt-dev] [PATCH i-g-t v2 03/11] tools/intel_guc_logger: Add GT-ID selection for intel_guc_logger
  2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 03/11] tools/intel_guc_logger: Add GT-ID selection for intel_guc_logger Alan Previn
@ 2023-03-14 21:54   ` Teres Alexis, Alan Previn
  0 siblings, 0 replies; 19+ messages in thread
From: Teres Alexis, Alan Previn @ 2023-03-14 21:54 UTC (permalink / raw)
  To: igt-dev

On Tue, 2022-12-06 at 00:58 -0800, Alan Previn wrote:
> With the introduction of MTL and multi-tile products, add a new
> cmd line param for users to select which GT to collect GuC relay
> logs from.
> 
alan:snip
> @@ -538,9 +569,10 @@ static void process_command_line(int argc, char **argv, struct global_t *data)
>  		"  -t --testduration=sec  max duration in seconds for which the logger should run\n"
>  		"  -p --polltimeout=ms    polling timeout in ms, -1 == indefinite wait for the new data\n"
>  		"  -s --size=MB           max size of output file in MBs after which logging will be stopped\n"
> -		"  -d --discard           discard the old/boot-time logs before entering into the capture loop\n";
> +		"  -d --discard           discard the old/boot-time logs before entering into the capture loop\n"
> +		"  -i --gt_id             GT-ID of GuC to capture from, defaults to capture from gt0\n";
>  
> -	igt_simple_init_parse_opts(&argc, argv, "v:o:b:t:p:s:d", long_options,
> +	igt_simple_init_parse_opts(&argc, argv, "v:o:b:t:p:s:d:i", long_options,
alan: when retesting with MTL with both gt's, i realize above is a typo bug ... should have been "v:o:b:t:p:s:di:" ('i' needs the param).

alan:snip


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

end of thread, other threads:[~2023-03-14 21:54 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-12-06  8:58 [igt-dev] [PATCH i-g-t v2 00/11] Resurrect GuC Relay Logging Alan Previn
2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 01/11] tools/intel_guc_logger: Re-enable basic functionality Alan Previn
2023-01-20 20:26   ` [igt-dev] [i-g-t, v2, " Dong, Zhanjun
2023-03-14 21:46     ` Teres Alexis, Alan Previn
2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 02/11] tools/intel_guc_logger: Refactor intel_guc_logger globals into structs Alan Previn
2023-02-01  0:04   ` [igt-dev] [i-g-t, v2, " Dong, Zhanjun
2023-03-14 21:47     ` Teres Alexis, Alan Previn
2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 03/11] tools/intel_guc_logger: Add GT-ID selection for intel_guc_logger Alan Previn
2023-03-14 21:54   ` Teres Alexis, Alan Previn
2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 04/11] tools/intel_guc_logger: Add helper function for flusher code Alan Previn
2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 05/11] tools/intel_guc_logger: Add GuC Log header structure definition Alan Previn
2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 06/11] tools/intel_guc_logger: Concatenate log samples into a contiguous file Alan Previn
2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 07/11] tools/intel_guc_logger: Add overflow awareness Alan Previn
2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 08/11] tools/intel_guc_logger: Limit relay logging output file to 4GB Alan Previn
2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 09/11] tools/intel_guc_logger: By default don't change GuC log verbosity Alan Previn
2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 10/11] tools/intel_guc_logger: On exit, save any leftover GuC log data Alan Previn
2022-12-06  8:58 ` [igt-dev] [PATCH i-g-t v2 11/11] tools/intel_guc_logger: Add useful debug messages Alan Previn
2022-12-06  9:41 ` [igt-dev] ✓ Fi.CI.BAT: success for Resurrect GuC Relay Logging (rev2) Patchwork
2022-12-06 11:27 ` [igt-dev] ✓ Fi.CI.IGT: " 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.