All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tomeu Vizoso <tomeu.vizoso@collabora.com>
To: Intel GFX discussion <intel-gfx@lists.freedesktop.org>
Cc: Daniel Vetter <daniel.vetter@intel.com>,
	Tomeu Vizoso <tomeu.vizoso@collabora.com>
Subject: [PATCH i-g-t v3] lib/debugfs: Support new generic ABI for CRC capture
Date: Thu, 29 Sep 2016 17:04:04 +0200	[thread overview]
Message-ID: <1475161444-18329-1-git-send-email-tomeu.vizoso@collabora.com> (raw)

The kernel has now a new debugfs ABI that can also allow capturing frame
CRCs for drivers other than i915.

Add alternative codepaths so the new ABI is used if the kernel is recent
enough, and fall back to the legacy ABI if not.

Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
---

Have just dropped the additional testing of the legacy ABI if the new one is
available, so we just fallback to the old one if needed.

---
 lib/igt_debugfs.c          | 188 +++++++++++++++++++++++++++++++++------------
 lib/igt_debugfs.h          |   4 +-
 tests/kms_pipe_crc_basic.c |  38 ++++-----
 3 files changed, 158 insertions(+), 72 deletions(-)

diff --git a/lib/igt_debugfs.c b/lib/igt_debugfs.c
index fb13a88bf8cd..89b8d5ba98ca 100644
--- a/lib/igt_debugfs.c
+++ b/lib/igt_debugfs.c
@@ -25,6 +25,7 @@
 #include <inttypes.h>
 #include <sys/stat.h>
 #include <sys/mount.h>
+#include <dirent.h>
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -290,25 +291,23 @@ char *igt_crc_to_string(igt_crc_t *crc)
 {
 	char buf[128];
 
-	igt_assert_eq(crc->n_words, 5);
-
 	sprintf(buf, "%08x %08x %08x %08x %08x", crc->crc[0],
 		crc->crc[1], crc->crc[2], crc->crc[3], crc->crc[4]);
 
 	return strdup(buf);
 }
 
+#define MAX_CRC_ENTRIES 10
+#define MAX_LINE_LEN (10 + 11 * MAX_CRC_ENTRIES + 1)
+
 /* (6 fields, 8 chars each, space separated (5) + '\n') */
-#define PIPE_CRC_LINE_LEN       (6 * 8 + 5 + 1)
-/* account for \'0' */
-#define PIPE_CRC_BUFFER_LEN     (PIPE_CRC_LINE_LEN + 1)
+#define LEGACY_LINE_LEN       (6 * 8 + 5 + 1)
 
 struct _igt_pipe_crc {
 	int ctl_fd;
 	int crc_fd;
-	int line_len;
-	int buffer_len;
 	int flags;
+	bool is_legacy;
 
 	enum pipe pipe;
 	enum intel_pipe_crc_source source;
@@ -339,13 +338,26 @@ static bool igt_pipe_crc_do_start(igt_pipe_crc_t *pipe_crc)
 	/* Stop first just to make sure we don't have lingering state left. */
 	igt_pipe_crc_stop(pipe_crc);
 
-	sprintf(buf, "pipe %s %s", kmstest_pipe_name(pipe_crc->pipe),
-		pipe_crc_source_name(pipe_crc->source));
+	if (pipe_crc->is_legacy)
+		sprintf(buf, "pipe %s %s", kmstest_pipe_name(pipe_crc->pipe),
+			pipe_crc_source_name(pipe_crc->source));
+	else
+		sprintf(buf, "%s", pipe_crc_source_name(pipe_crc->source));
+
 	errno = 0;
 	igt_assert_eq(write(pipe_crc->ctl_fd, buf, strlen(buf)), strlen(buf));
 	if (errno != 0)
 		return false;
 
+	if (!pipe_crc->is_legacy) {
+		sprintf(buf, "crtc-%d/crc/data", pipe_crc->pipe);
+		errno = 0;
+		pipe_crc->crc_fd = igt_debugfs_open(buf, pipe_crc->flags);
+		if (pipe_crc->crc_fd == -1 && errno == EINVAL)
+			return false;
+		igt_assert_eq(errno, 0);
+	}
+
 	return true;
 }
 
