On Fri, Jul 14, 2017 at 04:18:50PM +0100, Liviu Dudau wrote: > From: Brian Starkey <brian.starkey@xxxxxxx> > > Separate out the CRC code for better compartmentalisation. Should ease > the addition of more/different CRC sources in the future. > > Signed-off-by: Brian Starkey <brian.starkey@xxxxxxx> Needs adjustements to gtkdoc I assume, plus a proper intro text for igt_crc.c. With that, and assuming you didn't change the code: Acked-by: Daniel Vetter <daniel.vetter@xxxxxxxx> > --- > lib/Makefile.sources | 2 + > lib/igt_chamelium.h | 1 + > lib/igt_crc.c | 563 ++++++++++++++++++++++++++++++++++++++ > lib/igt_crc.h | 125 +++++++++ > lib/igt_debugfs.c | 547 ------------------------------------ > lib/igt_debugfs.h | 81 ------ > tests/chamelium.c | 1 + > tests/kms_atomic_transition.c | 1 + > tests/kms_ccs.c | 1 + > tests/kms_chv_cursor_fail.c | 1 + > tests/kms_crtc_background_color.c | 1 + > tests/kms_cursor_crc.c | 1 + > tests/kms_cursor_legacy.c | 1 + > tests/kms_draw_crc.c | 1 + > tests/kms_fbc_crc.c | 1 + > tests/kms_flip_tiling.c | 1 + > tests/kms_frontbuffer_tracking.c | 1 + > tests/kms_mmap_write_crc.c | 1 + > tests/kms_mmio_vs_cs_flip.c | 1 + > tests/kms_pipe_color.c | 1 + > tests/kms_pipe_crc_basic.c | 1 + > tests/kms_plane.c | 1 + > tests/kms_plane_lowres.c | 1 + > tests/kms_plane_multiple.c | 1 + > tests/kms_plane_scaling.c | 1 + > tests/kms_pwrite_crc.c | 1 + > tests/kms_rotation_crc.c | 1 + > tests/kms_universal_plane.c | 1 + > tools/intel_display_crc.c | 1 + > 29 files changed, 714 insertions(+), 628 deletions(-) > create mode 100644 lib/igt_crc.c > create mode 100644 lib/igt_crc.h > > diff --git a/lib/Makefile.sources b/lib/Makefile.sources > index 53fdb54c..cfba15c9 100644 > --- a/lib/Makefile.sources > +++ b/lib/Makefile.sources > @@ -11,6 +11,8 @@ lib_source_list = \ > igt_debugfs.h \ > igt_aux.c \ > igt_aux.h \ > + igt_crc.c \ > + igt_crc.h \ > igt_edid_template.h \ > igt_gt.c \ > igt_gt.h \ > diff --git a/lib/igt_chamelium.h b/lib/igt_chamelium.h > index 81322ad2..ea5abc2e 100644 > --- a/lib/igt_chamelium.h > +++ b/lib/igt_chamelium.h > @@ -31,6 +31,7 @@ > #endif > > #include "igt.h" > +#include "igt_crc.h" > #include <stdbool.h> > > struct chamelium; > diff --git a/lib/igt_crc.c b/lib/igt_crc.c > new file mode 100644 > index 00000000..91a0b5a8 > --- /dev/null > +++ b/lib/igt_crc.c > @@ -0,0 +1,563 @@ > +/* > + * Copyright © 2013 Intel Corporation > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice (including the next > + * paragraph) shall be included in all copies or substantial portions of the > + * Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS > + * IN THE SOFTWARE. > + * > + */ > +#include <dirent.h> > +#include <errno.h> > +#include <fcntl.h> > +#include <stdio.h> > +#include <stdlib.h> > +#include <string.h> > +#include <sys/stat.h> > +#include <sys/types.h> > + > +#include "igt_aux.h" > +#include "igt_crc.h" > +#include "igt_core.h" > +#include "igt_debugfs.h" > +#include "igt_kms.h" > + > +/** > + * igt_assert_crc_equal: > + * @a: first pipe CRC value > + * @b: second pipe CRC value > + * > + * Compares two CRC values and fails the testcase if they don't match with > + * igt_fail(). Note that due to CRC collisions CRC based testcase can only > + * assert that CRCs match, never that they are different. Otherwise there might > + * be random testcase failures when different screen contents end up with the > + * same CRC by chance. > + */ > +void igt_assert_crc_equal(const igt_crc_t *a, const igt_crc_t *b) > +{ > + int i; > + > + for (i = 0; i < a->n_words; i++) > + igt_assert_eq_u32(a->crc[i], b->crc[i]); > +} > + > +/** > + * igt_crc_to_string: > + * @crc: pipe CRC value to print > + * > + * This formats @crc into a string buffer which is owned by igt_crc_to_string(). > + * The next call will override the buffer again, which makes this multithreading > + * unsafe. > + * > + * This should only ever be used for diagnostic debug output. > + */ > +char *igt_crc_to_string(igt_crc_t *crc) > +{ > + int i; > + char buf[128] = { 0 }; > + > + for (i = 0; i < crc->n_words; i++) > + sprintf(buf + strlen(buf), "%08x ", crc->crc[i]); > + > + 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 LEGACY_LINE_LEN (6 * 8 + 5 + 1) > + > +struct _igt_pipe_crc { > + int fd; > + int dir; > + int ctl_fd; > + int crc_fd; > + int flags; > + bool is_legacy; > + > + enum pipe pipe; > + enum intel_pipe_crc_source source; > +}; > + > +static const char *pipe_crc_sources[] = { > + "none", > + "plane1", > + "plane2", > + "pf", > + "pipe", > + "TV", > + "DP-B", > + "DP-C", > + "DP-D", > + "auto" > +}; > + > +static const char *pipe_crc_source_name(enum intel_pipe_crc_source source) > +{ > + return pipe_crc_sources[source]; > +} > + > +static bool igt_pipe_crc_do_start(igt_pipe_crc_t *pipe_crc) > +{ > + char buf[64]; > + > + /* Stop first just to make sure we don't have lingering state left. */ > + igt_pipe_crc_stop(pipe_crc); > + > + 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)); > + > + igt_assert_eq(write(pipe_crc->ctl_fd, buf, strlen(buf)), strlen(buf)); > + > + if (!pipe_crc->is_legacy) { > + int err; > + > + sprintf(buf, "crtc-%d/crc/data", pipe_crc->pipe); > + err = 0; > + > + pipe_crc->crc_fd = openat(pipe_crc->dir, buf, pipe_crc->flags); > + if (pipe_crc->crc_fd < 0) > + err = -errno; > + > + if (err == -EINVAL) > + return false; > + > + igt_assert_eq(err, 0); > + } > + > + errno = 0; > + return true; > +} > + > +static void igt_pipe_crc_pipe_off(int fd, enum pipe pipe) > +{ > + char buf[32]; > + > + sprintf(buf, "pipe %s none", kmstest_pipe_name(pipe)); > + igt_assert_eq(write(fd, buf, strlen(buf)), strlen(buf)); > +} > + > +static void igt_pipe_crc_reset(int drm_fd) > +{ > + struct dirent *dirent; > + const char *cmd = "none"; > + bool done = false; > + DIR *dir; > + int fdir; > + int fd; > + > + fdir = igt_debugfs_dir(drm_fd); > + if (fdir < 0) > + return; > + > + dir = fdopendir(fdir); > + if (!dir) { > + close(fdir); > + return; > + } > + > + while ((dirent = readdir(dir))) { > + char buf[128]; > + > + if (strcmp(dirent->d_name, "crtc-") != 0) > + continue; > + > + sprintf(buf, "%s/crc/control", dirent->d_name); > + fd = openat(fdir, buf, O_WRONLY); > + if (fd < 0) > + continue; > + > + igt_assert_eq(write(fd, cmd, strlen(cmd)), strlen(cmd)); > + close(fd); > + > + done = true; > + } > + closedir(dir); > + > + if (!done) { > + fd = openat(fdir, "i915_display_crtc_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(fdir); > +} > + > +static void pipe_crc_exit_handler(int sig) > +{ > + struct dirent *dirent; > + char buf[128]; > + DIR *dir; > + int fd; > + > + dir = opendir("/dev/dri"); > + if (!dir) > + return; > + > + /* > + * Try to reset CRC capture for all DRM devices, this is only needed > + * for the legacy CRC ABI and can be completely removed once the > + * legacy codepaths are removed. > + */ > + while ((dirent = readdir(dir))) { > + if (strncmp(dirent->d_name, "card", 4) != 0) > + continue; > + > + sprintf(buf, "/dev/dri/%s", dirent->d_name); > + fd = open(buf, O_WRONLY); > + > + igt_pipe_crc_reset(fd); > + > + close(fd); > + } > + closedir(dir); > +} > + > +/** > + * igt_require_pipe_crc: > + * > + * Convenience helper to check whether pipe CRC capturing is supported by the > + * kernel. Uses igt_skip to automatically skip the test/subtest if this isn't > + * the case. > + */ > +void igt_require_pipe_crc(int fd) > +{ > + const char *cmd = "pipe A none"; > + int ctl, written; > + > + ctl = igt_debugfs_open(fd, "crtc-0/crc/control", O_RDONLY); > + if (ctl < 0) { > + ctl = igt_debugfs_open(fd, "i915_display_crc_ctl", O_WRONLY); > + igt_require_f(ctl, > + "No display_crc_ctl found, kernel too old\n"); > + > + written = write(ctl, cmd, strlen(cmd)); > + igt_require_f(written < 0, > + "CRCs not supported on this platform\n"); > + } > + close(ctl); > +} > + > +static igt_pipe_crc_t * > +pipe_crc_new(int fd, enum pipe pipe, enum intel_pipe_crc_source source, int flags) > +{ > + igt_pipe_crc_t *pipe_crc; > + char buf[128]; > + int debugfs; > + > + debugfs = igt_debugfs_dir(fd); > + igt_assert(debugfs != -1); > + > + igt_install_exit_handler(pipe_crc_exit_handler); > + > + pipe_crc = calloc(1, sizeof(struct _igt_pipe_crc)); > + > + sprintf(buf, "crtc-%d/crc/control", pipe); > + pipe_crc->ctl_fd = openat(debugfs, buf, O_WRONLY); > + if (pipe_crc->ctl_fd == -1) { > + pipe_crc->ctl_fd = openat(debugfs, > + "i915_display_crc_ctl", O_WRONLY); > + igt_assert(pipe_crc->ctl_fd != -1); > + pipe_crc->is_legacy = true; > + } > + > + if (pipe_crc->is_legacy) { > + sprintf(buf, "i915_pipe_%s_crc", kmstest_pipe_name(pipe)); > + pipe_crc->crc_fd = openat(debugfs, 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->fd = fd; > + pipe_crc->dir = debugfs; > + pipe_crc->pipe = pipe; > + pipe_crc->source = source; > + pipe_crc->flags = flags; > + > + return pipe_crc; > +} > + > +/** > + * igt_pipe_crc_new: > + * @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. > + * > + * 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(int fd, enum pipe pipe, enum intel_pipe_crc_source source) > +{ > + return pipe_crc_new(fd, pipe, source, O_RDONLY); > +} > + > +/** > + * igt_pipe_crc_new_nonblock: > + * @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. > + * > + * 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(int fd, enum pipe pipe, enum intel_pipe_crc_source source) > +{ > + return pipe_crc_new(fd, pipe, source, O_RDONLY | O_NONBLOCK); > +} > + > +/** > + * igt_pipe_crc_free: > + * @pipe_crc: pipe CRC object > + * > + * Frees all resources associated with @pipe_crc. > + */ > +void igt_pipe_crc_free(igt_pipe_crc_t *pipe_crc) > +{ > + if (!pipe_crc) > + return; > + > + close(pipe_crc->ctl_fd); > + close(pipe_crc->crc_fd); > + close(pipe_crc->dir); > + free(pipe_crc); > +} > + > +static bool pipe_crc_init_from_string(igt_pipe_crc_t *pipe_crc, igt_crc_t *crc, > + const char *line) > +{ > + 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 = i; > + > + return true; > +} > + > +static int read_crc(igt_pipe_crc_t *pipe_crc, igt_crc_t *out) > +{ > + ssize_t bytes_read; > + 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, read_len); > + igt_reset_timeout(); > + > + if (bytes_read < 0 && errno == EAGAIN) > + igt_assert(pipe_crc->flags & O_NONBLOCK); > + > + if (bytes_read < 0) > + bytes_read = 0; > + > + buf[bytes_read] = '\0'; > + > + if (bytes_read && !pipe_crc_init_from_string(pipe_crc, out, buf)) > + return -EINVAL; > + > + return bytes_read; > +} > + > +static void read_one_crc(igt_pipe_crc_t *pipe_crc, igt_crc_t *out) > +{ > + while (read_crc(pipe_crc, out) == 0) > + usleep(1000); > +} > + > +/** > + * igt_pipe_crc_start: > + * @pipe_crc: pipe CRC object > + * > + * Starts the CRC capture process on @pipe_crc. > + */ > +void igt_pipe_crc_start(igt_pipe_crc_t *pipe_crc) > +{ > + igt_crc_t crc; > + > + igt_assert(igt_pipe_crc_do_start(pipe_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); > + } > +} > + > +/** > + * igt_pipe_crc_stop: > + * @pipe_crc: pipe CRC object > + * > + * Stops the CRC capture process on @pipe_crc. > + */ > +void igt_pipe_crc_stop(igt_pipe_crc_t *pipe_crc) > +{ > + char buf[32]; > + > + 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; > + } > +} > + > +/** > + * igt_pipe_crc_get_crcs: > + * @pipe_crc: pipe CRC object > + * @n_crcs: number of CRCs to capture > + * @out_crcs: buffer pointer for the captured CRC values > + * > + * Read up to @n_crcs from @pipe_crc. This function does not block, and will > + * return early if not enough CRCs can be captured, if @pipe_crc has been > + * opened using igt_pipe_crc_new_nonblock(). It will block until @n_crcs are > + * retrieved if @pipe_crc has been opened using igt_pipe_crc_new(). @out_crcs is > + * alloced by this function and must be released with free() by the caller. > + * > + * Callers must start and stop the capturing themselves by calling > + * igt_pipe_crc_start() and igt_pipe_crc_stop(). For one-shot CRC collecting > + * look at igt_pipe_crc_collect_crc(). > + * > + * Returns: > + * The number of CRCs captured. Should be equal to @n_crcs in blocking mode, but > + * can be less (even zero) in non-blocking mode. > + */ > +int > +igt_pipe_crc_get_crcs(igt_pipe_crc_t *pipe_crc, int n_crcs, > + igt_crc_t **out_crcs) > +{ > + igt_crc_t *crcs; > + int n = 0; > + > + crcs = calloc(n_crcs, sizeof(igt_crc_t)); > + > + do { > + igt_crc_t *crc = &crcs[n]; > + int ret; > + > + ret = read_crc(pipe_crc, crc); > + if (ret < 0) > + continue; > + if (ret == 0) > + break; > + > + n++; > + } while (n < n_crcs); > + > + *out_crcs = crcs; > + return n; > +} > + > +static void crc_sanity_checks(igt_crc_t *crc) > +{ > + int i; > + bool all_zero = true; > + > + for (i = 0; i < crc->n_words; i++) { > + igt_warn_on_f(crc->crc[i] == 0xffffffff, > + "Suspicious CRC: it looks like the CRC " > + "read back was from a register in a powered " > + "down well\n"); > + if (crc->crc[i]) > + all_zero = false; > + } > + > + igt_warn_on_f(all_zero, "Suspicious CRC: All values are 0.\n"); > +} > + > +/** > + * igt_pipe_crc_collect_crc: > + * @pipe_crc: pipe CRC object > + * @out_crc: buffer for the captured CRC values > + * > + * Read a single CRC from @pipe_crc. This function blocks until the CRC is > + * retrieved, irrespective of whether @pipe_crc has been opened with > + * igt_pipe_crc_new() or igt_pipe_crc_new_nonblock(). @out_crc must be > + * allocated by the caller. > + * > + * This function takes care of the pipe_crc book-keeping, it will start/stop > + * the collection of the CRC. > + * > + * This function also calls the interactive debug with the "crc" domain, so you > + * can make use of this feature to actually see the screen that is being CRC'd. > + * > + * For continuous CRC collection look at igt_pipe_crc_start(), > + * igt_pipe_crc_get_crcs() and igt_pipe_crc_stop(). > + */ > +void igt_pipe_crc_collect_crc(igt_pipe_crc_t *pipe_crc, igt_crc_t *out_crc) > +{ > + igt_debug_wait_for_keypress("crc"); > + > + igt_pipe_crc_start(pipe_crc); > + read_one_crc(pipe_crc, out_crc); > + igt_pipe_crc_stop(pipe_crc); > + > + crc_sanity_checks(out_crc); > +} > + > diff --git a/lib/igt_crc.h b/lib/igt_crc.h > new file mode 100644 > index 00000000..b0623baf > --- /dev/null > +++ b/lib/igt_crc.h > @@ -0,0 +1,125 @@ > +/* > + * Copyright © 2013 Intel Corporation > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice (including the next > + * paragraph) shall be included in all copies or substantial portions of the > + * Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS > + * IN THE SOFTWARE. > + * > + * # Pipe CRC Support > + * > + * This library wraps up the kernel's support for capturing pipe CRCs into a > + * neat and tidy package. For the detailed usage see all the functions which > + * work on #igt_pipe_crc_t. This is supported on all platforms and outputs. > + * > + * Actually using pipe CRCs to write modeset tests is a bit tricky though, so > + * there is no way to directly check a CRC: Both the details of the plane > + * blending, color correction and other hardware and how exactly the CRC is > + * computed at each tap point vary by hardware generation and are not disclosed. > + * > + * The only way to use #igt_crc_t CRCs therefore is to compare CRCs among each > + * another either for equality or difference. Otherwise CRCs must be treated as > + * completely opaque values. Note that not even CRCs from different pipes or tap > + * points on the same platform can be compared. Hence only use > + * igt_assert_crc_equal() to inspect CRC values captured by the same > + * #igt_pipe_crc_t object. > + */ > + > +#ifndef __IGT_CRC_H__ > +#define __IGT_CRC_H__ > + > +#include <stdbool.h> > +#include <stdint.h> > + > +enum pipe; > + > +/** > + * igt_pipe_crc_t: > + * > + * Pipe CRC support structure. Needs to be allocated and set up with > + * igt_pipe_crc_new() for a specific pipe and pipe CRC source value. > + */ > +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 > + * @n_words: internal field, don't access > + * @crc: internal field, don't access > + * > + * Pipe CRC value. All other members than @frame are private and should not be > + * inspected by testcases. > + */ > +typedef struct { > + uint32_t frame; > + bool has_valid_frame; > + int n_words; > + uint32_t crc[DRM_MAX_CRC_NR]; > +} igt_crc_t; > + > +/** > + * intel_pipe_crc_source: > + * @INTEL_PIPE_CRC_SOURCE_NONE: No source > + * @INTEL_PIPE_CRC_SOURCE_PLANE1: Plane 1 > + * @INTEL_PIPE_CRC_SOURCE_PLANE2: Plane 2 > + * @INTEL_PIPE_CRC_SOURCE_PF: Panel Filter > + * @INTEL_PIPE_CRC_SOURCE_PIPE: Pipe > + * @INTEL_PIPE_CRC_SOURCE_TV: TV > + * @INTEL_PIPE_CRC_SOURCE_DP_B: DisplayPort B > + * @INTEL_PIPE_CRC_SOURCE_DP_C: DisplayPort C > + * @INTEL_PIPE_CRC_SOURCE_DP_D: DisplayPort D > + * @INTEL_PIPE_CRC_SOURCE_AUTO: Automatic source selection > + * @INTEL_PIPE_CRC_SOURCE_MAX: Number of available sources > + * > + * Enumeration of all supported pipe CRC sources. Not all platforms and all > + * outputs support all of them. Generic tests should just use > + * INTEL_PIPE_CRC_SOURCE_AUTO. It should always map to an end-of-pipe CRC > + * suitable for checking planes, cursor, color correction and any other > + * output-agnostic features. > + */ > +enum intel_pipe_crc_source { > + INTEL_PIPE_CRC_SOURCE_NONE, > + INTEL_PIPE_CRC_SOURCE_PLANE1, > + INTEL_PIPE_CRC_SOURCE_PLANE2, > + INTEL_PIPE_CRC_SOURCE_PF, > + INTEL_PIPE_CRC_SOURCE_PIPE, > + INTEL_PIPE_CRC_SOURCE_TV, > + INTEL_PIPE_CRC_SOURCE_DP_B, > + INTEL_PIPE_CRC_SOURCE_DP_C, > + INTEL_PIPE_CRC_SOURCE_DP_D, > + INTEL_PIPE_CRC_SOURCE_AUTO, > + INTEL_PIPE_CRC_SOURCE_MAX, > +}; > + > +void igt_assert_crc_equal(const igt_crc_t *a, const igt_crc_t *b); > +char *igt_crc_to_string(igt_crc_t *crc); > + > +void igt_require_pipe_crc(int fd); > +igt_pipe_crc_t * > +igt_pipe_crc_new(int fd, enum pipe pipe, enum intel_pipe_crc_source source); > +igt_pipe_crc_t * > +igt_pipe_crc_new_nonblock(int fd, 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); > +__attribute__((warn_unused_result)) > +int igt_pipe_crc_get_crcs(igt_pipe_crc_t *pipe_crc, int n_crcs, > + igt_crc_t **out_crcs); > +void igt_pipe_crc_collect_crc(igt_pipe_crc_t *pipe_crc, igt_crc_t *out_crc); > + > +#endif /* __IGT_CRC_H__ */ > diff --git a/lib/igt_debugfs.c b/lib/igt_debugfs.c > index 80f25c61..e08b7ae8 100644 > --- a/lib/igt_debugfs.c > +++ b/lib/igt_debugfs.c > @@ -51,24 +51,6 @@ > * basic functions to access debugfs files with e.g. igt_debugfs_open() it also > * provides higher-level wrappers for some debugfs features. > * > - * # Pipe CRC Support > - * > - * This library wraps up the kernel's support for capturing pipe CRCs into a > - * neat and tidy package. For the detailed usage see all the functions which > - * work on #igt_pipe_crc_t. This is supported on all platforms and outputs. > - * > - * Actually using pipe CRCs to write modeset tests is a bit tricky though, so > - * there is no way to directly check a CRC: Both the details of the plane > - * blending, color correction and other hardware and how exactly the CRC is > - * computed at each tap point vary by hardware generation and are not disclosed. > - * > - * The only way to use #igt_crc_t CRCs therefore is to compare CRCs among each > - * another either for equality or difference. Otherwise CRCs must be treated as > - * completely opaque values. Note that not even CRCs from different pipes or tap > - * points on the same platform can be compared. Hence only use > - * igt_assert_crc_equal() to inspect CRC values captured by the same > - * #igt_pipe_crc_t object. > - * > * # Other debugfs interface wrappers > * > * This covers the miscellaneous debugfs interface wrappers: > @@ -277,235 +259,6 @@ bool igt_debugfs_search(int device, const char *filename, const char *substring) > return matched; > } > > -/* > - * Pipe CRC > - */ > - > -/** > - * igt_assert_crc_equal: > - * @a: first pipe CRC value > - * @b: second pipe CRC value > - * > - * Compares two CRC values and fails the testcase if they don't match with > - * igt_fail(). Note that due to CRC collisions CRC based testcase can only > - * assert that CRCs match, never that they are different. Otherwise there might > - * be random testcase failures when different screen contents end up with the > - * same CRC by chance. > - */ > -void igt_assert_crc_equal(const igt_crc_t *a, const igt_crc_t *b) > -{ > - int i; > - > - for (i = 0; i < a->n_words; i++) > - igt_assert_eq_u32(a->crc[i], b->crc[i]); > -} > - > -/** > - * igt_crc_to_string: > - * @crc: pipe CRC value to print > - * > - * This formats @crc into a string buffer which is owned by igt_crc_to_string(). > - * The next call will override the buffer again, which makes this multithreading > - * unsafe. > - * > - * This should only ever be used for diagnostic debug output. > - */ > -char *igt_crc_to_string(igt_crc_t *crc) > -{ > - int i; > - char buf[128] = { 0 }; > - > - for (i = 0; i < crc->n_words; i++) > - sprintf(buf + strlen(buf), "%08x ", crc->crc[i]); > - > - 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 LEGACY_LINE_LEN (6 * 8 + 5 + 1) > - > -struct _igt_pipe_crc { > - int fd; > - int dir; > - int ctl_fd; > - int crc_fd; > - int flags; > - bool is_legacy; > - > - enum pipe pipe; > - enum intel_pipe_crc_source source; > -}; > - > -static const char *pipe_crc_sources[] = { > - "none", > - "plane1", > - "plane2", > - "pf", > - "pipe", > - "TV", > - "DP-B", > - "DP-C", > - "DP-D", > - "auto" > -}; > - > -static const char *pipe_crc_source_name(enum intel_pipe_crc_source source) > -{ > - return pipe_crc_sources[source]; > -} > - > -static bool igt_pipe_crc_do_start(igt_pipe_crc_t *pipe_crc) > -{ > - char buf[64]; > - > - /* Stop first just to make sure we don't have lingering state left. */ > - igt_pipe_crc_stop(pipe_crc); > - > - 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)); > - > - igt_assert_eq(write(pipe_crc->ctl_fd, buf, strlen(buf)), strlen(buf)); > - > - if (!pipe_crc->is_legacy) { > - int err; > - > - sprintf(buf, "crtc-%d/crc/data", pipe_crc->pipe); > - err = 0; > - > - pipe_crc->crc_fd = openat(pipe_crc->dir, buf, pipe_crc->flags); > - if (pipe_crc->crc_fd < 0) > - err = -errno; > - > - if (err == -EINVAL) > - return false; > - > - igt_assert_eq(err, 0); > - } > - > - errno = 0; > - return true; > -} > - > -static void igt_pipe_crc_pipe_off(int fd, enum pipe pipe) > -{ > - char buf[32]; > - > - sprintf(buf, "pipe %s none", kmstest_pipe_name(pipe)); > - igt_assert_eq(write(fd, buf, strlen(buf)), strlen(buf)); > -} > - > -static void igt_pipe_crc_reset(int drm_fd) > -{ > - struct dirent *dirent; > - const char *cmd = "none"; > - bool done = false; > - DIR *dir; > - int fdir; > - int fd; > - > - fdir = igt_debugfs_dir(drm_fd); > - if (fdir < 0) > - return; > - > - dir = fdopendir(fdir); > - if (!dir) { > - close(fdir); > - return; > - } > - > - while ((dirent = readdir(dir))) { > - char buf[128]; > - > - if (strcmp(dirent->d_name, "crtc-") != 0) > - continue; > - > - sprintf(buf, "%s/crc/control", dirent->d_name); > - fd = openat(fdir, buf, O_WRONLY); > - if (fd < 0) > - continue; > - > - igt_assert_eq(write(fd, cmd, strlen(cmd)), strlen(cmd)); > - close(fd); > - > - done = true; > - } > - closedir(dir); > - > - if (!done) { > - fd = openat(fdir, "i915_display_crtc_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(fdir); > -} > - > -static void pipe_crc_exit_handler(int sig) > -{ > - struct dirent *dirent; > - char buf[128]; > - DIR *dir; > - int fd; > - > - dir = opendir("/dev/dri"); > - if (!dir) > - return; > - > - /* > - * Try to reset CRC capture for all DRM devices, this is only needed > - * for the legacy CRC ABI and can be completely removed once the > - * legacy codepaths are removed. > - */ > - while ((dirent = readdir(dir))) { > - if (strncmp(dirent->d_name, "card", 4) != 0) > - continue; > - > - sprintf(buf, "/dev/dri/%s", dirent->d_name); > - fd = open(buf, O_WRONLY); > - > - igt_pipe_crc_reset(fd); > - > - close(fd); > - } > - closedir(dir); > -} > - > -/** > - * igt_require_pipe_crc: > - * > - * Convenience helper to check whether pipe CRC capturing is supported by the > - * kernel. Uses igt_skip to automatically skip the test/subtest if this isn't > - * the case. > - */ > -void igt_require_pipe_crc(int fd) > -{ > - const char *cmd = "pipe A none"; > - int ctl, written; > - > - ctl = igt_debugfs_open(fd, "crtc-0/crc/control", O_RDONLY); > - if (ctl < 0) { > - ctl = igt_debugfs_open(fd, "i915_display_crc_ctl", O_WRONLY); > - igt_require_f(ctl, > - "No display_crc_ctl found, kernel too old\n"); > - > - written = write(ctl, cmd, strlen(cmd)); > - igt_require_f(written < 0, > - "CRCs not supported on this platform\n"); > - } > - close(ctl); > -} > - > static void igt_hpd_storm_exit_handler(int sig) > { > int fd = drm_open_driver_master(DRIVER_INTEL); > @@ -627,306 +380,6 @@ void igt_require_hpd_storm_ctl(int drm_fd) > close(fd); > } > > -static igt_pipe_crc_t * > -pipe_crc_new(int fd, enum pipe pipe, enum intel_pipe_crc_source source, int flags) > -{ > - igt_pipe_crc_t *pipe_crc; > - char buf[128]; > - int debugfs; > - > - debugfs = igt_debugfs_dir(fd); > - igt_assert(debugfs != -1); > - > - igt_install_exit_handler(pipe_crc_exit_handler); > - > - pipe_crc = calloc(1, sizeof(struct _igt_pipe_crc)); > - > - sprintf(buf, "crtc-%d/crc/control", pipe); > - pipe_crc->ctl_fd = openat(debugfs, buf, O_WRONLY); > - if (pipe_crc->ctl_fd == -1) { > - pipe_crc->ctl_fd = openat(debugfs, > - "i915_display_crc_ctl", O_WRONLY); > - igt_assert(pipe_crc->ctl_fd != -1); > - pipe_crc->is_legacy = true; > - } > - > - if (pipe_crc->is_legacy) { > - sprintf(buf, "i915_pipe_%s_crc", kmstest_pipe_name(pipe)); > - pipe_crc->crc_fd = openat(debugfs, 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->fd = fd; > - pipe_crc->dir = debugfs; > - pipe_crc->pipe = pipe; > - pipe_crc->source = source; > - pipe_crc->flags = flags; > - > - return pipe_crc; > -} > - > -/** > - * igt_pipe_crc_new: > - * @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. > - * > - * 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(int fd, enum pipe pipe, enum intel_pipe_crc_source source) > -{ > - return pipe_crc_new(fd, pipe, source, O_RDONLY); > -} > - > -/** > - * igt_pipe_crc_new_nonblock: > - * @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. > - * > - * 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(int fd, enum pipe pipe, enum intel_pipe_crc_source source) > -{ > - return pipe_crc_new(fd, pipe, source, O_RDONLY | O_NONBLOCK); > -} > - > -/** > - * igt_pipe_crc_free: > - * @pipe_crc: pipe CRC object > - * > - * Frees all resources associated with @pipe_crc. > - */ > -void igt_pipe_crc_free(igt_pipe_crc_t *pipe_crc) > -{ > - if (!pipe_crc) > - return; > - > - close(pipe_crc->ctl_fd); > - close(pipe_crc->crc_fd); > - close(pipe_crc->dir); > - free(pipe_crc); > -} > - > -static bool pipe_crc_init_from_string(igt_pipe_crc_t *pipe_crc, igt_crc_t *crc, > - const char *line) > -{ > - 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 = i; > - > - return true; > -} > - > -static int read_crc(igt_pipe_crc_t *pipe_crc, igt_crc_t *out) > -{ > - ssize_t bytes_read; > - 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, read_len); > - igt_reset_timeout(); > - > - if (bytes_read < 0 && errno == EAGAIN) > - igt_assert(pipe_crc->flags & O_NONBLOCK); > - > - if (bytes_read < 0) > - bytes_read = 0; > - > - buf[bytes_read] = '\0'; > - > - if (bytes_read && !pipe_crc_init_from_string(pipe_crc, out, buf)) > - return -EINVAL; > - > - return bytes_read; > -} > - > -static void read_one_crc(igt_pipe_crc_t *pipe_crc, igt_crc_t *out) > -{ > - while (read_crc(pipe_crc, out) == 0) > - usleep(1000); > -} > - > -/** > - * igt_pipe_crc_start: > - * @pipe_crc: pipe CRC object > - * > - * Starts the CRC capture process on @pipe_crc. > - */ > -void igt_pipe_crc_start(igt_pipe_crc_t *pipe_crc) > -{ > - igt_crc_t crc; > - > - igt_assert(igt_pipe_crc_do_start(pipe_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); > - } > -} > - > -/** > - * igt_pipe_crc_stop: > - * @pipe_crc: pipe CRC object > - * > - * Stops the CRC capture process on @pipe_crc. > - */ > -void igt_pipe_crc_stop(igt_pipe_crc_t *pipe_crc) > -{ > - char buf[32]; > - > - 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; > - } > -} > - > -/** > - * igt_pipe_crc_get_crcs: > - * @pipe_crc: pipe CRC object > - * @n_crcs: number of CRCs to capture > - * @out_crcs: buffer pointer for the captured CRC values > - * > - * Read up to @n_crcs from @pipe_crc. This function does not block, and will > - * return early if not enough CRCs can be captured, if @pipe_crc has been > - * opened using igt_pipe_crc_new_nonblock(). It will block until @n_crcs are > - * retrieved if @pipe_crc has been opened using igt_pipe_crc_new(). @out_crcs is > - * alloced by this function and must be released with free() by the caller. > - * > - * Callers must start and stop the capturing themselves by calling > - * igt_pipe_crc_start() and igt_pipe_crc_stop(). For one-shot CRC collecting > - * look at igt_pipe_crc_collect_crc(). > - * > - * Returns: > - * The number of CRCs captured. Should be equal to @n_crcs in blocking mode, but > - * can be less (even zero) in non-blocking mode. > - */ > -int > -igt_pipe_crc_get_crcs(igt_pipe_crc_t *pipe_crc, int n_crcs, > - igt_crc_t **out_crcs) > -{ > - igt_crc_t *crcs; > - int n = 0; > - > - crcs = calloc(n_crcs, sizeof(igt_crc_t)); > - > - do { > - igt_crc_t *crc = &crcs[n]; > - int ret; > - > - ret = read_crc(pipe_crc, crc); > - if (ret < 0) > - continue; > - if (ret == 0) > - break; > - > - n++; > - } while (n < n_crcs); > - > - *out_crcs = crcs; > - return n; > -} > - > -static void crc_sanity_checks(igt_crc_t *crc) > -{ > - int i; > - bool all_zero = true; > - > - for (i = 0; i < crc->n_words; i++) { > - igt_warn_on_f(crc->crc[i] == 0xffffffff, > - "Suspicious CRC: it looks like the CRC " > - "read back was from a register in a powered " > - "down well\n"); > - if (crc->crc[i]) > - all_zero = false; > - } > - > - igt_warn_on_f(all_zero, "Suspicious CRC: All values are 0.\n"); > -} > - > -/** > - * igt_pipe_crc_collect_crc: > - * @pipe_crc: pipe CRC object > - * @out_crc: buffer for the captured CRC values > - * > - * Read a single CRC from @pipe_crc. This function blocks until the CRC is > - * retrieved, irrespective of whether @pipe_crc has been opened with > - * igt_pipe_crc_new() or igt_pipe_crc_new_nonblock(). @out_crc must be > - * allocated by the caller. > - * > - * This function takes care of the pipe_crc book-keeping, it will start/stop > - * the collection of the CRC. > - * > - * This function also calls the interactive debug with the "crc" domain, so you > - * can make use of this feature to actually see the screen that is being CRC'd. > - * > - * For continuous CRC collection look at igt_pipe_crc_start(), > - * igt_pipe_crc_get_crcs() and igt_pipe_crc_stop(). > - */ > -void igt_pipe_crc_collect_crc(igt_pipe_crc_t *pipe_crc, igt_crc_t *out_crc) > -{ > - igt_debug_wait_for_keypress("crc"); > - > - igt_pipe_crc_start(pipe_crc); > - read_one_crc(pipe_crc, out_crc); > - igt_pipe_crc_stop(pipe_crc); > - > - crc_sanity_checks(out_crc); > -} > - > /* > * Drop caches > */ > diff --git a/lib/igt_debugfs.h b/lib/igt_debugfs.h > index 7b846a83..01a5ee07 100644 > --- a/lib/igt_debugfs.h > +++ b/lib/igt_debugfs.h > @@ -29,8 +29,6 @@ > #include <stdint.h> > #include <stdio.h> > > -enum pipe; > - > const char *igt_debugfs_mount(void); > > int igt_debugfs_dir(int device); > @@ -50,85 +48,6 @@ bool igt_debugfs_search(int fd, const char *filename, const char *substring); > #define igt_debugfs_read(fd, filename, buf) \ > __igt_debugfs_read(fd, (filename), (buf), sizeof(buf)) > > -/* > - * Pipe CRC > - */ > - > -/** > - * igt_pipe_crc_t: > - * > - * Pipe CRC support structure. Needs to be allocated and set up with > - * igt_pipe_crc_new() for a specific pipe and pipe CRC source value. > - */ > -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 > - * @n_words: internal field, don't access > - * @crc: internal field, don't access > - * > - * Pipe CRC value. All other members than @frame are private and should not be > - * inspected by testcases. > - */ > -typedef struct { > - uint32_t frame; > - bool has_valid_frame; > - int n_words; > - uint32_t crc[DRM_MAX_CRC_NR]; > -} igt_crc_t; > - > -/** > - * intel_pipe_crc_source: > - * @INTEL_PIPE_CRC_SOURCE_NONE: No source > - * @INTEL_PIPE_CRC_SOURCE_PLANE1: Plane 1 > - * @INTEL_PIPE_CRC_SOURCE_PLANE2: Plane 2 > - * @INTEL_PIPE_CRC_SOURCE_PF: Panel Filter > - * @INTEL_PIPE_CRC_SOURCE_PIPE: Pipe > - * @INTEL_PIPE_CRC_SOURCE_TV: TV > - * @INTEL_PIPE_CRC_SOURCE_DP_B: DisplayPort B > - * @INTEL_PIPE_CRC_SOURCE_DP_C: DisplayPort C > - * @INTEL_PIPE_CRC_SOURCE_DP_D: DisplayPort D > - * @INTEL_PIPE_CRC_SOURCE_AUTO: Automatic source selection > - * @INTEL_PIPE_CRC_SOURCE_MAX: Number of available sources > - * > - * Enumeration of all supported pipe CRC sources. Not all platforms and all > - * outputs support all of them. Generic tests should just use > - * INTEL_PIPE_CRC_SOURCE_AUTO. It should always map to an end-of-pipe CRC > - * suitable for checking planes, cursor, color correction and any other > - * output-agnostic features. > - */ > -enum intel_pipe_crc_source { > - INTEL_PIPE_CRC_SOURCE_NONE, > - INTEL_PIPE_CRC_SOURCE_PLANE1, > - INTEL_PIPE_CRC_SOURCE_PLANE2, > - INTEL_PIPE_CRC_SOURCE_PF, > - INTEL_PIPE_CRC_SOURCE_PIPE, > - INTEL_PIPE_CRC_SOURCE_TV, > - INTEL_PIPE_CRC_SOURCE_DP_B, > - INTEL_PIPE_CRC_SOURCE_DP_C, > - INTEL_PIPE_CRC_SOURCE_DP_D, > - INTEL_PIPE_CRC_SOURCE_AUTO, > - INTEL_PIPE_CRC_SOURCE_MAX, > -}; > - > -void igt_assert_crc_equal(const igt_crc_t *a, const igt_crc_t *b); > -char *igt_crc_to_string(igt_crc_t *crc); > - > -void igt_require_pipe_crc(int fd); > -igt_pipe_crc_t * > -igt_pipe_crc_new(int fd, enum pipe pipe, enum intel_pipe_crc_source source); > -igt_pipe_crc_t * > -igt_pipe_crc_new_nonblock(int fd, 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); > -__attribute__((warn_unused_result)) > -int igt_pipe_crc_get_crcs(igt_pipe_crc_t *pipe_crc, int n_crcs, > - igt_crc_t **out_crcs); > -void igt_pipe_crc_collect_crc(igt_pipe_crc_t *pipe_crc, igt_crc_t *out_crc); > - > void igt_hpd_storm_set_threshold(int fd, unsigned int threshold); > void igt_hpd_storm_reset(int fd); > bool igt_hpd_storm_detected(int fd); > diff --git a/tests/chamelium.c b/tests/chamelium.c > index e26f0557..5482eb5b 100644 > --- a/tests/chamelium.c > +++ b/tests/chamelium.c > @@ -26,6 +26,7 @@ > > #include "config.h" > #include "igt.h" > +#include "igt_crc.h" > > #include <fcntl.h> > #include <string.h> > diff --git a/tests/kms_atomic_transition.c b/tests/kms_atomic_transition.c > index e22763bd..1b9233ad 100644 > --- a/tests/kms_atomic_transition.c > +++ b/tests/kms_atomic_transition.c > @@ -22,6 +22,7 @@ > */ > > #include "igt.h" > +#include "igt_crc.h" > #include "drmtest.h" > #include "sw_sync.h" > #include <errno.h> > diff --git a/tests/kms_ccs.c b/tests/kms_ccs.c > index 29d676af..66bd0f29 100644 > --- a/tests/kms_ccs.c > +++ b/tests/kms_ccs.c > @@ -23,6 +23,7 @@ > */ > > #include "igt.h" > +#include "igt_crc.h" > > IGT_TEST_DESCRIPTION("Test render compression (RC), in which the main surface " > "is complemented by a color control surface (CCS) that " > diff --git a/tests/kms_chv_cursor_fail.c b/tests/kms_chv_cursor_fail.c > index 3e74df11..b02958bd 100644 > --- a/tests/kms_chv_cursor_fail.c > +++ b/tests/kms_chv_cursor_fail.c > @@ -23,6 +23,7 @@ > */ > > #include "igt.h" > +#include "igt_crc.h" > #include <errno.h> > #include <limits.h> > #include <stdbool.h> > diff --git a/tests/kms_crtc_background_color.c b/tests/kms_crtc_background_color.c > index e12e1634..3bcabcac 100644 > --- a/tests/kms_crtc_background_color.c > +++ b/tests/kms_crtc_background_color.c > @@ -23,6 +23,7 @@ > */ > > #include "igt.h" > +#include "igt_crc.h" > #include <math.h> > > > diff --git a/tests/kms_cursor_crc.c b/tests/kms_cursor_crc.c > index 4c5e00c0..4693e9f4 100644 > --- a/tests/kms_cursor_crc.c > +++ b/tests/kms_cursor_crc.c > @@ -23,6 +23,7 @@ > */ > > #include "igt.h" > +#include "igt_crc.h" > #include <errno.h> > #include <limits.h> > #include <stdbool.h> > diff --git a/tests/kms_cursor_legacy.c b/tests/kms_cursor_legacy.c > index 8180b043..505e3f9d 100644 > --- a/tests/kms_cursor_legacy.c > +++ b/tests/kms_cursor_legacy.c > @@ -27,6 +27,7 @@ > #include <sys/poll.h> > > #include "igt.h" > +#include "igt_crc.h" > #include "igt_rand.h" > #include "igt_stats.h" > > diff --git a/tests/kms_draw_crc.c b/tests/kms_draw_crc.c > index c57d3a35..8cb4e147 100644 > --- a/tests/kms_draw_crc.c > +++ b/tests/kms_draw_crc.c > @@ -25,6 +25,7 @@ > /* This program tests whether the igt_draw library actually works. */ > > #include "igt.h" > +#include "igt_crc.h" > > #define MAX_CONNECTORS 32 > > diff --git a/tests/kms_fbc_crc.c b/tests/kms_fbc_crc.c > index 7964e052..10656b89 100644 > --- a/tests/kms_fbc_crc.c > +++ b/tests/kms_fbc_crc.c > @@ -23,6 +23,7 @@ > */ > > #include "igt.h" > +#include "igt_crc.h" > #include <errno.h> > #include <stdbool.h> > #include <stdio.h> > diff --git a/tests/kms_flip_tiling.c b/tests/kms_flip_tiling.c > index 5aae29a8..8e1a2fb4 100644 > --- a/tests/kms_flip_tiling.c > +++ b/tests/kms_flip_tiling.c > @@ -25,6 +25,7 @@ > */ > > #include "igt.h" > +#include "igt_crc.h" > #include <errno.h> > #include <stdbool.h> > #include <stdio.h> > diff --git a/tests/kms_frontbuffer_tracking.c b/tests/kms_frontbuffer_tracking.c > index e03524f1..c1b08669 100644 > --- a/tests/kms_frontbuffer_tracking.c > +++ b/tests/kms_frontbuffer_tracking.c > @@ -25,6 +25,7 @@ > */ > > #include "igt.h" > +#include "igt_crc.h" > #include "igt_sysfs.h" > #include <sys/types.h> > #include <sys/stat.h> > diff --git a/tests/kms_mmap_write_crc.c b/tests/kms_mmap_write_crc.c > index e5f089f6..79efa792 100644 > --- a/tests/kms_mmap_write_crc.c > +++ b/tests/kms_mmap_write_crc.c > @@ -31,6 +31,7 @@ > #include <string.h> > > #include "drmtest.h" > +#include "igt_crc.h" > #include "igt_debugfs.h" > #include "igt_kms.h" > #include "intel_chipset.h" > diff --git a/tests/kms_mmio_vs_cs_flip.c b/tests/kms_mmio_vs_cs_flip.c > index fa947d9c..ee1d202a 100644 > --- a/tests/kms_mmio_vs_cs_flip.c > +++ b/tests/kms_mmio_vs_cs_flip.c > @@ -22,6 +22,7 @@ > */ > > #include "igt.h" > +#include "igt_crc.h" > #include <errno.h> > #include <stdbool.h> > #include <stdio.h> > diff --git a/tests/kms_pipe_color.c b/tests/kms_pipe_color.c > index a3100fae..389fb3de 100644 > --- a/tests/kms_pipe_color.c > +++ b/tests/kms_pipe_color.c > @@ -28,6 +28,7 @@ > #include "drm.h" > #include "drmtest.h" > #include "igt.h" > +#include "igt_crc.h" > > IGT_TEST_DESCRIPTION("Test Color Features at Pipe level"); > > diff --git a/tests/kms_pipe_crc_basic.c b/tests/kms_pipe_crc_basic.c > index 35adddba..38da3a42 100644 > --- a/tests/kms_pipe_crc_basic.c > +++ b/tests/kms_pipe_crc_basic.c > @@ -23,6 +23,7 @@ > */ > > #include "igt.h" > +#include "igt_crc.h" > #include "igt_sysfs.h" > #include <errno.h> > #include <stdbool.h> > diff --git a/tests/kms_plane.c b/tests/kms_plane.c > index 1d92a62b..2fa58e8f 100644 > --- a/tests/kms_plane.c > +++ b/tests/kms_plane.c > @@ -25,6 +25,7 @@ > */ > > #include "igt.h" > +#include "igt_crc.h" > #include <errno.h> > #include <stdbool.h> > #include <stdio.h> > diff --git a/tests/kms_plane_lowres.c b/tests/kms_plane_lowres.c > index ee39759c..a4e37275 100644 > --- a/tests/kms_plane_lowres.c > +++ b/tests/kms_plane_lowres.c > @@ -23,6 +23,7 @@ > */ > > #include "igt.h" > +#include "igt_crc.h" > #include "drmtest.h" > #include <errno.h> > #include <stdbool.h> > diff --git a/tests/kms_plane_multiple.c b/tests/kms_plane_multiple.c > index f6c62235..1b60a067 100644 > --- a/tests/kms_plane_multiple.c > +++ b/tests/kms_plane_multiple.c > @@ -23,6 +23,7 @@ > */ > > #include "igt.h" > +#include "igt_crc.h" > #include "drmtest.h" > #include <errno.h> > #include <stdbool.h> > diff --git a/tests/kms_plane_scaling.c b/tests/kms_plane_scaling.c > index 1457894a..d554f27f 100644 > --- a/tests/kms_plane_scaling.c > +++ b/tests/kms_plane_scaling.c > @@ -23,6 +23,7 @@ > */ > > #include "igt.h" > +#include "igt_crc.h" > #include <math.h> > > > diff --git a/tests/kms_pwrite_crc.c b/tests/kms_pwrite_crc.c > index ee895db6..f1e6f023 100644 > --- a/tests/kms_pwrite_crc.c > +++ b/tests/kms_pwrite_crc.c > @@ -23,6 +23,7 @@ > */ > > #include "igt.h" > +#include "igt_crc.h" > #include <errno.h> > #include <limits.h> > #include <stdbool.h> > diff --git a/tests/kms_rotation_crc.c b/tests/kms_rotation_crc.c > index 83e37f12..fa361100 100644 > --- a/tests/kms_rotation_crc.c > +++ b/tests/kms_rotation_crc.c > @@ -23,6 +23,7 @@ > */ > > #include "igt.h" > +#include "igt_crc.h" > #include <math.h> > > #define MAX_FENCES 32 > diff --git a/tests/kms_universal_plane.c b/tests/kms_universal_plane.c > index 31f07804..14300b7a 100644 > --- a/tests/kms_universal_plane.c > +++ b/tests/kms_universal_plane.c > @@ -22,6 +22,7 @@ > */ > > #include "igt.h" > +#include "igt_crc.h" > #include <errno.h> > #include <stdbool.h> > #include <stdio.h> > diff --git a/tools/intel_display_crc.c b/tools/intel_display_crc.c > index d1b28ea7..104f432f 100644 > --- a/tools/intel_display_crc.c > +++ b/tools/intel_display_crc.c > @@ -30,6 +30,7 @@ > #include <unistd.h> > > #include "igt_core.h" > +#include "igt_crc.h" > #include "igt_debugfs.h" > #include "igt_kms.h" > > -- > 2.13.2 > > _______________________________________________ > dri-devel mailing list > dri-devel@xxxxxxxxxxxxxxxxxxxxx > https://lists.freedesktop.org/mailman/listinfo/dri-devel -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel