diff mbox

[IGT,11/11] lib: Add igt_psr_get_sink_crc() and change tests to use it.

Message ID 1499813316-15038-12-git-send-email-jim.bride@linux.intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

jim.bride@linux.intel.com July 11, 2017, 10:48 p.m. UTC
Our tests were sometimes using the string representation of the sink CRC
and sometimes a binary version, so for consistency's sake, as well as to
make the utility function return something closer to what the eDP spec
talks about, all sink CRC operations are now assuming that the sink CRC
is retrieved in binary form.

Signed-off-by: Jim Bride <jim.bride@linux.intel.com>
---
 lib/igt_psr.c                    | 59 ++++++++++++++++++++++++++++++++
 lib/igt_psr.h                    |  2 ++
 tests/kms_frontbuffer_tracking.c | 25 ++++++--------
 tests/kms_psr_sink_crc.c         | 74 ++++++++++++++++++----------------------
 4 files changed, 105 insertions(+), 55 deletions(-)
diff mbox

Patch

diff --git a/lib/igt_psr.c b/lib/igt_psr.c
index 2fda467..9ea2b93 100644
--- a/lib/igt_psr.c
+++ b/lib/igt_psr.c
@@ -172,3 +172,62 @@  bool igt_psr_find_good_mode(drmModeConnectorPtr connector,
 	}
 	return false;
 }
+
+/**
+ * igt_psr_open_sink_crc:
+ * @drm_fd: a file descriptor to the drm debugfs tree
+ *
+ * Returns a valid file descriptor to the sink CRC debugfs file
+ * if successful or -1 on an error.
+ */
+int igt_psr_open_sink_crc(int drm_fd)
+{
+	int crc_fd;
+
+	crc_fd = openat(drm_fd, "i915_sink_crc_eDP1", O_RDONLY);
+	igt_assert_lte(0, crc_fd);
+	return crc_fd;
+}
+
+
+/**
+ * igt_psr_get_sink_crc:
+ * @fd: a file descriptor to the sink CRC debugfs node
+ * @data: A six byte array of characters that holds the read CRC values
+ *
+ * Returns 0 on success non-zero on error.
+ */
+int igt_psr_get_sink_crc(int fd, char *data)
+{
+	int rc, errno_;
+	char buf[13]; /* two chars per byte x 6 bytes plus a '\0' */
+
+	memset(buf, 0, 13);
+	lseek(fd, 0, SEEK_SET);
+
+	rc = read(fd, buf, 12);
+	errno_ = errno;
+
+	if (rc == -1) {
+		if (errno_ == ENOTTY)
+			igt_info("Sink CRC not supported: panel doesn't support it\n");
+		else if (errno_ != ETIMEDOUT)
+			igt_assert_f(rc != -1, "Unexpected error: %d\n",
+				     errno_);
+		return errno_;
+	} else {
+		int i;
+		unsigned long long val = strtoull(buf, NULL, 16);
+
+		/*
+		 * Stuff the six CRC bytes into their individual locations.
+		 * We start from the least significant byte of the read value
+		 * to simplify masking, shifting each byte off as we set the
+		 * appropriate element in the array.
+		 */
+		for (i = 5; i >= 0; i--, val >>= 8) {
+			data[i] = (unsigned char) (val & 0xff);
+		}
+		return 0;
+	}
+}
diff --git a/lib/igt_psr.h b/lib/igt_psr.h
index f4c0a6b..6f9137b 100644
--- a/lib/igt_psr.h
+++ b/lib/igt_psr.h
@@ -36,5 +36,7 @@  void igt_psr_print_status(int fd);
 bool igt_psr_valid_connector(drmModeConnectorPtr connector);
 bool igt_psr_find_good_mode(drmModeConnectorPtr connector,
 			    drmModeModeInfoPtr *mode);
+int igt_psr_open_sink_crc(int drm_fd);
+int igt_psr_get_sink_crc(int fd, char *data);
 
 #endif /* IGT_PSR_H */
diff --git a/tests/kms_frontbuffer_tracking.c b/tests/kms_frontbuffer_tracking.c
index fe50cc7..06a1b99 100644
--- a/tests/kms_frontbuffer_tracking.c
+++ b/tests/kms_frontbuffer_tracking.c
@@ -183,7 +183,7 @@  struct {
 };
 
 
