[PATCH 1/1] tests/gem_seqno_wrap: dont sync when crossing half of seqno space

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



For seqno comparison to work they have to be less than UINT32_MAX/2
apart. So when crossing the half way of seqno space, be careful not
to sync anything as this causes gpu hangs. Do real test with
syncing only when we are about to wrap.

v2: Don't spam if no rendercopy was found, only warn once
---
 tests/gem_seqno_wrap.c |  168 +++++++++++++++++++++++++++++++++++-------------
 1 file changed, 123 insertions(+), 45 deletions(-)

diff --git a/tests/gem_seqno_wrap.c b/tests/gem_seqno_wrap.c
index b70f886..2b92cb8 100644
--- a/tests/gem_seqno_wrap.c
+++ b/tests/gem_seqno_wrap.c
@@ -47,7 +47,7 @@
 #include "intel_gpu_tools.h"
 #include "rendercopy.h"
 
-#define BUFFERS_TO_SYNC 128
+#define SAFETY_REGION 0x1f
 
 static int devid;
 static uint32_t last_seqno = 0;
@@ -64,6 +64,8 @@ struct option_struct {
 	int timeout;
 	int dontwrap;
 	int prewrap_space;
+	int random;
+	int buffers;
 };
 
 static struct option_struct options;
@@ -145,6 +147,7 @@ static void render_copyfunc(struct scratch_buf *src,
 {
 	const int src_x = 0, src_y = 0, dst_x = 0, dst_y = 0;
 	render_copyfunc_t rendercopy = get_render_copyfunc(devid);
+	static int warned = 0;
 
 	if (rendercopy) {
 		rendercopy(batch_3d,
@@ -153,27 +156,44 @@ static void render_copyfunc(struct scratch_buf *src,
 			   dst, dst_x, dst_y);
 		intel_batchbuffer_flush(batch_3d);
 	} else {
-		printf("No render copy found for this gen, test is shallow!\n");
+		if (!warned) {
+			printf("No render copy found for this gen, "
+			       "test is shallow!\n");
+			warned = 1;
+		}
 		intel_copy_bo(batch_blt, dst->bo, src->bo, width, height);
 		intel_batchbuffer_flush(batch_blt);
 	}
 }
 
-static int run_sync_test(void)
+static void exchange_uint(void *array, unsigned i, unsigned j)
+{
+	unsigned *i_arr = array;
+	unsigned i_tmp;
+
+	i_tmp = i_arr[i];
+	i_arr[i] = i_arr[j];
+	i_arr[j] = i_tmp;
+}
+
+static int run_sync_test(int num_buffers, bool verify)
 {
 	drm_intel_bufmgr *bufmgr;
-	int num_buffers = BUFFERS_TO_SYNC, max;
+	int max;
 	drm_intel_bo *src[128], *dst1[128], *dst2[128];
 	int width = 128, height = 128;
 	int fd;
 	int i;
 	int r = -1;
 	int failed = 0;
-
+	unsigned int *p_dst1, *p_dst2;
 	struct scratch_buf s_src[128], s_dst[128];
 
 	fd = drm_open_any();
 	assert(fd >= 0);
+
+	gem_quiescent_gpu(fd);
+
 	devid = intel_get_drm_devid(fd);
 
 	max = gem_aperture_size (fd) / (1024 * 1024) / 2;
@@ -187,7 +207,16 @@ static int run_sync_test(void)
 	batch_3d = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
 	assert(batch_3d);
 
+	p_dst1 = malloc(num_buffers * sizeof(unsigned int));
+	if (p_dst1 == NULL)
+		return -ENOMEM;
+
+	p_dst2 = malloc(num_buffers * sizeof(unsigned int));
+	if (p_dst2 == NULL)
+		return -ENOMEM;
+
 	for (i = 0; i < num_buffers; i++) {
+		p_dst1[i] = p_dst2[i] = i;
 		src[i] = create_bo(bufmgr, i, width, height);
 		dst1[i] = create_bo(bufmgr, ~i, width, height);
 		dst2[i] = create_bo(bufmgr, ~i, width, height);
@@ -195,19 +224,27 @@ static int run_sync_test(void)
 		init_buffer(bufmgr, &s_dst[i], dst1[i], width, height);
 	}
 
-	/* dummy = create_bo(bufmgr, 0, width, height); */
-
-	for (i = 0; i < num_buffers; i++) {
-		render_copyfunc(&s_src[i], &s_dst[i], width, height);
-		intel_copy_bo(batch_blt, dst2[i], dst1[i], width, height);
-	}
-
-	for (i = 0; i < num_buffers; i++) {
-		r = cmp_bo(dst2[i], i, width, height);
-		if (r) {
-			printf("buffer %d differs, seqno_before_test 0x%x, approximated seqno on test fail 0x%x\n",
-			       i, last_seqno_write, last_seqno_write + i * 2);
-			failed = -1;
+	drmtest_permute_array(p_dst1, num_buffers, exchange_uint);
+	drmtest_permute_array(p_dst2, num_buffers, exchange_uint);
+
+	for (i = 0; i < num_buffers; i++)
+		render_copyfunc(&s_src[i], &s_dst[p_dst1[i]], width, height);
+
+	/* Only sync between buffers if this is actual test run and
+	 * not a seqno filler */
+	if (verify) {
+		for (i = 0; i < num_buffers; i++)
+			intel_copy_bo(batch_blt, dst2[p_dst2[i]], dst1[p_dst1[i]],
+				      width, height);
+
+		for (i = 0; i < num_buffers; i++) {
+			r = cmp_bo(dst2[p_dst2[i]], i, width, height);
+			if (r) {
+				printf("buffer %d differs, seqno_before_test 0x%x, "
+				       " approximated seqno on test fail 0x%x\n",
+				       i, last_seqno_write, last_seqno_write + i * 2);
+				failed = -1;
+			}
 		}
 	}
 
@@ -221,6 +258,11 @@ static int run_sync_test(void)
 	intel_batchbuffer_free(batch_blt);
 	drm_intel_bufmgr_destroy(bufmgr);
 
+	free(p_dst1);
+	free(p_dst2);
+
+	gem_quiescent_gpu(fd);
+
 	close(fd);
 
 	return failed;
@@ -270,7 +312,9 @@ static int run_cmd(char *s)
 			if (r == pid) {
 				if(WIFEXITED(status)) {
 					if (WEXITSTATUS(status))
-						fprintf(stderr, "child returned with %d\n", WEXITSTATUS(status));
+						fprintf(stderr,
+						    "child returned with %d\n",
+							WEXITSTATUS(status));
 					return WEXITSTATUS(status);
 				}
 			} else if (r != 0) {
@@ -365,9 +409,25 @@ static int write_seqno(uint32_t seqno)
 
 static uint32_t calc_prewrap_val(void)
 {
-	const int pval = options.prewrap_space - 1;
+	const int pval = options.prewrap_space;
+
+	if (options.random == 0)
+		return pval;
 
-	return (pval >> 1) + (random() % (pval >> 1));
+	return random() % pval;
+}
+
+static int seqno_near_boundary(uint32_t seqno)
+{
+	if (seqno > UINT32_MAX - options.prewrap_space ||
+	    seqno < options.prewrap_space)
+		return 1;
+
+	if (seqno < UINT32_MAX/2 + SAFETY_REGION &&
+	    seqno > UINT32_MAX/2 - SAFETY_REGION)
+		return 1;
+
+	return 0;
 }
 
 static int run_once(void)
@@ -382,29 +442,25 @@ static int run_once(void)
 	r = read_seqno(&seqno_before);
 	assert(r == 0);
 
-	if (seqno_before == last_seqno) {
-		sleep(2);
-		return 0;
-	}
-
 	seqno = last_seqno = seqno_before;
 
-	if (seqno < UINT32_MAX - options.prewrap_space) {
-		if (seqno < UINT32_MAX/2)
-			seqno = UINT32_MAX/2 - options.prewrap_space;
-		else
+	/* Skip seqno write if close to boundary */
+	if (!seqno_near_boundary(seqno)) {
+		if (seqno > UINT32_MAX/2 + 1)
 			seqno = UINT32_MAX - pw_val;
-
-		if ((int)(seqno - seqno_before) <= 0)
-			return 0;
+		else
+			seqno = UINT32_MAX/2 - SAFETY_REGION;
 
 		if (!options.dontwrap) {
 			r = write_seqno(seqno);
 			if (r < 0) {
-				fprintf(stderr, "write_seqno returned %d\n", r);
+				fprintf(stderr,
+					"write_seqno 0x%x returned %d\n",
+					seqno, r);
 
-				/* We might fail if we are at background and some
-				 * operations were done between seqno read and this write
+				/* We might fail if we are at background and
+				 * some operations were done between seqno
+				 * read and this write
 				 */
 				if (!options.background)
 					return r;
@@ -412,11 +468,18 @@ static int run_once(void)
 		}
 	}
 
-	if (options.background == 0) {
-		if (strnlen(options.cmd, sizeof(options.cmd)) > 0) {
-			r = run_cmd(options.cmd);
+	if (!options.background) {
+		/* Only run tests if we are across the half way of seqno space.
+		 * If we are not, run something which just increments seqnos
+		 */
+		if (seqno >= UINT32_MAX/2 + 1) {
+			if (strnlen(options.cmd, sizeof(options.cmd)) > 0) {
+				r = run_cmd(options.cmd);
+			} else {
+				r = run_sync_test(options.buffers, true);
+			}
 		} else {
-			r = run_sync_test();
+			r = run_sync_test(options.buffers, false);
 		}
 
 		if (r != 0) {
@@ -434,7 +497,8 @@ static int run_once(void)
 	if (seqno_before > seqno_after) {
 		if (options.verbose)
 			printf("before 0x%x, after 0x%x , diff %d\n",
-			       seqno_before, seqno_after, seqno_after - seqno_before);
+			       seqno_before, seqno_after,
+			       seqno_after - seqno_before);
 
 		return 1;
 	}
@@ -452,6 +516,8 @@ static void print_usage(const char *s)
 	printf("    -t --timeout=sec      set timeout to wait for testrun to sec seconds\n");
 	printf("    -d --dontwrap         don't wrap just run the test\n");
 	printf("    -p --prewrap=n        set seqno to WRAP - n for each testrun\n");
+	printf("    -r --norandom         dont randomize prewrap space\n");
+	printf("    -i --buffers          number of buffers to copy\n");
 	exit(-1);
 }
 
@@ -467,17 +533,21 @@ static void parse_options(int argc, char **argv)
 		{"dontwrap", no_argument, 0, 'd'},
 		{"verbose", no_argument, 0, 'v'},
 		{"prewrap", required_argument, 0, 'p'},
+		{"norandom", no_argument, 0, 'r'},
+		{"buffers", required_argument, 0, 'i'},
 	};
 
 	strcpy(options.cmd, "");
-	options.rounds = 5;
+	options.rounds = 50;
 	options.background = 0;
 	options.dontwrap = 0;
 	options.timeout = 20;
 	options.verbose = 0;
-	options.prewrap_space = BUFFERS_TO_SYNC/2;
+	options.random = 1;
+	options.prewrap_space = 30;
+	options.buffers = 20;
 
-	while((c = getopt_long(argc, argv, "c:n:bvt:dp:",
+	while((c = getopt_long(argc, argv, "c:n:bvt:dp:ri:",
 			       long_options, &option_index)) != -1) {
 		switch(c) {
 		case 'b':
@@ -497,15 +567,23 @@ static void parse_options(int argc, char **argv)
 			options.cmd[sizeof(options.cmd) - 1] = 0;
 			printf("cmd set to %s\n", options.cmd);
 			break;
+		case 'i':
+			options.buffers = atoi(optarg);
+			printf("buffers %d\n", options.buffers);
+			break;
 		case 't':
 			options.timeout = atoi(optarg);
 			if (options.timeout == 0)
 				options.timeout = 10;
-			printf("setting timeout to %d seconds\n", options.timeout);
+			printf("setting timeout to %d seconds\n",
+			       options.timeout);
 			break;
 		case 'v':
 			options.verbose = 1;
 			break;
+		case 'r':
+			options.random = 0;
+			break;
 		case 'p':
 			options.prewrap_space = atoi(optarg);
 			if (options.prewrap_space == 0)
-- 
1.7.9.5



[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux