[i-g-t PATCH] tests/intel/xe_pm: one suspend/resume cycle for all xe engines

Peter Senna Tschudin peter.senna at linux.intel.com
Wed Sep 25 12:51:06 UTC 2024


*** Please do not merge. This is intended for testing and RFC only. ***

This patch changes the behavior from running one suspend/resume cycle for each
xe engine to running a single suspend and resume cycle for all engines.

This patch is not good enough for upstream, and it introduces issues.
However it reduces the runtime of tests/intel/xe_pm from ~60 minutes to ~10
minutes. The main reason for sending this patch is for CI to test it.

Signed-off-by: Peter Senna Tschudin <peter.senna at linux.intel.com>
---
 tests/intel/xe_pm.c | 149 +++++++++++++++++++++++++++++++++++++-------
 1 file changed, 128 insertions(+), 21 deletions(-)

diff --git a/tests/intel/xe_pm.c b/tests/intel/xe_pm.c
index eee89428c..2659ff572 100644
--- a/tests/intel/xe_pm.c
+++ b/tests/intel/xe_pm.c
@@ -54,6 +54,28 @@ typedef struct {
 uint64_t orig_threshold;
 int fw_handle = -1;
 
+pthread_mutex_t suspend_lock = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
+pthread_mutex_t child_ready_lock = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t child_ready_cond = PTHREAD_COND_INITIALIZER;
+bool child_ready = false;
+
+#define NUM_THREADS MAX_N_EXEC_QUEUES * 4
+pthread_t threads[NUM_THREADS];
+int thread_number = 0;
+
+struct test_exec_args {
+	device_t device;
+	struct drm_xe_engine_class_instance *eci;
+	int n_exec_queues;
+	int n_execs;
+	enum igt_suspend_state s_state;
+	enum igt_acpi_d_state d_state;
+	unsigned int flags;
+};
+
+enum igt_suspend_state global_s_state = SUSPEND_STATE_NUM;
+
 static void dpms_on_off(device_t device, int mode)
 {
 	int i;
@@ -273,6 +295,7 @@ static void close_fw_handle(int sig)
  * @prefetch:	prefetch
  * @unbind-all:	unbind-all
  */
+
 static void
 test_exec(device_t device, struct drm_xe_engine_class_instance *eci,
 	  int n_exec_queues, int n_execs, enum igt_suspend_state s_state,
@@ -396,10 +419,14 @@ test_exec(device_t device, struct drm_xe_engine_class_instance *eci,
 		igt_assert_eq(data[i].data, 0xc0ffee);
 
 		if (i == n_execs / 2 && s_state != NO_SUSPEND) {
-			enum igt_suspend_test test = s_state == SUSPEND_STATE_DISK ?
-				SUSPEND_TEST_DEVICES : SUSPEND_TEST_NONE;
-
-			igt_system_suspend_autoresume(s_state, test);
+			pthread_mutex_lock(&child_ready_lock);
+			child_ready = true;
+			pthread_cond_signal(&child_ready_cond);
+			pthread_mutex_unlock(&child_ready_lock);
+
+			pthread_mutex_lock(&suspend_lock);
+			pthread_cond_wait(&suspend_cond, &suspend_lock);
+			pthread_mutex_unlock(&suspend_lock);
 		}
 	}
 
@@ -440,8 +467,76 @@ NULL));
 			   active_time);
 		igt_assert(in_d3(device, d_state));
 	}
+	pthread_mutex_lock(&child_ready_lock);
+	child_ready = true;
+	pthread_cond_signal(&child_ready_cond);
+	pthread_mutex_unlock(&child_ready_lock);
+}
+
+static void*
+test_exec_wrapper(void *args) {
+
+	struct test_exec_args *exec_args = (struct test_exec_args *)args;
+
+	test_exec(exec_args->device, exec_args->eci, exec_args->n_exec_queues,
+		exec_args->n_execs, exec_args->s_state, exec_args->d_state,
+		exec_args->flags);
+
+	return NULL;
+}
+
+static void
+threaded_test_exec_h1(device_t device, struct drm_xe_engine_class_instance *eci,
+	  int n_exec_queues, int n_execs, enum igt_suspend_state s_state,
+	  enum igt_acpi_d_state d_state, unsigned int flags) {
+
+	struct test_exec_args args;
+
+	args.device = device;
+	args.eci = eci;
+	args.n_exec_queues = n_exec_queues;
+	args.n_execs = n_execs;
+	args.s_state = s_state;
+	args.d_state = d_state;
+	args.flags = flags;
+
+	if (global_s_state == SUSPEND_STATE_NUM)
+		global_s_state = s_state;
+	else if (global_s_state != s_state) {
+		igt_info("Something went wrong? Two different suspend states in a single run\n");
+		global_s_state = s_state;
+	}
+
+	pthread_create(&threads[thread_number], NULL, test_exec_wrapper, &args);
+	thread_number++;
+
+	pthread_mutex_lock(&child_ready_lock);
+	while(!child_ready)
+		pthread_cond_wait(&child_ready_cond, &child_ready_lock);
+	child_ready = false;
+	pthread_mutex_unlock(&child_ready_lock);
+}
+
+static void
+threaded_test_exec_h2(void) {
+
+	enum igt_suspend_test test = global_s_state == SUSPEND_STATE_DISK ? SUSPEND_TEST_DEVICES : SUSPEND_TEST_NONE;
+
+	igt_system_suspend_autoresume(global_s_state, test);
+
+	sleep(2);
+	pthread_mutex_lock(&suspend_lock);
+	pthread_cond_broadcast(&suspend_cond);
+	pthread_mutex_unlock(&suspend_lock);
+
+	for (int i = 0; i < thread_number; i++)
+		pthread_join(threads[i], NULL);
+
+	thread_number = 0;
+	global_s_state = SUSPEND_STATE_NUM;
 }
 