-#define SINK_CRC_SIZE 12
+#define SINK_CRC_SIZE 6
 typedef struct {
 	char data[SINK_CRC_SIZE];
 } sink_crc_t;
@@ -916,32 +916,27 @@  static bool fbc_wait_until_enabled(void)
 
 static void get_sink_crc(sink_crc_t *crc, bool mandatory)
 {
-	int rc, errno_;
+	int rc;
+	const char bad_crc[6] = {0, 0, 0, 0, 0, 0};
 
 	if (!sink_crc.supported) {
-		memcpy(crc, "unsupported!", SINK_CRC_SIZE);
+		memcpy(crc, bad_crc, SINK_CRC_SIZE);
 		return;
 	}
 
-	lseek(sink_crc.fd, 0, SEEK_SET);
-
-	rc = read(sink_crc.fd, crc->data, SINK_CRC_SIZE);
-	errno_ = errno;
+	rc = igt_psr_get_sink_crc(sink_crc.fd, crc->data);
 
-	if (rc == -1 && errno_ == ENOTTY) {
+	if (rc == ENOTTY) {
 		igt_info("Sink CRC not supported: panel doesn't support it\n");
 		sink_crc.supported = false;
-	} else if (rc == -1 && errno_ == ETIMEDOUT) {
-		if (sink_crc.reliable) {
-			igt_info("Sink CRC is unreliable on this machine.\n");
+	} else if (rc == ETIMEDOUT) {
+		if (sink_crc.reliable)
 			sink_crc.reliable = false;
-		}
 
 		if (mandatory)
 			igt_skip("Sink CRC is unreliable on this machine.\n");
 	} else {
-		igt_assert_f(rc != -1, "Unexpected error: %d\n", errno_);
-		igt_assert(rc == SINK_CRC_SIZE);
+		igt_assert_f(rc == 0, "Unexpected error: %d\n", rc);
 	}
 }
 
@@ -1410,7 +1405,7 @@  static void setup_sink_crc(void)
 	fill_fb_region(&prim_mode_params.fb, COLOR_PRIM_BG);
 	set_mode_for_params(&prim_mode_params);
 
-	sink_crc.fd = openat(drm.debugfs, "i915_sink_crc_eDP1", O_RDONLY);
+	sink_crc.fd = igt_psr_open_sink_crc(drm.debugfs);
 	igt_assert_lte(0, sink_crc.fd);
 
 	/* Do a first read to try to detect if it's supported. */
diff --git a/tests/kms_psr_sink_crc.c b/tests/kms_psr_sink_crc.c
index eb1bbb3..90a6b34 100644
--- a/tests/kms_psr_sink_crc.c
+++ b/tests/kms_psr_sink_crc.c
@@ -33,7 +33,7 @@ 
 
 bool running_with_psr_disabled;
 
-#define CRC_BLACK "000000000000"
+#define SINK_CRC_SIZE 6
 
 enum operations {
 	PAGE_FLIP,
@@ -64,6 +64,8 @@  static const char *op_str(enum operations op)
 
 typedef struct {
 	int drm_fd;
+	int debugfs_fd;
+	int crc_fd;
 	int test_plane;
 	enum operations op;
 	uint32_t devid;
@@ -125,7 +127,7 @@  static void display_init(data_t *data)
 	igt_display_init(&data->display, data->drm_fd);
 	setup_output(data);
 
-		/* We need to be able to do a modeset before we enable PSR to
+	/* We need to be able to do a modeset before we enable PSR to
 	 * ensure that we are running at a mode such that PSR setup can
 	 * complete within a single vblank interval.
 	 */
@@ -150,6 +152,8 @@  static void display_init(data_t *data)
 
 static void display_fini(data_t *data)
 {
+	close(data->crc_fd);
+	close(data->debugfs_fd);
 	igt_output_override_mode(data->output, NULL);
 	igt_display_fini(&data->display);
 }
@@ -233,58 +237,43 @@  static bool wait_psr_entry(data_t *data)
 }
 
 static void get_sink_crc(data_t *data, char *crc) {
-	int dir;
+	int rc, tries = 10;
 
 	if (igt_interactive_debug)
 		return;
 
-	dir = igt_debugfs_dir(data->drm_fd);
-	igt_require_f(igt_sysfs_scanf(dir, "i915_sink_crc_eDP1", "%s\n", crc),
-		      "Sink CRC is unreliable on this machine. Try manual debug with --interactive-debug=no-crc\n");
-	close(dir);
+	memset(crc, 0, SINK_CRC_SIZE);
+	do {
+		rc = igt_psr_get_sink_crc(data->crc_fd, crc);
+		if (rc)
+			usleep(50000);
+	} while (rc && --tries);
 
-	igt_debug("%s\n", crc);
+	if (rc)
+		igt_skip("Could not get sink CRC after ten tries.\n");
+
+	igt_debug("crc values: 0x%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx\n",
+		  crc[0], crc[1], crc[2], crc[3], crc[4], crc[5]);
 	igt_debug_wait_for_keypress("crc");
 
 	/* The important value was already taken.
 	 * Now give a time for human eyes
 	 */
 	usleep(300000);
-
-	/* Black screen is always invalid */
-	igt_assert(strcmp(crc, CRC_BLACK) != 0);
 }
 
 static bool is_green(char *crc)
 {
-	char color_mask[5] = "FFFF\0";
-	char rs[5], gs[5], bs[5];
-	unsigned int rh, gh, bh, mask;
-	int ret;
+	unsigned int rh, gh, bh;
 
 	if (igt_interactive_debug)
 		return false;
 
-	sscanf(color_mask, "%4x", &mask);
-
-	memcpy(rs, &crc[0], 4);
-	rs[4] = '\0';
-	ret = sscanf(rs, "%4x", &rh);
-	igt_require(ret > 0);
-
-	memcpy(gs, &crc[4], 4);
-	gs[4] = '\0';
-	ret = sscanf(gs, "%4x", &gh);
-	igt_require(ret > 0);
-
-	memcpy(bs, &crc[8], 4);
-	bs[4] = '\0';
-	ret = sscanf(bs, "%4x", &bh);
-	igt_require(ret > 0);
+	rh = (crc[1] << 8) | crc[0];
+	gh = (crc[3] << 8) | crc[2];
+	bh = (crc[5] << 8) | crc[4];
 
-	return ((rh & mask) == 0 &&
-		(gh & mask) != 0 &&
-		(bh & mask) == 0);
+	return ((rh == 0) && (gh != 0) && (bh == 0));
 }
 
 #define assert_or_manual(condition, expected)             \
@@ -298,8 +287,8 @@  static void run_test(data_t *data)
 	uint32_t handle = data->fb_white.gem_handle;
 	igt_plane_t *test_plane;
 	void *ptr;
-	char ref_crc[12];
-	char crc[12];
+	char ref_crc[SINK_CRC_SIZE];
+	char crc[SINK_CRC_SIZE];
 	const char *expected = "";
 
 	/* Confirm that screen became Green */
@@ -356,10 +345,13 @@  static void run_test(data_t *data)
 		memset(ptr, 0xff, data->mod_size);
 		get_sink_crc(data, crc);
 		if (data->test_plane == DRM_PLANE_TYPE_PRIMARY)
-			assert_or_manual(strcmp(ref_crc, crc) == 0, "screen WHITE");
+			assert_or_manual(memcmp(ref_crc, crc,
+						SINK_CRC_SIZE) == 0,
+					 "screen WHITE");
 		else
-			assert_or_manual(strcmp(ref_crc, crc) == 0,
-			       "GREEN background with WHITE box");
+			assert_or_manual(memcmp(ref_crc, crc,
+						SINK_CRC_SIZE) == 0,
+					 "GREEN background with WHITE box");
 
 		igt_info("Waiting 10s...\n");
 		sleep(10);
@@ -401,7 +393,7 @@  static void run_test(data_t *data)
 		break;
 	}
 	get_sink_crc(data, crc);
-	assert_or_manual(strcmp(ref_crc, crc) != 0, expected);
+	assert_or_manual(memcmp(ref_crc, crc, SINK_CRC_SIZE) != 0, expected);
 }
 
 static void test_cleanup(data_t *data) {
@@ -513,6 +505,8 @@  int main(int argc, char *argv[])
 
 	igt_fixture {
 		data.drm_fd = drm_open_driver_master(DRIVER_INTEL);
+		data.debugfs_fd = igt_debugfs_dir(data.drm_fd);
+		data.crc_fd = igt_psr_open_sink_crc(data.debugfs_fd);
 		kmstest_set_vt_graphics_mode();
 		data.devid = intel_get_drm_devid(data.drm_fd);
 		data.bufmgr = drm_intel_bufmgr_gem_init(data.drm_fd, 4096);