@@ -359,15 +371,45 @@ static void igt_pipe_crc_pipe_off(int fd, enum pipe pipe)
 
 static void igt_pipe_crc_reset(void)
 {
+	igt_debugfs_t *debugfs = __igt_debugfs_singleton();
 	int fd;
+	struct dirent *dirent;
+	char buf[128];
+	const char *cmd = "none";
+	bool done = false;
+	DIR *dir;
+
+	dir = opendir(debugfs->dri_path);
+	if (dir) {
+		while ((dirent = readdir(dir))) {
+			if (strcmp(dirent->d_name, "crtc-") != 0)
+				continue;
+
+			sprintf(buf, "%s/%s/crc/control", debugfs->dri_path,
+				dirent->d_name);
+			fd = open(buf, O_WRONLY);
+			if (fd == -1)
+				continue;
+
+			igt_assert_eq(write(fd, cmd, strlen(cmd)), strlen(cmd));
+			done = true;
+
+			close(fd);
+		}
+		closedir(dir);
+	}
 
-	fd = igt_debugfs_open("i915_display_crc_ctl", O_WRONLY);
+	if (done)
+		return;
 
-	igt_pipe_crc_pipe_off(fd, PIPE_A);
-	igt_pipe_crc_pipe_off(fd, PIPE_B);
-	igt_pipe_crc_pipe_off(fd, PIPE_C);
+	fd = igt_debugfs_open("i915_display_crc_ctl", O_WRONLY);
+	if (fd != -1) {
+		igt_pipe_crc_pipe_off(fd, PIPE_A);
+		igt_pipe_crc_pipe_off(fd, PIPE_B);
+		igt_pipe_crc_pipe_off(fd, PIPE_C);
 
-	close(fd);
+		close(fd);
+	}
 }
 
 static void pipe_crc_exit_handler(int sig)
@@ -389,13 +431,16 @@ void igt_require_pipe_crc(void)
 	size_t written;
 	int ret;
 
-	ctl = igt_debugfs_fopen("i915_display_crc_ctl", "r+");
-	igt_require_f(ctl,
-		      "No display_crc_ctl found, kernel too old\n");
-	written = fwrite(cmd, 1, strlen(cmd), ctl);
-	ret = fflush(ctl);
-	igt_require_f((written == strlen(cmd) && ret == 0) || errno != ENODEV,
-		      "CRCs not supported on this platform\n");
+	ctl = igt_debugfs_fopen("crtc-0/crc/control", "r+");
+	if (!ctl) {
+		ctl = igt_debugfs_fopen("i915_display_crc_ctl", "r+");
+		igt_require_f(ctl,
+			      "No display_crc_ctl found, kernel too old\n");
+		written = fwrite(cmd, 1, strlen(cmd), ctl);
+		ret = fflush(ctl);
+		igt_require_f((written == strlen(cmd) && ret == 0) || errno != ENODEV,
+			      "CRCs not supported on this platform\n");
+	}
 
 	fclose(ctl);
 }
@@ -410,15 +455,23 @@ pipe_crc_new(enum pipe pipe, enum intel_pipe_crc_source source, int flags)
 
 	pipe_crc = calloc(1, sizeof(struct _igt_pipe_crc));
 
-	pipe_crc->ctl_fd = igt_debugfs_open("i915_display_crc_ctl", O_WRONLY);
-	igt_assert(pipe_crc->ctl_fd != -1);
+	sprintf(buf, "crtc-%d/crc/control", pipe);
+	pipe_crc->ctl_fd = igt_debugfs_open(buf, O_WRONLY);
+	if (pipe_crc->ctl_fd == -1) {
+		pipe_crc->ctl_fd = igt_debugfs_open("i915_display_crc_ctl",
+						    O_WRONLY);
+		igt_assert(pipe_crc->ctl_fd != -1);
+		pipe_crc->is_legacy = true;
+	}
 
-	sprintf(buf, "i915_pipe_%s_crc", kmstest_pipe_name(pipe));
-	pipe_crc->crc_fd = igt_debugfs_open(buf, flags);
-	igt_assert(pipe_crc->crc_fd != -1);
+	if (pipe_crc->is_legacy) {
+		sprintf(buf, "i915_pipe_%s_crc", kmstest_pipe_name(pipe));
+		pipe_crc->crc_fd = igt_debugfs_open(buf, flags);
+		igt_assert(pipe_crc->crc_fd != -1);
+	} else {
+		pipe_crc->crc_fd = -1;
+	}
 
-	pipe_crc->line_len = PIPE_CRC_LINE_LEN;
-	pipe_crc->buffer_len = PIPE_CRC_BUFFER_LEN;
 	pipe_crc->pipe = pipe;
 	pipe_crc->source = source;
 	pipe_crc->flags = flags;
