From patchwork Thu Sep 8 12:38:43 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomeu Vizoso X-Patchwork-Id: 9321265 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 1F9C9607D3 for ; Thu, 8 Sep 2016 12:39:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0BAF2297DB for ; Thu, 8 Sep 2016 12:39:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AD3102982C; Thu, 8 Sep 2016 12:39:14 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 5811B297DB for ; Thu, 8 Sep 2016 12:39:13 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id DE8F66E1D3; Thu, 8 Sep 2016 12:39:12 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mail-wm0-x241.google.com (mail-wm0-x241.google.com [IPv6:2a00:1450:400c:c09::241]) by gabe.freedesktop.org (Postfix) with ESMTPS id 14D906E1D3 for ; Thu, 8 Sep 2016 12:39:11 +0000 (UTC) Received: by mail-wm0-x241.google.com with SMTP id w12so7694978wmf.1 for ; Thu, 08 Sep 2016 05:39:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id; bh=dYWGIfSCv7lY11kA768MJMsQTSWO4/3NKfSOiogs+Xo=; b=de13XAbPTjMwgFuOiS+AuhniXQZHaya9YJfddadNaOdRqHwK6Vpnsy2dcsU9ECvTVV WtcDiTIAv//Dz1VrKXA+7y0UkLO8bUJFLjuKvgfqlKxFQjizRTG4GKQMofWdYM5L4JMG dLrmUzlDvPsTheHRzy0uPx4bjR15aAPFvXALHhhRX/Q+mNEudklJwKhvaMOJRbzRLDLO fNCeosdUJbK5Kn40/NDYfKEUQH3jevDO+gKqzC/HWKMfwtxTW16FAxgyWhvYymieB6r4 6lft3qw7Qs9hawa8yCpenCSY6KtCQZVg0xkMeGWRKjpZFX0N5UGBMbdEmFxJYYutMM5V pNrw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id; bh=dYWGIfSCv7lY11kA768MJMsQTSWO4/3NKfSOiogs+Xo=; b=kRZHhdr1B6iJs9MLW1uOy3s5zFiE4zcDb43i4RXU/ndV85wxkcB7UxSo7YhSr4sMCn 7t06wApyGaCYxVHD9O3tQl/+ytY52SRDoKe4h1pgyTaL7Er3Q8p9FEYqoYIyIXlExzJk 0ALVjJ5JTq/uemAiBxnAPD/k/69S3z8w3elXpMmX4spHfOM/C//Ho3dOgpx1/cRiXuuC +5+v3A3I4arCrBGWculMhzVBCGFO5luHpW4fr1ObCRNu647WNVcYaLSn3qOVkWGF4bG4 3KVRyNM/DrFJFd2JzbmzKTwJhaFozCULtsAdchvvvGoBK4ETaGyYtEQoRIrLI8hPh+xH L+Eg== X-Gm-Message-State: AE9vXwObysNhVOlfukGulRAKRfAJQqeS+d5+GWDo/NRYyrHZ8GGYb01ybZn0QZQ9uR6jsQ== X-Received: by 10.28.88.207 with SMTP id m198mr8407803wmb.79.1473338349370; Thu, 08 Sep 2016 05:39:09 -0700 (PDT) Received: from cizrna.lan ([109.72.12.101]) by smtp.gmail.com with ESMTPSA id 17sm9509806wmf.6.2016.09.08.05.39.07 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 08 Sep 2016 05:39:08 -0700 (PDT) From: Tomeu Vizoso To: Intel GFX discussion Date: Thu, 8 Sep 2016 14:38:43 +0200 Message-Id: <1473338324-6986-1-git-send-email-tomeu.vizoso@collabora.com> X-Mailer: git-send-email 2.7.4 Cc: Tomeu Vizoso Subject: [Intel-gfx] [PATCH i-g-t 1/2] lib/debugfs: Support new generic ABI for CRC capture X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP The kernel has now a new debugfs ABI that can also allow capturing frame CRCs for drivers other than i915. Add alternative codepaths so the new ABI is used if the kernel is recent enough, and fall back to the legacy ABI if not. Signed-off-by: Tomeu Vizoso --- lib/igt_debugfs.c | 236 +++++++++++++++++++++++++++++++++++---------- lib/igt_debugfs.h | 8 +- tests/kms_pipe_crc_basic.c | 162 +++++++++++++++++++++++-------- 3 files changed, 311 insertions(+), 95 deletions(-) diff --git a/lib/igt_debugfs.c b/lib/igt_debugfs.c index afb83617b85b..1bbbabc9f1c9 100644 --- a/lib/igt_debugfs.c +++ b/lib/igt_debugfs.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -247,6 +248,10 @@ bool igt_debugfs_search(const char *filename, const char *substring) * Pipe CRC */ +#define CRC_DEFAULTS 0 +#define CRC_FORCE_LEGACY (1 << 0) +#define CRC_NONBLOCK (1 << 1) + /** * igt_assert_crc_equal: * @a: first pipe CRC value @@ -280,25 +285,23 @@ char *igt_crc_to_string(igt_crc_t *crc) { char buf[128]; - igt_assert_eq(crc->n_words, 5); - sprintf(buf, "%08x %08x %08x %08x %08x", crc->crc[0], crc->crc[1], crc->crc[2], crc->crc[3], crc->crc[4]); return strdup(buf); } +#define MAX_CRC_ENTRIES 10 +#define MAX_LINE_LEN (10 + 11 * MAX_CRC_ENTRIES + 1) + /* (6 fields, 8 chars each, space separated (5) + '\n') */ -#define PIPE_CRC_LINE_LEN (6 * 8 + 5 + 1) -/* account for \'0' */ -#define PIPE_CRC_BUFFER_LEN (PIPE_CRC_LINE_LEN + 1) +#define LEGACY_LINE_LEN (6 * 8 + 5 + 1) struct _igt_pipe_crc { int ctl_fd; int crc_fd; - int line_len; - int buffer_len; int flags; + bool is_legacy; enum pipe pipe; enum intel_pipe_crc_source source; @@ -319,23 +322,39 @@ static const char *pipe_crc_sources[] = { static const char *pipe_crc_source_name(enum intel_pipe_crc_source source) { - return pipe_crc_sources[source]; + return pipe_crc_sources[source]; } static bool igt_pipe_crc_do_start(igt_pipe_crc_t *pipe_crc) { char buf[64]; + int mode = O_RDONLY; /* Stop first just to make sure we don't have lingering state left. */ igt_pipe_crc_stop(pipe_crc); - sprintf(buf, "pipe %s %s", kmstest_pipe_name(pipe_crc->pipe), - pipe_crc_source_name(pipe_crc->source)); + if (pipe_crc->is_legacy) + sprintf(buf, "pipe %s %s", kmstest_pipe_name(pipe_crc->pipe), + pipe_crc_source_name(pipe_crc->source)); + else + sprintf(buf, "%s", pipe_crc_source_name(pipe_crc->source)); + errno = 0; igt_assert_eq(write(pipe_crc->ctl_fd, buf, strlen(buf)), strlen(buf)); if (errno != 0) return false; + if (!pipe_crc->is_legacy) { + sprintf(buf, "crtc-%d/crc/data", pipe_crc->pipe); + errno = 0; + if (pipe_crc->flags & CRC_NONBLOCK) + mode |= O_NONBLOCK; + pipe_crc->crc_fd = igt_debugfs_open(buf, mode); + if (pipe_crc->crc_fd == -1 && errno == EINVAL) + return false; + igt_assert_eq(errno, 0); + } + return true; } @@ -349,15 +368,38 @@ static void igt_pipe_crc_pipe_off(int fd, enum pipe pipe) static void igt_pipe_crc_reset(void) { + igt_debugfs_t *debugfs = __igt_debugfs_singleton(); int fd; + struct dirent *dirent; + char buf[128]; + const char *cmd = "none"; + DIR *dir; fd = igt_debugfs_open("i915_display_crc_ctl", O_WRONLY); + if (fd != -1) { + igt_pipe_crc_pipe_off(fd, PIPE_A); + igt_pipe_crc_pipe_off(fd, PIPE_B); + igt_pipe_crc_pipe_off(fd, PIPE_C); + + close(fd); + } - igt_pipe_crc_pipe_off(fd, PIPE_A); - igt_pipe_crc_pipe_off(fd, PIPE_B); - igt_pipe_crc_pipe_off(fd, PIPE_C); + dir = opendir(debugfs->dri_path); + if (dir) { + while ((dirent = readdir(dir))) { + if (strcmp(dirent->d_name, "crtc-") != 0) + continue; - close(fd); + sprintf(buf, "%s/%s/crc/control", debugfs->dri_path, + dirent->d_name); + fd = open(buf, O_WRONLY); + + igt_assert_eq(write(fd, cmd, strlen(cmd)), strlen(cmd)); + + close(fd); + } + closedir(dir); + } } static void pipe_crc_exit_handler(int sig) @@ -379,13 +421,16 @@ void igt_require_pipe_crc(void) size_t written; int ret; - ctl = igt_debugfs_fopen("i915_display_crc_ctl", "r+"); - igt_require_f(ctl, - "No display_crc_ctl found, kernel too old\n"); - written = fwrite(cmd, 1, strlen(cmd), ctl); - ret = fflush(ctl); - igt_require_f((written == strlen(cmd) && ret == 0) || errno != ENODEV, - "CRCs not supported on this platform\n"); + ctl = igt_debugfs_fopen("crtc-0/crc/control", "r+"); + if (!ctl) { + ctl = igt_debugfs_fopen("i915_display_crc_ctl", "r+"); + igt_require_f(ctl, + "No display_crc_ctl found, kernel too old\n"); + written = fwrite(cmd, 1, strlen(cmd), ctl); + ret = fflush(ctl); + igt_require_f((written == strlen(cmd) && ret == 0) || errno != ENODEV, + "CRCs not supported on this platform\n"); + } fclose(ctl); } @@ -395,20 +440,34 @@ pipe_crc_new(enum pipe pipe, enum intel_pipe_crc_source source, int flags) { igt_pipe_crc_t *pipe_crc; char buf[128]; + int mode = O_RDONLY; igt_install_exit_handler(pipe_crc_exit_handler); pipe_crc = calloc(1, sizeof(struct _igt_pipe_crc)); - pipe_crc->ctl_fd = igt_debugfs_open("i915_display_crc_ctl", O_WRONLY); - igt_assert(pipe_crc->ctl_fd != -1); + if (!(flags & CRC_FORCE_LEGACY)) { + sprintf(buf, "crtc-%d/crc/control", pipe); + pipe_crc->ctl_fd = igt_debugfs_open(buf, O_WRONLY); + } + + if (pipe_crc->ctl_fd == -1 || flags & CRC_FORCE_LEGACY) { + pipe_crc->ctl_fd = igt_debugfs_open("i915_display_crc_ctl", + O_WRONLY); + igt_assert(pipe_crc->ctl_fd != -1); + pipe_crc->is_legacy = true; + } - sprintf(buf, "i915_pipe_%s_crc", kmstest_pipe_name(pipe)); - pipe_crc->crc_fd = igt_debugfs_open(buf, flags); - igt_assert(pipe_crc->crc_fd != -1); + if (pipe_crc->is_legacy) { + sprintf(buf, "i915_pipe_%s_crc", kmstest_pipe_name(pipe)); + if (flags & CRC_NONBLOCK) + mode |= O_NONBLOCK; + pipe_crc->crc_fd = igt_debugfs_open(buf, mode); + igt_assert(pipe_crc->crc_fd != -1); + } else { + pipe_crc->crc_fd = -1; + } - pipe_crc->line_len = PIPE_CRC_LINE_LEN; - pipe_crc->buffer_len = PIPE_CRC_BUFFER_LEN; pipe_crc->pipe = pipe; pipe_crc->source = source; pipe_crc->flags = flags; @@ -431,7 +490,7 @@ pipe_crc_new(enum pipe pipe, enum intel_pipe_crc_source source, int flags) igt_pipe_crc_t * igt_pipe_crc_new(enum pipe pipe, enum intel_pipe_crc_source source) { - return pipe_crc_new(pipe, source, O_RDONLY); + return pipe_crc_new(pipe, source, CRC_DEFAULTS); } /** @@ -449,7 +508,43 @@ igt_pipe_crc_new(enum pipe pipe, enum intel_pipe_crc_source source) igt_pipe_crc_t * igt_pipe_crc_new_nonblock(enum pipe pipe, enum intel_pipe_crc_source source) { - return pipe_crc_new(pipe, source, O_RDONLY | O_NONBLOCK); + return pipe_crc_new(pipe, source, CRC_NONBLOCK); +} + +/** + * igt_pipe_crc_new_legacy: + * @pipe: display pipe to use as source + * @source: CRC tap point to use as source + * + * This sets up a new pipe CRC capture object for the given @pipe and @source + * in blocking mode. The old i915-specific ABI will be used. + * + * Returns: A pipe CRC object for the given @pipe and @source. The library + * assumes that the source is always available since recent kernels support at + * least INTEL_PIPE_CRC_SOURCE_AUTO everywhere. + */ +igt_pipe_crc_t *igt_pipe_crc_new_legacy(enum pipe pipe, + enum intel_pipe_crc_source source) +{ + return pipe_crc_new(pipe, source, CRC_FORCE_LEGACY); +} + +/** + * igt_pipe_crc_new_nonblock_legacy: + * @pipe: display pipe to use as source + * @source: CRC tap point to use as source + * + * This sets up a new pipe CRC capture object for the given @pipe and @source + * in nonblocking mode. The old i915-specific ABI will be used. + * + * Returns: A pipe CRC object for the given @pipe and @source. The library + * assumes that the source is always available since recent kernels support at + * least INTEL_PIPE_CRC_SOURCE_AUTO everywhere. + */ +igt_pipe_crc_t *igt_pipe_crc_new_nonblock_legacy(enum pipe pipe, + enum intel_pipe_crc_source source) +{ + return pipe_crc_new(pipe, source, CRC_NONBLOCK | CRC_FORCE_LEGACY); } /** @@ -468,34 +563,59 @@ void igt_pipe_crc_free(igt_pipe_crc_t *pipe_crc) free(pipe_crc); } -static bool pipe_crc_init_from_string(igt_crc_t *crc, const char *line) +static bool pipe_crc_init_from_string(igt_pipe_crc_t *pipe_crc, igt_crc_t *crc, + const char *line) { - int n; + int n, i; + const char *buf; + + if (pipe_crc->is_legacy) { + crc->has_valid_frame = true; + crc->n_words = 5; + n = sscanf(line, "%8u %8x %8x %8x %8x %8x", &crc->frame, + &crc->crc[0], &crc->crc[1], &crc->crc[2], + &crc->crc[3], &crc->crc[4]); + return n == 6; + } + + if (strncmp(line, "XXXXXXXXXX", 10) == 0) + crc->has_valid_frame = false; + else { + crc->has_valid_frame = true; + crc->frame = strtoul(line, NULL, 16); + } + + buf = line + 10; + for (i = 0; *buf != '\n'; i++, buf += 11) + crc->crc[i] = strtoul(buf, NULL, 16); - crc->n_words = 5; - n = sscanf(line, "%8u %8x %8x %8x %8x %8x", &crc->frame, &crc->crc[0], - &crc->crc[1], &crc->crc[2], &crc->crc[3], &crc->crc[4]); - return n == 6; + crc->n_words = i; + + return true; } static int read_crc(igt_pipe_crc_t *pipe_crc, igt_crc_t *out) { ssize_t bytes_read; - char buf[pipe_crc->buffer_len]; + char buf[MAX_LINE_LEN + 1]; + size_t read_len; + + if (pipe_crc->is_legacy) + read_len = LEGACY_LINE_LEN; + else + read_len = MAX_LINE_LEN; igt_set_timeout(5, "CRC reading"); - bytes_read = read(pipe_crc->crc_fd, &buf, pipe_crc->line_len); + bytes_read = read(pipe_crc->crc_fd, &buf, read_len); igt_reset_timeout(); if (bytes_read < 0 && errno == EAGAIN) { - igt_assert(pipe_crc->flags & O_NONBLOCK); + igt_assert(pipe_crc->flags & CRC_NONBLOCK); bytes_read = 0; - } else { - igt_assert_eq(bytes_read, pipe_crc->line_len); } buf[bytes_read] = '\0'; - if (bytes_read && !pipe_crc_init_from_string(out, buf)) + if (bytes_read && !pipe_crc_init_from_string(pipe_crc, out, buf)) return -EINVAL; return bytes_read; @@ -519,15 +639,18 @@ void igt_pipe_crc_start(igt_pipe_crc_t *pipe_crc) igt_assert(igt_pipe_crc_do_start(pipe_crc)); - /* - * For some no yet identified reason, the first CRC is bonkers. So - * let's just wait for the next vblank and read out the buggy result. - * - * On CHV sometimes the second CRC is bonkers as well, so don't trust - * that one either. - */ - read_one_crc(pipe_crc, &crc); - read_one_crc(pipe_crc, &crc); + if (pipe_crc->is_legacy) { + /* + * For some no yet identified reason, the first CRC is + * bonkers. So let's just wait for the next vblank and read + * out the buggy result. + * + * On CHV sometimes the second CRC is bonkers as well, so + * don't trust that one either. + */ + read_one_crc(pipe_crc, &crc); + read_one_crc(pipe_crc, &crc); + } } /** @@ -540,8 +663,15 @@ void igt_pipe_crc_stop(igt_pipe_crc_t *pipe_crc) { char buf[32]; - sprintf(buf, "pipe %s none", kmstest_pipe_name(pipe_crc->pipe)); - igt_assert_eq(write(pipe_crc->ctl_fd, buf, strlen(buf)), strlen(buf)); + if (pipe_crc->is_legacy) { + sprintf(buf, "pipe %s none", + kmstest_pipe_name(pipe_crc->pipe)); + igt_assert_eq(write(pipe_crc->ctl_fd, buf, strlen(buf)), + strlen(buf)); + } else { + close(pipe_crc->crc_fd); + pipe_crc->crc_fd = -1; + } } /** diff --git a/lib/igt_debugfs.h b/lib/igt_debugfs.h index 1a757b84a19a..84d5c0a0a84b 100644 --- a/lib/igt_debugfs.h +++ b/lib/igt_debugfs.h @@ -60,6 +60,7 @@ bool igt_debugfs_search(const char *filename, const char *substring); */ typedef struct _igt_pipe_crc igt_pipe_crc_t; +#define DRM_MAX_CRC_NR 10 /** * igt_crc_t: * @frame: frame number of the capture CRC @@ -71,8 +72,9 @@ typedef struct _igt_pipe_crc igt_pipe_crc_t; */ typedef struct { uint32_t frame; + bool has_valid_frame; int n_words; - uint32_t crc[5]; + uint32_t crc[DRM_MAX_CRC_NR]; } igt_crc_t; /** @@ -117,6 +119,10 @@ igt_pipe_crc_t * igt_pipe_crc_new(enum pipe pipe, enum intel_pipe_crc_source source); igt_pipe_crc_t * igt_pipe_crc_new_nonblock(enum pipe pipe, enum intel_pipe_crc_source source); +igt_pipe_crc_t * +igt_pipe_crc_new_legacy(enum pipe pipe, enum intel_pipe_crc_source source); +igt_pipe_crc_t * +igt_pipe_crc_new_nonblock_legacy(enum pipe pipe, enum intel_pipe_crc_source source); void igt_pipe_crc_free(igt_pipe_crc_t *pipe_crc); void igt_pipe_crc_start(igt_pipe_crc_t *pipe_crc); void igt_pipe_crc_stop(igt_pipe_crc_t *pipe_crc); diff --git a/tests/kms_pipe_crc_basic.c b/tests/kms_pipe_crc_basic.c index 4de53bc77a3a..3de974c315e7 100644 --- a/tests/kms_pipe_crc_basic.c +++ b/tests/kms_pipe_crc_basic.c @@ -58,10 +58,31 @@ static void test_bad_command(data_t *data, const char *cmd) fclose(ctl); } +static void test_bad_source(data_t *data) +{ + FILE *f; + size_t written; + const char *source = "foo"; + + f = igt_debugfs_fopen("crtc-0/crc/control", "w"); + igt_require(f); + written = fwrite(source, 1, strlen(source), f); + fflush(f); + igt_assert_eq(written, strlen(source)); + igt_assert(!ferror(f)); + igt_assert(!errno); + fclose(f); + + f = igt_debugfs_fopen("crtc-0/crc/data", "w"); + igt_assert(!f); + igt_assert_eq(errno, EINVAL); +} + #define N_CRCS 3 #define TEST_SEQUENCE (1<<0) #define TEST_NONBLOCK (1<<1) +#define TEST_LEGACY (1<<2) static int test_read_crc_for_output(data_t *data, int pipe, igt_output_t *output, @@ -104,10 +125,22 @@ test_read_crc_for_output(data_t *data, int pipe, igt_output_t *output, igt_display_commit(display); - if (flags & TEST_NONBLOCK) - pipe_crc = igt_pipe_crc_new_nonblock(pipe, INTEL_PIPE_CRC_SOURCE_AUTO); - else - pipe_crc = igt_pipe_crc_new(pipe, INTEL_PIPE_CRC_SOURCE_AUTO); + if (flags & TEST_LEGACY) { + if (flags & TEST_NONBLOCK) + pipe_crc = igt_pipe_crc_new_nonblock_legacy( + pipe, + INTEL_PIPE_CRC_SOURCE_AUTO); + else + pipe_crc = igt_pipe_crc_new_legacy(pipe, + INTEL_PIPE_CRC_SOURCE_AUTO); + } else { + if (flags & TEST_NONBLOCK) + pipe_crc = igt_pipe_crc_new_nonblock(pipe, + INTEL_PIPE_CRC_SOURCE_AUTO); + else + pipe_crc = igt_pipe_crc_new(pipe, + INTEL_PIPE_CRC_SOURCE_AUTO); + } igt_pipe_crc_start(pipe_crc); @@ -143,9 +176,16 @@ test_read_crc_for_output(data_t *data, int pipe, igt_output_t *output, for (j = 0; j < (n_crcs - 1); j++) igt_assert_crc_equal(&crcs[j], &crcs[j + 1]); - if (flags & TEST_SEQUENCE) - for (j = 0; j < (n_crcs - 1); j++) - igt_assert_eq(crcs[j].frame + 1, crcs[j + 1].frame); + if (flags & TEST_SEQUENCE) { + if (!crcs[0].has_valid_frame) { + igt_info("Skipping connector, its 'auto' source doesn't give us frame numbers.\n"); + goto skip; + } else { + for (j = 0; j < (n_crcs - 1); j++) + igt_assert_eq(crcs[j].frame + 1, + crcs[j + 1].frame); + } + } free(crcs); igt_pipe_crc_free(pipe_crc); @@ -156,6 +196,17 @@ test_read_crc_for_output(data_t *data, int pipe, igt_output_t *output, } return 1; + +skip: + if (crcs) + free(crcs); + igt_pipe_crc_free(pipe_crc); + igt_remove_fb(data->drm_fd, &data->fb); + igt_plane_set_fb(primary, NULL); + + igt_output_set_pipe(output, PIPE_ANY); + + return 0; } static void test_read_crc(data_t *data, int pipe, unsigned flags) @@ -166,8 +217,10 @@ static void test_read_crc(data_t *data, int pipe, unsigned flags) igt_skip_on(pipe >= data->display.n_pipes); - for_each_connected_output(display, output) { + if (flags & TEST_LEGACY) + igt_require_intel(data->drm_fd); + for_each_connected_output(display, output) { igt_info("%s: Testing connector %s using pipe %s\n", igt_subtest_name(), igt_output_name(output), kmstest_pipe_name(pipe)); @@ -178,6 +231,46 @@ static void test_read_crc(data_t *data, int pipe, unsigned flags) igt_require_f(valid_connectors, "No connector found for pipe %i\n", pipe); } +static void test_read_crcs(data_t *data, unsigned flags) +{ + const char *postfix; + + if (flags & TEST_LEGACY) + postfix = "-legacy"; + else + postfix = ""; + + for (int i = 0; i < 3; i++) { + igt_subtest_f("read-crc-pipe-%c%s", 'A'+i, postfix) + test_read_crc(data, i, 0 | flags); + + igt_subtest_f("read-crc-pipe-%c-frame-sequence%s", 'A'+i, postfix) + test_read_crc(data, i, TEST_SEQUENCE | flags); + + igt_subtest_f("nonblocking-crc-pipe-%c%s", 'A'+i, postfix) + test_read_crc(data, i, TEST_NONBLOCK | flags); + + igt_subtest_f("nonblocking-crc-pipe-%c-frame-sequence%s", + 'A'+i, postfix) + test_read_crc(data, i, TEST_SEQUENCE | TEST_NONBLOCK | flags); + + igt_subtest_f("suspend-read-crc-pipe-%c%s", 'A'+i, postfix) { + igt_skip_on(i >= data->display.n_pipes); + igt_system_suspend_autoresume(); + + test_read_crc(data, i, flags); + } + + igt_subtest_f("hang-read-crc-pipe-%c%s", 'A'+i, postfix) { + igt_hang_ring_t hang = + igt_hang_ring(data->drm_fd, I915_EXEC_RENDER); + test_read_crc(data, i, flags); + igt_post_hang_ring(data->drm_fd, hang); + test_read_crc(data, i, flags); + } + } +} + data_t data = {0, }; igt_main @@ -185,7 +278,7 @@ igt_main igt_skip_on_simulation(); igt_fixture { - data.drm_fd = drm_open_driver_master(DRIVER_INTEL); + data.drm_fd = drm_open_driver_master(DRIVER_ANY); igt_enable_connectors(); @@ -196,47 +289,34 @@ igt_main igt_display_init(&data.display, data.drm_fd); } - igt_subtest("bad-pipe") + igt_subtest("bad-source") { + test_bad_source(&data); + } + + test_read_crcs(&data, 0); + + igt_subtest("bad-pipe-legacy") { + igt_require_intel(data.drm_fd); test_bad_command(&data, "pipe D none"); + } - igt_subtest("bad-source") + igt_subtest("bad-source-legacy") { + igt_require_intel(data.drm_fd); test_bad_command(&data, "pipe A foo"); + } - igt_subtest("bad-nb-words-1") + igt_subtest("bad-nb-words-1-legacy") { + igt_require_intel(data.drm_fd); test_bad_command(&data, "pipe foo"); + } - igt_subtest("bad-nb-words-3") + igt_subtest("bad-nb-words-3-legacy") { + igt_require_intel(data.drm_fd); test_bad_command(&data, "pipe A none option"); - - for (int i = 0; i < 3; i++) { - igt_subtest_f("read-crc-pipe-%c", 'A'+i) - test_read_crc(&data, i, 0); - - igt_subtest_f("read-crc-pipe-%c-frame-sequence", 'A'+i) - test_read_crc(&data, i, TEST_SEQUENCE); - - igt_subtest_f("nonblocking-crc-pipe-%c", 'A'+i) - test_read_crc(&data, i, TEST_NONBLOCK); - - igt_subtest_f("nonblocking-crc-pipe-%c-frame-sequence", 'A'+i) - test_read_crc(&data, i, TEST_SEQUENCE | TEST_NONBLOCK); - - igt_subtest_f("suspend-read-crc-pipe-%c", 'A'+i) { - igt_skip_on(i >= data.display.n_pipes); - igt_system_suspend_autoresume(); - - test_read_crc(&data, i, 0); - } - - igt_subtest_f("hang-read-crc-pipe-%c", 'A'+i) { - igt_hang_ring_t hang = - igt_hang_ring(data.drm_fd, I915_EXEC_RENDER); - test_read_crc(&data, i, 0); - igt_post_hang_ring(data.drm_fd, hang); - test_read_crc(&data, i, 0); - } } + test_read_crcs(&data, TEST_LEGACY); + igt_fixture { igt_display_fini(&data.display); }