[igt-dev] [RFC 1/1] tests/psr: PSR H/W tracking validation

Anshuman Gupta anshuman.gupta at intel.com
Sat Oct 5 04:42:17 UTC 2019


Validate the PSR PRE_ENTRY and PST_EXIT PSR IIR
interrupts in order to validate PSR H/W tracking.

Signed-off-by: Anshuman Gupta <anshuman.gupta at intel.com>
---
 lib/igt_psr.c   |  14 ++++++
 lib/igt_psr.h   |   3 ++
 tests/kms_psr.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 129 insertions(+)

diff --git a/lib/igt_psr.c b/lib/igt_psr.c
index b92ea73f..3c2fbce0 100644
--- a/lib/igt_psr.c
+++ b/lib/igt_psr.c
@@ -163,6 +163,20 @@ bool psr_disable(int debugfs_fd)
 	return psr_set(debugfs_fd, -1);
 }
 
+void psr_enable_irq_debug(int debugfs_fd)
+{
+	char buf[PSR_DEBUG_MAX_LEN];
+	int psr_debug, ret;
+
+	igt_debugfs_simple_read(debugfs_fd, "i915_edp_psr_debug", buf,
+				sizeof(buf));
+	ret = sscanf(buf, "%d", &psr_debug);
+	igt_assert_eq(ret, 1);
+	psr_debug |= PSR_DEBUG_IRQ;
+	snprintf(buf, sizeof(buf), "%d", psr_debug);
+	psr_write(debugfs_fd, buf);
+}
+
 bool psr_sink_support(int debugfs_fd, enum psr_mode mode)
 {
 	char buf[PSR_STATUS_MAX_LEN];
diff --git a/lib/igt_psr.h b/lib/igt_psr.h
index ca385736..2843e99c 100644
--- a/lib/igt_psr.h
+++ b/lib/igt_psr.h
@@ -29,6 +29,8 @@
 #include "igt_aux.h"
 
 #define PSR_STATUS_MAX_LEN 512
+#define PSR_DEBUG_MAX_LEN 64
+#define PSR_DEBUG_IRQ 0x10
 
 enum psr_mode {
 	PSR_MODE_1,
@@ -39,6 +41,7 @@ bool psr_wait_entry(int debugfs_fd, enum psr_mode mode);
 bool psr_wait_update(int debugfs_fd, enum psr_mode mode);
 bool psr_long_wait_update(int debugfs_fd, enum psr_mode mode);
 bool psr_enable(int debugfs_fd, enum psr_mode);
+void psr_enable_irq_debug(int debugfs_fd);
 bool psr_disable(int debugfs_fd);
 bool psr_sink_support(int debugfs_fd, enum psr_mode);
 bool psr2_wait_su(int debugfs_fd, uint16_t *num_su_blocks);
diff --git a/tests/kms_psr.c b/tests/kms_psr.c
index 39de0112..2eb4411b 100644
--- a/tests/kms_psr.c
+++ b/tests/kms_psr.c
@@ -30,9 +30,11 @@
 #include <stdio.h>
 #include <string.h>
 #include "intel_bufmgr.h"
+#include "limits.h"
 
 enum operations {
 	PAGE_FLIP,
+	PAGE_FLIP_HW_TRACKING,
 	MMAP_GTT,
 	MMAP_CPU,
 	BLT,
@@ -41,10 +43,16 @@ enum operations {
 	PLANE_ONOFF,
 };
 
+enum psr_irq_type {
+	IRQ_PRE_ENTRY,
+	IRQ_POST_EXIT,
+};
+
 static const char *op_str(enum operations op)
 {
 	static const char * const name[] = {
 		[PAGE_FLIP] = "page_flip",
+		[PAGE_FLIP_HW_TRACKING] = "page_flip_hw_tracking",
 		[MMAP_GTT] = "mmap_gtt",
 		[MMAP_CPU] = "mmap_cpu",
 		[BLT] = "blt",
@@ -62,6 +70,7 @@ typedef struct {
 	enum operations op;
 	int test_plane_id;
 	enum psr_mode op_psr_mode;
+	bool psr_irq_debug;
 	uint32_t devid;
 	uint32_t crtc_id;
 	igt_display_t display;
@@ -206,6 +215,55 @@ static bool psr_wait_entry_if_enabled(data_t *data)
 	return psr_wait_entry(data->debugfs_fd, data->op_psr_mode);
 }
 
+static uint64_t read_psr_irq_ktime(const char *irq_ktime)
+{
+	char *e;
+	unsigned long ret;
+	char *s = strchr(irq_ktime, ':');
+
+	assert(s);
+	s++;
+	ret = strtol(s, &e, 10);
+	assert(((ret != LONG_MIN && ret != ULONG_MAX) || errno != ERANGE) &&
+	       e > s && *e == '\n' && ret >= 0);
+	return ret;
+}
+
+static uint64_t get_psr_irq_time(int debugfs_fd, enum psr_irq_type type)
+{
+	char buf[PSR_STATUS_MAX_LEN];
+	char *str;
+	const char *irq = type == IRQ_PRE_ENTRY ? "Last attempted entry at"
+						: "Last exit at";
+
+	igt_debugfs_simple_read(debugfs_fd, "i915_edp_psr_status", buf,
+				sizeof(buf));
+	str = strstr(buf, irq);
+	return read_psr_irq_ktime(str);
+}
+
+static bool psr_pre_entry_irq_check(int debugfs_fd, uint64_t prev_entry_time)
+{
+	uint64_t irq_entry_time;
+
+	irq_entry_time = get_psr_irq_time(debugfs_fd, IRQ_PRE_ENTRY);
+	igt_debug("PSR IRQ pre entry time %lu\n", irq_entry_time);
+	return (irq_entry_time > prev_entry_time);
+}
+
+static bool psr_wait_pre_entry(int debugfs_fd, uint64_t ktime)
+{
+	return igt_wait(psr_pre_entry_irq_check(debugfs_fd, ktime), 500, 20);
+}
+
+static bool psr_wait_pre_entry_if_enabled(data_t *data, uint64_t ktime)
+{
+	if (data->with_psr_disabled)
+		return true;
+
+	return psr_wait_pre_entry(data->debugfs_fd, ktime);
+}
+
 static bool psr_wait_update_if_enabled(data_t *data)
 {
 	if (data->with_psr_disabled)
@@ -214,6 +272,28 @@ static bool psr_wait_update_if_enabled(data_t *data)
 	return psr_wait_update(data->debugfs_fd, data->op_psr_mode);
 }
 
+static bool psr_post_exit_irq_check(int debugfs_fd, uint64_t prev_exit_time)
+{
+	uint64_t irq_exit_time;
+
+	irq_exit_time = get_psr_irq_time(debugfs_fd, IRQ_POST_EXIT);
+	igt_debug("PSR IRQ posr exit time %lu\n", irq_exit_time);
+	return (irq_exit_time > prev_exit_time);
+}
+
+static bool psr_wait_post_exit(int debugfs_fd, uint64_t ktime)
+{
+	return igt_wait(psr_post_exit_irq_check(debugfs_fd, ktime), 40, 10);
+}
+
+static bool psr_wait_post_exit_if_enabled(data_t *data, uint64_t ktime)
+{
+	if (data->with_psr_disabled)
+		return true;
+
+	return psr_wait_post_exit(data->debugfs_fd, ktime);
+}
+
 static bool psr_enable_if_enabled(data_t *data)
 {
 	if (data->with_psr_disabled)
@@ -222,6 +302,14 @@ static bool psr_enable_if_enabled(data_t *data)
 	return psr_enable(data->debugfs_fd, data->op_psr_mode);
 }
 
+static void psr_enable_irq_debug_if_enabled(data_t *data)
+{
+	if (data->with_psr_disabled)
+		return;
+
+	psr_enable_irq_debug(data->debugfs_fd);
+}
+
 static inline void manual(const char *expected)
 {
 	igt_debug_manual_check("all", expected);
@@ -243,10 +331,14 @@ static void run_test(data_t *data)
 	igt_plane_t *test_plane = data->test_plane;
 	void *ptr;
 	const char *expected = "";
+	uint64_t ktime;
 
 	/* Confirm that screen became Green */
 	manual("screen GREEN");
 
+	if (data->op == PAGE_FLIP_HW_TRACKING)
+		ktime = get_psr_irq_time(data->debugfs_fd, IRQ_PRE_ENTRY);
+
 	/* Confirm screen stays Green after PSR got active */
 	igt_assert(psr_wait_entry_if_enabled(data));
 	manual("screen GREEN");
@@ -261,9 +353,17 @@ static void run_test(data_t *data)
 	else
 		manual("GREEN background with WHITE box");
 
+	if (data->op == PAGE_FLIP_HW_TRACKING)
+		igt_assert(psr_wait_pre_entry_if_enabled(data, ktime));
+
 	igt_assert(psr_wait_entry_if_enabled(data));
+
+	if (data->op == PAGE_FLIP_HW_TRACKING)
+		ktime = get_psr_irq_time(data->debugfs_fd, IRQ_POST_EXIT);
+
 	switch (data->op) {
 	case PAGE_FLIP:
+	case PAGE_FLIP_HW_TRACKING:
 		/* Only in use when testing primary plane */
 		igt_assert(drmModePageFlip(data->drm_fd, data->crtc_id,
 					   data->fb_green.fb_id, 0, NULL) == 0);
@@ -310,6 +410,10 @@ static void run_test(data_t *data)
 		break;
 	}
 	igt_assert(psr_wait_update_if_enabled(data));
+
+	if (data->op == PAGE_FLIP_HW_TRACKING)
+		igt_assert(psr_wait_post_exit_if_enabled(data, ktime));
+
 	manual(expected);
 }
 
@@ -390,6 +494,10 @@ static void test_setup(data_t *data)
 	if (data->op_psr_mode == PSR_MODE_2)
 		igt_require(data->supports_psr2);
 	psr_enable_if_enabled(data);
+
+	if (data->psr_irq_debug)
+		psr_enable_irq_debug_if_enabled(data);
+
 	setup_test_plane(data, data->test_plane_id);
 	igt_assert(psr_wait_entry_if_enabled(data));
 }
@@ -475,6 +583,10 @@ igt_main_args("", long_options, help_str, opt_handler, &data)
 				      op_str(op)) {
 				data.op = op;
 				data.test_plane_id = DRM_PLANE_TYPE_PRIMARY;
+
+				if (data.op == PAGE_FLIP_HW_TRACKING)
+					data.psr_irq_debug = true;
+
 				test_setup(&data);
 				run_test(&data);
 				test_cleanup(&data);
-- 
2.21.0



More information about the igt-dev mailing list