+
 /**
  * SUBTEST: vram-d3cold-threshold
  * Functionality: pm - d3cold
@@ -719,7 +814,7 @@ igt_main
 
 		/* Always perform initial once-basic exec checking for health */
 		xe_for_each_engine(device.fd_xe, hwe)
-			test_exec(device, hwe, 1, 1, NO_SUSPEND, NO_RPM, 0);
+			threaded_test_exec_h1(device, hwe, 1, 1, NO_SUSPEND, NO_RPM, 0);
 
 		igt_pm_get_d3cold_allowed(device.pci_slot_name, &d3cold_allowed);
 		igt_assert(igt_setup_runtime_pm(device.fd_xe));
@@ -731,14 +826,15 @@ igt_main
 		igt_subtest_f("%s-basic", s->name) {
 			enum igt_suspend_test test = s->state == SUSPEND_STATE_DISK ?
 				SUSPEND_TEST_DEVICES : SUSPEND_TEST_NONE;
-
 			igt_system_suspend_autoresume(s->state, test);
 		}
 
 		igt_subtest_f("%s-basic-exec", s->name) {
 			xe_for_each_engine(device.fd_xe, hwe)
-				test_exec(device, hwe, 1, 2, s->state,
-					  NO_RPM, 0);
+				threaded_test_exec_h1(device, hwe, 1, 2, s->state,
+					  				  NO_RPM, 0);
+			if (thread_number > 0)
+				threaded_test_exec_h2();
 		}
 
 		igt_subtest_f("%s-exec-after", s->name) {
@@ -747,21 +843,27 @@ igt_main
 
 			igt_system_suspend_autoresume(s->state, test);
 			xe_for_each_engine(device.fd_xe, hwe)
-				test_exec(device, hwe, 1, 2, NO_SUSPEND,
-					  NO_RPM, 0);
+				threaded_test_exec_h1(device, hwe, 1, 2, NO_SUSPEND,
+					  				  NO_RPM, 0);
+			if (thread_number > 0)
+				threaded_test_exec_h2();
 		}
 
 		igt_subtest_f("%s-multiple-execs", s->name) {
 			xe_for_each_engine(device.fd_xe, hwe)
-				test_exec(device, hwe, 16, 32, s->state,
-					  NO_RPM, 0);
+				threaded_test_exec_h1(device, hwe, 16, 32, s->state,
+									  NO_RPM, 0);
+			if (thread_number > 0)
+				threaded_test_exec_h2();
 		}
 
 		for (const struct vm_op *op = vm_op; op->name; op++) {
 			igt_subtest_f("%s-vm-bind-%s", s->name, op->name) {
 				xe_for_each_engine(device.fd_xe, hwe)
-					test_exec(device, hwe, 16, 32, s->state,
-						  NO_RPM, op->flags);
+					threaded_test_exec_h1(device, hwe, 16, 32, s->state,
+										  NO_RPM, op->flags);
+				if (thread_number > 0)
+					threaded_test_exec_h2();
 			}
 		}
 
@@ -769,8 +871,10 @@ igt_main
 			igt_subtest_f("%s-%s-basic-exec", s->name, d->name) {
 				igt_assert(setup_d3(device, d->state));
 				xe_for_each_engine(device.fd_xe, hwe)
-					test_exec(device, hwe, 1, 2, s->state,
-						  NO_RPM, 0);
+					threaded_test_exec_h1(device, hwe, 1, 2, s->state,
+										  NO_RPM, 0);
+				if (thread_number > 0)
+					threaded_test_exec_h2();
 				cleanup_d3(device);
 			}
 		}
@@ -793,16 +897,20 @@ igt_main
 		igt_subtest_f("%s-basic-exec", d->name) {
 			igt_assert(setup_d3(device, d->state));
 			xe_for_each_engine(device.fd_xe, hwe)
-				test_exec(device, hwe, 1, 1,
-					  NO_SUSPEND, d->state, 0);
+				threaded_test_exec_h1(device, hwe, 1, 1, NO_SUSPEND,
+									  d->state, 0);
+			if (thread_number > 0)
+				threaded_test_exec_h2();
 			cleanup_d3(device);
 		}
 
 		igt_subtest_f("%s-multiple-execs", d->name) {
 			igt_assert(setup_d3(device, d->state));
 			xe_for_each_engine(device.fd_xe, hwe)
-				test_exec(device, hwe, 16, 32,
-					  NO_SUSPEND, d->state, 0);
+				threaded_test_exec_h1(device, hwe, 16, 32, NO_SUSPEND,
+									  d->state, 0);
+			if (thread_number > 0)
+				threaded_test_exec_h2();
 			cleanup_d3(device);
 		}
 
@@ -842,7 +950,6 @@ igt_main
 			test_mocs_suspend_resume(device, NO_SUSPEND, d->state);
 			cleanup_d3(device);
 		}
-
 	}
 
 	igt_describe("Validate whether card is limited to d3hot,"
-- 
2.34.1



More information about the igt-dev mailing list