From patchwork Thu Dec 13 10:43:35 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Kuoppala X-Patchwork-Id: 1871671 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork1.kernel.org (Postfix) with ESMTP id 4619C3FC71 for ; Thu, 13 Dec 2012 10:43:51 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 1BE99E5F09 for ; Thu, 13 Dec 2012 02:43:51 -0800 (PST) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by gabe.freedesktop.org (Postfix) with ESMTP id 27A6EE5F09 for ; Thu, 13 Dec 2012 02:43:42 -0800 (PST) Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga102.jf.intel.com with ESMTP; 13 Dec 2012 02:42:51 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.84,273,1355126400"; d="scan'208";a="256878148" Received: from gaia.fi.intel.com (HELO gaia) ([10.237.72.78]) by orsmga002.jf.intel.com with ESMTP; 13 Dec 2012 02:43:40 -0800 Received: by gaia (Postfix, from userid 1000) id 4770F40723; Thu, 13 Dec 2012 12:43:37 +0200 (EET) From: Mika Kuoppala To: intel-gfx@lists.freedesktop.org Date: Thu, 13 Dec 2012 12:43:35 +0200 Message-Id: <1355395415-19722-1-git-send-email-mika.kuoppala@intel.com> X-Mailer: git-send-email 1.7.9.5 Subject: [Intel-gfx] [PATCH 1/1] tests/gem_seqno_wrap: dont sync when crossing half of seqno space X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org 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)