@@ -478,34 +531,59 @@ void igt_pipe_crc_free(igt_pipe_crc_t *pipe_crc)
 	free(pipe_crc);
 }
 
-static bool pipe_crc_init_from_string(igt_crc_t *crc, const char *line)
+static bool pipe_crc_init_from_string(igt_pipe_crc_t *pipe_crc, igt_crc_t *crc,
+				      const char *line)
 {
-	int n;
+	int n, i;
+	const char *buf;
 
-	crc->n_words = 5;
-	n = sscanf(line, "%8u %8x %8x %8x %8x %8x", &crc->frame, &crc->crc[0],
-		   &crc->crc[1], &crc->crc[2], &crc->crc[3], &crc->crc[4]);
-	return n == 6;
+	if (pipe_crc->is_legacy) {
+		crc->has_valid_frame = true;
+		crc->n_words = 5;
+		n = sscanf(line, "%8u %8x %8x %8x %8x %8x", &crc->frame,
+			   &crc->crc[0], &crc->crc[1], &crc->crc[2],
+			   &crc->crc[3], &crc->crc[4]);
+		return n == 6;
+	}
+
+	if (strncmp(line, "XXXXXXXXXX", 10) == 0)
+		crc->has_valid_frame = false;
+	else {
+		crc->has_valid_frame = true;
+		crc->frame = strtoul(line, NULL, 16);
+	}
+
+	buf = line + 10;
+	for (i = 0; *buf != '\n'; i++, buf += 11)
+		crc->crc[i] = strtoul(buf, NULL, 16);
+
+	crc->n_words = i;
+
+	return true;
 }
 
 static int read_crc(igt_pipe_crc_t *pipe_crc, igt_crc_t *out)
 {
 	ssize_t bytes_read;
-	char buf[pipe_crc->buffer_len];
+	char buf[MAX_LINE_LEN + 1];
+	size_t read_len;
+
+	if (pipe_crc->is_legacy)
+		read_len = LEGACY_LINE_LEN;
+	else
+		read_len = MAX_LINE_LEN;
 
 	igt_set_timeout(5, "CRC reading");
-	bytes_read = read(pipe_crc->crc_fd, &buf, pipe_crc->line_len);
+	bytes_read = read(pipe_crc->crc_fd, &buf, read_len);
 	igt_reset_timeout();
 
 	if (bytes_read < 0 && errno == EAGAIN) {
 		igt_assert(pipe_crc->flags & O_NONBLOCK);
 		bytes_read = 0;
-	} else {
-		igt_assert_eq(bytes_read, pipe_crc->line_len);
 	}
 	buf[bytes_read] = '\0';
 
-	if (bytes_read && !pipe_crc_init_from_string(out, buf))
+	if (bytes_read && !pipe_crc_init_from_string(pipe_crc, out, buf))
 		return -EINVAL;
 
 	return bytes_read;
@@ -529,15 +607,18 @@ void igt_pipe_crc_start(igt_pipe_crc_t *pipe_crc)
 
 	igt_assert(igt_pipe_crc_do_start(pipe_crc));
 
-	/*
-	 * For some no yet identified reason, the first CRC is bonkers. So
-	 * let's just wait for the next vblank and read out the buggy result.
-	 *
-	 * On CHV sometimes the second CRC is bonkers as well, so don't trust
-	 * that one either.
-	 */
-	read_one_crc(pipe_crc, &crc);
-	read_one_crc(pipe_crc, &crc);
+	if (pipe_crc->is_legacy) {
+		/*
+		 * For some no yet identified reason, the first CRC is
+		 * bonkers. So let's just wait for the next vblank and read
+		 * out the buggy result.
+		 *
+		 * On CHV sometimes the second CRC is bonkers as well, so
+		 * don't trust that one either.
+		 */
+		read_one_crc(pipe_crc, &crc);
+		read_one_crc(pipe_crc, &crc);
+	}
 }
 
 /**
@@ -550,8 +631,15 @@ void igt_pipe_crc_stop(igt_pipe_crc_t *pipe_crc)
 {
 	char buf[32];
 
-	sprintf(buf, "pipe %s none", kmstest_pipe_name(pipe_crc->pipe));
-	igt_assert_eq(write(pipe_crc->ctl_fd, buf, strlen(buf)), strlen(buf));
+	if (pipe_crc->is_legacy) {
+		sprintf(buf, "pipe %s none",
+			kmstest_pipe_name(pipe_crc->pipe));
+		igt_assert_eq(write(pipe_crc->ctl_fd, buf, strlen(buf)),
+			      strlen(buf));
+	} else {
+		close(pipe_crc->crc_fd);
+		pipe_crc->crc_fd = -1;
+	}
 }
 
 /**
diff --git a/lib/igt_debugfs.h b/lib/igt_debugfs.h
index 8289e9d09c4a..e1f7076b6dc7 100644
--- a/lib/igt_debugfs.h
+++ b/lib/igt_debugfs.h
@@ -62,6 +62,7 @@ bool igt_debugfs_search(const char *filename, const char *substring);
  */
 typedef struct _igt_pipe_crc igt_pipe_crc_t;
 
