[Intel-gfx] [PATCH i-g-t v3] lib/debugfs: Support new generic ABI for CRC capture
Robert Foss
robert.foss at collabora.com
Tue Nov 29 21:40:14 UTC 2016
Hi tomeu,
This patch does not seem to apply cleanly on upstream/master.
Rob.
> 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 <tomeu.vizoso at collabora.com>
>
> ---
>
> Have just rebased this, and made sure we fallback to the old ABI when
> accessing the debugfs files directly from kms_pipe_crc_basic.
>
> Thanks,
>
> Tomeu
> ---
> lib/igt_debugfs.c | 190 +++++++++++++++++++++++++++++++++
> ------------
> lib/igt_debugfs.h | 4 +-
> tests/kms_pipe_crc_basic.c | 30 ++++++-
> 3 files changed, 171 insertions(+), 53 deletions(-)
>
> diff --git a/lib/igt_debugfs.c b/lib/igt_debugfs.c
> index 9142e3f78868..3d92c6a10a41 100644
> --- a/lib/igt_debugfs.c
> +++ b/lib/igt_debugfs.c
> @@ -25,6 +25,7 @@
> #include <inttypes.h>
> #include <sys/stat.h>
> #include <sys/mount.h>
> +#include <dirent.h>
> #include <errno.h>
> #include <stdio.h>
> #include <stdlib.h>
> @@ -291,25 +292,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;
> @@ -340,13 +339,26 @@ static bool
> igt_pipe_crc_do_start(igt_pipe_crc_t *pipe_crc)
> /* 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;
> + pipe_crc->crc_fd = igt_debugfs_open(buf, pipe_crc-
> >flags);
> + if (pipe_crc->crc_fd == -1 && errno == EINVAL)
> + return false;
> + igt_assert_eq(errno, 0);
> + }
> +
> return true;
> }
>
> @@ -360,15 +372,45 @@ 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";
> + bool done = false;
> + DIR *dir;
> +
> + dir = opendir(debugfs->dri_path);
> + if (dir) {
> + while ((dirent = readdir(dir))) {
> + if (strcmp(dirent->d_name, "crtc-") != 0)
> + continue;
> +
> + sprintf(buf, "%s/%s/crc/control", debugfs-
> >dri_path,
> + dirent->d_name);
> + fd = open(buf, O_WRONLY);
> + if (fd == -1)
> + continue;
> +
> + igt_assert_eq(write(fd, cmd, strlen(cmd)),
> strlen(cmd));
> + done = true;
> +
> + close(fd);
> + }
> + closedir(dir);
> + }
>
> - fd = igt_debugfs_open("i915_display_crc_ctl", O_WRONLY);
> + if (done)
> + return;
>
> - igt_pipe_crc_pipe_off(fd, PIPE_A);
> - igt_pipe_crc_pipe_off(fd, PIPE_B);
> - igt_pipe_crc_pipe_off(fd, PIPE_C);
> + 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);
> + close(fd);
> + }
> }
>
> static void pipe_crc_exit_handler(int sig)
> @@ -390,13 +432,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);
> }
> @@ -411,15 +456,25 @@ pipe_crc_new(enum pipe pipe, enum
> intel_pipe_crc_source source, int flags)
>
> 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);
> + sprintf(buf, "crtc-%d/crc/control", pipe);
> + pipe_crc->ctl_fd = igt_debugfs_open(buf, O_WRONLY);
> + if (pipe_crc->ctl_fd == -1) {
> + 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));
> + pipe_crc->crc_fd = igt_debugfs_open(buf, flags);
> + igt_assert(pipe_crc->crc_fd != -1);
> + igt_debug("Using legacy frame CRC ABI\n");
> + } else {
> + pipe_crc->crc_fd = -1;
> + igt_debug("Using generic frame CRC ABI\n");
> + }
>
> - 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;
> @@ -479,34 +534,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;
>
> - 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 (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 = 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);
> 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;
> @@ -530,15 +610,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);
> + }
> }
>
> /**
> @@ -551,8 +634,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 fb189322633f..4c6572cd244c 100644
> --- a/lib/igt_debugfs.h
> +++ b/lib/igt_debugfs.h
> @@ -62,6 +62,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
> @@ -73,8 +74,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;
>
> /**
> diff --git a/tests/kms_pipe_crc_basic.c b/tests/kms_pipe_crc_basic.c
> index 04d5a1345760..b106f9bd05ee 100644
> --- a/tests/kms_pipe_crc_basic.c
> +++ b/tests/kms_pipe_crc_basic.c
> @@ -49,6 +49,8 @@ static void test_bad_command(data_t *data, const
> char *cmd)
> size_t written;
>
> ctl = igt_debugfs_fopen("i915_display_crc_ctl", "r+");
> + igt_require(ctl);
> +
> written = fwrite(cmd, 1, strlen(cmd), ctl);
> fflush(ctl);
> igt_assert_eq(written, strlen(cmd));
> @@ -58,6 +60,30 @@ 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");
> + if (!f) {
> + test_bad_command(data, "pipe A foo");
> + return;
> + }
> +
> + 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)
> @@ -185,7 +211,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();
>
> @@ -200,7 +226,7 @@ igt_main
> test_bad_command(&data, "pipe D none");
>
> igt_subtest("bad-source")
> - test_bad_command(&data, "pipe A foo");
> + test_bad_source(&data);
>
> igt_subtest("bad-nb-words-1")
> test_bad_command(&data, "pipe foo");
More information about the Intel-gfx
mailing list