+#define DRM_MAX_CRC_NR 10
 /**
  * igt_crc_t:
  * @frame: frame number of the capture CRC
@@ -73,8 +74,9 @@ typedef struct _igt_pipe_crc igt_pipe_crc_t;
  */
 typedef struct {
 	uint32_t frame;
+	bool has_valid_frame;
 	int n_words;
-	uint32_t crc[5];
+	uint32_t crc[DRM_MAX_CRC_NR];
 } igt_crc_t;
 
 /**
diff --git a/tests/kms_pipe_crc_basic.c b/tests/kms_pipe_crc_basic.c
index 2d2f2d698486..a45736b0d54e 100644
--- a/tests/kms_pipe_crc_basic.c
+++ b/tests/kms_pipe_crc_basic.c
@@ -43,19 +43,24 @@ static struct {
 	{ .r = 0.0, .g = 1.0, .b = 1.0 },
 };
 
-static void test_bad_command(data_t *data, const char *cmd)
+static void test_bad_source(data_t *data)
 {
-	FILE *ctl;
+	FILE *f;
 	size_t written;
-
-	ctl = igt_debugfs_fopen("i915_display_crc_ctl", "r+");
-	written = fwrite(cmd, 1, strlen(cmd), ctl);
-	fflush(ctl);
-	igt_assert_eq(written, strlen(cmd));
-	igt_assert(ferror(ctl));
+	const char *source = "foo";
+
+	f = igt_debugfs_fopen("crtc-0/crc/control", "w");
+	igt_require(f);
+	written = fwrite(source, 1, strlen(source), f);
+	fflush(f);
+	igt_assert_eq(written, strlen(source));
+	igt_assert(!ferror(f));
+	igt_assert(!errno);
+	fclose(f);
+
+	f = igt_debugfs_fopen("crtc-0/crc/data", "w");
+	igt_assert(!f);
 	igt_assert_eq(errno, EINVAL);
-
-	fclose(ctl);
 }
 
 #define N_CRCS	3
@@ -185,7 +190,7 @@ igt_main
 	igt_skip_on_simulation();
 
 	igt_fixture {
-		data.drm_fd = drm_open_driver_master(DRIVER_INTEL);
+		data.drm_fd = drm_open_driver_master(DRIVER_ANY);
 
 		igt_enable_connectors();
 
@@ -196,17 +201,8 @@ igt_main
 		igt_display_init(&data.display, data.drm_fd);
 	}
 
-	igt_subtest("bad-pipe")
-		test_bad_command(&data, "pipe D none");
-
 	igt_subtest("bad-source")
-		test_bad_command(&data, "pipe A foo");
-
-	igt_subtest("bad-nb-words-1")
-		test_bad_command(&data, "pipe foo");
-
-	igt_subtest("bad-nb-words-3")
-		test_bad_command(&data, "pipe A none option");
+		test_bad_source(&data);
 
 	for (int i = 0; i < 3; i++) {
 		igt_subtest_f("read-crc-pipe-%c", 'A'+i)
-- 
2.7.4

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

             reply	other threads:[~2016-09-29 15:05 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-09-29 15:04 Tomeu Vizoso [this message]
2016-11-17  9:31 [PATCH i-g-t v3] lib/debugfs: Support new generic ABI for CRC capture Tomeu Vizoso
2016-11-29 21:40 ` Robert Foss

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1475161444-18329-1-git-send-email-tomeu.vizoso@collabora.com \
    --to=tomeu.vizoso@collabora.com \
    --cc=daniel.vetter@intel.com \
    --cc=intel-gfx@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.