diff -Nru intel-gpu-tools-1.21/assembler/meson.build intel-gpu-tools-1.22/assembler/meson.build --- intel-gpu-tools-1.21/assembler/meson.build 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/assembler/meson.build 2018-03-09 14:22:59.000000000 +0000 @@ -35,13 +35,11 @@ executable('intel-gen4disasm', 'disasm-main.c', link_with : lib_brw, install : true) -pkgconfigdir = join_paths(get_option('libdir'), 'pgkconfig') - conf_data = configuration_data() -conf_data.set('prefix', get_option('prefix')) +conf_data.set('prefix', prefix) conf_data.set('exec_prefix', '${prefix}') -conf_data.set('libdir', join_paths('${prefix}', get_option('libdir'))) -conf_data.set('includedir', join_paths('${prefix}', get_option('includedir'))) +conf_data.set('libdir', join_paths('${prefix}', libdir)) +conf_data.set('includedir', join_paths('${prefix}', includedir)) conf_data.set('VERSION', meson.project_version()) configure_file(input : 'intel-gen4asm.pc.in', output : 'intel-gen4asm.pc', configuration : conf_data, install_dir : pkgconfigdir) diff -Nru intel-gpu-tools-1.21/benchmarks/gem_exec_ctx.c intel-gpu-tools-1.22/benchmarks/gem_exec_ctx.c --- intel-gpu-tools-1.21/benchmarks/gem_exec_ctx.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/benchmarks/gem_exec_ctx.c 2018-03-09 14:22:59.000000000 +0000 @@ -64,7 +64,7 @@ return handle; } -static uint32_t __gem_context_create(int fd) +static uint32_t __gem_context_create_local(int fd) { struct drm_i915_gem_context_create create; @@ -101,7 +101,7 @@ execbuf.flags |= LOCAL_I915_EXEC_HANDLE_LUT; execbuf.flags |= LOCAL_I915_EXEC_NO_RELOC; if (mode != DEFAULT) { - execbuf.rsvd1 = __gem_context_create(fd); + execbuf.rsvd1 = __gem_context_create_local(fd); if (execbuf.rsvd1 == 0) return 77; } @@ -125,7 +125,7 @@ uint32_t ctx = 0; if (mode != DEFAULT && mode != NOP) { - execbuf.rsvd1 = __gem_context_create(fd); + execbuf.rsvd1 = __gem_context_create_local(fd); ctx = gem_context_create(fd); } diff -Nru intel-gpu-tools-1.21/benchmarks/gem_exec_trace.c intel-gpu-tools-1.22/benchmarks/gem_exec_trace.c --- intel-gpu-tools-1.21/benchmarks/gem_exec_trace.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/benchmarks/gem_exec_trace.c 2018-03-09 14:22:59.000000000 +0000 @@ -105,7 +105,7 @@ return 1e3*(end->tv_sec - start->tv_sec) + 1e-6*(end->tv_nsec - start->tv_nsec); } -static uint32_t __gem_context_create(int fd) +static uint32_t __gem_context_create_local(int fd) { struct drm_i915_gem_context_create arg = {}; drmIoctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &arg); @@ -216,7 +216,7 @@ num_ctx = new_ctx; } - ctx[t->handle] = __gem_context_create(fd); + ctx[t->handle] = __gem_context_create_local(fd); break; } case DEL_CTX: diff -Nru intel-gpu-tools-1.21/benchmarks/meson.build intel-gpu-tools-1.22/benchmarks/meson.build --- intel-gpu-tools-1.21/benchmarks/meson.build 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/benchmarks/meson.build 2018-03-09 14:22:59.000000000 +0000 @@ -27,16 +27,18 @@ ] endif +benchmarksdir = join_paths(libexecdir, 'benchmarks') + foreach prog : benchmark_progs # FIXME meson doesn't like binaries with the same name # meanwhile just suffix with _bench executable(prog + '_bench', prog + '.c', install : true, - install_dir : join_paths(get_option('libexecdir'), 'intel-gpu-tools', 'benchmarks'), + install_dir : benchmarksdir, dependencies : test_deps) endforeach executable('gem_wsim_bench', 'gem_wsim.c', install : true, - install_dir : join_paths(get_option('libexecdir'), 'intel-gpu-tools', 'benchmarks'), + install_dir : benchmarksdir, dependencies : test_deps + [ lib_igt_perf ]) diff -Nru intel-gpu-tools-1.21/configure.ac intel-gpu-tools-1.22/configure.ac --- intel-gpu-tools-1.21/configure.ac 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/configure.ac 2018-03-09 14:22:59.000000000 +0000 @@ -22,7 +22,7 @@ AC_PREREQ([2.60]) AC_INIT([intel-gpu-tools], - [1.21], + [1.22], [https://bugs.freedesktop.org/enter_bug.cgi?product=DRI&component=IGT], [intel-gpu-tools]) @@ -176,11 +176,7 @@ # for testdisplay PKG_CHECK_MODULES(CAIRO, [cairo >= 1.12.0]) -PKG_CHECK_MODULES(LIBUDEV, [libudev], [udev=yes], [udev=no]) -AM_CONDITIONAL(HAVE_UDEV, [test "x$udev" = xyes]) -if test x"$udev" = xyes; then - AC_DEFINE(HAVE_UDEV,1,[Enable udev-based monitor hotplug detection]) -fi +PKG_CHECK_MODULES(LIBUDEV, [libudev]) PKG_CHECK_MODULES(GLIB, [glib-2.0], [glib=yes], [glib=no]) if test x"$glib" = xyes; then AC_DEFINE(HAVE_GLIB,1,[Enable glib support]) @@ -210,9 +206,6 @@ fi PKG_CHECK_MODULES(PIXMAN, pixman-1, [], [AC_MSG_ERROR([Failed to find pixman, required by chamelium.])]) - if test x"$udev" != xyes; then - AC_MSG_ERROR([Failed to find udev, required by chamelium.]) - fi if test x"$glib" != xyes; then AC_MSG_ERROR([Failed to find glib, required by chamelium.]) fi @@ -270,10 +263,10 @@ [Enable building of amdgpu tests (default: auto)]), [AMDGPU=$enableval], [AMDGPU=auto]) if test "x$AMDGPU" = xauto; then - PKG_CHECK_EXISTS([libdrm_amdgpu], [AMDGPU=yes], [AMDGPU=no]) + PKG_CHECK_EXISTS([libdrm_amdgpu >= 2.4.81], [AMDGPU=yes], [AMDGPU=no]) fi if test "x$AMDGPU" = xyes; then - PKG_CHECK_MODULES(DRM_AMDGPU, [libdrm_amdgpu >= 2.4.76]) + PKG_CHECK_MODULES(DRM_AMDGPU, [libdrm_amdgpu >= 2.4.81]) AC_DEFINE(HAVE_LIBDRM_AMDGPU, 1, [Have amdgpu support]) fi AM_CONDITIONAL(HAVE_LIBDRM_AMDGPU, [test "x$AMDGPU" = xyes]) diff -Nru intel-gpu-tools-1.21/CONTRIBUTING intel-gpu-tools-1.22/CONTRIBUTING --- intel-gpu-tools-1.21/CONTRIBUTING 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/CONTRIBUTING 2018-03-09 14:22:59.000000000 +0000 @@ -6,11 +6,21 @@ A short list of contribution guidelines: - Please submit patches formatted with git send-email/git format-patch or - equivalent to + equivalent to: + + Development mailing list for IGT GPU Tools + + For a transition period patches are accepted on both the igt-dev mailing list + and the former intel-gfx mailing list (with the appropriate patch + subjectprefix, see below). + + During the transition period, feel free to send patches to both lists if you + have a need to do so, as they will get deduplicated so they only appear and + are tested in one Patchwork instance. Intel GFX discussion - Please use --subject-prefix="PATCH i-g-t" so that i-g-t patches are easily + Please use --subject-prefix="PATCH i-g-t" so IGT patches are easily identified in the massive amount mails on intel-gfx. To ensure this is always done, meson.sh (and autogen.sh) will run: @@ -18,29 +28,27 @@ on its first invocation. -- intel-gpu-tools is MIT lincensed and we require contributions to follow the +- intel-gpu-tools is MIT licensed and we require contributions to follow the developer's certificate of origin: http://developercertificate.org/ - When submitting new testcases please follow the naming conventions documented - in the generated documentation. Also please make full use of all the helpers and - convenience macros provided by the igt library. The semantic patch lib/igt.cocci - can help with the more automatic conversions. + in the generated documentation. Also please make full use of all the helpers + and convenience macros provided by the igt library. The semantic patch + lib/igt.cocci can help with the more automatic conversions. - Patches need to be reviewed on the mailing list. Exceptions only apply for testcases and tooling for drivers with just a single contributor (e.g. vc4). In this case patches must still be submitted to the mailing list first. - Testcase should preferrably be cross-reviewed by the same people who write and + Testcase should preferably be cross-reviewed by the same people who write and review the kernel feature itself. - When patches from new contributors (without commit access) are stuck, for anything related to the regular releases, issues with packaging and integrating platform support or any other intel-gpu-tools issues, please contact one of the maintainers (listed in the MAINTAINERS file) and cc the - intel-gfx mailing list. + igt-dev mailing list. -- Especially changes to the testcase should get tested on relevant platforms - before committing. For Intel employees that's best done using PRTS, see the - relevant internal howtos. Everyone else can just run piglit with i-g-t tests - locally. +- Changes to the testcases are automatically tested. Take the results into + account before merging. Happy hacking! diff -Nru intel-gpu-tools-1.21/debian/changelog intel-gpu-tools-1.22/debian/changelog --- intel-gpu-tools-1.21/debian/changelog 2018-02-20 17:09:16.000000000 +0000 +++ intel-gpu-tools-1.22/debian/changelog 2018-03-19 13:17:19.000000000 +0000 @@ -1,3 +1,9 @@ +intel-gpu-tools (1.22-1) unstable; urgency=medium + + * New upstream release. + + -- Timo Aaltonen Mon, 19 Mar 2018 15:17:17 +0200 + intel-gpu-tools (1.21-2) unstable; urgency=medium * control: Add peg to build-depends, needed for intel-gpu-overlay. diff -Nru intel-gpu-tools-1.21/lib/i915/gem_context.c intel-gpu-tools-1.22/lib/i915/gem_context.c --- intel-gpu-tools-1.21/lib/i915/gem_context.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/i915/gem_context.c 2018-03-09 14:22:59.000000000 +0000 @@ -44,6 +44,52 @@ */ /** + * gem_has_contexts: + * @fd: open i915 drm file descriptor + * + * Queries whether context creation is supported or not. + * + * Returns: Context creation availability. + */ +bool gem_has_contexts(int fd) +{ + uint32_t ctx_id = 0; + + __gem_context_create(fd, &ctx_id); + if (ctx_id) + gem_context_destroy(fd, ctx_id); + + return ctx_id; +} + +/** + * gem_require_contexts: + * @fd: open i915 drm file descriptor + * + * This helper will automatically skip the test on platforms where context + * support is not available. + */ +void gem_require_contexts(int fd) +{ + igt_require(gem_has_contexts(fd)); +} + +int __gem_context_create(int fd, uint32_t *ctx_id) +{ + struct drm_i915_gem_context_create create; + int err = 0; + + memset(&create, 0, sizeof(create)); + if (igt_ioctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &create) == 0) + *ctx_id = create.ctx_id; + else + err = -errno; + + errno = 0; + return err; +} + +/** * gem_context_create: * @fd: open i915 drm file descriptor * @@ -55,18 +101,12 @@ */ uint32_t gem_context_create(int fd) { - struct drm_i915_gem_context_create create; + uint32_t ctx_id; - memset(&create, 0, sizeof(create)); - if (igt_ioctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &create)) { - int err = -errno; - igt_skip_on(err == -ENODEV || errno == -EINVAL); - igt_assert_eq(err, 0); - } - igt_assert(create.ctx_id != 0); - errno = 0; + igt_assert_eq(__gem_context_create(fd, &ctx_id), 0); + igt_assert(ctx_id != 0); - return create.ctx_id; + return ctx_id; } int __gem_context_destroy(int fd, uint32_t ctx_id) diff -Nru intel-gpu-tools-1.21/lib/i915/gem_context.h intel-gpu-tools-1.22/lib/i915/gem_context.h --- intel-gpu-tools-1.21/lib/i915/gem_context.h 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/i915/gem_context.h 2018-03-09 14:22:59.000000000 +0000 @@ -25,10 +25,15 @@ #define GEM_CONTEXT_H uint32_t gem_context_create(int fd); +int __gem_context_create(int fd, uint32_t *ctx_id); void gem_context_destroy(int fd, uint32_t ctx_id); int __gem_context_destroy(int fd, uint32_t ctx_id); + +bool gem_has_contexts(int fd); +void gem_require_contexts(int fd); void gem_context_require_bannable(int fd); void gem_context_require_param(int fd, uint64_t param); + void gem_context_get_param(int fd, struct drm_i915_gem_context_param *p); void gem_context_set_param(int fd, struct drm_i915_gem_context_param *p); int __gem_context_set_param(int fd, struct drm_i915_gem_context_param *p); diff -Nru intel-gpu-tools-1.21/lib/i915/gem_ring.c intel-gpu-tools-1.22/lib/i915/gem_ring.c --- intel-gpu-tools-1.21/lib/i915/gem_ring.c 1970-01-01 00:00:00.000000000 +0000 +++ intel-gpu-tools-1.22/lib/i915/gem_ring.c 2018-03-09 14:22:59.000000000 +0000 @@ -0,0 +1,131 @@ +/* + * Copyright © 2014 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 "gem_ring.h" + +#include +#include + +#include "intel_reg.h" +#include "drmtest.h" +#include "ioctl_wrappers.h" +#include "igt_dummyload.h" + +static int __execbuf(int fd, struct drm_i915_gem_execbuffer2 *execbuf) +{ + int err; + + err = 0; + if (ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, execbuf)) + err = -errno; + + errno = 0; + return err; +} + +static void alarm_handler(int sig) +{ +} + +/** + * gem_measure_ring_inflight: + * @fd: open i915 drm file descriptor + * @engine: execbuf engine flag + * @flags: flags to affect measurement: + * - MEASURE_RING_NEW_CTX: use a new context to account for the space + * used by the lrc init. + * + * This function calculates the maximum number of batches that can be inserted + * at the same time in the ring on the selected engine. + * + * Returns: + * Number of batches that fit in the ring + */ +unsigned int +gem_measure_ring_inflight(int fd, unsigned int engine, enum measure_ring_flags flags) +{ + struct sigaction old_sa, sa = { .sa_handler = alarm_handler }; + struct drm_i915_gem_exec_object2 obj[2]; + struct drm_i915_gem_execbuffer2 execbuf; + const uint32_t bbe = MI_BATCH_BUFFER_END; + unsigned int count, last; + struct itimerval itv; + IGT_CORK_HANDLE(cork); + + memset(obj, 0, sizeof(obj)); + obj[1].handle = gem_create(fd, 4096); + gem_write(fd, obj[1].handle, 0, &bbe, sizeof(bbe)); + + memset(&execbuf, 0, sizeof(execbuf)); + execbuf.buffers_ptr = to_user_pointer(&obj[1]); + execbuf.buffer_count = 1; + execbuf.flags = engine; + gem_execbuf(fd, &execbuf); + gem_sync(fd, obj[1].handle); + + obj[0].handle = igt_cork_plug(&cork, fd); + + execbuf.buffers_ptr = to_user_pointer(obj); + execbuf.buffer_count = 2; + + if (flags & MEASURE_RING_NEW_CTX) + execbuf.rsvd1 = gem_context_create(fd); + + sigaction(SIGALRM, &sa, &old_sa); + itv.it_interval.tv_sec = 0; + itv.it_interval.tv_usec = 1000; + itv.it_value.tv_sec = 0; + itv.it_value.tv_usec = 10000; + setitimer(ITIMER_REAL, &itv, NULL); + + last = -1; + count = 0; + do { + if (__execbuf(fd, &execbuf) == 0) { + count++; + continue; + } + + if (last == count) + break; + + last = count; + } while (1); + + igt_assert_eq(__execbuf(fd, &execbuf), -EINTR); + + memset(&itv, 0, sizeof(itv)); + setitimer(ITIMER_REAL, &itv, NULL); + sigaction(SIGALRM, &old_sa, NULL); + + igt_cork_unplug(&cork); + gem_close(fd, obj[0].handle); + gem_close(fd, obj[1].handle); + + if (flags & MEASURE_RING_NEW_CTX) + gem_context_destroy(fd, execbuf.rsvd1); + + gem_quiescent_gpu(fd); + + return count; +} diff -Nru intel-gpu-tools-1.21/lib/i915/gem_ring.h intel-gpu-tools-1.22/lib/i915/gem_ring.h --- intel-gpu-tools-1.21/lib/i915/gem_ring.h 1970-01-01 00:00:00.000000000 +0000 +++ intel-gpu-tools-1.22/lib/i915/gem_ring.h 2018-03-09 14:22:59.000000000 +0000 @@ -0,0 +1,36 @@ +/* + * Copyright © 2014 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. + */ + +#ifndef GEM_RING_H +#define GEM_RING_H + +#include + +enum measure_ring_flags { + MEASURE_RING_NEW_CTX = 1 +}; + +unsigned int +gem_measure_ring_inflight(int fd, unsigned int engine, enum measure_ring_flags flags); + +#endif /* GEM_RING_H */ diff -Nru intel-gpu-tools-1.21/lib/i915_pciids.h intel-gpu-tools-1.22/lib/i915_pciids.h --- intel-gpu-tools-1.21/lib/i915_pciids.h 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/i915_pciids.h 2018-03-09 14:22:59.000000000 +0000 @@ -414,24 +414,21 @@ INTEL_CFL_U_GT2_IDS(info), \ INTEL_CFL_U_GT3_IDS(info) -/* CNL U 2+2 */ -#define INTEL_CNL_U_GT2_IDS(info) \ - INTEL_VGA_DEVICE(0x5A52, info), \ - INTEL_VGA_DEVICE(0x5A5A, info), \ - INTEL_VGA_DEVICE(0x5A42, info), \ - INTEL_VGA_DEVICE(0x5A4A, info) - -/* CNL Y 2+2 */ -#define INTEL_CNL_Y_GT2_IDS(info) \ +/* CNL */ +#define INTEL_CNL_IDS(info) \ INTEL_VGA_DEVICE(0x5A51, info), \ INTEL_VGA_DEVICE(0x5A59, info), \ INTEL_VGA_DEVICE(0x5A41, info), \ INTEL_VGA_DEVICE(0x5A49, info), \ - INTEL_VGA_DEVICE(0x5A71, info), \ - INTEL_VGA_DEVICE(0x5A79, info) - -#define INTEL_CNL_IDS(info) \ - INTEL_CNL_U_GT2_IDS(info), \ - INTEL_CNL_Y_GT2_IDS(info) + INTEL_VGA_DEVICE(0x5A52, info), \ + INTEL_VGA_DEVICE(0x5A5A, info), \ + INTEL_VGA_DEVICE(0x5A42, info), \ + INTEL_VGA_DEVICE(0x5A4A, info), \ + INTEL_VGA_DEVICE(0x5A50, info), \ + INTEL_VGA_DEVICE(0x5A40, info), \ + INTEL_VGA_DEVICE(0x5A54, info), \ + INTEL_VGA_DEVICE(0x5A5C, info), \ + INTEL_VGA_DEVICE(0x5A44, info), \ + INTEL_VGA_DEVICE(0x5A4C, info) #endif /* _I915_PCIIDS_H */ diff -Nru intel-gpu-tools-1.21/lib/igt_aux.c intel-gpu-tools-1.22/lib/igt_aux.c --- intel-gpu-tools-1.21/lib/igt_aux.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/igt_aux.c 2018-03-09 14:22:59.000000000 +0000 @@ -50,6 +50,7 @@ #include #include +#include #include "drmtest.h" #include "i915_drm.h" @@ -425,8 +426,6 @@ igt_stop_helper(&shrink_helper); } -#ifdef HAVE_UDEV -#include static struct igt_helper_process hang_detector; static void __attribute__((noreturn)) @@ -506,17 +505,6 @@ { igt_stop_helper(&hang_detector); } -#else -void igt_fork_hang_detector(int fd) -{ - if (igt_only_list_subtests()) - return; -} - -void igt_stop_hang_detector(void) -{ -} -#endif /** * igt_check_boolean_env_var: @@ -578,6 +566,22 @@ } /** + * igt_exchange_int64: + * @array: pointer to the array of int64_t + * @i: first position + * @j: second position + * + * Exchanges the two values at array indices @i and @j. Useful as an exchange + * function for igt_permute_array(). + */ +void igt_exchange_int64(void *array, unsigned i, unsigned j) +{ + int64_t *a = array; + + igt_swap(a[i], a[j]); +} + +/** * igt_permute_array: * @array: pointer to array * @size: size of the array diff -Nru intel-gpu-tools-1.21/lib/igt_aux.h intel-gpu-tools-1.22/lib/igt_aux.h --- intel-gpu-tools-1.21/lib/igt_aux.h 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/igt_aux.h 2018-03-09 14:22:59.000000000 +0000 @@ -29,6 +29,7 @@ #define IGT_AUX_H #include +#include #include #include #include @@ -117,6 +118,7 @@ for (struct timespec t__={}; igt_nsec_elapsed(&t__)>>20 < (t); ) void igt_exchange_int(void *array, unsigned i, unsigned j); +void igt_exchange_int64(void *array, unsigned i, unsigned j); void igt_permute_array(void *array, unsigned size, void (*exchange_func)(void *array, unsigned i, @@ -251,30 +253,28 @@ * True of COND evaluated to true, false otherwise. */ #define igt_wait(COND, timeout_ms, interval_ms) ({ \ - struct timeval start_, end_, diff_; \ - int elapsed_ms_; \ - bool ret_ = false; \ + const unsigned long interval_us__ = 1000 * (interval_ms); \ + const unsigned long timeout_ms__ = (timeout_ms); \ + struct timespec tv__ = {}; \ + bool ret__; \ \ - igt_assert(gettimeofday(&start_, NULL) == 0); \ do { \ + uint64_t elapsed__ = igt_nsec_elapsed(&tv__) >> 20; \ + \ if (COND) { \ - ret_ = true; \ + igt_debug("%s took %"PRIu64"ms\n", #COND, elapsed__); \ + ret__ = true; \ + break; \ + } \ + if (elapsed__ > timeout_ms__) { \ + ret__ = false; \ break; \ } \ \ - usleep(interval_ms * 1000); \ - \ - igt_assert(gettimeofday(&end_, NULL) == 0); \ - timersub(&end_, &start_, &diff_); \ - \ - elapsed_ms_ = diff_.tv_sec * 1000 + \ - diff_.tv_usec / 1000; \ - } while (elapsed_ms_ < timeout_ms); \ - \ - if (!ret_ && (COND)) \ - ret_ = true; \ + usleep(interval_us__); \ + } while (1); \ \ - ret_; \ + ret__; \ }) struct igt_mean; diff -Nru intel-gpu-tools-1.21/lib/igt.cocci intel-gpu-tools-1.22/lib/igt.cocci --- intel-gpu-tools-1.21/lib/igt.cocci 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/igt.cocci 2018-03-09 14:22:59.000000000 +0000 @@ -1,5 +1,5 @@ -// Semantic patch for common patters and their replacement by igt infrastructure -// and macros. Please run with +// Semantic patch for common patterns and their replacement by igt +// infrastructure and macros. Please run with // // spatch --sp-file lib/igt.cocci --in-place tests/*.c // diff -Nru intel-gpu-tools-1.21/lib/igt_core.c intel-gpu-tools-1.22/lib/igt_core.c --- intel-gpu-tools-1.21/lib/igt_core.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/igt_core.c 2018-03-09 14:22:59.000000000 +0000 @@ -70,6 +70,7 @@ #include "igt_core.h" #include "igt_aux.h" #include "igt_sysfs.h" +#include "igt_sysrq.h" #include "igt_rc.h" #define UNW_LOCAL_ONLY @@ -386,16 +387,7 @@ pthread_mutex_unlock(&log_buffer_mutex); } -__attribute__((format(printf, 1, 2))) -static void kmsg(const char *format, ...) -#define KERN_EMER "<0>" -#define KERN_ALERT "<1>" -#define KERN_CRIT "<2>" -#define KERN_ERR "<3>" -#define KERN_WARNING "<4>" -#define KERN_NOTICE "<5>" -#define KERN_INFO "<6>" -#define KERN_DEBUG "<7>" +void igt_kmsg(const char *format, ...) { va_list ap; FILE *file; @@ -525,7 +517,7 @@ static void common_exit_handler(int sig) { if (!igt_only_list_subtests()) { - kick_fbcon(true); + bind_fbcon(true); } /* When not killed by a signal check that igt_exit() has been properly @@ -810,8 +802,8 @@ exit(ret == -1 ? 0 : IGT_EXIT_INVALID); if (!list_subtests) { - kick_fbcon(false); - kmsg(KERN_INFO "[IGT] %s: executing\n", command_str); + bind_fbcon(false); + igt_kmsg(KMSG_INFO "%s: executing\n", command_str); print_version(); sync(); @@ -938,7 +930,8 @@ return false; } - kmsg(KERN_INFO "[IGT] %s: starting subtest %s\n", command_str, subtest_name); + igt_kmsg(KMSG_INFO "%s: starting subtest %s\n", + command_str, subtest_name); igt_debug("Starting subtest: %s\n", subtest_name); _igt_log_buffer_reset(); @@ -1145,6 +1138,28 @@ } /** + * igt_fatal_error: Stop test execution on fatal errors + * + * Stop test execution or optionally, if the IGT_REBOOT_ON_FATAL_ERROR + * environment variable is set, reboot the machine. + * + * Since out test runner (piglit) does support fatal test exit codes, we + * implement the default behaviour by waiting endlessly. + */ +void __attribute__((noreturn)) igt_fatal_error(void) +{ + if (igt_check_boolean_env_var("IGT_REBOOT_ON_FATAL_ERROR", false)) { + igt_warn("FATAL ERROR - REBOOTING\n"); + igt_sysrq_reboot(); + } else { + igt_warn("FATAL ERROR\n"); + for (;;) + pause(); + } +} + + +/** * igt_can_fail: * * Returns true if called from either an #igt_fixture, #igt_subtest or a @@ -1447,8 +1462,8 @@ } if (command_str) - kmsg(KERN_INFO "[IGT] %s: exiting, ret=%d\n", - command_str, igt_exitcode); + igt_kmsg(KMSG_INFO "%s: exiting, ret=%d\n", + command_str, igt_exitcode); igt_debug("Exiting with status code %d\n", igt_exitcode); for (int c = 0; c < num_test_children; c++) diff -Nru intel-gpu-tools-1.21/lib/igt_core.h intel-gpu-tools-1.22/lib/igt_core.h --- intel-gpu-tools-1.21/lib/igt_core.h 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/igt_core.h 2018-03-09 14:22:59.000000000 +0000 @@ -311,6 +311,7 @@ const char *format, ...) __attribute__((noreturn)); void igt_exit(void) __attribute__((noreturn)); +void igt_fatal_error(void) __attribute__((noreturn)); /** * igt_ignore_warn: @@ -932,4 +933,21 @@ free(buf); \ } while (0) +/** + * igt_kmsg: + * @format: printf-style format string with optional args + * + * Writes a message into the kernel log file (/dev/kmsg). + */ +__attribute__((format(printf, 1, 2))) +void igt_kmsg(const char *format, ...); +#define KMSG_EMER "<0>[IGT] " +#define KMSG_ALERT "<1>[IGT] " +#define KMSG_CRIT "<2>[IGT] " +#define KMSG_ERR "<3>[IGT] " +#define KMSG_WARNING "<4>[IGT] " +#define KMSG_NOTICE "<5>[IGT] " +#define KMSG_INFO "<6>[IGT] " +#define KMSG_DEBUG "<7>[IGT] " + #endif /* IGT_CORE_H */ diff -Nru intel-gpu-tools-1.21/lib/igt_debugfs.c intel-gpu-tools-1.22/lib/igt_debugfs.c --- intel-gpu-tools-1.21/lib/igt_debugfs.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/igt_debugfs.c 2018-03-09 14:22:59.000000000 +0000 @@ -110,6 +110,20 @@ return dev != st.st_dev; } +static const char *__igt_debugfs_mount(void) +{ + if (is_mountpoint("/sys/kernel/debug")) + return "/sys/kernel/debug"; + + if (is_mountpoint("/debug")) + return "/debug"; + + if (mount("debug", "/sys/kernel/debug", "debugfs", 0, 0)) + return NULL; + + return "/sys/kernel/debug"; +} + /** * igt_debugfs_mount: * @@ -121,16 +135,12 @@ */ const char *igt_debugfs_mount(void) { - if (is_mountpoint("/sys/kernel/debug")) - return "/sys/kernel/debug"; - - if (is_mountpoint("/debug")) - return "/debug"; + static const char *path; - if (mount("debug", "/sys/kernel/debug", "debugfs", 0, 0)) - return NULL; + if (!path) + path = __igt_debugfs_mount(); - return "/sys/kernel/debug"; + return path; } /** @@ -315,12 +325,10 @@ static bool igt_find_crc_mismatch(const igt_crc_t *a, const igt_crc_t *b, int *index) { + int nwords = min(a->n_words, b->n_words); int i; - if (a->n_words != b->n_words) - return true; - - for (i = 0; i < a->n_words; i++) { + for (i = 0; i < nwords; i++) { if (a->crc[i] != b->crc[i]) { if (index) *index = i; @@ -329,6 +337,12 @@ } } + if (a->n_words != b->n_words) { + if (index) + *index = i; + return true; + } + return false; } @@ -706,15 +720,12 @@ bytes_read = read(pipe_crc->crc_fd, &buf, MAX_LINE_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'; + bytes_read = -errno; + else + buf[bytes_read] = '\0'; - if (bytes_read && !pipe_crc_init_from_string(pipe_crc, out, buf)) + if (bytes_read > 0 && !pipe_crc_init_from_string(pipe_crc, out, buf)) return -EINVAL; return bytes_read; @@ -722,7 +733,9 @@ static void read_one_crc(igt_pipe_crc_t *pipe_crc, igt_crc_t *out) { - while (read_crc(pipe_crc, out) == 0) + int ret; + + while ((ret = read_crc(pipe_crc, out)) <= 0 && ret != -EINVAL) usleep(1000); } @@ -795,10 +808,11 @@ int ret; ret = read_crc(pipe_crc, crc); + if (ret == -EAGAIN) + break; + if (ret < 0) continue; - if (ret == 0) - break; n++; } while (n < n_crcs); @@ -854,6 +868,68 @@ crc_sanity_checks(out_crc); } +/** + * igt_pipe_crc_drain: + * @pipe_crc: pipe CRC object + * + * Discards all currently queued CRC values from @pipe_crc. This function does + * not block, and is useful to flush @pipe_crc. Afterwards you can get a fresh + * CRC with igt_pipe_crc_get_single(). + */ +void igt_pipe_crc_drain(igt_pipe_crc_t *pipe_crc) +{ + int ret; + igt_crc_t crc; + + fcntl(pipe_crc->crc_fd, F_SETFL, pipe_crc->flags | O_NONBLOCK); + + do { + ret = read_crc(pipe_crc, &crc); + } while (ret > 0 || ret == -EINVAL); + + fcntl(pipe_crc->crc_fd, F_SETFL, pipe_crc->flags); +} + +/** + * igt_pipe_crc_get_single: + * @pipe_crc: pipe CRC object + * @crc: buffer pointer for the captured CRC value + * + * Read a single @crc from @pipe_crc. This function does not block + * when nonblocking CRC is requested, and will return false if no CRC + * can be captured. + * + * If opened in blocking mode it will always block until a new CRC is read, like + * igt_pipe_crc_collect_crc(). + * + * 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(). + * + * If capturing has been going on for a while and a fresh crc is required, + * you will need to call igt_pipe_crc_drain() first to remove stale entries. + * + * Returns: + * Whether a crc is captured, only false in non-blocking mode. + */ +bool +igt_pipe_crc_get_single(igt_pipe_crc_t *pipe_crc, igt_crc_t *crc) +{ + bool found = true; + + if (pipe_crc->flags & O_NONBLOCK) { + int ret = read_crc(pipe_crc, crc); + + found = ret > 0; + } else + read_one_crc(pipe_crc, crc); + + if (found) + crc_sanity_checks(crc); + + return found; +} + /* * Drop caches */ diff -Nru intel-gpu-tools-1.21/lib/igt_debugfs.h intel-gpu-tools-1.22/lib/igt_debugfs.h --- intel-gpu-tools-1.21/lib/igt_debugfs.h 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/igt_debugfs.h 2018-03-09 14:22:59.000000000 +0000 @@ -130,6 +130,8 @@ __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_drain(igt_pipe_crc_t *pipe_crc); +bool igt_pipe_crc_get_single(igt_pipe_crc_t *pipe_crc, igt_crc_t *out_crc); 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); diff -Nru intel-gpu-tools-1.21/lib/igt_draw.c intel-gpu-tools-1.22/lib/igt_draw.c --- intel-gpu-tools-1.21/lib/igt_draw.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/igt_draw.c 2018-03-09 14:22:59.000000000 +0000 @@ -557,6 +557,7 @@ intel_batchbuffer_flush(batch); intel_batchbuffer_free(batch); + drm_intel_bo_unreference(dst); } static void draw_rect_render(int fd, struct cmd_data *cmd_data, @@ -624,6 +625,8 @@ rect->h, &dst_buf, adjusted_dst_x, rect->y); intel_batchbuffer_free(batch); + drm_intel_bo_unreference(src); + drm_intel_bo_unreference(dst); gem_close(fd, tmp.handle); } diff -Nru intel-gpu-tools-1.21/lib/igt_dummyload.c intel-gpu-tools-1.22/lib/igt_dummyload.c --- intel-gpu-tools-1.21/lib/igt_dummyload.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/igt_dummyload.c 2018-03-09 14:22:59.000000000 +0000 @@ -25,16 +25,19 @@ #include #include #include +#include #include #include "igt_core.h" +#include "drmtest.h" #include "igt_dummyload.h" #include "igt_gt.h" #include "intel_chipset.h" #include "intel_reg.h" #include "ioctl_wrappers.h" #include "sw_sync.h" +#include "igt_vgem.h" /** * SECTION:igt_dummyload @@ -205,7 +208,6 @@ spin->out_fence = emit_recursive_batch(spin, fd, ctx, engine, dep, out_fence); - igt_assert(gem_bo_busy(fd, spin->handle)); pthread_mutex_lock(&list_lock); igt_list_add(&spin->link, &spin_list); @@ -238,9 +240,14 @@ igt_spin_t * igt_spin_batch_new(int fd, uint32_t ctx, unsigned engine, uint32_t dep) { + igt_spin_t *spin; + igt_require_gem(fd); - return __igt_spin_batch_new(fd, ctx, engine, dep); + spin = __igt_spin_batch_new(fd, ctx, engine, dep); + igt_assert(gem_bo_busy(fd, spin->handle)); + + return spin; } igt_spin_t * @@ -267,10 +274,16 @@ igt_spin_t * igt_spin_batch_new_fence(int fd, uint32_t ctx, unsigned engine) { + igt_spin_t *spin; + igt_require_gem(fd); igt_require(gem_has_exec_fence(fd)); - return __igt_spin_batch_new_fence(fd, ctx, engine); + spin = __igt_spin_batch_new_fence(fd, ctx, engine); + igt_assert(gem_bo_busy(fd, spin->handle)); + igt_assert(poll(&(struct pollfd){spin->out_fence, POLLIN}, 1, 0) == 0); + + return spin; } static void notify(union sigval arg) @@ -371,3 +384,120 @@ igt_spin_batch_end(iter); pthread_mutex_unlock(&list_lock); } + +static uint32_t plug_vgem_handle(struct igt_cork *cork, int fd) +{ + struct vgem_bo bo; + int dmabuf; + uint32_t handle; + + cork->vgem.device = drm_open_driver(DRIVER_VGEM); + igt_require(vgem_has_fences(cork->vgem.device)); + + bo.width = bo.height = 1; + bo.bpp = 4; + vgem_create(cork->vgem.device, &bo); + cork->vgem.fence = vgem_fence_attach(cork->vgem.device, &bo, VGEM_FENCE_WRITE); + + dmabuf = prime_handle_to_fd(cork->vgem.device, bo.handle); + handle = prime_fd_to_handle(fd, dmabuf); + close(dmabuf); + + return handle; +} + +static void unplug_vgem_handle(struct igt_cork *cork) +{ + vgem_fence_signal(cork->vgem.device, cork->vgem.fence); + close(cork->vgem.device); +} + +static uint32_t plug_sync_fd(struct igt_cork *cork) +{ + int fence; + + igt_require_sw_sync(); + + cork->sw_sync.timeline = sw_sync_timeline_create(); + fence = sw_sync_timeline_create_fence(cork->sw_sync.timeline, 1); + + return fence; +} + +static void unplug_sync_fd(struct igt_cork *cork) +{ + sw_sync_timeline_inc(cork->sw_sync.timeline, 1); + close(cork->sw_sync.timeline); +} + +/** + * igt_cork_plug: + * @fd: open drm file descriptor + * @method: method to utilize for corking. + * @cork: structure that will be filled with the state of the cork bo. + * Note: this has to match the corking method. + * + * This function provides a mechanism to stall submission. It provides two + * blocking methods: + * + * VGEM_BO. + * Imports a vgem bo with a fence attached to it. This bo can be used as a + * dependency during submission to stall execution until the fence is signaled. + * + * SW_SYNC: + * Creates a timeline and then a fence on that timeline. The fence can be used + * as an input fence to a request, the request will be stalled until the fence + * is signaled. + * + * The parameters required to unblock the execution and to cleanup are stored in + * the provided cork structure. + * + * Returns: + * Handle of the imported BO / Sw sync fence FD. + */ +uint32_t igt_cork_plug(struct igt_cork *cork, int fd) +{ + igt_assert(cork->fd == -1); + + switch (cork->type) { + case CORK_SYNC_FD: + return plug_sync_fd(cork); + + case CORK_VGEM_HANDLE: + return plug_vgem_handle(cork, fd); + + default: + igt_assert_f(0, "Invalid cork type!\n"); + return 0; + } +} + +/** + * igt_cork_unplug: + * @method: method to utilize for corking. + * @cork: cork state from igt_cork_plug() + * + * This function unblocks the execution by signaling the fence attached to the + * imported bo and does the necessary post-processing. + * + * NOTE: the handle returned by igt_cork_plug is not closed during this phase. + */ +void igt_cork_unplug(struct igt_cork *cork) +{ + igt_assert(cork->fd != -1); + + switch (cork->type) { + case CORK_SYNC_FD: + unplug_sync_fd(cork); + break; + + case CORK_VGEM_HANDLE: + unplug_vgem_handle(cork); + break; + + default: + igt_assert_f(0, "Invalid cork type!\n"); + } + + cork->fd = -1; /* Reset cork */ +} diff -Nru intel-gpu-tools-1.21/lib/igt_dummyload.h intel-gpu-tools-1.22/lib/igt_dummyload.h --- intel-gpu-tools-1.21/lib/igt_dummyload.h 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/igt_dummyload.h 2018-03-09 14:22:59.000000000 +0000 @@ -61,4 +61,36 @@ void igt_terminate_spin_batches(void); +enum igt_cork_type { + CORK_SYNC_FD = 1, + CORK_VGEM_HANDLE +}; + +struct igt_cork_vgem { + int device; + uint32_t fence; +}; + +struct igt_cork_sw_sync { + int timeline; +}; + +struct igt_cork { + enum igt_cork_type type; + + union { + int fd; + + struct igt_cork_vgem vgem; + struct igt_cork_sw_sync sw_sync; + }; +}; + +#define IGT_CORK(name, cork_type) struct igt_cork name = { .type = cork_type, .fd = -1} +#define IGT_CORK_HANDLE(name) IGT_CORK(name, CORK_VGEM_HANDLE) +#define IGT_CORK_FENCE(name) IGT_CORK(name, CORK_SYNC_FD) + +uint32_t igt_cork_plug(struct igt_cork *cork, int fd); +void igt_cork_unplug(struct igt_cork *cork); + #endif /* __IGT_DUMMYLOAD_H__ */ diff -Nru intel-gpu-tools-1.21/lib/igt_fb.c intel-gpu-tools-1.22/lib/igt_fb.c --- intel-gpu-tools-1.21/lib/igt_fb.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/igt_fb.c 2018-03-09 14:22:59.000000000 +0000 @@ -32,6 +32,7 @@ #include "drmtest.h" #include "igt_fb.h" #include "igt_kms.h" +#include "igt_x86.h" #include "ioctl_wrappers.h" #include "intel_chipset.h" @@ -54,26 +55,43 @@ */ /* drm fourcc/cairo format maps */ -#define DF(did, cid, _bpp, _depth) \ - { DRM_FORMAT_##did, CAIRO_FORMAT_##cid, # did, _bpp, _depth } +#define DF(did, cid, ...) \ + { DRM_FORMAT_##did, CAIRO_FORMAT_##cid, # did, __VA_ARGS__ } static struct format_desc_struct { uint32_t drm_id; cairo_format_t cairo_id; const char *name; int bpp; int depth; + int planes; + int plane_bpp[4]; } format_desc[] = { DF(RGB565, RGB16_565, 16, 16), //DF(RGB888, INVALID, 24, 24), DF(XRGB8888, RGB24, 32, 24), DF(XRGB2101010, RGB30, 32, 30), DF(ARGB8888, ARGB32, 32, 32), + DF(NV12, RGB24, 32, -1, 2, {8, 16}), }; #undef DF #define for_each_format(f) \ for (f = format_desc; f - format_desc < ARRAY_SIZE(format_desc); f++) +static struct format_desc_struct *lookup_drm_format(uint32_t drm_format) +{ + struct format_desc_struct *format; + + for_each_format(format) { + if (format->drm_id != drm_format) + continue; + + return format; + } + + return NULL; +} + /** * igt_get_fb_tile_size: * @fd: the DRM file descriptor @@ -142,26 +160,73 @@ } } -/** - * igt_calc_fb_size: - * @fd: the DRM file descriptor - * @width: width of the framebuffer in pixels - * @height: height of the framebuffer in pixels - * @bpp: bytes per pixel of the framebuffer - * @tiling: tiling layout of the framebuffer (as framebuffer modifier) - * @size_ret: returned size for the framebuffer - * @stride_ret: returned stride for the framebuffer - * - * This function returns valid stride and size values for a framebuffer with the - * specified parameters. - */ -void igt_calc_fb_size(int fd, int width, int height, int bpp, uint64_t tiling, - unsigned *size_ret, unsigned *stride_ret) +static unsigned planar_width(struct format_desc_struct *format, unsigned width, int plane) +{ + if (format->drm_id == DRM_FORMAT_NV12 && plane == 1) + return (width + 1) / 2; + + return width; +} + +static unsigned planar_stride(struct format_desc_struct *format, unsigned width, int plane) +{ + unsigned cpp = format->plane_bpp[plane] / 8; + + return planar_width(format, width, plane) * cpp; +} + +static unsigned planar_height(struct format_desc_struct *format, unsigned height, int plane) +{ + if (format->drm_id == DRM_FORMAT_NV12 && plane == 1) + return (height + 1) / 2; + + return height; +} + +static void calc_fb_size_planar(int fd, int width, int height, + struct format_desc_struct *format, + uint64_t tiling, unsigned *size_ret, + unsigned *stride_ret, unsigned *offsets) +{ + int plane; + unsigned stride = 0, tile_width, tile_height; + + *size_ret = 0; + + for (plane = 0; plane < format->planes; plane++) { + unsigned plane_stride; + + igt_get_fb_tile_size(fd, tiling, format->plane_bpp[plane], &tile_width, &tile_height); + + plane_stride = ALIGN(planar_stride(format, width, plane), tile_width); + if (stride < plane_stride) + stride = plane_stride; + } + + for (plane = 0; plane < format->planes; plane++) { + if (offsets) + offsets[plane] = *size_ret; + + igt_get_fb_tile_size(fd, tiling, format->plane_bpp[plane], &tile_width, &tile_height); + + *size_ret += stride * ALIGN(planar_height(format, height, plane), tile_height); + } + + if (offsets) + for (; plane < ARRAY_SIZE(format->plane_bpp); plane++) + offsets[plane] = 0; + + *stride_ret = stride; +} + +static void calc_fb_size_packed(int fd, int width, int height, + struct format_desc_struct *format, uint64_t tiling, + unsigned *size_ret, unsigned *stride_ret) { unsigned int tile_width, tile_height, stride, size; - int byte_width = width * (bpp / 8); + int byte_width = width * (format->bpp / 8); - igt_get_fb_tile_size(fd, tiling, bpp, &tile_width, &tile_height); + igt_get_fb_tile_size(fd, tiling, format->bpp, &tile_width, &tile_height); if (tiling != LOCAL_DRM_FORMAT_MOD_NONE && intel_gen(intel_get_drm_devid(fd)) <= 3) { @@ -175,7 +240,7 @@ * tiled. But then that failure is expected. */ - v = width * bpp / 8; + v = byte_width; for (stride = 512; stride < v; stride *= 2) ; @@ -192,6 +257,31 @@ } /** + * igt_calc_fb_size: + * @fd: the DRM file descriptor + * @width: width of the framebuffer in pixels + * @height: height of the framebuffer in pixels + * @format: drm fourcc pixel format code + * @tiling: tiling layout of the framebuffer (as framebuffer modifier) + * @size_ret: returned size for the framebuffer + * @stride_ret: returned stride for the framebuffer + * + * This function returns valid stride and size values for a framebuffer with the + * specified parameters. + */ +void igt_calc_fb_size(int fd, int width, int height, uint32_t drm_format, uint64_t tiling, + unsigned *size_ret, unsigned *stride_ret) +{ + struct format_desc_struct *format = lookup_drm_format(drm_format); + igt_assert(format); + + if (format->planes > 1) + calc_fb_size_planar(fd, width, height, format, tiling, size_ret, stride_ret, NULL); + else + calc_fb_size_packed(fd, width, height, format, tiling, size_ret, stride_ret); +} + +/** * igt_fb_mod_to_tiling: * @modifier: DRM framebuffer modifier * @@ -244,19 +334,29 @@ } /* helpers to create nice-looking framebuffers */ -static int create_bo_for_fb(int fd, int width, int height, uint32_t format, +static int create_bo_for_fb(int fd, int width, int height, + struct format_desc_struct *format, uint64_t tiling, unsigned size, unsigned stride, unsigned *size_ret, unsigned *stride_ret, - bool *is_dumb) + uint32_t *offsets, bool *is_dumb) { - int bpp = igt_drm_format_to_bpp(format); int bo; - if (tiling || size || stride) { + igt_assert(format); + + if (offsets) + memset(offsets, 0, ARRAY_SIZE(format->plane_bpp) * sizeof(*offsets)); + + if (tiling || size || stride || format->planes > 1) { unsigned calculated_size, calculated_stride; - igt_calc_fb_size(fd, width, height, bpp, tiling, - &calculated_size, &calculated_stride); + if (format->planes > 1) + calc_fb_size_planar(fd, width, height, format, tiling, + &calculated_size, &calculated_stride, offsets); + else + calc_fb_size_packed(fd, width, height, format, tiling, + &calculated_size, &calculated_stride); + if (stride == 0) stride = calculated_stride; if (size == 0) @@ -266,14 +366,20 @@ *is_dumb = false; if (is_i915_device(fd)) { - uint32_t *ptr; + uint8_t *ptr; bo = gem_create(fd, size); gem_set_tiling(fd, bo, igt_fb_mod_to_tiling(tiling), stride); /* Ensure the framebuffer is preallocated */ - ptr = gem_mmap__gtt(fd, bo, size, PROT_READ); - igt_assert(*ptr == 0); + ptr = gem_mmap__gtt(fd, bo, size, PROT_READ | PROT_WRITE); + igt_assert(*(uint32_t *)ptr == 0); + + if (format->drm_id == DRM_FORMAT_NV12) { + /* component formats have a different zero point */ + memset(ptr, 16, offsets[1]); + memset(ptr + offsets[1], 0x80, (height + 1)/2 * stride); + } gem_munmap(ptr, size); if (size_ret) @@ -293,7 +399,7 @@ if (is_dumb) *is_dumb = true; - return kmstest_dumb_create(fd, width, height, bpp, stride_ret, + return kmstest_dumb_create(fd, width, height, format->bpp, stride_ret, size_ret); } } @@ -321,8 +427,8 @@ unsigned stride, unsigned *size_ret, unsigned *stride_ret, bool *is_dumb) { - return create_bo_for_fb(fd, width, height, format, modifier, 0, stride, - size_ret, stride_ret, is_dumb); + return create_bo_for_fb(fd, width, height, lookup_drm_format(format), + modifier, 0, stride, size_ret, stride_ret, NULL, is_dumb); } /** @@ -663,15 +769,20 @@ struct igt_fb *fb, unsigned bo_size, unsigned bo_stride) { + struct format_desc_struct *f = lookup_drm_format(format); uint32_t fb_id; + int i; + + igt_assert_f(f, "DRM format %08x not found\n", format); memset(fb, 0, sizeof(*fb)); igt_debug("%s(width=%d, height=%d, format=0x%x, tiling=0x%"PRIx64", size=%d)\n", __func__, width, height, format, tiling, bo_size); - fb->gem_handle = create_bo_for_fb(fd, width, height, format, tiling, - bo_size, bo_stride, &fb->size, - &fb->stride, &fb->is_dumb); + fb->gem_handle = create_bo_for_fb(fd, width, height, f, + tiling, bo_size, bo_stride, + &fb->size, &fb->stride, + fb->offsets, &fb->is_dumb); igt_assert(fb->gem_handle > 0); igt_debug("%s(handle=%d, pitch=%d)\n", @@ -680,22 +791,24 @@ if (tiling != LOCAL_DRM_FORMAT_MOD_NONE && tiling != LOCAL_I915_FORMAT_MOD_X_TILED) { do_or_die(__kms_addfb(fd, fb->gem_handle, width, height, - fb->stride, format, tiling, + fb->stride, format, tiling, fb->offsets, LOCAL_DRM_MODE_FB_MODIFIERS, &fb_id)); } else { uint32_t handles[4]; uint32_t pitches[4]; - uint32_t offsets[4]; memset(handles, 0, sizeof(handles)); memset(pitches, 0, sizeof(pitches)); - memset(offsets, 0, sizeof(offsets)); handles[0] = fb->gem_handle; pitches[0] = fb->stride; + for (i = 0; i < f->planes; i++) { + handles[i] = fb->gem_handle; + pitches[i] = fb->stride; + } do_or_die(drmModeAddFB2(fd, width, height, format, - handles, pitches, offsets, + handles, pitches, fb->offsets, &fb_id, 0)); } @@ -705,6 +818,17 @@ fb->drm_format = format; fb->fb_id = fb_id; fb->fd = fd; + fb->num_planes = f->planes ?: 1; + fb->plane_bpp[0] = f->bpp; + fb->plane_height[0] = height; + fb->plane_width[0] = width; + + /* if f->planes is set, then plane_bpp is valid too so use that. */ + for (i = 0; i < f->planes; i++) { + fb->plane_bpp[i] = f->plane_bpp[i]; + fb->plane_height[i] = planar_height(f, height, i); + fb->plane_width[i] = planar_width(f, width, i); + } return fb_id; } @@ -771,8 +895,7 @@ cr = igt_get_cairo_ctx(fd, fb); igt_paint_color(cr, 0, 0, width, height, r, g, b); - igt_assert(cairo_status(cr) == 0); - cairo_destroy(cr); + igt_put_cairo_ctx(fd, fb, cr); return fb_id; } @@ -809,8 +932,7 @@ cr = igt_get_cairo_ctx(fd, fb); igt_paint_test_pattern(cr, width, height); - igt_assert(cairo_status(cr) == 0); - cairo_destroy(cr); + igt_put_cairo_ctx(fd, fb, cr); return fb_id; } @@ -853,8 +975,7 @@ cr = igt_get_cairo_ctx(fd, fb); igt_paint_color(cr, 0, 0, width, height, r, g, b); igt_paint_test_pattern(cr, width, height); - igt_assert(cairo_status(cr) == 0); - cairo_destroy(cr); + igt_put_cairo_ctx(fd, fb, cr); return fb_id; } @@ -897,8 +1018,7 @@ cr = igt_get_cairo_ctx(fd, fb); igt_paint_image(cr, filename, 0, 0, width, height); - igt_assert(cairo_status(cr) == 0); - cairo_destroy(cr); + igt_put_cairo_ctx(fd, fb, cr); return fb_id; } @@ -998,7 +1118,7 @@ layout.right.x, layout.right.y, layout.right.width, layout.right.height); - cairo_destroy(cr); + igt_put_cairo_ctx(drm_fd, &fb, cr); return fb_id; } @@ -1015,100 +1135,117 @@ drm_format, igt_format_str(drm_format)); } +struct fb_blit_linear { + uint32_t handle; + unsigned size, stride; + uint8_t *map; + bool is_dumb; + uint32_t offsets[4]; +}; + struct fb_blit_upload { int fd; struct igt_fb *fb; - struct { - uint32_t handle; - unsigned size, stride; - uint8_t *map; - bool is_dumb; - } linear; + struct fb_blit_linear linear; }; -static void destroy_cairo_surface__blit(void *arg) +static void free_linear_mapping(int fd, struct igt_fb *fb, struct fb_blit_linear *linear) { - struct fb_blit_upload *blit = arg; - struct igt_fb *fb = blit->fb; unsigned int obj_tiling = igt_fb_mod_to_tiling(fb->tiling); + int i; - gem_munmap(blit->linear.map, blit->linear.size); - fb->cairo_surface = NULL; + gem_munmap(linear->map, linear->size); + gem_set_domain(fd, linear->handle, + I915_GEM_DOMAIN_GTT, 0); + + for (i = 0; i < fb->num_planes; i++) + igt_blitter_fast_copy__raw(fd, + linear->handle, + linear->offsets[i], + linear->stride, + I915_TILING_NONE, + 0, 0, /* src_x, src_y */ + fb->plane_width[i], fb->plane_height[i], + fb->plane_bpp[i], + fb->gem_handle, + fb->offsets[i], + fb->stride, + obj_tiling, + 0, 0 /* dst_x, dst_y */); - gem_set_domain(blit->fd, blit->linear.handle, - I915_GEM_DOMAIN_GTT, 0); + gem_sync(fd, linear->handle); + gem_close(fd, linear->handle); +} + +static void destroy_cairo_surface__blit(void *arg) +{ + struct fb_blit_upload *blit = arg; - igt_blitter_fast_copy__raw(blit->fd, - blit->linear.handle, - blit->linear.stride, - I915_TILING_NONE, - 0, 0, /* src_x, src_y */ - fb->width, fb->height, - igt_drm_format_to_bpp(fb->drm_format), - fb->gem_handle, - fb->stride, - obj_tiling, - 0, 0 /* dst_x, dst_y */); + blit->fb->cairo_surface = NULL; - gem_sync(blit->fd, blit->linear.handle); - gem_close(blit->fd, blit->linear.handle); + free_linear_mapping(blit->fd, blit->fb, &blit->linear); free(blit); } -static void create_cairo_surface__blit(int fd, struct igt_fb *fb) +static void setup_linear_mapping(int fd, struct igt_fb *fb, struct fb_blit_linear *linear) { - struct fb_blit_upload *blit; - cairo_format_t cairo_format; unsigned int obj_tiling = igt_fb_mod_to_tiling(fb->tiling); - - blit = malloc(sizeof(*blit)); - igt_assert(blit); + int i; /* * We create a linear BO that we'll map for the CPU to write to (using * cairo). This linear bo will be then blitted to its final * destination, tiling it at the same time. */ - blit->linear.handle = create_bo_for_fb(fd, fb->width, fb->height, - fb->drm_format, + linear->handle = create_bo_for_fb(fd, fb->width, fb->height, + lookup_drm_format(fb->drm_format), LOCAL_DRM_FORMAT_MOD_NONE, 0, - 0, &blit->linear.size, - &blit->linear.stride, - &blit->linear.is_dumb); + 0, &linear->size, + &linear->stride, + linear->offsets, &linear->is_dumb); - igt_assert(blit->linear.handle > 0); - - blit->fd = fd; - blit->fb = fb; + igt_assert(linear->handle > 0); /* Copy fb content to linear BO */ - gem_set_domain(fd, blit->linear.handle, + gem_set_domain(fd, linear->handle, I915_GEM_DOMAIN_GTT, 0); - igt_blitter_fast_copy__raw(fd, - fb->gem_handle, - fb->stride, - obj_tiling, - 0, 0, /* src_x, src_y */ - fb->width, fb->height, - igt_drm_format_to_bpp(fb->drm_format), - blit->linear.handle, - blit->linear.stride, - I915_TILING_NONE, - 0, 0 /* dst_x, dst_y */); + for (i = 0; i < fb->num_planes; i++) + igt_blitter_fast_copy__raw(fd, + fb->gem_handle, + fb->offsets[i], + fb->stride, + obj_tiling, + 0, 0, /* src_x, src_y */ + fb->plane_width[i], fb->plane_height[i], + fb->plane_bpp[i], + linear->handle, linear->offsets[i], + linear->stride, + I915_TILING_NONE, + 0, 0 /* dst_x, dst_y */); - gem_sync(fd, blit->linear.handle); + gem_sync(fd, linear->handle); - gem_set_domain(fd, blit->linear.handle, + gem_set_domain(fd, linear->handle, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU); /* Setup cairo context */ - blit->linear.map = gem_mmap__cpu(fd, - blit->linear.handle, - 0, - blit->linear.size, - PROT_READ | PROT_WRITE); + linear->map = gem_mmap__cpu(fd, linear->handle, + 0, linear->size, PROT_READ | PROT_WRITE); +} + +static void create_cairo_surface__blit(int fd, struct igt_fb *fb) +{ + struct fb_blit_upload *blit; + cairo_format_t cairo_format; + + blit = malloc(sizeof(*blit)); + igt_assert(blit); + + blit->fd = fd; + blit->fb = fb; + setup_linear_mapping(fd, fb, &blit->linear); cairo_format = drm_format_to_cairo(fb->drm_format); fb->cairo_surface = @@ -1170,13 +1307,240 @@ fb, destroy_cairo_surface__gtt); } +struct fb_convert_blit_upload { + int fd; + struct igt_fb *fb; + + struct { + uint8_t *map; + unsigned stride, size; + } rgb24; + + struct fb_blit_linear linear; +}; + +static uint8_t clamprgb(float val) { + if (val < 0) + return 0; + if (val > 255) + return 255; + + return (uint8_t)val; +} + +static void convert_nv12_to_rgb24(struct igt_fb *fb, struct fb_convert_blit_upload *blit) +{ + int i, j; + const uint8_t *y, *uv; + uint8_t *rgb24 = blit->rgb24.map; + unsigned rgb24_stride = blit->rgb24.stride, planar_stride = blit->linear.stride; + uint8_t *buf = malloc(blit->linear.size); + + /* + * Reading from the BO is awfully slow because of lack of read caching, + * it's faster to copy the whole BO to a temporary buffer and convert + * from there. + */ + igt_memcpy_from_wc(buf, blit->linear.map, blit->linear.size); + y = &buf[blit->linear.offsets[0]]; + uv = &buf[blit->linear.offsets[1]]; + + /* Convert from limited color range BT.601 */ + for (i = 0; i < fb->height / 2; i++) { + for (j = 0; j < fb->width; j++) { + float r_, g_, b_, y0, y1, cb, cr; + /* Convert 1x2 pixel blocks */ + + y0 = 1.164f * (y[j] - 16.f); + y1 = 1.164f * (y[j + planar_stride] - 16.f); + + cb = uv[j & ~1] - 128.f; + cr = uv[j | 1] - 128.f; + + r_ = 0.000f * cb + 1.596f * cr; + g_ = -0.392f * cb + -0.813f * cr; + b_ = 2.017f * cb + 0.000f * cr; + + rgb24[j * 4 + 2] = clamprgb(y0 + r_); + rgb24[j * 4 + 2 + rgb24_stride] = clamprgb(y1 + r_); + + rgb24[j * 4 + 1] = clamprgb(y0 + g_); + rgb24[j * 4 + 1 + rgb24_stride] = clamprgb(y1 + g_); + + rgb24[j * 4] = clamprgb(y0 + b_); + rgb24[j * 4 + rgb24_stride] = clamprgb(y1 + b_); + } + + rgb24 += 2 * rgb24_stride; + y += 2 * planar_stride; + uv += planar_stride; + } + + if (fb->height & 1) { + /* Convert last row */ + for (j = 0; j < fb->width; j++) { + float r_, g_, b_, y0, cb, cr; + /* Convert single pixel */ + + cb = uv[j & ~1] - 128.f; + cr = uv[j | 1] - 128.f; + + y0 = 1.164f * (y[j] - 16.f); + r_ = 0.000f * cb + 1.596f * cr; + g_ = -0.392f * cb + -0.813f * cr; + b_ = 2.017f * cb + 0.000f * cr; + + rgb24[j * 4 + 2] = clamprgb(y0 + r_); + rgb24[j * 4 + 1] = clamprgb(y0 + g_); + rgb24[j * 4] = clamprgb(y0 + b_); + } + } + + free(buf); +} + +static void convert_rgb24_to_nv12(struct igt_fb *fb, struct fb_convert_blit_upload *blit) +{ + int i, j; + uint8_t *y = &blit->linear.map[blit->linear.offsets[0]]; + uint8_t *uv = &blit->linear.map[blit->linear.offsets[1]]; + const uint8_t *rgb24 = blit->rgb24.map; + unsigned rgb24_stride = blit->rgb24.stride; + unsigned planar_stride = blit->linear.stride; + + igt_assert_f(fb->drm_format == DRM_FORMAT_NV12, + "Conversion not implemented for !NV12 planar formats\n"); + + for (i = 0; i < fb->plane_height[0]; i++) { + /* Use limited color range BT.601 */ + + for (j = 0; j < fb->plane_width[0]; j++) { + float yf = 0.257f * rgb24[j * 4 + 2] + + 0.504f * rgb24[j * 4 + 1] + + 0.098f * rgb24[j * 4] + 16; + + y[j] = (uint8_t)yf; + } + + rgb24 += rgb24_stride; + y += planar_stride; + } + + rgb24 = blit->rgb24.map; + + for (i = 0; i < fb->height / 2; i++) { + for (j = 0; j < fb->plane_width[1]; j++) { + /* + * Pixel center for Cb'Cr' is between the left top and + * bottom pixel in a 2x2 block, so take the average. + */ + float uf = -0.148f/2 * rgb24[j * 8 + 2] + + -0.148f/2 * rgb24[j * 8 + 2 + rgb24_stride] + + -0.291f/2 * rgb24[j * 8 + 1] + + -0.291f/2 * rgb24[j * 8 + 1 + rgb24_stride] + + 0.439f/2 * rgb24[j * 8] + + 0.439f/2 * rgb24[j * 8 + rgb24_stride] + 128; + float vf = 0.439f/2 * rgb24[j * 8 + 2] + + 0.439f/2 * rgb24[j * 8 + 2 + rgb24_stride] + + -0.368f/2 * rgb24[j * 8 + 1] + + -0.368f/2 * rgb24[j * 8 + 1 + rgb24_stride] + + -0.071f/2 * rgb24[j * 8] + + -0.071f/2 * rgb24[j * 8 + rgb24_stride] + 128; + uv[j * 2] = (uint8_t)uf; + uv[j * 2 + 1] = (uint8_t)vf; + } + + rgb24 += 2 * rgb24_stride; + uv += planar_stride; + } + + /* Last row cannot be interpolated between 2 pixels, take the single value */ + if (i < fb->plane_height[1]) { + for (j = 0; j < fb->plane_width[1]; j++) { + float uf = -0.148f * rgb24[j * 8 + 2] + + -0.291f * rgb24[j * 8 + 1] + + 0.439f * rgb24[j * 8] + 128; + float vf = 0.439f * rgb24[j * 8 + 2] + + -0.368f * rgb24[j * 8 + 1] + + -0.071f * rgb24[j * 8] + 128; + + uv[j * 2] = (uint8_t)uf; + uv[j * 2 + 1] = (uint8_t)vf; + } + } +} + +static void destroy_cairo_surface__convert(void *arg) +{ + struct fb_convert_blit_upload *blit = arg; + struct igt_fb *fb = blit->fb; + + /* Convert back to planar! */ + igt_assert_f(fb->drm_format == DRM_FORMAT_NV12, + "Conversion not implemented for !NV12 planar formats\n"); + + convert_rgb24_to_nv12(fb, blit); + + munmap(blit->rgb24.map, blit->rgb24.size); + + if (blit->linear.handle) + free_linear_mapping(blit->fd, blit->fb, &blit->linear); + else + gem_munmap(blit->linear.map, fb->size); + + free(blit); + + fb->cairo_surface = NULL; +} + +static void create_cairo_surface__convert(int fd, struct igt_fb *fb) +{ + struct fb_convert_blit_upload *blit = malloc(sizeof(*blit)); + igt_assert(blit); + + blit->fd = fd; + blit->fb = fb; + blit->rgb24.stride = ALIGN(fb->width * 4, 16); + blit->rgb24.size = ALIGN(blit->rgb24.stride * fb->height, sysconf(_SC_PAGESIZE)); + blit->rgb24.map = mmap(NULL, blit->rgb24.size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + igt_assert(blit->rgb24.map != MAP_FAILED); + + if (fb->tiling == LOCAL_I915_FORMAT_MOD_Y_TILED || + fb->tiling == LOCAL_I915_FORMAT_MOD_Yf_TILED) { + setup_linear_mapping(fd, fb, &blit->linear); + } else { + blit->linear.handle = 0; + blit->linear.map = gem_mmap__gtt(fd, fb->gem_handle, fb->size, + PROT_READ | PROT_WRITE); + igt_assert(blit->linear.map); + blit->linear.stride = fb->stride; + blit->linear.size = fb->size; + memcpy(blit->linear.offsets, fb->offsets, sizeof(fb->offsets)); + } + + /* Convert to linear! */ + igt_assert_f(fb->drm_format == DRM_FORMAT_NV12, + "Conversion not implemented for !NV12 planar formats\n"); + convert_nv12_to_rgb24(fb, blit); + + fb->cairo_surface = + cairo_image_surface_create_for_data(blit->rgb24.map, + CAIRO_FORMAT_RGB24, + fb->width, fb->height, + blit->rgb24.stride); + + cairo_surface_set_user_data(fb->cairo_surface, + (cairo_user_data_key_t *)create_cairo_surface__convert, + blit, destroy_cairo_surface__convert); +} + /** * igt_get_cairo_surface: * @fd: open drm file descriptor * @fb: pointer to an #igt_fb structure * - * This function stores the contents of the supplied framebuffer into a cairo - * surface and returns it. + * This function stores the contents of the supplied framebuffer's plane + * into a cairo surface and returns it. * * Returns: * A pointer to a cairo surface with the contents of the framebuffer. @@ -1184,7 +1548,9 @@ cairo_surface_t *igt_get_cairo_surface(int fd, struct igt_fb *fb) { if (fb->cairo_surface == NULL) { - if (fb->tiling == LOCAL_I915_FORMAT_MOD_Y_TILED || + if (fb->num_planes > 1) + create_cairo_surface__convert(fd, fb); + else if (fb->tiling == LOCAL_I915_FORMAT_MOD_Y_TILED || fb->tiling == LOCAL_I915_FORMAT_MOD_Yf_TILED) create_cairo_surface__blit(fd, fb); else @@ -1206,7 +1572,7 @@ * * This initializes a cairo surface for @fb and then allocates a drawing context * for it. The return cairo drawing context should be released by calling - * cairo_destroy(). This also sets a default font for drawing text on + * igt_put_cairo_ctx(). This also sets a default font for drawing text on * framebuffers. * * Returns: @@ -1230,6 +1596,24 @@ } /** + * igt_put_cairo_ctx: + * @fd: open i915 drm file descriptor + * @fb: pointer to an #igt_fb structure + * @cr: the cairo context returned by igt_get_cairo_ctx. + * + * This releases the cairo surface @cr returned by igt_get_cairo_ctx() + * for @fb, and writes the changes out to the framebuffer if cairo doesn't + * have native support for the format. + */ +void igt_put_cairo_ctx(int fd, struct igt_fb *fb, cairo_t *cr) +{ + cairo_status_t ret = cairo_status(cr); + igt_assert_f(ret == CAIRO_STATUS_SUCCESS, "Cairo failed to draw with %s\n", cairo_status_to_string(ret)); + + cairo_destroy(cr); +} + +/** * igt_remove_fb: * @fd: open i915 drm file descriptor * @fb: pointer to an #igt_fb structure @@ -1240,9 +1624,13 @@ */ void igt_remove_fb(int fd, struct igt_fb *fb) { + if (!fb || !fb->fb_id) + return; + cairo_surface_destroy(fb->cairo_surface); do_or_die(drmModeRmFB(fd, fb->fb_id)); gem_close(fd, fb->gem_handle); + fb->fb_id = 0; } /** @@ -1277,14 +1665,12 @@ */ uint32_t igt_drm_format_to_bpp(uint32_t drm_format) { - struct format_desc_struct *f; - - for_each_format(f) - if (f->drm_id == drm_format) - return f->bpp; + struct format_desc_struct *f = lookup_drm_format(drm_format); - igt_assert_f(0, "can't find a bpp format for %08x (%s)\n", + igt_assert_f(f, "can't find a bpp format for %08x (%s)\n", drm_format, igt_format_str(drm_format)); + + return f->bpp; } /** @@ -1297,44 +1683,25 @@ */ const char *igt_format_str(uint32_t drm_format) { - struct format_desc_struct *f; - - for_each_format(f) - if (f->drm_id == drm_format) - return f->name; + struct format_desc_struct *f = lookup_drm_format(drm_format); - return "invalid"; + return f ? f->name : "invalid"; } /** - * igt_get_all_cairo_formats: - * @formats: pointer to pointer to store the allocated formats array - * @format_count: pointer to integer to store the size of the allocated array + * igt_fb_supported_format: + * @drm_format: drm fourcc to test. * - * This functions returns an array of all the drm fourcc codes supported by - * cairo and this library. + * This functions returns whether @drm_format can be succesfully created by + * igt_create_fb() and drawn to by igt_get_cairo_ctx(). */ -void igt_get_all_cairo_formats(const uint32_t **formats, int *format_count) +bool igt_fb_supported_format(uint32_t drm_format) { - static uint32_t *drm_formats; - static int n_formats; - - if (!drm_formats) { - struct format_desc_struct *f; - uint32_t *format; - - n_formats = 0; - for_each_format(f) - if (f->cairo_id != CAIRO_FORMAT_INVALID) - n_formats++; + struct format_desc_struct *f; - drm_formats = calloc(n_formats, sizeof(*drm_formats)); - format = &drm_formats[0]; - for_each_format(f) - if (f->cairo_id != CAIRO_FORMAT_INVALID) - *format++ = f->drm_id; - } + for_each_format(f) + if (f->drm_id == drm_format) + return f->cairo_id != CAIRO_FORMAT_INVALID; - *formats = drm_formats; - *format_count = n_formats; + return false; } diff -Nru intel-gpu-tools-1.21/lib/igt_fb.h intel-gpu-tools-1.22/lib/igt_fb.h --- intel-gpu-tools-1.21/lib/igt_fb.h 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/igt_fb.h 2018-03-09 14:22:59.000000000 +0000 @@ -50,6 +50,11 @@ * @size: size in bytes of the underlying backing storage * @cairo_surface: optionally attached cairo drawing surface * @domain: current domain for cache flushing tracking on i915.ko + * @num_planes: Amount of planes on this fb. >1 for planar formats. + * @offsets: Offset for each plane in bytes. + * @plane_bpp: The bpp for each plane. + * @plane_width: The width for each plane. + * @plane_height: The height for each plane. * * Tracking structure for KMS framebuffer objects. */ @@ -66,6 +71,11 @@ unsigned int size; cairo_surface_t *cairo_surface; unsigned int domain; + unsigned int num_planes; + uint32_t offsets[4]; + unsigned int plane_bpp[4]; + unsigned int plane_width[4]; + unsigned int plane_height[4]; } igt_fb_t; /** @@ -90,7 +100,7 @@ void igt_get_fb_tile_size(int fd, uint64_t tiling, int fb_bpp, unsigned *width_ret, unsigned *height_ret); -void igt_calc_fb_size(int fd, int width, int height, int bpp, uint64_t tiling, +void igt_calc_fb_size(int fd, int width, int height, uint32_t format, uint64_t tiling, unsigned *size_ret, unsigned *stride_ret); unsigned int igt_create_fb_with_bo_size(int fd, int width, int height, @@ -131,6 +141,7 @@ cairo_surface_t *igt_get_cairo_surface(int fd, struct igt_fb *fb); cairo_surface_t *igt_cairo_image_surface_create_from_png(const char *filename); cairo_t *igt_get_cairo_ctx(int fd, struct igt_fb *fb); +void igt_put_cairo_ctx(int fd, struct igt_fb *fb, cairo_t *cr); void igt_paint_color(cairo_t *cr, int x, int y, int w, int h, double r, double g, double b); void igt_paint_color_alpha(cairo_t *cr, int x, int y, int w, int h, @@ -151,7 +162,7 @@ uint32_t igt_bpp_depth_to_drm_format(int bpp, int depth); uint32_t igt_drm_format_to_bpp(uint32_t drm_format); const char *igt_format_str(uint32_t drm_format); -void igt_get_all_cairo_formats(const uint32_t **formats, int *format_count); +bool igt_fb_supported_format(uint32_t drm_format); #endif /* __IGT_FB_H__ */ diff -Nru intel-gpu-tools-1.21/lib/igt_gt.c intel-gpu-tools-1.22/lib/igt_gt.c --- intel-gpu-tools-1.21/lib/igt_gt.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/igt_gt.c 2018-03-09 14:22:59.000000000 +0000 @@ -126,11 +126,10 @@ static unsigned context_get_ban(int fd, unsigned ctx) { - struct drm_i915_gem_context_param param; - - param.param = I915_CONTEXT_PARAM_BANNABLE; - param.value = 0; - param.size = 0; + struct drm_i915_gem_context_param param = { + .ctx_id = ctx, + .param = I915_CONTEXT_PARAM_BANNABLE, + }; if (__gem_context_get_param(fd, ¶m) == -EINVAL) { igt_assert(param.value == 0); @@ -143,13 +142,11 @@ static void context_set_ban(int fd, unsigned ctx, unsigned ban) { - struct drm_i915_gem_context_param param; - - memset(¶m, 0, sizeof(param)); - param.ctx_id = ctx; - param.value = ban; - param.size = 0; - param.param = I915_CONTEXT_PARAM_BANNABLE; + struct drm_i915_gem_context_param param = { + .ctx_id = ctx, + .param = I915_CONTEXT_PARAM_BANNABLE, + .value = ban, + }; if(__gem_context_set_param(fd, ¶m) == -EINVAL) { igt_assert(param.value == ban); @@ -160,7 +157,9 @@ igt_hang_t igt_allow_hang(int fd, unsigned ctx, unsigned flags) { - struct drm_i915_gem_context_param param; + struct drm_i915_gem_context_param param = { + .ctx_id = ctx, + }; unsigned ban; igt_assert(igt_sysfs_set_parameter @@ -172,9 +171,6 @@ if (!igt_check_boolean_env_var("IGT_HANG_WITHOUT_RESET", false)) igt_require(has_gpu_reset(fd)); - param.ctx_id = ctx; - param.size = 0; - if ((flags & HANG_ALLOW_CAPTURE) == 0) { param.param = I915_CONTEXT_PARAM_NO_ERROR_CAPTURE; param.value = 1; @@ -194,7 +190,6 @@ void igt_disallow_hang(int fd, igt_hang_t arg) { - context_set_ban(fd, arg.ctx, arg.ban); if ((arg.flags & HANG_ALLOW_CAPTURE) == 0) { @@ -276,6 +271,7 @@ uint32_t b[16]; unsigned ban; unsigned len; + int gen; igt_require_hang_ring(fd, ring); @@ -296,7 +292,6 @@ } ban = context_get_ban(fd, ctx); - if ((flags & HANG_ALLOW_BAN) == 0) context_set_ban(fd, ctx, 0); @@ -310,12 +305,26 @@ memset(b, 0xc5, sizeof(b)); - len = 2; - if (intel_gen(intel_get_drm_devid(fd)) >= 8) + len = 0; + gen = intel_gen(intel_get_drm_devid(fd)); + if (gen >= 8) { + b[len++] = MI_BATCH_BUFFER_START | 1 << 8 | 1; + b[len++] = 0; + b[len++] = 0; + } else if (gen >= 6) { + b[len++] = MI_BATCH_BUFFER_START | 1 << 8; + b[len++] = 0; + } else { + b[len++] = MI_BATCH_BUFFER_START | 2 << 6; + b[len] = 0; + if (gen < 4) { + b[len] |= 1; + reloc.delta = 1; + } len++; - b[0] = MI_BATCH_BUFFER_START | (len - 2); - b[len] = MI_BATCH_BUFFER_END; - b[len+1] = MI_NOOP; + } + b[len++] = MI_BATCH_BUFFER_END; + b[len] = MI_NOOP; gem_write(fd, exec.handle, 0, b, sizeof(b)); reloc.offset = sizeof(uint32_t); @@ -364,8 +373,7 @@ if (arg.handle == 0) return; - gem_set_domain(fd, arg.handle, - I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT); + gem_sync(fd, arg.handle); gem_close(fd, arg.handle); context_set_ban(fd, arg.ctx, arg.ban); @@ -402,6 +410,7 @@ igt_sysfs_scanf(dir, "i915_wedged", "%d", &wedged); close(dir); + errno = 0; igt_assert(!wedged); } @@ -659,3 +668,26 @@ gem_class_instance_to_eb_flags(gem_fd, class, instance)); } + +bool gem_ring_is_physical_engine(int fd, unsigned ring) +{ + if (ring == I915_EXEC_DEFAULT) + return false; + + /* BSD uses an extra flag to chose between aliasing modes */ + if ((ring & 63) == I915_EXEC_BSD) { + bool explicit_bsd = ring & (3 << 13); + bool has_bsd2 = gem_has_bsd2(fd); + return explicit_bsd ? has_bsd2 : !has_bsd2; + } + + return true; +} + +bool gem_ring_has_physical_engine(int fd, unsigned ring) +{ + if (!gem_ring_is_physical_engine(fd, ring)) + return false; + + return gem_has_ring(fd, ring); +} diff -Nru intel-gpu-tools-1.21/lib/igt_gt.h intel-gpu-tools-1.22/lib/igt_gt.h --- intel-gpu-tools-1.21/lib/igt_gt.h 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/igt_gt.h 2018-03-09 14:22:59.000000000 +0000 @@ -81,6 +81,15 @@ e__++) \ for_if (gem_has_ring(fd__, flags__ = e__->exec_id | e__->flags)) +#define for_each_physical_engine(fd__, flags__) \ + for (const struct intel_execution_engine *e__ = intel_execution_engines;\ + e__->name; \ + e__++) \ + for_if (gem_ring_has_physical_engine(fd__, flags__ = e__->exec_id | e__->flags)) + +bool gem_ring_is_physical_engine(int fd, unsigned int ring); +bool gem_ring_has_physical_engine(int fd, unsigned int ring); + bool gem_can_store_dword(int fd, unsigned int engine); extern const struct intel_execution_engine2 { diff -Nru intel-gpu-tools-1.21/lib/igt_kmod.c intel-gpu-tools-1.22/lib/igt_kmod.c --- intel-gpu-tools-1.21/lib/igt_kmod.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/igt_kmod.c 2018-03-09 14:22:59.000000000 +0000 @@ -294,7 +294,7 @@ return IGT_EXIT_FAILURE; } - kick_fbcon(true); + bind_fbcon(true); igt_kmod_load("snd_hda_intel", NULL); return IGT_EXIT_SUCCESS; @@ -310,7 +310,7 @@ igt_i915_driver_unload(void) { /* unbind vt */ - kick_fbcon(false); + bind_fbcon(false); if (igt_kmod_is_loaded("snd_hda_intel")) { igt_terminate_process(SIGTERM, "alsactl"); diff -Nru intel-gpu-tools-1.21/lib/igt_kms.c intel-gpu-tools-1.22/lib/igt_kms.c --- intel-gpu-tools-1.21/lib/igt_kms.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/igt_kms.c 2018-03-09 14:22:59.000000000 +0000 @@ -39,9 +39,8 @@ #elif HAVE_SYS_KD_H #include #endif -#ifdef HAVE_UDEV + #include -#endif #include #include #include @@ -361,9 +360,9 @@ /** * kmstest_plane_type_name: - * @plane: display plane + * @plane_type: display plane type * - * Returns: String representing @plane, e.g. "overlay". + * Returns: String representing @plane_type, e.g. "overlay". */ const char *kmstest_plane_type_name(int plane_type) { @@ -618,6 +617,14 @@ return create.handle; } +/** + * kmstest_dumb_map_buffer: + * @fd: Opened drm file descriptor + * @handle: Offset in the file referred to by fd + * @size: Length of the mapping, must be greater than 0 + * @prot: Describes the memory protection of the mapping + * Returns: A pointer representing the start of the virtual mapping + */ void *kmstest_dumb_map_buffer(int fd, uint32_t handle, uint64_t size, unsigned prot) { @@ -1108,11 +1115,10 @@ bool found_it = false; for (i = 0; i < connector->count_props; i++) { - struct drm_mode_get_property prop; + struct drm_mode_get_property prop = { + .prop_id = connector->props[i], + }; - prop.prop_id = connector->props[i]; - prop.count_values = 0; - prop.count_enum_blobs = 0; if (drmIoctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop)) continue; @@ -1426,6 +1432,16 @@ return 0; } +/** + * kmstest_get_vblank: + * @fd: Opened drm file descriptor + * @pipe: Display pipe + * @flags: Flags passed to drm_ioctl_wait_vblank + * + * Blocks or request a signal when a specified vblank event occurs + * + * Returns 0 on success or non-zero unsigned integer otherwise + */ unsigned int kmstest_get_vblank(int fd, int pipe, unsigned int flags) { union drm_wait_vblank vbl; @@ -1553,6 +1569,14 @@ igt_assert(ncrtc == 1); } +/** + * igt_assert_plane_visible: + * @fd: Opened file descriptor + * @pipe: Display pipe + * @visibility: Boolean parameter to test against the plane's current visibility state + * + * Asserts only if the plane's visibility state matches the status being passed by @visibility + */ void igt_assert_plane_visible(int fd, enum pipe pipe, bool visibility) { struct kmstest_crtc crtc; @@ -1936,11 +1960,24 @@ LOG_UNINDENT(display); } +/** + * igt_display_get_n_pipes: + * @display: A pointer to an #igt_display_t structure + * + * Returns total number of pipes for the given @display + */ int igt_display_get_n_pipes(igt_display_t *display) { return display->n_pipes; } +/** + * igt_display_require_output: + * @display: A pointer to an #igt_display_t structure + * + * Checks whether there's a valid @pipe/@output combination for the given @display + * Skips test if a valid combination of @pipe and @output is not found + */ void igt_display_require_output(igt_display_t *display) { enum pipe pipe; @@ -1952,6 +1989,14 @@ igt_skip("No valid crtc/connector combinations found.\n"); } +/** + * igt_display_require_output_on_pipe: + * @display: A pointer to an #igt_display_t structure + * @pipe: Display pipe + * + * Checks whether there's a valid @pipe/@output combination for the given @display and @pipe + * Skips test if a valid @pipe is not found + */ void igt_display_require_output_on_pipe(igt_display_t *display, enum pipe pipe) { igt_output_t *output; @@ -2112,7 +2157,16 @@ return &pipe->planes[plane_idx]; } - +/** + * igt_pipe_get_plane_type: + * @pipe: Target pipe + * @plane_type: Cursor, primary or an overlay plane + * + * Finds a valid plane type for the given @pipe otherwise + * it skips the test if the right combination of @pipe/@plane_type is not found + * + * Returns: A #igt_plane_t structure that matches the requested plane type + */ igt_plane_t *igt_pipe_get_plane_type(igt_pipe_t *pipe, int plane_type) { int i, plane_idx = -1; @@ -2622,11 +2676,12 @@ } /** - * igt_plane_get_prop - Return current value on a plane for a given property. - * + * igt_plane_get_prop: * @plane: Target plane. * @prop: Property to check. * + * Return current value on a plane for a given property. + * * Returns: The value the property is set to, if this * is a blob, the blob id is returned. This can be passed * to drmModeGetPropertyBlob() to get the contents of the blob. @@ -2672,11 +2727,12 @@ } /** - * igt_output_get_prop - Return current value on an output for a given property. - * + * igt_output_get_prop: * @output: Target output. * @prop: Property to return. * + * Return current value on an output for a given property. + * * Returns: The value the property is set to, if this * is a blob, the blob id is returned. This can be passed * to drmModeGetPropertyBlob() to get the contents of the blob. @@ -2722,11 +2778,12 @@ } /** - * igt_pipe_obj_get_prop - Return current value on a pipe for a given property. - * + * igt_pipe_obj_get_prop: * @pipe: Target pipe. * @prop: Property to return. * + * Return current value on a pipe for a given property. + * * Returns: The value the property is set to, if this * is a blob, the blob id is returned. This can be passed * to drmModeGetPropertyBlob() to get the contents of the blob. @@ -3153,24 +3210,44 @@ }; while (poll(&pfd, 1, 0) > 0) { - struct drm_event ev; - char buf[128]; - - read(display->drm_fd, &ev, sizeof(ev)); - igt_info("Dropping event type %u length %u\n", ev.type, ev.length); - igt_assert(ev.length <= sizeof(buf)); - read(display->drm_fd, buf, ev.length); - ret++; + struct drm_event *ev; + char buf[4096]; + ssize_t retval; + + retval = read(display->drm_fd, &buf, sizeof(buf)); + igt_assert_lt(0, retval); + + for (int i = 0; i < retval; i += ev->length) { + ev = (struct drm_event *)&buf[i]; + + igt_info("Dropping event type %u length %u\n", ev->type, ev->length); + igt_assert(ev->length + i <= sizeof(buf)); + ret++; + } } return ret; } +/** + * igt_output_name: + * @output: Target output + * + * Returns: String representing a connector's name, e.g. "DP-1". + */ const char *igt_output_name(igt_output_t *output) { return output->name; } +/** + * igt_output_get_mode: + * @output: Target output + * + * Get the current mode of the given connector + * + * Returns: A #drmModeModeInfo struct representing the current mode + */ drmModeModeInfo *igt_output_get_mode(igt_output_t *output) { if (output->use_override_mode) @@ -3205,6 +3282,15 @@ } } +/* + * igt_output_set_pipe: + * @output: Target output for which the pipe is being set to + * @pipe: Display pipe to set to + * + * This function sets a @pipe to a specific @output connector by + * setting the CRTC_ID property of the @pipe. The pipe + * is only activated for all pipes except PIPE_NONE. + */ void igt_output_set_pipe(igt_output_t *output, enum pipe pipe) { igt_display_t *display = output->display; @@ -3286,6 +3372,16 @@ return igt_pipe_get_plane(pipe, plane_idx); } +/** + * igt_output_get_plane_type: + * @output: Target output + * @plane_type: Cursor, primary or an overlay plane + * + * Finds a valid plane type for the given @output otherwise + * the test is skipped if the right combination of @output/@plane_type is not found + * + * Returns: A #igt_plane_t structure that matches the requested plane type + */ igt_plane_t *igt_output_get_plane_type(igt_output_t *output, int plane_type) { igt_pipe_t *pipe; @@ -3296,6 +3392,16 @@ return igt_pipe_get_plane_type(pipe, plane_type); } +/** + * igt_plane_set_fb: + * @plane: Plane + * @fb: Framebuffer pointer + * + * Pairs a given @framebuffer to a @plane + * + * This function also sets a default size and position for the framebuffer + * to avoid crashes on applications that ignore to set these. + */ void igt_plane_set_fb(igt_plane_t *plane, struct igt_fb *fb) { igt_pipe_t *pipe = plane->pipe; @@ -3354,6 +3460,15 @@ igt_plane_set_prop_value(plane, IGT_PLANE_IN_FENCE_FD, fd); } +/** + * igt_plane_set_position: + * @plane: Plane pointer for which position is to be set + * @x: X coordinate + * @y: Y coordinate + * + * This function sets a new (x,y) position for the given plane. + * New position will be committed at plane commit time via drmModeSetPlane(). + */ void igt_plane_set_position(igt_plane_t *plane, int x, int y) { igt_pipe_t *pipe = plane->pipe; @@ -3451,6 +3566,15 @@ } } +/** + * igt_plane_set_rotation: + * @plane: Plane pointer for which rotation is to be set + * @rotation: Plane rotation value (0, 90, 180, 270) + * + * This function sets a new rotation for the requested @plane. + * New @rotation will be committed at plane commit time via + * drmModeSetPlane(). + */ void igt_plane_set_rotation(igt_plane_t *plane, igt_rotation_t rotation) { igt_pipe_t *pipe = plane->pipe; @@ -3475,6 +3599,14 @@ igt_pipe_obj_set_prop_value(pipe, IGT_CRTC_OUT_FENCE_PTR, (ptrdiff_t)&pipe->out_fence_fd); } +/** + * igt_wait_for_vblank_count: + * @drm_fd: A drm file descriptor + * @pipe: Pipe to wait_for_vblank on + * @count: Number of vblanks to wait on + * + * Waits for a given number of vertical blank intervals + */ void igt_wait_for_vblank_count(int drm_fd, enum pipe pipe, int count) { drmVBlank wait_vbl; @@ -3490,6 +3622,13 @@ igt_assert(drmWaitVBlank(drm_fd, &wait_vbl) == 0); } +/** + * igt_wait_for_vblank: + * @drm_fd: A drm file descriptor + * @pipe: Pipe to wait_for_vblank on + * + * Waits for 1 vertical blank intervals + */ void igt_wait_for_vblank(int drm_fd, enum pipe pipe) { igt_wait_for_vblank_count(drm_fd, pipe, 1); @@ -3558,8 +3697,6 @@ "detect"); } -#ifdef HAVE_UDEV - /** * igt_watch_hotplug: * @@ -3652,6 +3789,7 @@ /** * igt_cleanup_hotplug: + * @mon: A udev monitor initialized with #igt_watch_hotplug * * Cleanup the resources allocated by #igt_watch_hotplug */ @@ -3663,7 +3801,6 @@ mon = NULL; udev_unref(udev); } -#endif /** * kmstest_get_vbl_flag: diff -Nru intel-gpu-tools-1.21/lib/igt_kms.h intel-gpu-tools-1.22/lib/igt_kms.h --- intel-gpu-tools-1.21/lib/igt_kms.h 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/igt_kms.h 2018-03-09 14:22:59.000000000 +0000 @@ -47,7 +47,9 @@ * @PIPE_A: First crtc. * @PIPE_B: Second crtc. * @PIPE_C: Third crtc. - * ... and so on. + * @PIPE_D: Fourth crtc. + * @PIPE_E: Fifth crtc. + * @PIPE_F: Sixth crtc. * @IGT_MAX_PIPES: Max number of pipes allowed. */ enum pipe { @@ -495,11 +497,12 @@ #define IGT_FIXED(i,f) ((i) << 16 | (f)) /** - * igt_plane_has_prop - Check whether plane supports a given property. - * + * igt_plane_has_prop: * @plane: Plane to check. * @prop: Property to check. * + * Check whether plane supports a given property. + * * Returns: True if the property is supported, otherwise false. */ static inline bool @@ -530,11 +533,12 @@ const void *ptr, size_t length); /** - * igt_output_has_prop - Check whether output supports a given property. - * + * igt_output_has_prop: * @output: Output to check. * @prop: Property to check. * + * Check whether output supports a given property. + * * Returns: True if the property is supported, otherwise false. */ static inline bool @@ -564,11 +568,12 @@ const void *ptr, size_t length); /** - * igt_pipe_obj_has_prop - Check whether pipe supports a given property. - * + * igt_pipe_obj_has_prop: * @pipe: Pipe to check. * @prop: Property to check. * + * Check whether pipe supports a given property. + * * Returns: True if the property is supported, otherwise false. */ static inline bool @@ -580,12 +585,13 @@ uint64_t igt_pipe_obj_get_prop(igt_pipe_t *pipe, enum igt_atomic_crtc_properties prop); /** - * igt_pipe_get_prop - Return current value on a pipe for a given property. - * + * igt_pipe_get_prop: * @display: Pointer to display. * @pipe: Target pipe. * @prop: Property to return. * + * Return current value on a pipe for a given property. + * * Returns: The value the property is set to, if this * is a blob, the blob id is returned. This can be passed * to drmModeGetPropertyBlob() to get the contents of the blob. @@ -598,12 +604,13 @@ } /** - * igt_pipe_has_prop - Check whether pipe supports a given property. - * + * igt_pipe_has_prop: * @display: Pointer to display. * @pipe: Pipe to check. * @prop: Property to check. * + * Check whether pipe supports a given property. + * * Returns: True if the property is supported, otherwise false. */ static inline bool @@ -640,7 +647,7 @@ #define igt_pipe_set_prop_value(display, pipe, prop, value) \ igt_pipe_obj_set_prop_value(&(display)->pipes[(pipe)], prop, value) -extern void igt_pipe_obj_replace_prop_blob(igt_pipe_t *pipe_obj, +extern void igt_pipe_obj_replace_prop_blob(igt_pipe_t *pipe, enum igt_atomic_crtc_properties prop, const void *ptr, size_t length); @@ -658,12 +665,10 @@ const unsigned char* igt_kms_get_base_edid(void); const unsigned char* igt_kms_get_alt_edid(void); -#ifdef HAVE_UDEV struct udev_monitor *igt_watch_hotplug(void); bool igt_hotplug_detected(struct udev_monitor *mon, int timeout_secs); void igt_flush_hotplugs(struct udev_monitor *mon); void igt_cleanup_hotplug(struct udev_monitor *mon); -#endif #endif /* __IGT_KMS_H__ */ diff -Nru intel-gpu-tools-1.21/lib/igt_perf.c intel-gpu-tools-1.22/lib/igt_perf.c --- intel-gpu-tools-1.21/lib/igt_perf.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/igt_perf.c 2018-03-09 14:22:59.000000000 +0000 @@ -4,6 +4,7 @@ #include #include #include +#include #include "igt_perf.h" @@ -31,6 +32,8 @@ _perf_open(uint64_t type, uint64_t config, int group, uint64_t format) { struct perf_event_attr attr = { }; + int nr_cpus = get_nprocs_conf(); + int cpu = 0, ret; attr.type = type; if (attr.type == 0) @@ -42,7 +45,11 @@ attr.read_format = format; attr.config = config; - return perf_event_open(&attr, -1, 0, group, 0); + do { + ret = perf_event_open(&attr, -1, cpu++, group, 0); + } while ((ret < 0 && errno == EINVAL) && (cpu < nr_cpus)); + + return ret; } int perf_i915_open(uint64_t config) diff -Nru intel-gpu-tools-1.21/lib/igt_pm.c intel-gpu-tools-1.22/lib/igt_pm.c --- intel-gpu-tools-1.21/lib/igt_pm.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/igt_pm.c 2018-03-09 14:22:59.000000000 +0000 @@ -63,6 +63,46 @@ /* Remember to fix this if adding longer strings */ #define MAX_POLICY_STRLEN strlen(MAX_PERFORMANCE_STR) +static char __igt_pm_audio_runtime_power_save[64]; +static char __igt_pm_audio_runtime_control[64]; + +static void __igt_pm_audio_runtime_exit_handler(int sig) +{ + int fd; + + igt_debug("Restoring audio power management to '%s' and '%s'\n", + __igt_pm_audio_runtime_power_save, + __igt_pm_audio_runtime_control); + + fd = open("/sys/module/snd_hda_intel/parameters/power_save", O_WRONLY); + if (fd < 0) + return; + if (write(fd, __igt_pm_audio_runtime_power_save, + strlen(__igt_pm_audio_runtime_power_save)) != + strlen(__igt_pm_audio_runtime_power_save)) + igt_warn("Failed to restore audio power_save to '%s'\n", + __igt_pm_audio_runtime_power_save); + close(fd); + + fd = open("/sys/bus/pci/devices/0000:00:03.0/power/control", O_WRONLY); + if (fd < 0) + return; + if (write(fd, __igt_pm_audio_runtime_control, + strlen(__igt_pm_audio_runtime_control)) != + strlen(__igt_pm_audio_runtime_control)) + igt_warn("Failed to restore audio control to '%s'\n", + __igt_pm_audio_runtime_control); + close(fd); +} + +static void strchomp(char *str) +{ + int len = strlen(str); + + if (len && str[len - 1] == '\n') + str[len - 1] = 0; +} + /** * igt_pm_enable_audio_runtime_pm: * @@ -78,16 +118,32 @@ { int fd; - fd = open("/sys/module/snd_hda_intel/parameters/power_save", O_WRONLY); + /* Check if already enabled. */ + if (__igt_pm_audio_runtime_power_save[0]) + return; + + fd = open("/sys/module/snd_hda_intel/parameters/power_save", O_RDWR); if (fd >= 0) { + igt_assert(read(fd, __igt_pm_audio_runtime_power_save, + sizeof(__igt_pm_audio_runtime_power_save)) > 0); + strchomp(__igt_pm_audio_runtime_power_save); + igt_install_exit_handler(__igt_pm_audio_runtime_exit_handler); igt_assert_eq(write(fd, "1\n", 2), 2); close(fd); } - fd = open("/sys/bus/pci/devices/0000:00:03.0/power/control", O_WRONLY); + fd = open("/sys/bus/pci/devices/0000:00:03.0/power/control", O_RDWR); if (fd >= 0) { + igt_assert(read(fd, __igt_pm_audio_runtime_control, + sizeof(__igt_pm_audio_runtime_control)) > 0); + strchomp(__igt_pm_audio_runtime_control); igt_assert_eq(write(fd, "auto\n", 5), 5); close(fd); } + + igt_debug("Saved audio power management as '%s' and '%s'\n", + __igt_pm_audio_runtime_power_save, + __igt_pm_audio_runtime_control); + /* Give some time for it to react. */ sleep(1); } @@ -238,6 +294,38 @@ /* We just leak this on exit ... */ int pm_status_fd = -1; +static char __igt_pm_runtime_autosuspend[64]; +static char __igt_pm_runtime_control[64]; + +static void __igt_pm_runtime_exit_handler(int sig) +{ + int fd; + + igt_debug("Restoring runtime management to '%s' and '%s'\n", + __igt_pm_runtime_autosuspend, + __igt_pm_runtime_control); + + fd = open(POWER_DIR "/autosuspend_delay_ms", O_WRONLY); + if (fd < 0) + return; + if (write(fd, __igt_pm_runtime_autosuspend, + strlen(__igt_pm_runtime_autosuspend)) != + strlen(__igt_pm_runtime_autosuspend)) + igt_warn("Failed to restore runtime pm autosuspend delay to '%s'\n", + __igt_pm_runtime_autosuspend); + close(fd); + + fd = open(POWER_DIR "/control", O_WRONLY); + if (fd < 0) + return; + if (write(fd, __igt_pm_runtime_control, + strlen(__igt_pm_runtime_control)) != + strlen(__igt_pm_runtime_control)) + igt_warn("Failed to restore runtime pm control to '%s'\n", + __igt_pm_runtime_control); + close(fd); +} + /** * igt_setup_runtime_pm: * @@ -261,12 +349,29 @@ /* Our implementation uses autosuspend. Try to set it to 0ms so the test * suite goes faster and we have a higher probability of triggering race * conditions. */ - fd = open(POWER_DIR "/autosuspend_delay_ms", O_WRONLY); + fd = open(POWER_DIR "/autosuspend_delay_ms", O_RDWR); igt_assert_f(fd >= 0, "Can't open " POWER_DIR "/autosuspend_delay_ms\n"); - /* If we fail to write to the file, it means this system doesn't support - * runtime PM. */ + /* + * Save previous values to be able to install exit handler to restore + * them on test exit. + */ + size = read(fd, __igt_pm_runtime_autosuspend, + sizeof(__igt_pm_runtime_autosuspend)); + + /* + * If we fail to read from the file, it means this system doesn't + * support runtime PM. + */ + if (size <= 0) { + close(fd); + return false; + } + + strchomp(__igt_pm_runtime_autosuspend); + igt_install_exit_handler(__igt_pm_runtime_exit_handler); + size = write(fd, "0\n", 2); close(fd); @@ -278,6 +383,13 @@ fd = open(POWER_DIR "/control", O_RDWR); igt_assert_f(fd >= 0, "Can't open " POWER_DIR "/control\n"); + igt_assert(read(fd, __igt_pm_runtime_control, + sizeof(__igt_pm_runtime_control)) > 0); + strchomp(__igt_pm_runtime_control); + + igt_debug("Saved runtime power management as '%s' and '%s'\n", + __igt_pm_runtime_autosuspend, __igt_pm_runtime_control); + size = write(fd, "auto\n", 5); igt_assert(size == 5); diff -Nru intel-gpu-tools-1.21/lib/igt_sysfs.c intel-gpu-tools-1.22/lib/igt_sysfs.c --- intel-gpu-tools-1.21/lib/igt_sysfs.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/igt_sysfs.c 2018-03-09 14:22:59.000000000 +0000 @@ -503,14 +503,7 @@ return igt_sysfs_printf(dir, attr, "%d", value) == 1; } -/** - * kick_fbcon: - * @enable: boolean value - * - * This functions enables/disables the text console running on top of the - * framebuffer device. - */ -void kick_fbcon(bool enable) +static void bind_con(const char *name, bool enable) { const char *path = "/sys/class/vtconsole"; DIR *dir; @@ -538,21 +531,40 @@ if (len >= 0) buf[len] = '\0'; - if (!strstr(buf, enable ? "dummy device" : - "frame buffer device")) + if (!strstr(buf, name)) continue; sprintf(buf, "%s/%s/bind", path, de->d_name); fd = open(buf, O_WRONLY); if (fd != -1) { - igt_ignore_warn(write(fd, "0\n", 2)); + igt_ignore_warn(write(fd, enable ? "1\n" : "0\n", 2)); close(fd); } + break; } closedir(dir); } /** + * bind_fbcon: + * @enable: boolean value + * + * This functions enables/disables the text console running on top of the + * framebuffer device. + */ +void bind_fbcon(bool enable) +{ + /* + * The vtcon bind interface seems somewhat broken. Possibly + * depending on the order the console drivers have been + * registered you either have to unbind the old driver, + * or bind the new driver. Let's do both. + */ + bind_con("dummy device", !enable); + bind_con("frame buffer device", enable); +} + +/** * kick_snd_hda_intel: * * This functions unbinds the snd_hda_intel driver so the module cand be diff -Nru intel-gpu-tools-1.21/lib/igt_sysfs.h intel-gpu-tools-1.22/lib/igt_sysfs.h --- intel-gpu-tools-1.21/lib/igt_sysfs.h 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/igt_sysfs.h 2018-03-09 14:22:59.000000000 +0000 @@ -55,7 +55,7 @@ bool igt_sysfs_get_boolean(int dir, const char *attr); bool igt_sysfs_set_boolean(int dir, const char *attr, bool value); -void kick_fbcon(bool enable); +void bind_fbcon(bool enable); void kick_snd_hda_intel(void); #endif /* __IGT_SYSFS_H__ */ diff -Nru intel-gpu-tools-1.21/lib/igt_sysrq.c intel-gpu-tools-1.22/lib/igt_sysrq.c --- intel-gpu-tools-1.21/lib/igt_sysrq.c 1970-01-01 00:00:00.000000000 +0000 +++ intel-gpu-tools-1.22/lib/igt_sysrq.c 2018-03-09 14:22:59.000000000 +0000 @@ -0,0 +1,27 @@ +#include +#include +#include +#include + +#include "igt_core.h" + +#include "igt_sysrq.h" + +/** + * igt_sysrq_reboot: Reboots the machine + * + * Syncs filesystems and immediately reboots the machine. + */ +void igt_sysrq_reboot(void) +{ + sync(); + + /* Try to be nice at first, and if that fails pull the trigger */ + if (reboot(RB_AUTOBOOT)) { + int fd = open("/proc/sysrq-trigger", O_WRONLY); + igt_ignore_warn(write(fd, "b", 2)); + close(fd); + } + + abort(); +} diff -Nru intel-gpu-tools-1.21/lib/igt_sysrq.h intel-gpu-tools-1.22/lib/igt_sysrq.h --- intel-gpu-tools-1.21/lib/igt_sysrq.h 1970-01-01 00:00:00.000000000 +0000 +++ intel-gpu-tools-1.22/lib/igt_sysrq.h 2018-03-09 14:22:59.000000000 +0000 @@ -0,0 +1,30 @@ +/* + * Copyright © 2018 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. + * + */ + +#ifndef __IGT_SYSRQ_H__ +#define __IGT_SYSRQ_H__ + +void igt_sysrq_reboot(void) __attribute__((noreturn)); + +#endif /* __IGT_SYSRQ_H__ */ diff -Nru intel-gpu-tools-1.21/lib/igt_vc4.c intel-gpu-tools-1.22/lib/igt_vc4.c --- intel-gpu-tools-1.21/lib/igt_vc4.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/igt_vc4.c 2018-03-09 14:22:59.000000000 +0000 @@ -149,3 +149,30 @@ return get.modifier; } + +int igt_vc4_get_param(int fd, uint32_t param, uint64_t *val) +{ + struct drm_vc4_get_param arg = { + .param = param, + }; + int ret; + + ret = igt_ioctl(fd, DRM_IOCTL_VC4_GET_PARAM, &arg); + if (ret) + return ret; + + *val = arg.value; + return 0; +} + +bool igt_vc4_purgeable_bo(int fd, int handle, bool purgeable) +{ + struct drm_vc4_gem_madvise arg = { + .handle = handle, + .madv = purgeable ? VC4_MADV_DONTNEED : VC4_MADV_WILLNEED, + }; + + do_ioctl(fd, DRM_IOCTL_VC4_GEM_MADVISE, &arg); + + return arg.retained; +} diff -Nru intel-gpu-tools-1.21/lib/igt_vc4.h intel-gpu-tools-1.22/lib/igt_vc4.h --- intel-gpu-tools-1.21/lib/igt_vc4.h 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/igt_vc4.h 2018-03-09 14:22:59.000000000 +0000 @@ -27,6 +27,8 @@ uint32_t igt_vc4_get_cleared_bo(int fd, size_t size, uint32_t clearval); int igt_vc4_create_bo(int fd, size_t size); void *igt_vc4_mmap_bo(int fd, uint32_t handle, uint32_t size, unsigned prot); +int igt_vc4_get_param(int fd, uint32_t param, uint64_t *val); +bool igt_vc4_purgeable_bo(int fd, int handle, bool purgeable); void igt_vc4_set_tiling(int fd, uint32_t handle, uint64_t modifier); uint64_t igt_vc4_get_tiling(int fd, uint32_t handle); diff -Nru intel-gpu-tools-1.21/lib/igt_x86.c intel-gpu-tools-1.22/lib/igt_x86.c --- intel-gpu-tools-1.21/lib/igt_x86.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/igt_x86.c 2018-03-09 14:22:59.000000000 +0000 @@ -36,7 +36,11 @@ #endif #include "igt_x86.h" +#include "igt_aux.h" + +#include #include +#include /** * SECTION:igt_x86 @@ -174,3 +178,115 @@ return ret; } #endif + +#if defined(__x86_64__) && !defined(__clang__) +#pragma GCC push_options +#pragma GCC target("sse4.1") +#pragma GCC diagnostic ignored "-Wpointer-arith" + +#include +static void memcpy_from_wc_sse41(void *dst, const void *src, unsigned long len) +{ + char buf[16]; + + /* Flush the internal buffer of potential stale gfx data */ + _mm_mfence(); + + if ((uintptr_t)src & 15) { + __m128i *S = (__m128i *)((uintptr_t)src & ~15); + unsigned long misalign = (uintptr_t)src & 15; + unsigned long copy = min(len, 16 - misalign); + + _mm_storeu_si128((__m128i *)buf, + _mm_stream_load_si128(S)); + + memcpy(dst, buf + misalign, copy); + + dst += copy; + src += copy; + len -= copy; + } + + /* We assume we are doing bulk transfers, so prefer aligned moves */ + if (((uintptr_t)dst & 15) == 0) { + while (len >= 64) { + __m128i *S = (__m128i *)src; + __m128i *D = (__m128i *)dst; + __m128i tmp[4]; + + tmp[0] = _mm_stream_load_si128(S + 0); + tmp[1] = _mm_stream_load_si128(S + 1); + tmp[2] = _mm_stream_load_si128(S + 2); + tmp[3] = _mm_stream_load_si128(S + 3); + + _mm_store_si128(D + 0, tmp[0]); + _mm_store_si128(D + 1, tmp[1]); + _mm_store_si128(D + 2, tmp[2]); + _mm_store_si128(D + 3, tmp[3]); + + src += 64; + dst += 64; + len -= 64; + } + } else { + while (len >= 64) { + __m128i *S = (__m128i *)src; + __m128i *D = (__m128i *)dst; + __m128i tmp[4]; + + tmp[0] = _mm_stream_load_si128(S + 0); + tmp[1] = _mm_stream_load_si128(S + 1); + tmp[2] = _mm_stream_load_si128(S + 2); + tmp[3] = _mm_stream_load_si128(S + 3); + + _mm_storeu_si128(D + 0, tmp[0]); + _mm_storeu_si128(D + 1, tmp[1]); + _mm_storeu_si128(D + 2, tmp[2]); + _mm_storeu_si128(D + 3, tmp[3]); + + src += 64; + dst += 64; + len -= 64; + } + } + + while (len >= 16) { + _mm_storeu_si128((__m128i *)dst, + _mm_stream_load_si128((__m128i *)src)); + + src += 16; + dst += 16; + len -= 16; + } + + if (len) { + _mm_storeu_si128((__m128i *)buf, + _mm_stream_load_si128((__m128i *)src)); + memcpy(dst, buf, len); + } +} + +#pragma GCC pop_options + +static void memcpy_from_wc(void *dst, const void *src, unsigned long len) +{ + memcpy(dst, src, len); +} + +static void (*resolve_memcpy_from_wc(void))(void *, const void *, unsigned long) +{ + if (igt_x86_features() & SSE4_1) + return memcpy_from_wc_sse41; + + return memcpy_from_wc; +} + +void igt_memcpy_from_wc(void *dst, const void *src, unsigned long len) + __attribute__((ifunc("resolve_memcpy_from_wc"))); + +#else +void igt_memcpy_from_wc(void *dst, const void *src, unsigned long len) +{ + memcpy(dst, src, len); +} +#endif diff -Nru intel-gpu-tools-1.21/lib/igt_x86.h intel-gpu-tools-1.22/lib/igt_x86.h --- intel-gpu-tools-1.21/lib/igt_x86.h 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/igt_x86.h 2018-03-09 14:22:59.000000000 +0000 @@ -55,4 +55,6 @@ } #endif +void igt_memcpy_from_wc(void *dst, const void *src, unsigned long len); + #endif /* IGT_X86_H */ diff -Nru intel-gpu-tools-1.21/lib/intel_batchbuffer.c intel-gpu-tools-1.22/lib/intel_batchbuffer.c --- intel-gpu-tools-1.21/lib/intel_batchbuffer.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/intel_batchbuffer.c 2018-03-09 14:22:59.000000000 +0000 @@ -554,11 +554,12 @@ static void fill_relocation(struct drm_i915_gem_relocation_entry *reloc, - uint32_t gem_handle, uint32_t offset, /* in dwords */ + uint32_t gem_handle, uint32_t delta, /* in bytes */ + uint32_t offset, /* in dwords */ uint32_t read_domains, uint32_t write_domains) { reloc->target_handle = gem_handle; - reloc->delta = 0; + reloc->delta = delta; reloc->offset = offset * sizeof(uint32_t); reloc->presumed_offset = 0; reloc->read_domains = read_domains; @@ -599,6 +600,7 @@ * igt_blitter_fast_copy__raw: * @fd: file descriptor of the i915 driver * @src_handle: GEM handle of the source buffer + * @src_delta: offset into the source GEM bo, in bytes * @src_stride: Stride (in bytes) of the source buffer * @src_tiling: Tiling mode of the source buffer * @src_x: X coordinate of the source region to copy @@ -606,7 +608,8 @@ * @width: Width of the region to copy * @height: Height of the region to copy * @bpp: source and destination bits per pixel - * @dst_handle: GEM handle of the source buffer + * @dst_handle: GEM handle of the destination buffer + * @dst_delta: offset into the destination GEM bo, in bytes * @dst_stride: Stride (in bytes) of the destination buffer * @dst_tiling: Tiling mode of the destination buffer * @dst_x: X coordinate of destination @@ -617,6 +620,7 @@ void igt_blitter_fast_copy__raw(int fd, /* src */ uint32_t src_handle, + unsigned int src_delta, unsigned int src_stride, unsigned int src_tiling, unsigned int src_x, unsigned src_y, @@ -629,6 +633,7 @@ /* dst */ uint32_t dst_handle, + unsigned dst_delta, unsigned int dst_stride, unsigned int dst_tiling, unsigned int dst_x, unsigned dst_y) @@ -659,11 +664,11 @@ batch[i++] = dword1 | dst_pitch; batch[i++] = (dst_y << 16) | dst_x; /* dst x1,y1 */ batch[i++] = ((dst_y + height) << 16) | (dst_x + width); /* dst x2,y2 */ - batch[i++] = 0; /* dst address lower bits */ + batch[i++] = dst_delta; /* dst address lower bits */ batch[i++] = 0; /* dst address upper bits */ batch[i++] = (src_y << 16) | src_x; /* src x1,y1 */ batch[i++] = src_pitch; - batch[i++] = 0; /* src address lower bits */ + batch[i++] = src_delta; /* src address lower bits */ batch[i++] = 0; /* src address upper bits */ batch[i++] = MI_BATCH_BUFFER_END; batch[i++] = MI_NOOP; @@ -673,9 +678,9 @@ batch_handle = gem_create(fd, 4096); gem_write(fd, batch_handle, 0, batch, sizeof(batch)); - fill_relocation(&relocs[0], dst_handle, 4, + fill_relocation(&relocs[0], dst_handle, dst_delta, 4, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER); - fill_relocation(&relocs[1], src_handle, 8, I915_GEM_DOMAIN_RENDER, 0); + fill_relocation(&relocs[1], src_handle, src_delta, 8, I915_GEM_DOMAIN_RENDER, 0); fill_object(&objs[0], dst_handle, NULL, 0); fill_object(&objs[1], src_handle, NULL, 0); @@ -690,12 +695,14 @@ * igt_blitter_fast_copy: * @batch: batchbuffer object * @src: source i-g-t buffer object + * @src_delta: offset into the source i-g-t bo * @src_x: source pixel x-coordination * @src_y: source pixel y-coordination * @width: width of the copied rectangle * @height: height of the copied rectangle * @bpp: source and destination bits per pixel * @dst: destination i-g-t buffer object + * @dst_delta: offset into the destination i-g-t bo * @dst_x: destination pixel x-coordination * @dst_y: destination pixel y-coordination * @@ -704,10 +711,12 @@ * The source and destination surfaces cannot overlap. */ void igt_blitter_fast_copy(struct intel_batchbuffer *batch, - struct igt_buf *src, unsigned src_x, unsigned src_y, + struct igt_buf *src, unsigned src_delta, + unsigned src_x, unsigned src_y, unsigned width, unsigned height, int bpp, - struct igt_buf *dst, unsigned dst_x, unsigned dst_y) + struct igt_buf *dst, unsigned dst_delta, + unsigned dst_x, unsigned dst_y) { uint32_t src_pitch, dst_pitch; uint32_t dword0, dword1; @@ -731,11 +740,11 @@ OUT_BATCH(dword1 | dst_pitch); OUT_BATCH((dst_y << 16) | dst_x); /* dst x1,y1 */ OUT_BATCH(((dst_y + height) << 16) | (dst_x + width)); /* dst x2,y2 */ - OUT_RELOC(dst->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); + OUT_RELOC(dst->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, dst_delta); OUT_BATCH(0); /* dst address upper bits */ OUT_BATCH((src_y << 16) | src_x); /* src x1,y1 */ OUT_BATCH(src_pitch); - OUT_RELOC(src->bo, I915_GEM_DOMAIN_RENDER, 0, 0); + OUT_RELOC(src->bo, I915_GEM_DOMAIN_RENDER, 0, src_delta); OUT_BATCH(0); /* src address upper bits */ ADVANCE_BATCH(); diff -Nru intel-gpu-tools-1.21/lib/intel_batchbuffer.h intel-gpu-tools-1.22/lib/intel_batchbuffer.h --- intel-gpu-tools-1.21/lib/intel_batchbuffer.h 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/intel_batchbuffer.h 2018-03-09 14:22:59.000000000 +0000 @@ -226,14 +226,17 @@ unsigned igt_buf_height(struct igt_buf *buf); void igt_blitter_fast_copy(struct intel_batchbuffer *batch, - struct igt_buf *src, unsigned src_x, unsigned src_y, - unsigned width, unsigned height, - int bpp, - struct igt_buf *dst, unsigned dst_x, unsigned dst_y); + struct igt_buf *src, unsigned src_delta, + unsigned src_x, unsigned src_y, + unsigned width, unsigned height, + int bpp, + struct igt_buf *dst, unsigned dst_delta, + unsigned dst_x, unsigned dst_y); void igt_blitter_fast_copy__raw(int fd, /* src */ uint32_t src_handle, + unsigned int src_delta, unsigned int src_stride, unsigned int src_tiling, unsigned int src_x, unsigned src_y, @@ -246,6 +249,7 @@ /* dst */ uint32_t dst_handle, + unsigned int dst_delta, unsigned int dst_stride, unsigned int dst_tiling, unsigned int dst_x, unsigned dst_y); diff -Nru intel-gpu-tools-1.21/lib/ioctl_wrappers.c intel-gpu-tools-1.22/lib/ioctl_wrappers.c --- intel-gpu-tools-1.21/lib/ioctl_wrappers.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/ioctl_wrappers.c 2018-03-09 14:22:59.000000000 +0000 @@ -208,10 +208,10 @@ arg.caching = caching; err = 0; - if (igt_ioctl(fd, DRM_IOCTL_I915_GEM_SET_CACHING, &arg)) { + if (igt_ioctl(fd, DRM_IOCTL_I915_GEM_SET_CACHING, &arg)) err = -errno; - igt_assert(errno == ENOTTY || errno == EINVAL); - } + + errno = 0; return err; } @@ -229,7 +229,6 @@ void gem_set_caching(int fd, uint32_t handle, uint32_t caching) { igt_require(__gem_set_caching(fd, handle, caching) == 0); - errno = 0; } /** @@ -1405,6 +1404,22 @@ errno = 0; } +static void reset_device(int fd) +{ + int dir; + + dir = igt_debugfs_dir(fd); + igt_require(dir >= 0); + + if (ioctl(fd, DRM_IOCTL_I915_GEM_THROTTLE)) { + igt_info("Found wedged device, trying to reset and continue\n"); + igt_sysfs_set(dir, "i915_wedged", "-1"); + } + igt_sysfs_set(dir, "i915_next_seqno", "1"); + + close(dir); +} + void igt_require_gem(int fd) { char path[256]; @@ -1427,15 +1442,12 @@ * itself, which avoids accidentally hanging when setting up long * sequences of batches. */ - err = igt_debugfs_dir(fd); - if (err != -1) { - igt_sysfs_printf(err, "i915_next_seqno", "1"); - close(err); - } + reset_device(fd); err = 0; if (ioctl(fd, DRM_IOCTL_I915_GEM_THROTTLE)) err = -errno; + close(fd); igt_require_f(err == 0, "Unresponsive i915/GEM device\n"); @@ -1659,10 +1671,10 @@ int __kms_addfb(int fd, uint32_t handle, uint32_t width, uint32_t height, uint32_t stride, uint32_t pixel_format, uint64_t modifier, - uint32_t flags, uint32_t *buf_id) + uint32_t *offsets, uint32_t flags, uint32_t *buf_id) { struct drm_mode_fb_cmd2 f; - int ret; + int ret, i; igt_require_fb_modifiers(fd); @@ -1676,6 +1688,13 @@ f.pitches[0] = stride; f.modifier[0] = modifier; + for (i = 1; i < 4 && offsets && offsets[i]; i++) { + f.handles[i] = handle; + f.pitches[i] = stride; + f.modifier[i] = modifier; + f.offsets[i] = offsets[i]; + } + ret = igt_ioctl(fd, DRM_IOCTL_MODE_ADDFB2, &f); *buf_id = f.fb_id; diff -Nru intel-gpu-tools-1.21/lib/ioctl_wrappers.h intel-gpu-tools-1.22/lib/ioctl_wrappers.h --- intel-gpu-tools-1.21/lib/ioctl_wrappers.h 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/ioctl_wrappers.h 2018-03-09 14:22:59.000000000 +0000 @@ -236,7 +236,7 @@ */ int __kms_addfb(int fd, uint32_t handle, uint32_t width, uint32_t height, uint32_t stride, uint32_t pixel_format, uint64_t modifier, - uint32_t flags, uint32_t *buf_id); + uint32_t *offsets, uint32_t flags, uint32_t *buf_id); /** * to_user_pointer: diff -Nru intel-gpu-tools-1.21/lib/Makefile.sources intel-gpu-tools-1.22/lib/Makefile.sources --- intel-gpu-tools-1.21/lib/Makefile.sources 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/Makefile.sources 2018-03-09 14:22:59.000000000 +0000 @@ -9,6 +9,8 @@ i915/gem_scheduler.h \ i915/gem_submission.c \ i915/gem_submission.h \ + i915/gem_ring.h \ + i915/gem_ring.c \ i915_3d.h \ i915_reg.h \ i915_pciids.h \ @@ -33,6 +35,8 @@ igt_stats.h \ igt_sysfs.c \ igt_sysfs.h \ + igt_sysrq.c \ + igt_sysrq.h \ igt_x86.h \ igt_x86.c \ igt_vgem.c \ diff -Nru intel-gpu-tools-1.21/lib/meson.build intel-gpu-tools-1.22/lib/meson.build --- intel-gpu-tools-1.21/lib/meson.build 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/lib/meson.build 2018-03-09 14:22:59.000000000 +0000 @@ -1,62 +1,9 @@ -lib_headers = [ - 'debug.h', - 'drmtest.h', - 'i830_reg.h', - 'i915/gem_context.h', - 'i915/gem_scheduler.h', - 'i915/gem_submission.h', - 'i915_3d.h', - 'i915_reg.h', - 'i915_pciids.h', - 'igt.h', - 'igt_debugfs.h', - 'igt_device.h', - 'igt_aux.h', - 'igt_edid_template.h', - 'igt_gt.h', - 'igt_gvt.h', - 'igt_primes.h', - 'igt_rand.h', - 'igt_rc.h', - 'igt_stats.h', - 'igt_syncobj.h', - 'igt_sysfs.h', - 'igt_x86.h', - 'igt_vgem.h', - 'instdone.h', - 'intel_batchbuffer.h', - 'intel_chipset.h', - 'intel_io.h', - 'intel_reg.h', - 'ioctl_wrappers.h', - 'media_fill.h', - 'media_spin.h', - 'gpgpu_fill.h', - 'gen7_media.h', - 'gen8_media.h', - 'gen6_render.h', - 'gen7_render.h', - 'gen8_render.h', - 'gen9_render.h', - 'rendercopy.h', - 'sw_sync.h', - 'igt_kms.h', - 'igt_fb.h', - 'igt_core.h', - 'igt_draw.h', - 'igt_pm.h', - 'igt_dummyload.h', - 'uwildmat/uwildmat.h', - 'igt_kmod.h', - 'igt_vc4.h', - 'vc4_packet.h', -] - lib_sources = [ 'drmtest.c', 'i915/gem_context.c', 'i915/gem_scheduler.c', 'i915/gem_submission.c', + 'i915/gem_ring.c', 'igt_debugfs.c', 'igt_device.c', 'igt_aux.c', @@ -67,6 +14,7 @@ 'igt_stats.c', 'igt_syncobj.c', 'igt_sysfs.c', + 'igt_sysrq.c', 'igt_vgem.c', 'igt_x86.c', 'instdone.c', @@ -119,8 +67,8 @@ if libdrm_intel.found() lib_deps += libdrm_intel else - lib_headers += 'stubs/drm/intel_bufmgr.h' lib_sources += 'stubs/drm/intel_bufmgr.c' + inc = [ inc, include_directories('stubs/drm') ] endif if valgrind.found() @@ -129,23 +77,19 @@ if gsl.found() and pixman.found() lib_deps += [ gsl, pixman ] - lib_headers += [ 'igt_frame.h', 'igt_audio.h' ] lib_sources += [ 'igt_frame.c', 'igt_audio.c' ] endif if alsa.found() lib_deps += alsa - lib_headers += 'igt_alsa.h' lib_sources += 'igt_alsa.c' endif if chamelium.found() lib_deps += chamelium - lib_headers += 'igt_chamelium.h' lib_sources += 'igt_chamelium.c' endif -pkgdatadir = join_paths(get_option('prefix'), get_option('datadir'), 'intel-gpu-tools') srcdir = join_paths(meson.source_root(), 'tests') lib_version = vcs_tag(input : 'version.h.in', output : 'version.h', @@ -160,7 +104,7 @@ include_directories: inc, dependencies : lib_deps, c_args : [ - '-DIGT_DATADIR="@0@"'.format(pkgdatadir), + '-DIGT_DATADIR="@0@"'.format(join_paths(prefix, datadir)), '-DIGT_SRCDIR="@0@"'.format(srcdir), '-DIGT_LOG_DOMAIN="@0@"'.format(f.split('.')[0]), ]) diff -Nru intel-gpu-tools-1.21/MAINTAINERS intel-gpu-tools-1.22/MAINTAINERS --- intel-gpu-tools-1.21/MAINTAINERS 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/MAINTAINERS 2018-03-09 14:22:59.000000000 +0000 @@ -1 +1,2 @@ Petri Latvala +Arkadiusz Hiler diff -Nru intel-gpu-tools-1.21/man/intel_aubdump.rst intel-gpu-tools-1.22/man/intel_aubdump.rst --- intel-gpu-tools-1.21/man/intel_aubdump.rst 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/man/intel_aubdump.rst 2018-03-09 14:22:59.000000000 +0000 @@ -6,7 +6,7 @@ Launch an application and capture rendering to an AUB ----------------------------------------------------- .. include:: defs.rst -:Author: Intel Graphics for Linux +:Author: IGT Developers :Date: 2016-03-01 :Version: |PACKAGE_STRING| :Copyright: 2015-2016 Intel Corporation diff -Nru intel-gpu-tools-1.21/man/intel_audio_dump.rst intel-gpu-tools-1.22/man/intel_audio_dump.rst --- intel-gpu-tools-1.21/man/intel_audio_dump.rst 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/man/intel_audio_dump.rst 2018-03-09 14:22:59.000000000 +0000 @@ -6,7 +6,7 @@ Dump the Intel GPU registers for HDMI audio setup ------------------------------------------------- .. include:: defs.rst -:Author: Intel Graphics for Linux +:Author: IGT Developers :Date: 2016-03-01 :Version: |PACKAGE_STRING| :Copyright: 2010,2012,2016 Intel Corporation diff -Nru intel-gpu-tools-1.21/man/intel_bios_dumper.rst intel-gpu-tools-1.22/man/intel_bios_dumper.rst --- intel-gpu-tools-1.21/man/intel_bios_dumper.rst 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/man/intel_bios_dumper.rst 2018-03-09 14:22:59.000000000 +0000 @@ -6,7 +6,7 @@ Save the Intel video BIOS contents to a file -------------------------------------------- .. include:: defs.rst -:Author: Intel Graphics for Linux +:Author: IGT Developers :Date: 2016-03-01 :Version: |PACKAGE_STRING| :Copyright: 2010,2012,2016 Intel Corporation diff -Nru intel-gpu-tools-1.21/man/intel_error_decode.rst intel-gpu-tools-1.22/man/intel_error_decode.rst --- intel-gpu-tools-1.21/man/intel_error_decode.rst 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/man/intel_error_decode.rst 2018-03-09 14:22:59.000000000 +0000 @@ -6,7 +6,7 @@ Decode an Intel GPU dump automatically captured by the kernel at the time of an error ------------------------------------------------------------------------------------- .. include:: defs.rst -:Author: Intel Graphics for Linux +:Author: IGT Developers :Date: 2016-03-01 :Version: |PACKAGE_STRING| :Copyright: 2010,2012,2016 Intel Corporation diff -Nru intel-gpu-tools-1.21/man/intel_gpu_frequency.rst intel-gpu-tools-1.22/man/intel_gpu_frequency.rst --- intel-gpu-tools-1.21/man/intel_gpu_frequency.rst 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/man/intel_gpu_frequency.rst 2018-03-09 14:22:59.000000000 +0000 @@ -6,7 +6,7 @@ Manipulate Intel GPU frequencies -------------------------------- .. include:: defs.rst -:Author: Intel Graphics for Linux +:Author: IGT Developers :Date: 2016-03-01 :Version: |PACKAGE_STRING| :Copyright: 2015-2016 Intel Corporation diff -Nru intel-gpu-tools-1.21/man/intel_gpu_top.rst intel-gpu-tools-1.22/man/intel_gpu_top.rst --- intel-gpu-tools-1.21/man/intel_gpu_top.rst 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/man/intel_gpu_top.rst 2018-03-09 14:22:59.000000000 +0000 @@ -6,7 +6,7 @@ Display a top-like summary of Intel GPU usage --------------------------------------------- .. include:: defs.rst -:Author: Intel Graphics for Linux +:Author: IGT Developers :Date: 2016-03-01 :Version: |PACKAGE_STRING| :Copyright: 2009,2011,2012,2016 Intel Corporation diff -Nru intel-gpu-tools-1.21/man/intel_gtt.rst intel-gpu-tools-1.22/man/intel_gtt.rst --- intel-gpu-tools-1.21/man/intel_gtt.rst 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/man/intel_gtt.rst 2018-03-09 14:22:59.000000000 +0000 @@ -6,7 +6,7 @@ Dump the contents of an Intel GPU's GTT --------------------------------------- .. include:: defs.rst -:Author: Intel Graphics for Linux +:Author: IGT Developers :Date: 2016-03-01 :Version: |PACKAGE_STRING| :Copyright: 2010,2012,2016 Intel Corporation diff -Nru intel-gpu-tools-1.21/man/intel_infoframes.rst intel-gpu-tools-1.22/man/intel_infoframes.rst --- intel-gpu-tools-1.21/man/intel_infoframes.rst 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/man/intel_infoframes.rst 2018-03-09 14:22:59.000000000 +0000 @@ -6,7 +6,7 @@ View and change HDMI InfoFrames ------------------------------- .. include:: defs.rst -:Author: Intel Graphics for Linux +:Author: IGT Developers :Date: 2016-03-01 :Version: |PACKAGE_STRING| :Copyright: 2012,2016 Intel Corporation diff -Nru intel-gpu-tools-1.21/man/intel_lid.rst intel-gpu-tools-1.22/man/intel_lid.rst --- intel-gpu-tools-1.21/man/intel_lid.rst 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/man/intel_lid.rst 2018-03-09 14:22:59.000000000 +0000 @@ -6,7 +6,7 @@ Poll the values of different reports about laptop lid state ----------------------------------------------------------- .. include:: defs.rst -:Author: Intel Graphics for Linux +:Author: IGT Developers :Date: 2016-03-01 :Version: |PACKAGE_STRING| :Copyright: 2010,2012-2013,2016 Intel Corporation diff -Nru intel-gpu-tools-1.21/man/intel_panel_fitter.rst intel-gpu-tools-1.22/man/intel_panel_fitter.rst --- intel-gpu-tools-1.21/man/intel_panel_fitter.rst 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/man/intel_panel_fitter.rst 2018-03-09 14:22:59.000000000 +0000 @@ -6,7 +6,7 @@ Change the panel fitter settings -------------------------------- .. include:: defs.rst -:Author: Intel Graphics for Linux +:Author: IGT Developers :Date: 2016-03-01 :Version: |PACKAGE_STRING| :Copyright: 2012,2016 Intel Corporation diff -Nru intel-gpu-tools-1.21/man/intel_reg.rst intel-gpu-tools-1.22/man/intel_reg.rst --- intel-gpu-tools-1.21/man/intel_reg.rst 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/man/intel_reg.rst 2018-03-09 14:22:59.000000000 +0000 @@ -103,7 +103,7 @@ REGISTER REFERENCES =================== -Registers are defined as [(PORTNAME|PORTNUM|MMIO-OFFSET):](REGNAME|REGADDR). +Registers are defined as [(PORTNAME|PORTNUM|ENGINE|MMIO-OFFSET):](REGNAME|REGADDR). PORTNAME The register access method, most often MMIO, which is the default. The @@ -120,6 +120,13 @@ Numbers above 0xff are automatically interpreted as MMIO offsets, not port numbers. +ENGINE + Instead of cpu based MMIO, specified engine can be used for access method. + Batchbuffer will be targeted for the engine to do read/write. The list of + available engines is architecture specific and can be found with + "intel_reg help". Prefixing engine name with '-' uses non-privileged + batchbuffer for access. + MMIO-OFFSET Use MMIO, and add this offset to the register address. diff -Nru intel-gpu-tools-1.21/man/intel_stepping.rst intel-gpu-tools-1.22/man/intel_stepping.rst --- intel-gpu-tools-1.21/man/intel_stepping.rst 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/man/intel_stepping.rst 2018-03-09 14:22:59.000000000 +0000 @@ -6,7 +6,7 @@ Display the stepping information for an Intel GPU ------------------------------------------------- .. include:: defs.rst -:Author: Intel Graphics for Linux +:Author: IGT Developers :Date: 2016-03-01 :Version: |PACKAGE_STRING| :Copyright: 2009,2012,2016 Intel Corporation diff -Nru intel-gpu-tools-1.21/man/intel_upload_blit_large_gtt.rst intel-gpu-tools-1.22/man/intel_upload_blit_large_gtt.rst --- intel-gpu-tools-1.21/man/intel_upload_blit_large_gtt.rst 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/man/intel_upload_blit_large_gtt.rst 2018-03-09 14:22:59.000000000 +0000 @@ -6,7 +6,7 @@ Microbenchmark of Intel GPU performance --------------------------------------- .. include:: defs.rst -:Author: Intel Graphics for Linux +:Author: IGT Developers :Date: 2016-03-01 :Version: |PACKAGE_STRING| :Copyright: 2009,2012,2016 Intel Corporation diff -Nru intel-gpu-tools-1.21/man/intel_upload_blit_large_map.rst intel-gpu-tools-1.22/man/intel_upload_blit_large_map.rst --- intel-gpu-tools-1.21/man/intel_upload_blit_large_map.rst 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/man/intel_upload_blit_large_map.rst 2018-03-09 14:22:59.000000000 +0000 @@ -6,7 +6,7 @@ Microbenchmark of Intel GPU performance --------------------------------------- .. include:: defs.rst -:Author: Intel Graphics for Linux +:Author: IGT Developers :Date: 2016-03-01 :Version: |PACKAGE_STRING| :Copyright: 2009,2012,2016 Intel Corporation diff -Nru intel-gpu-tools-1.21/man/intel_upload_blit_large.rst intel-gpu-tools-1.22/man/intel_upload_blit_large.rst --- intel-gpu-tools-1.21/man/intel_upload_blit_large.rst 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/man/intel_upload_blit_large.rst 2018-03-09 14:22:59.000000000 +0000 @@ -6,7 +6,7 @@ Microbenchmark of Intel GPU performance --------------------------------------- .. include:: defs.rst -:Author: Intel Graphics for Linux +:Author: IGT Developers :Date: 2016-03-01 :Version: |PACKAGE_STRING| :Copyright: 2009,2012,2016 Intel Corporation diff -Nru intel-gpu-tools-1.21/man/intel_upload_blit_small.rst intel-gpu-tools-1.22/man/intel_upload_blit_small.rst --- intel-gpu-tools-1.21/man/intel_upload_blit_small.rst 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/man/intel_upload_blit_small.rst 2018-03-09 14:22:59.000000000 +0000 @@ -6,7 +6,7 @@ Microbenchmark of Intel GPU performance --------------------------------------- .. include:: defs.rst -:Author: Intel Graphics for Linux +:Author: IGT Developers :Date: 2016-03-01 :Version: |PACKAGE_STRING| :Copyright: 2009,2012,2016 Intel Corporation diff -Nru intel-gpu-tools-1.21/man/intel_vbt_decode.rst intel-gpu-tools-1.22/man/intel_vbt_decode.rst --- intel-gpu-tools-1.21/man/intel_vbt_decode.rst 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/man/intel_vbt_decode.rst 2018-03-09 14:22:59.000000000 +0000 @@ -6,7 +6,7 @@ Intel Video BIOS Table parser ----------------------------- .. include:: defs.rst -:Author: Intel Graphics for Linux +:Author: IGT Developers :Date: 2016-03-01 :Version: |PACKAGE_STRING| :Copyright: 2010,2012,2016 Intel Corporation diff -Nru intel-gpu-tools-1.21/man/meson.build intel-gpu-tools-1.22/man/meson.build --- intel-gpu-tools-1.21/man/meson.build 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/man/meson.build 2018-03-09 14:22:59.000000000 +0000 @@ -34,6 +34,6 @@ input: manpage + '.rst', output : manpage + '.1.gz', install : true, - install_dir : join_paths(get_option('mandir'), 'man1')) + install_dir : join_paths(mandir, 'man1')) endforeach endif diff -Nru intel-gpu-tools-1.21/meson.build intel-gpu-tools-1.22/meson.build --- intel-gpu-tools-1.21/meson.build 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/meson.build 2018-03-09 14:22:59.000000000 +0000 @@ -1,5 +1,5 @@ project('intel-gpu-tools', 'c', - version : '1.21', + version : '1.22', default_options: [ 'warning_level=2', 'c_std=gnu99', @@ -32,10 +32,11 @@ config = configuration_data() -libdrm = dependency('libdrm', version : '>=2.4.82') -libdrm_intel = dependency('libdrm_intel', required : false) -libdrm_nouveau = dependency('libdrm_nouveau', required : false) -libdrm_amdgpu = dependency('libdrm_amdgpu', required : false) +libdrm_version = '>=2.4.82' +libdrm = dependency('libdrm', version : libdrm_version) +libdrm_intel = dependency('libdrm_intel', version : libdrm_version, required : false) +libdrm_nouveau = dependency('libdrm_nouveau', version : libdrm_version, required : false) +libdrm_amdgpu = dependency('libdrm_amdgpu', version : libdrm_version, required : false) pciaccess = dependency('pciaccess', version : '>=0.10') libkmod = dependency('libkmod') @@ -47,13 +48,8 @@ config.set('HAVE_VALGRIND', 1) endif -cairo = dependency('cairo', version : '>1.12.0', required : false) - -libudev = dependency('libudev', required : false) -if libudev.found() - config.set('HAVE_UDEV', 1) -endif - +cairo = dependency('cairo', version : '>1.12.0', required : true) +libudev = dependency('libudev', required : true) glib = dependency('glib-2.0', required : false) if glib.found() config.set('HAVE_GLIB', 1) @@ -127,6 +123,15 @@ configure_file(output: 'config.h', install: false, configuration: config) +prefix = get_option('prefix') +bindir = get_option('bindir') +datadir = join_paths(get_option('datadir'), 'intel-gpu-tools') +includedir = get_option('includedir') +libdir = get_option('libdir') +libexecdir = join_paths(get_option('libexecdir'), 'intel-gpu-tools') +mandir = get_option('mandir') +pkgconfigdir = join_paths(libdir, 'pkgconfig') + subdir('lib') subdir('tests') subdir('benchmarks') @@ -138,4 +143,7 @@ endif endif subdir('man') -subdir('docs') +# has_exe_wrapper() is undefined if building natively +if not meson.is_cross_build() or not meson.has_exe_wrapper() + subdir('docs') +endif diff -Nru intel-gpu-tools-1.21/NEWS intel-gpu-tools-1.22/NEWS --- intel-gpu-tools-1.21/NEWS 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/NEWS 2018-03-09 14:22:59.000000000 +0000 @@ -1,5 +1,53 @@ +Release 1.22 (2018-03-09) +------------------------- + +General changes: + +- Libudev has been made a mandatory dependency. (Antonio Argenziano) + +- Documentation changed to refer to the new igt-dev mailing + list. (Rhys Kidd) + +Library changes: + +- Refactored timer usage for smaller code size. (Chris Wilson) + +- Various fixes to support planar framebuffers. (Maarten Lankhorst) + +- Added support for fetching the most recent CRC without waiting for a + vblank, along with flushing the queue of already collected + CRCs. (Maarten Lankhorst) + +- Added a helper to mark BOs purgeable on vc4. (Boris Brezillon) + +- Moved handling of a "cork" BO into lib from various tests. + (Daniele Ceraolo Spurio) + +- Added support for looping over physical i915 engines, as opposed to + uABI engines that can alias. (Chris Wilson) + +- Added an accelerated method for reading from WC buffers. + (Chris Wilson) + +Tools changes: + +- Improved intel_vbt_decode output, updated the data from current + kernel. (Jani Nikula) + +- intel_reg can now read/write registers using a given engine. + (Mika Kuoppala) + +- Aubdump can now simulate enhanced execlist submission, for + gen11+. (Scott D Phillips) + + + + + +And many other bug fixes, improvements, cleanups and new tests. + Release 1.21 (2018-01-16) ------------- +------------------------- Library changes: diff -Nru intel-gpu-tools-1.21/overlay/overlay.c intel-gpu-tools-1.22/overlay/overlay.c --- intel-gpu-tools-1.21/overlay/overlay.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/overlay/overlay.c 2018-03-09 14:22:59.000000000 +0000 @@ -840,6 +840,7 @@ printf("\t--geometry|-G x++\tExact window placement and size\n"); printf("\t--position|-P (top|middle|bottom)-(left|centre|right)\tPlace the window in a particular corner\n"); printf("\t--size|-S x | %%\t\t\tWindow size\n"); + printf("\t--foreground|-f\t\t\t\t\t\tKeep the application in foreground\n"); printf("\t--help|-h\t\t\t\t\t\tThis help message\n"); } @@ -850,6 +851,7 @@ {"geometry", 1, 0, 'G'}, {"position", 1, 0, 'P'}, {"size", 1, 0, 'S'}, + {"foreground", 0, 0, 'f'}, {"help", 0, 0, 'h'}, {NULL, 0, 0, 0,} }; diff -Nru intel-gpu-tools-1.21/overlay/tracepoint_format.leg intel-gpu-tools-1.22/overlay/tracepoint_format.leg --- intel-gpu-tools-1.21/overlay/tracepoint_format.leg 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/overlay/tracepoint_format.leg 2018-03-09 14:22:59.000000000 +0000 @@ -1,28 +1,27 @@ TracepointFmt = - 'name' ':' Space n:PropertyName EndLine - { free(v.string); } - 'ID:' Space v:Number EndLine - { yy->ctx.tp->event_id = v.integer; } + 'name' ':' Space n:PropertyName EndLine { free(n.string); } + 'ID:' Space v:Number EndLine { yy->ctx.tp->event_id = v.integer; } 'format:' EndLine Field+ 'print fmt:' [^.]* !. -Field = Space (Property ';' Space)+ EndLine - { yy->ctx.tp->n_fields++; } - | EndLine +Field = Space (Property ';' Space)+ EndLine + { yy->ctx.tp->n_fields++; } + | EndLine -Property = 'offset' ':' v:Number - { yy->ctx.tp->fields[yy->ctx.tp->n_fields].offset = v.integer; } - | 'size' ':' v:Number - { yy->ctx.tp->fields[yy->ctx.tp->n_fields].size = v.integer; } - | 'signed' ':' v:Number - { yy->ctx.tp->fields[yy->ctx.tp->n_fields].is_signed = v.integer != 0; } - | 'field' ':' v:PropertyValue - { snprintf(yy->ctx.tp->fields[yy->ctx.tp->n_fields].name, - sizeof(yy->ctx.tp->fields[yy->ctx.tp->n_fields].name), - "%s", strrchr(v.string, ' ') + 1); free(v.string); } - | n:PropertyName ':' v:PropertyValue - { free(n.string); free(v.string); } +Property = 'offset' ':' v:Number + { yy->ctx.tp->fields[yy->ctx.tp->n_fields].offset = v.integer; } + | 'size' ':' v:Number + { yy->ctx.tp->fields[yy->ctx.tp->n_fields].size = v.integer; } + | 'signed' ':' v:Number + { yy->ctx.tp->fields[yy->ctx.tp->n_fields].is_signed = v.integer != 0; } + | 'field' ':' v:PropertyValue + { snprintf(yy->ctx.tp->fields[yy->ctx.tp->n_fields].name, + sizeof(yy->ctx.tp->fields[yy->ctx.tp->n_fields].name), + "%s", strrchr(v.string, ' ') + 1); + free(v.string); } + | n:PropertyName ':' v:PropertyValue + { free(n.string); free(v.string); } PropertyName = < [A-Za-z0-9_]+ > { $$.string = strdup(yytext); } diff -Nru intel-gpu-tools-1.21/README intel-gpu-tools-1.22/README --- intel-gpu-tools-1.21/README 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/README 2018-03-09 14:22:59.000000000 +0000 @@ -99,7 +99,7 @@ up the 2D build to ship them. Instead, here's a separate package for people debugging the driver. - These tools generally must be run as root, safe for the ones that just + These tools generally must be run as root, except for the ones that just decode dumps. debugger/ diff -Nru intel-gpu-tools-1.21/tests/amdgpu/amd_prime.c intel-gpu-tools-1.22/tests/amdgpu/amd_prime.c --- intel-gpu-tools-1.21/tests/amdgpu/amd_prime.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/amdgpu/amd_prime.c 2018-03-09 14:22:59.000000000 +0000 @@ -179,12 +179,8 @@ struct cork c; nengine = 0; - for_each_engine(i915, engine) { - if (engine == 0) - continue; - + for_each_physical_engine(i915, engine) engines[nengine++] = engine; - } igt_require(nengine); memset(obj, 0, sizeof(obj)); @@ -416,8 +412,10 @@ igt_require(err == 0); } - igt_subtest("i915-to-amd") + igt_subtest("i915-to-amd") { + gem_require_contexts(i915); i915_to_amd(i915, amd, device); + } igt_subtest("amd-to-i915") amd_to_i915(i915, amd, device); diff -Nru intel-gpu-tools-1.21/tests/debugfs_test.c intel-gpu-tools-1.22/tests/debugfs_test.c --- intel-gpu-tools-1.21/tests/debugfs_test.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/debugfs_test.c 2018-03-09 14:22:59.000000000 +0000 @@ -61,8 +61,9 @@ int sub_fd; ssize_t ret; - igt_set_timeout(5, "reading sysfs entry"); + igt_kmsg(KMSG_DEBUG "Reading file \"%s\"\n", dirent->d_name); igt_debug("%sReading file \"%s\"\n", tabs, dirent->d_name); + igt_set_timeout(5, "reading sysfs entry"); sub_fd = openat(path_fd, dirent->d_name, O_RDONLY); if (sub_fd == -1) { diff -Nru intel-gpu-tools-1.21/tests/drv_hangman.c intel-gpu-tools-1.22/tests/drv_hangman.c --- intel-gpu-tools-1.21/tests/drv_hangman.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/drv_hangman.c 2018-03-09 14:22:59.000000000 +0000 @@ -129,6 +129,14 @@ FILE *file = open_error(); char *line = NULL; size_t line_size = 0; + bool found = false; + + igt_debug("%s(expected ring name=%s, expected offset=%"PRIx64")\n", + __func__, expected_ring_name, expected_offset); + igt_debugfs_dump(device, "i915_error_state"); + + igt_assert(getline(&line, &line_size, file) != -1); + igt_assert(strcasecmp(line, "No error state collected")); while (getline(&line, &line_size, file) > 0) { char *dashes; @@ -168,12 +176,18 @@ 4*i, batch[i]); igt_assert(strstr(line, expected_line)); } + + found = true; break; } } free(line); fclose(file); + + clear_error_state(); + + igt_assert(found); } static void test_error_state_capture(unsigned ring_id, @@ -183,8 +197,6 @@ igt_hang_t hang; uint64_t offset; - igt_require(gem_has_ring(device, ring_id)); - clear_error_state(); hang = igt_hang_ctx(device, 0, ring_id, HANG_ALLOW_CAPTURE, &offset); @@ -255,23 +267,11 @@ if (e->exec_id == 0) continue; - /* - * If the device has 2 BSD rings then due to obtuse aliasing - * in the API, we can not determine which ring I915_EXEC_BSD - * will map to, and so must skip the test; as the matching name - * may be either bsd or bsd2 depending on the kernel/test - * ordering. - * - * Here we are not checking that executing on every ABI engine - * results in a detectable hang, but that a hang generated - * from a specific HW engine gives an indentifiable result. - */ - if (e->exec_id == I915_EXEC_BSD && e->flags == 0) - continue; - - igt_subtest_f("error-state-capture-%s", e->name) + igt_subtest_f("error-state-capture-%s", e->name) { + igt_require(gem_ring_has_physical_engine(device, e->exec_id | e->flags)); test_error_state_capture(e->exec_id | e->flags, e->full_name); + } } igt_subtest("hangcheck-unterminated") diff -Nru intel-gpu-tools-1.21/tests/gem_busy.c intel-gpu-tools-1.22/tests/gem_busy.c --- intel-gpu-tools-1.21/tests/gem_busy.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_busy.c 2018-03-09 14:22:59.000000000 +0000 @@ -28,6 +28,7 @@ #include "igt.h" #include "igt_rand.h" #include "igt_vgem.h" +#include "i915/gem_ring.h" #define LOCAL_EXEC_NO_RELOC (1<<11) #define PAGE_ALIGN(x) ALIGN(x, 4096) @@ -156,7 +157,7 @@ #define PARALLEL 1 #define HANG 2 -static void one(int fd, unsigned ring, uint32_t flags, unsigned test_flags) +static void one(int fd, unsigned ring, unsigned test_flags) { const int gen = intel_gen(intel_get_drm_devid(fd)); struct drm_i915_gem_exec_object2 obj[2]; @@ -165,6 +166,7 @@ struct drm_i915_gem_relocation_entry store[1024+1]; struct drm_i915_gem_execbuffer2 execbuf; unsigned size = ALIGN(ARRAY_SIZE(store)*16 + 4, 4096); + const unsigned uabi = ring & 63; uint32_t read[2], write[2]; struct timespec tv; uint32_t *batch, *bbe; @@ -173,7 +175,7 @@ memset(&execbuf, 0, sizeof(execbuf)); execbuf.buffers_ptr = to_user_pointer(obj); execbuf.buffer_count = 2; - execbuf.flags = ring | flags; + execbuf.flags = ring; if (gen < 6) execbuf.flags |= I915_EXEC_SECURE; @@ -245,20 +247,17 @@ __gem_busy(fd, obj[BATCH].handle, &read[BATCH], &write[BATCH]); if (test_flags & PARALLEL) { - const struct intel_execution_engine *e; - - for (e = intel_execution_engines; e->name; e++) { - if (e->exec_id == 0 || e->exec_id == ring) - continue; + unsigned other; - if (!gem_has_ring(fd, e->exec_id | e->flags)) + for_each_physical_engine(fd, other) { + if (other == ring) continue; - if (!gem_can_store_dword(fd, e->exec_id | e->flags)) + if (!gem_can_store_dword(fd, other)) continue; - igt_debug("Testing %s in parallel\n", e->name); - one(fd, e->exec_id, e->flags, 0); + igt_debug("Testing %s in parallel\n", e__->name); + one(fd, other, 0); } } @@ -269,11 +268,11 @@ timeout = 1; } - igt_assert_eq(write[SCRATCH], ring); - igt_assert_eq_u32(read[SCRATCH], 1 << ring); + igt_assert_eq(write[SCRATCH], uabi); + igt_assert_eq_u32(read[SCRATCH], 1 << uabi); igt_assert_eq(write[BATCH], 0); - igt_assert_eq_u32(read[BATCH], 1 << ring); + igt_assert_eq_u32(read[BATCH], 1 << uabi); /* Calling busy in a loop should be enough to flush the rendering */ memset(&tv, 0, sizeof(tv)); @@ -299,105 +298,10 @@ u32[j] = tmp; } -struct cork { - int device; - uint32_t handle; - uint32_t fence; -}; - -static void plug(int fd, struct cork *c) -{ - struct vgem_bo bo; - int dmabuf; - - c->device = drm_open_driver(DRIVER_VGEM); - - bo.width = bo.height = 1; - bo.bpp = 4; - vgem_create(c->device, &bo); - c->fence = vgem_fence_attach(c->device, &bo, VGEM_FENCE_WRITE); - - dmabuf = prime_handle_to_fd(c->device, bo.handle); - c->handle = prime_fd_to_handle(fd, dmabuf); - close(dmabuf); -} - -static void unplug(struct cork *c) -{ - vgem_fence_signal(c->device, c->fence); - close(c->device); -} - -static void alarm_handler(int sig) -{ -} - -static int __execbuf(int fd, struct drm_i915_gem_execbuffer2 *execbuf) -{ - return ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, execbuf); -} - -static unsigned int measure_ring_size(int fd) -{ - struct sigaction sa = { .sa_handler = alarm_handler }; - struct drm_i915_gem_exec_object2 obj[2]; - struct drm_i915_gem_execbuffer2 execbuf; - const uint32_t bbe = MI_BATCH_BUFFER_END; - unsigned int count, last; - struct itimerval itv; - struct cork c; - - memset(obj, 0, sizeof(obj)); - obj[1].handle = gem_create(fd, 4096); - gem_write(fd, obj[1].handle, 0, &bbe, sizeof(bbe)); - - memset(&execbuf, 0, sizeof(execbuf)); - execbuf.buffers_ptr = to_user_pointer(obj + 1); - execbuf.buffer_count = 1; - gem_execbuf(fd, &execbuf); - gem_sync(fd, obj[1].handle); - - plug(fd, &c); - obj[0].handle = c.handle; - - execbuf.buffers_ptr = to_user_pointer(obj); - execbuf.buffer_count = 2; - - sigaction(SIGALRM, &sa, NULL); - itv.it_interval.tv_sec = 0; - itv.it_interval.tv_usec = 100; - itv.it_value.tv_sec = 0; - itv.it_value.tv_usec = 1000; - setitimer(ITIMER_REAL, &itv, NULL); - - last = -1; - count = 0; - do { - if (__execbuf(fd, &execbuf) == 0) { - count++; - continue; - } - - if (last == count) - break; - - last = count; - } while (1); - - memset(&itv, 0, sizeof(itv)); - setitimer(ITIMER_REAL, &itv, NULL); - - unplug(&c); - gem_close(fd, obj[1].handle); - gem_quiescent_gpu(fd); - - return count; -} - static void close_race(int fd) { const unsigned int ncpus = sysconf(_SC_NPROCESSORS_ONLN); - const unsigned int nhandles = measure_ring_size(fd) / 2; + const unsigned int nhandles = gem_measure_ring_inflight(fd, 0, 0) / 2; unsigned int engines[16], nengine; unsigned long *control; uint32_t *handles; @@ -591,10 +495,10 @@ continue; igt_subtest_f("extended-%s", e->name) { - gem_require_ring(fd, e->exec_id | e->flags); + igt_require(gem_ring_has_physical_engine(fd, e->exec_id | e->flags)); igt_require(gem_can_store_dword(fd, e->exec_id | e->flags)); gem_quiescent_gpu(fd); - one(fd, e->exec_id, e->flags, 0); + one(fd, e->exec_id | e->flags, 0); gem_quiescent_gpu(fd); } } @@ -605,11 +509,11 @@ continue; igt_subtest_f("extended-parallel-%s", e->name) { - gem_require_ring(fd, e->exec_id | e->flags); + igt_require(gem_ring_has_physical_engine(fd, e->exec_id | e->flags)); igt_require(gem_can_store_dword(fd, e->exec_id | e->flags)); gem_quiescent_gpu(fd); - one(fd, e->exec_id, e->flags, PARALLEL); + one(fd, e->exec_id | e->flags, PARALLEL); gem_quiescent_gpu(fd); } } @@ -670,11 +574,11 @@ igt_subtest_f("extended-hang-%s", e->name) { igt_skip_on_simulation(); - gem_require_ring(fd, e->exec_id | e->flags); + igt_require(gem_ring_has_physical_engine(fd, e->exec_id | e->flags)); igt_require(gem_can_store_dword(fd, e->exec_id | e->flags)); gem_quiescent_gpu(fd); - one(fd, e->exec_id, e->flags, HANG); + one(fd, e->exec_id | e->flags, HANG); gem_quiescent_gpu(fd); } } diff -Nru intel-gpu-tools-1.21/tests/gem_close_race.c intel-gpu-tools-1.22/tests/gem_close_race.c --- intel-gpu-tools-1.21/tests/gem_close_race.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_close_race.c 2018-03-09 14:22:59.000000000 +0000 @@ -119,8 +119,7 @@ gem_pwrite.size = sizeof(buf); gem_pwrite.data_ptr = to_user_pointer(buf); if (drmIoctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &gem_pwrite) == 0) { - while (loops-- && - drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf) == 0) + while (loops-- && __gem_execbuf(fd, &execbuf) == 0) ; } diff -Nru intel-gpu-tools-1.21/tests/gem_concurrent_all.c intel-gpu-tools-1.22/tests/gem_concurrent_all.c --- intel-gpu-tools-1.21/tests/gem_concurrent_all.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_concurrent_all.c 2018-03-09 14:22:59.000000000 +0000 @@ -960,7 +960,7 @@ execbuf.buffers_ptr = to_user_pointer(&obj); execbuf.buffer_count = 1; - for_each_engine(fd, engine) { + for_each_physical_engine(fd, engine) { hang = igt_hang_ring(fd, engine); execbuf.flags = engine; diff -Nru intel-gpu-tools-1.21/tests/gem_ctx_bad_destroy.c intel-gpu-tools-1.22/tests/gem_ctx_bad_destroy.c --- intel-gpu-tools-1.21/tests/gem_ctx_bad_destroy.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_ctx_bad_destroy.c 2018-03-09 14:22:59.000000000 +0000 @@ -45,6 +45,8 @@ igt_fixture { fd = drm_open_driver_render(DRIVER_INTEL); + gem_require_contexts(fd); + ctx_id = gem_context_create(fd); /* Make sure a proper destroy works first */ gem_context_destroy(fd, ctx_id); diff -Nru intel-gpu-tools-1.21/tests/gem_ctx_create.c intel-gpu-tools-1.22/tests/gem_ctx_create.c --- intel-gpu-tools-1.21/tests/gem_ctx_create.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_ctx_create.c 2018-03-09 14:22:59.000000000 +0000 @@ -45,7 +45,7 @@ static unsigned ppgtt_engines[16]; static unsigned ppgtt_nengine; -static int __gem_context_create(int fd, struct drm_i915_gem_context_create *arg) +static int __gem_context_create_local(int fd, struct drm_i915_gem_context_create *arg) { int ret = 0; if (drmIoctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, arg)) @@ -233,7 +233,6 @@ static void maximum(int fd, int ncpus, unsigned mode) { - struct drm_i915_gem_context_create create; const uint32_t bbe = MI_BATCH_BUFFER_END; struct drm_i915_gem_execbuffer2 execbuf; struct drm_i915_gem_exec_object2 obj[2]; @@ -241,8 +240,8 @@ unsigned ctx_size = context_size(fd); uint32_t *contexts = NULL; unsigned long count = 0; + uint32_t ctx_id; - memset(&create, 0, sizeof(create)); do { int err; @@ -255,14 +254,14 @@ err = -ENOMEM; if (avail_mem > (count + 1) * ctx_size) - err = __gem_context_create(fd, &create); + err = __gem_context_create(fd, &ctx_id); if (err) { igt_info("Created %lu contexts, before failing with '%s' [%d]\n", count, strerror(-err), -err); break; } - contexts[count++] = create.ctx_id; + contexts[count++] = ctx_id; } while (1); igt_require(count); @@ -320,16 +319,10 @@ fd = drm_open_driver(DRIVER_INTEL); igt_require_gem(fd); + gem_require_contexts(fd); - memset(&create, 0, sizeof(create)); - igt_require(__gem_context_create(fd, &create) == 0); - gem_context_destroy(fd, create.ctx_id); - - for_each_engine(fd, engine) { - if (engine == 0) - continue; + for_each_physical_engine(fd, engine) all_engines[all_nengine++] = engine; - } igt_require(all_nengine); if (gem_uses_full_ppgtt(fd)) { @@ -347,7 +340,7 @@ memset(&create, 0, sizeof(create)); create.ctx_id = rand(); create.pad = 0; - igt_assert_eq(__gem_context_create(fd, &create), 0); + igt_assert_eq(__gem_context_create_local(fd, &create), 0); igt_assert(create.ctx_id != 0); gem_context_destroy(fd, create.ctx_id); } @@ -356,7 +349,7 @@ memset(&create, 0, sizeof(create)); create.ctx_id = rand(); create.pad = 1; - igt_assert_eq(__gem_context_create(fd, &create), -EINVAL); + igt_assert_eq(__gem_context_create_local(fd, &create), -EINVAL); } igt_subtest("maximum-mem") diff -Nru intel-gpu-tools-1.21/tests/gem_ctx_exec.c intel-gpu-tools-1.22/tests/gem_ctx_exec.c --- intel-gpu-tools-1.21/tests/gem_ctx_exec.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_ctx_exec.c 2018-03-09 14:22:59.000000000 +0000 @@ -52,7 +52,6 @@ { struct drm_i915_gem_execbuffer2 execbuf; struct drm_i915_gem_exec_object2 gem_exec; - int ret = 0; gem_exec.handle = handle; gem_exec.relocation_count = 0; @@ -75,10 +74,7 @@ i915_execbuffer2_set_context_id(execbuf, ctx_id); execbuf.rsvd2 = 0; - ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, - &execbuf); - - return ret; + return __gem_execbuf(fd, &execbuf); } static void big_exec(int fd, uint32_t handle, int ring) @@ -116,7 +112,7 @@ execbuf.buffer_count = 1; i915_execbuffer2_set_context_id(execbuf, ctx_id1); - do_ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); + gem_execbuf(fd, &execbuf); for (i = 0; i < num_buffers; i++) { uint32_t tmp_handle = gem_create(fd, 4096); @@ -127,8 +123,7 @@ execbuf.buffer_count = i + 1; /* figure out how many buffers we can exactly fit */ - while (drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, - &execbuf) != 0) { + while (__gem_execbuf(fd, &execbuf) != 0) { i--; gem_close(fd, gem_exec[i].handle); gem_exec[i].handle = handle; @@ -140,10 +135,10 @@ i - 1, num_buffers); /* double check that it works */ - do_ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); + gem_execbuf(fd, &execbuf); i915_execbuffer2_set_context_id(execbuf, ctx_id2); - do_ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); + gem_execbuf(fd, &execbuf); gem_sync(fd, handle); } @@ -158,11 +153,9 @@ fd = drm_open_driver_render(DRIVER_INTEL); igt_require_gem(fd); - handle = gem_create(fd, 4096); + gem_require_contexts(fd); - /* check that we can create contexts. */ - ctx_id = gem_context_create(fd); - gem_context_destroy(fd, ctx_id); + handle = gem_create(fd, 4096); gem_write(fd, handle, 0, batch, sizeof(batch)); } diff -Nru intel-gpu-tools-1.21/tests/gem_ctx_isolation.c intel-gpu-tools-1.22/tests/gem_ctx_isolation.c --- intel-gpu-tools-1.21/tests/gem_ctx_isolation.c 1970-01-01 00:00:00.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_ctx_isolation.c 2018-03-09 14:22:59.000000000 +0000 @@ -0,0 +1,677 @@ +/* + * Copyright © 2017 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 "igt.h" +#include "igt_dummyload.h" + +#define MAX_REG 0x40000 +#define NUM_REGS (MAX_REG / sizeof(uint32_t)) + +#define PAGE_ALIGN(x) ALIGN(x, 4096) + +#define DIRTY1 0x1 +#define DIRTY2 0x2 +#define RESET 0x4 + +#define BIT(x) (1ul << (x)) +#define ENGINE(x, y) BIT(4*(x) + (y)) + +enum { + RCS0 = ENGINE(I915_ENGINE_CLASS_RENDER, 0), + BCS0 = ENGINE(I915_ENGINE_CLASS_COPY, 0), + VCS0 = ENGINE(I915_ENGINE_CLASS_VIDEO, 0), + VCS1 = ENGINE(I915_ENGINE_CLASS_VIDEO, 1), + VECS0 = ENGINE(I915_ENGINE_CLASS_VIDEO_ENHANCE, 0), +}; + +#define ALL ~0u +#define GEN_RANGE(x, y) ((ALL >> (32 - (y - x + 1))) << x) +#define GEN4 (ALL << 4) +#define GEN5 (ALL << 5) +#define GEN6 (ALL << 6) +#define GEN7 (ALL << 7) +#define GEN8 (ALL << 8) +#define GEN9 (ALL << 9) + +#define NOCTX 0 + +#define LAST_KNOWN_GEN 10 + +static const struct named_register { + const char *name; + unsigned int gen_mask; + unsigned int engine_mask; + uint32_t offset; + uint32_t count; +} nonpriv_registers[] = { + { "NOPID", NOCTX, RCS0, 0x2094 }, + { "MI_PREDICATE_RESULT_2", NOCTX, RCS0, 0x23bc }, + { "INSTPM", GEN9, RCS0, 0x20c0 }, + { "IA_VERTICES_COUNT", GEN4, RCS0, 0x2310, 2 }, + { "IA_PRIMITIVES_COUNT", GEN4, RCS0, 0x2318, 2 }, + { "VS_INVOCATION_COUNT", GEN4, RCS0, 0x2320, 2 }, + { "HS_INVOCATION_COUNT", GEN4, RCS0, 0x2300, 2 }, + { "DS_INVOCATION_COUNT", GEN4, RCS0, 0x2308, 2 }, + { "GS_INVOCATION_COUNT", GEN4, RCS0, 0x2328, 2 }, + { "GS_PRIMITIVES_COUNT", GEN4, RCS0, 0x2330, 2 }, + { "CL_INVOCATION_COUNT", GEN4, RCS0, 0x2338, 2 }, + { "CL_PRIMITIVES_COUNT", GEN4, RCS0, 0x2340, 2 }, + { "PS_INVOCATION_COUNT_0", GEN4, RCS0, 0x22c8, 2 }, + { "PS_DEPTH_COUNT_0", GEN4, RCS0, 0x22d8, 2 }, + { "GPUGPU_DISPATCHDIMX", GEN8, RCS0, 0x2500 }, + { "GPUGPU_DISPATCHDIMY", GEN8, RCS0, 0x2504 }, + { "GPUGPU_DISPATCHDIMZ", GEN8, RCS0, 0x2508 }, + { "MI_PREDICATE_SRC0", GEN8, RCS0, 0x2400, 2 }, + { "MI_PREDICATE_SRC1", GEN8, RCS0, 0x2408, 2 }, + { "MI_PREDICATE_DATA", GEN8, RCS0, 0x2410, 2 }, + { "MI_PRED_RESULT", GEN8, RCS0, 0x2418 }, + { "3DPRIM_END_OFFSET", GEN6, RCS0, 0x2420 }, + { "3DPRIM_START_VERTEX", GEN6, RCS0, 0x2430 }, + { "3DPRIM_VERTEX_COUNT", GEN6, RCS0, 0x2434 }, + { "3DPRIM_INSTANCE_COUNT", GEN6, RCS0, 0x2438 }, + { "3DPRIM_START_INSTANCE", GEN6, RCS0, 0x243c }, + { "3DPRIM_BASE_VERTEX", GEN6, RCS0, 0x2440 }, + { "GPGPU_THREADS_DISPATCHED", GEN8, RCS0, 0x2290, 2 }, + { "PS_INVOCATION_COUNT_1", GEN8, RCS0, 0x22f0, 2 }, + { "PS_DEPTH_COUNT_1", GEN8, RCS0, 0x22f8, 2 }, + { "BB_OFFSET", GEN8, RCS0, 0x2158 }, + { "MI_PREDICATE_RESULT_1", GEN8, RCS0, 0x241c }, + { "CS_GPR", GEN8, RCS0, 0x2600, 32 }, + { "OA_CTX_CONTROL", GEN8, RCS0, 0x2360 }, + { "OACTXID", GEN8, RCS0, 0x2364 }, + { "PS_INVOCATION_COUNT_2", GEN8, RCS0, 0x2448, 2 }, + { "PS_DEPTH_COUNT_2", GEN8, RCS0, 0x2450, 2 }, + { "Cache_Mode_0", GEN7, RCS0, 0x7000 }, + { "Cache_Mode_1", GEN7, RCS0, 0x7004 }, + { "GT_MODE", GEN8, RCS0, 0x7008 }, + { "L3_Config", GEN7, RCS0, 0x7034 }, + { "TD_CTL", GEN8, RCS0, 0xe400 }, + { "TD_CTL2", GEN8, RCS0, 0xe404 }, + { "SO_NUM_PRIMS_WRITEN0", GEN6, RCS0, 0x5200, 2 }, + { "SO_NUM_PRIMS_WRITEN1", GEN6, RCS0, 0x5208, 2 }, + { "SO_NUM_PRIMS_WRITEN2", GEN6, RCS0, 0x5210, 2 }, + { "SO_NUM_PRIMS_WRITEN3", GEN6, RCS0, 0x5218, 2 }, + { "SO_PRIM_STORAGE_NEEDED0", GEN6, RCS0, 0x5240, 2 }, + { "SO_PRIM_STORAGE_NEEDED1", GEN6, RCS0, 0x5248, 2 }, + { "SO_PRIM_STORAGE_NEEDED2", GEN6, RCS0, 0x5250, 2 }, + { "SO_PRIM_STORAGE_NEEDED3", GEN6, RCS0, 0x5258, 2 }, + { "SO_WRITE_OFFSET0", GEN7, RCS0, 0x5280 }, + { "SO_WRITE_OFFSET1", GEN7, RCS0, 0x5284 }, + { "SO_WRITE_OFFSET2", GEN7, RCS0, 0x5288 }, + { "SO_WRITE_OFFSET3", GEN7, RCS0, 0x528c }, + { "OA_CONTROL", NOCTX, RCS0, 0x2b00 }, + { "PERF_CNT_1", NOCTX, RCS0, 0x91b8, 2 }, + { "PERF_CNT_2", NOCTX, RCS0, 0x91c0, 2 }, + + /* Privileged (enabled by w/a + FORCE_TO_NONPRIV) */ + { "CTX_PREEMPT", NOCTX /* GEN_RANGE(9, 10) */, RCS0, 0x2248 }, + { "CS_CHICKEN1", GEN_RANGE(9, 10), RCS0, 0x2580 }, + { "HDC_CHICKEN1", GEN_RANGE(9, 10), RCS0, 0x7304 }, + { "L3SQREG1", GEN8, RCS0, 0xb010 }, + + { "BCS_GPR", GEN9, BCS0, 0x22600, 32 }, + { "BCS_SWCTRL", GEN8, BCS0, 0x22200 }, + + { "VCS0_GPR", GEN9, VCS0, 0x12600, 32 }, + { "MFC_VDBOX1", NOCTX, VCS0, 0x12800, 64 }, + + { "VCS1_GPR", GEN9, VCS1, 0x1c600, 32 }, + { "MFC_VDBOX2", NOCTX, VCS1, 0x1c800, 64 }, + + { "VECS_GPR", GEN9, VECS0, 0x1a600, 32 }, + + {} +}, ignore_registers[] = { + { "RCS timestamp", GEN6, ~0u, 0x2358 }, + { "VCS0 timestamp", GEN7, ~0u, 0x12358 }, + { "VCS1 timestamp", GEN7, ~0u, 0x1c358 }, + { "BCS timestamp", GEN7, ~0u, 0x22358 }, + { "VECS timestamp", GEN8, ~0u, 0x1a358 }, + {} +}; + +static const char *register_name(uint32_t offset, char *buf, size_t len) +{ + for (const struct named_register *r = nonpriv_registers; r->name; r++) { + unsigned int width = r->count ? 4*r->count : 4; + if (offset >= r->offset && offset < r->offset + width) { + if (r->count <= 1) + return r->name; + + snprintf(buf, len, "%s[%d]", + r->name, (offset - r->offset)/4); + return buf; + } + } + + return "unknown"; +} + +static bool ignore_register(uint32_t offset) +{ + for (const struct named_register *r = ignore_registers; r->name; r++) { + unsigned int width = r->count ? 4*r->count : 4; + if (offset >= r->offset && offset < r->offset + width) + return true; + } + + return false; +} + +static uint32_t read_regs(int fd, + uint32_t ctx, + const struct intel_execution_engine2 *e, + unsigned int flags) +{ + const unsigned int gen = intel_gen(intel_get_drm_devid(fd)); + const unsigned int gen_bit = 1 << gen; + const unsigned int engine_bit = ENGINE(e->class, e->instance); + const bool r64b = gen >= 8; + struct drm_i915_gem_exec_object2 obj[2]; + struct drm_i915_gem_relocation_entry *reloc; + struct drm_i915_gem_execbuffer2 execbuf; + unsigned int regs_size, batch_size, n; + uint32_t *batch, *b; + + reloc = calloc(NUM_REGS, sizeof(*reloc)); + igt_assert(reloc); + + regs_size = NUM_REGS * sizeof(uint32_t); + regs_size = PAGE_ALIGN(regs_size); + + batch_size = NUM_REGS * 4 * sizeof(uint32_t) + 4; + batch_size = PAGE_ALIGN(batch_size); + + memset(obj, 0, sizeof(obj)); + obj[0].handle = gem_create(fd, regs_size); + obj[1].handle = gem_create(fd, batch_size); + obj[1].relocs_ptr = to_user_pointer(reloc); + + b = batch = gem_mmap__cpu(fd, obj[1].handle, 0, batch_size, PROT_WRITE); + gem_set_domain(fd, obj[1].handle, + I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU); + + n = 0; + for (const struct named_register *r = nonpriv_registers; r->name; r++) { + if (!(r->engine_mask & engine_bit)) + continue; + if (!(r->gen_mask & gen_bit)) + continue; + + for (unsigned count = r->count ?: 1, offset = r->offset; + count--; offset += 4) { + *b++ = 0x24 << 23 | (1 + r64b); /* SRM */ + *b++ = offset; + reloc[n].target_handle = obj[0].handle; + reloc[n].presumed_offset = 0; + reloc[n].offset = (b - batch) * sizeof(*b); + reloc[n].delta = offset; + reloc[n].read_domains = I915_GEM_DOMAIN_RENDER; + reloc[n].write_domain = I915_GEM_DOMAIN_RENDER; + *b++ = offset; + if (r64b) + *b++ = 0; + n++; + } + } + + obj[1].relocation_count = n; + *b++ = MI_BATCH_BUFFER_END; + munmap(batch, batch_size); + + memset(&execbuf, 0, sizeof(execbuf)); + execbuf.buffers_ptr = to_user_pointer(obj); + execbuf.buffer_count = 2; + execbuf.flags = + gem_class_instance_to_eb_flags(fd, e->class, e->instance); + execbuf.rsvd1 = ctx; + gem_execbuf(fd, &execbuf); + gem_close(fd, obj[1].handle); + free(reloc); + + return obj[0].handle; +} + +static void write_regs(int fd, + uint32_t ctx, + const struct intel_execution_engine2 *e, + unsigned int flags, + uint32_t value) +{ + const unsigned int gen_bit = 1 << intel_gen(intel_get_drm_devid(fd)); + const unsigned int engine_bit = ENGINE(e->class, e->instance); + struct drm_i915_gem_exec_object2 obj; + struct drm_i915_gem_execbuffer2 execbuf; + unsigned int batch_size; + uint32_t *batch, *b; + + batch_size = NUM_REGS * 3 * sizeof(uint32_t) + 4; + batch_size = PAGE_ALIGN(batch_size); + + memset(&obj, 0, sizeof(obj)); + obj.handle = gem_create(fd, batch_size); + + b = batch = gem_mmap__cpu(fd, obj.handle, 0, batch_size, PROT_WRITE); + gem_set_domain(fd, obj.handle, + I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU); + for (const struct named_register *r = nonpriv_registers; r->name; r++) { + if (!(r->engine_mask & engine_bit)) + continue; + if (!(r->gen_mask & gen_bit)) + continue; + for (unsigned count = r->count ?: 1, offset = r->offset; + count--; offset += 4) { + *b++ = 0x22 << 23 | 1; /* LRI */ + *b++ = offset; + *b++ = value; + } + } + *b++ = MI_BATCH_BUFFER_END; + munmap(batch, batch_size); + + memset(&execbuf, 0, sizeof(execbuf)); + execbuf.buffers_ptr = to_user_pointer(&obj); + execbuf.buffer_count = 1; + execbuf.flags = + gem_class_instance_to_eb_flags(fd, e->class, e->instance); + execbuf.rsvd1 = ctx; + gem_execbuf(fd, &execbuf); + gem_close(fd, obj.handle); +} + +static void restore_regs(int fd, + uint32_t ctx, + const struct intel_execution_engine2 *e, + unsigned int flags, + uint32_t regs) +{ + const unsigned int gen = intel_gen(intel_get_drm_devid(fd)); + const unsigned int gen_bit = 1 << gen; + const unsigned int engine_bit = ENGINE(e->class, e->instance); + const bool r64b = gen >= 8; + struct drm_i915_gem_exec_object2 obj[2]; + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_relocation_entry *reloc; + unsigned int batch_size, n; + uint32_t *batch, *b; + + if (gen < 7) /* no LRM */ + return; + + reloc = calloc(NUM_REGS, sizeof(*reloc)); + igt_assert(reloc); + + batch_size = NUM_REGS * 3 * sizeof(uint32_t) + 4; + batch_size = PAGE_ALIGN(batch_size); + + memset(obj, 0, sizeof(obj)); + obj[0].handle = regs; + obj[1].handle = gem_create(fd, batch_size); + obj[1].relocs_ptr = to_user_pointer(reloc); + + b = batch = gem_mmap__cpu(fd, obj[1].handle, 0, batch_size, PROT_WRITE); + gem_set_domain(fd, obj[1].handle, + I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU); + + n = 0; + for (const struct named_register *r = nonpriv_registers; r->name; r++) { + if (!(r->engine_mask & engine_bit)) + continue; + if (!(r->gen_mask & gen_bit)) + continue; + + for (unsigned count = r->count ?: 1, offset = r->offset; + count--; offset += 4) { + *b++ = 0x29 << 23 | (1 + r64b); /* LRM */ + *b++ = offset; + reloc[n].target_handle = obj[0].handle; + reloc[n].presumed_offset = 0; + reloc[n].offset = (b - batch) * sizeof(*b); + reloc[n].delta = offset; + reloc[n].read_domains = I915_GEM_DOMAIN_RENDER; + reloc[n].write_domain = 0; + *b++ = offset; + if (r64b) + *b++ = 0; + n++; + } + } + obj[1].relocation_count = n; + *b++ = MI_BATCH_BUFFER_END; + munmap(batch, batch_size); + + memset(&execbuf, 0, sizeof(execbuf)); + execbuf.buffers_ptr = to_user_pointer(obj); + execbuf.buffer_count = 2; + execbuf.flags = + gem_class_instance_to_eb_flags(fd, e->class, e->instance); + execbuf.rsvd1 = ctx; + gem_execbuf(fd, &execbuf); + gem_close(fd, obj[1].handle); +} + +__attribute__((unused)) +static void dump_regs(int fd, + const struct intel_execution_engine2 *e, + unsigned int regs) +{ + const int gen = intel_gen(intel_get_drm_devid(fd)); + const unsigned int gen_bit = 1 << gen; + const unsigned int engine_bit = ENGINE(e->class, e->instance); + unsigned int regs_size; + uint32_t *out; + + regs_size = NUM_REGS * sizeof(uint32_t); + regs_size = PAGE_ALIGN(regs_size); + + out = gem_mmap__cpu(fd, regs, 0, regs_size, PROT_READ); + gem_set_domain(fd, regs, I915_GEM_DOMAIN_CPU, 0); + + for (const struct named_register *r = nonpriv_registers; r->name; r++) { + if (!(r->engine_mask & engine_bit)) + continue; + if (!(r->gen_mask & gen_bit)) + continue; + + if (r->count <= 1) { + igt_debug("0x%04x (%s): 0x%08x\n", + r->offset, r->name, out[r->offset/4]); + } else { + for (unsigned x = 0; x < r->count; x++) + igt_debug("0x%04x (%s[%d]): 0x%08x\n", + r->offset+4*x, r->name, x, + out[r->offset/4 + x]); + } + } + munmap(out, regs_size); +} + +static void compare_regs(int fd, uint32_t A, uint32_t B, const char *who) +{ + unsigned int num_errors; + unsigned int regs_size; + uint32_t *a, *b; + char buf[80]; + + regs_size = NUM_REGS * sizeof(uint32_t); + regs_size = PAGE_ALIGN(regs_size); + + a = gem_mmap__cpu(fd, A, 0, regs_size, PROT_READ); + gem_set_domain(fd, A, I915_GEM_DOMAIN_CPU, 0); + + b = gem_mmap__cpu(fd, B, 0, regs_size, PROT_READ); + gem_set_domain(fd, B, I915_GEM_DOMAIN_CPU, 0); + + num_errors = 0; + for (unsigned int n = 0; n < NUM_REGS; n++) { + uint32_t offset = n * sizeof(uint32_t); + if (a[n] != b[n] && !ignore_register(offset)) { + igt_warn("Register 0x%04x (%s): A=%08x B=%08x\n", + offset, + register_name(offset, buf, sizeof(buf)), + a[n], b[n]); + num_errors++; + } + } + munmap(b, regs_size); + munmap(a, regs_size); + + igt_assert_f(num_errors == 0, + "%d registers mistached between %s.\n", + num_errors, who); +} + +static void isolation(int fd, + const struct intel_execution_engine2 *e, + unsigned int flags) +{ + static const uint32_t values[] = { + 0x0, + 0xffffffff, + 0xcccccccc, + 0x33333333, + 0x55555555, + 0xaaaaaaaa, + 0xdeadbeef + }; + unsigned int engine = gem_class_instance_to_eb_flags(fd, + e->class, + e->instance); + unsigned int num_values = + flags & (DIRTY1 | DIRTY2) ? ARRAY_SIZE(values) : 1; + + gem_quiescent_gpu(fd); + + for (int v = 0; v < num_values; v++) { + igt_spin_t *spin = NULL; + uint32_t ctx[2], regs[2], tmp; + + ctx[0] = gem_context_create(fd); + regs[0] = read_regs(fd, ctx[0], e, flags); + + spin = igt_spin_batch_new(fd, ctx[0], engine, 0); + + if (flags & DIRTY1) { + igt_debug("%s[%d]: Setting all registers of ctx 0 to 0x%08x\n", + __func__, v, values[v]); + write_regs(fd, ctx[0], e, flags, values[v]); + } + + /* + * We create and execute a new context, whilst the HW is + * occupied with the previous context (we should switch from + * the old to the new proto-context without idling, which could + * then load the powercontext). If all goes well, we only see + * the default values from this context, but if goes badly we + * see the corruption from the previous context instead! + */ + ctx[1] = gem_context_create(fd); + regs[1] = read_regs(fd, ctx[1], e, flags); + + if (flags & DIRTY2) { + igt_debug("%s[%d]: Setting all registers of ctx 1 to 0x%08x\n", + __func__, v, ~values[v]); + write_regs(fd, ctx[1], e, flags, ~values[v]); + } + + /* + * Restore the original register values before the HW idles. + * Or else it may never restart! + */ + tmp = read_regs(fd, ctx[0], e, flags); + restore_regs(fd, ctx[0], e, flags, regs[0]); + + igt_spin_batch_free(fd, spin); + + if (!(flags & DIRTY1)) + compare_regs(fd, regs[0], tmp, "two reads of the same ctx"); + compare_regs(fd, regs[0], regs[1], "two virgin contexts"); + + for (int n = 0; n < ARRAY_SIZE(ctx); n++) { + gem_close(fd, regs[n]); + gem_context_destroy(fd, ctx[n]); + } + gem_close(fd, tmp); + } +} + +#define NOSLEEP (0 << 8) +#define S3_DEVICES (1 << 8) +#define S3 (2 << 8) +#define S4_DEVICES (3 << 8) +#define S4 (4 << 8) +#define SLEEP_MASK (0xf << 8) + +static void preservation(int fd, + const struct intel_execution_engine2 *e, + unsigned int flags) +{ + static const uint32_t values[] = { + 0x0, + 0xffffffff, + 0xcccccccc, + 0x33333333, + 0x55555555, + 0xaaaaaaaa, + 0xdeadbeef + }; + const unsigned int num_values = ARRAY_SIZE(values); + unsigned int engine = + gem_class_instance_to_eb_flags(fd, e->class, e->instance); + uint32_t ctx[num_values +1 ]; + uint32_t regs[num_values + 1][2]; + igt_spin_t *spin; + + gem_quiescent_gpu(fd); + + ctx[num_values] = gem_context_create(fd); + spin = igt_spin_batch_new(fd, ctx[num_values], engine, 0); + regs[num_values][0] = read_regs(fd, ctx[num_values], e, flags); + for (int v = 0; v < num_values; v++) { + ctx[v] = gem_context_create(fd); + write_regs(fd, ctx[v], e, flags, values[v]); + + regs[v][0] = read_regs(fd, ctx[v], e, flags); + + } + gem_close(fd, read_regs(fd, ctx[num_values], e, flags)); + igt_spin_batch_free(fd, spin); + + if (flags & RESET) + igt_force_gpu_reset(fd); + + switch (flags & SLEEP_MASK) { + case NOSLEEP: + break; + + case S3_DEVICES: + igt_system_suspend_autoresume(SUSPEND_STATE_MEM, + SUSPEND_TEST_DEVICES); + break; + + case S3: + igt_system_suspend_autoresume(SUSPEND_STATE_MEM, + SUSPEND_TEST_NONE); + break; + + case S4_DEVICES: + igt_system_suspend_autoresume(SUSPEND_STATE_DISK, + SUSPEND_TEST_DEVICES); + break; + + case S4: + igt_system_suspend_autoresume(SUSPEND_STATE_DISK, + SUSPEND_TEST_NONE); + break; + } + + spin = igt_spin_batch_new(fd, ctx[num_values], engine, 0); + for (int v = 0; v < num_values; v++) + regs[v][1] = read_regs(fd, ctx[v], e, flags); + regs[num_values][1] = read_regs(fd, ctx[num_values], e, flags); + igt_spin_batch_free(fd, spin); + + for (int v = 0; v < num_values; v++) { + char buf[80]; + + snprintf(buf, sizeof(buf), "dirty %x context\n", values[v]); + compare_regs(fd, regs[v][0], regs[v][1], buf); + + gem_close(fd, regs[v][0]); + gem_close(fd, regs[v][1]); + gem_context_destroy(fd, ctx[v]); + } + compare_regs(fd, regs[num_values][0], regs[num_values][1], "clean"); + gem_context_destroy(fd, ctx[num_values]); +} + +static unsigned int __has_context_isolation(int fd) +{ + struct drm_i915_getparam gp; + int value = 0; + + memset(&gp, 0, sizeof(gp)); + gp.param = 50; /* I915_PARAM_HAS_CONTEXT_ISOLATION */ + gp.value = &value; + + igt_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp); + errno = 0; + + return value; +} + +igt_main +{ + unsigned int has_context_isolation = 0; + int fd = -1; + + igt_fixture { + int gen; + + fd = drm_open_driver(DRIVER_INTEL); + igt_require_gem(fd); + igt_require(gem_has_contexts(fd)); + + has_context_isolation = __has_context_isolation(fd); + igt_require(has_context_isolation); + + gen = intel_gen(intel_get_drm_devid(fd)); + //igt_ci_fail_on(gen > LAST_KNOWN_GEN); + igt_skip_on(gen > LAST_KNOWN_GEN); + } + + for (const struct intel_execution_engine2 *e = intel_execution_engines2; + e->name; e++) { + igt_subtest_group { + igt_fixture { + igt_require(has_context_isolation & (1 << e->class)); + gem_require_engine(fd, e->class, e->instance); + igt_fork_hang_detector(fd); + } + + igt_subtest_f("%s-clean", e->name) + isolation(fd, e, 0); + igt_subtest_f("%s-dirty-create", e->name) + isolation(fd, e, DIRTY1); + igt_subtest_f("%s-dirty-switch", e->name) + isolation(fd, e, DIRTY2); + + igt_subtest_f("%s-none", e->name) + preservation(fd, e, 0); + igt_subtest_f("%s-S3", e->name) + preservation(fd, e, S3); + igt_subtest_f("%s-S4", e->name) + preservation(fd, e, S4); + + igt_fixture { + igt_stop_hang_detector(); + } + + igt_subtest_f("%s-reset", e->name) { + igt_hang_t hang = igt_allow_hang(fd, 0, 0); + preservation(fd, e, RESET); + igt_disallow_hang(fd, hang); + } + } + } +} diff -Nru intel-gpu-tools-1.21/tests/gem_ctx_param.c intel-gpu-tools-1.22/tests/gem_ctx_param.c --- intel-gpu-tools-1.21/tests/gem_ctx_param.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_ctx_param.c 2018-03-09 14:22:59.000000000 +0000 @@ -24,10 +24,125 @@ * Daniel Vetter */ +#include +#include + #include "igt.h" IGT_TEST_DESCRIPTION("Basic test for context set/get param input validation."); +#define BIT(x) (1ul << (x)) + +#define NEW_CTX BIT(0) +#define USER BIT(1) + +static int reopen_driver(int fd) +{ + char path[256]; + + snprintf(path, sizeof(path), "/proc/self/fd/%d", fd); + fd = open(path, O_RDWR); + igt_assert_lte(0, fd); + + return fd; +} + +static void set_priority(int i915) +{ + static const int64_t test_values[] = { + /* Test space too big, pick significant values */ + INT_MIN, + + I915_CONTEXT_MIN_USER_PRIORITY - 1, + I915_CONTEXT_MIN_USER_PRIORITY, + I915_CONTEXT_MIN_USER_PRIORITY + 1, + + I915_CONTEXT_DEFAULT_PRIORITY - 1, + I915_CONTEXT_DEFAULT_PRIORITY, + I915_CONTEXT_DEFAULT_PRIORITY + 1, + + I915_CONTEXT_MAX_USER_PRIORITY - 1, + I915_CONTEXT_MAX_USER_PRIORITY, + I915_CONTEXT_MAX_USER_PRIORITY + 1, + + INT_MAX + }; + unsigned int size; + int64_t *values; + + igt_require(getuid() == 0); + + size = ARRAY_SIZE(test_values); + values = malloc(sizeof(test_values) * 8); + igt_assert(values); + + for (unsigned i = 0; i < size; i++) { + values[i + 0*size] = test_values[i]; + values[i + 1*size] = test_values[i] | (uint64_t)1 << 32; + values[i + 2*size] = test_values[i] | (uint64_t)rand() << 32; + values[i + 3*size] = test_values[i] ^ rand(); + values[i + 4*size] = rand() % (I915_CONTEXT_MAX_USER_PRIORITY - I915_CONTEXT_MIN_USER_PRIORITY) + I915_CONTEXT_MIN_USER_PRIORITY; + values[i + 5*size] = rand(); + values[i + 6*size] = rand() | (uint64_t)rand() << 32; + values[i + 7*size] = (uint64_t)test_values[i] << 32; + } + size *= 8; + + igt_permute_array(values, size, igt_exchange_int64); + + igt_fork(flags, NEW_CTX | USER) { + int fd = reopen_driver(i915); + struct drm_i915_gem_context_param arg = { + .param = I915_CONTEXT_PARAM_PRIORITY, + .ctx_id = flags & NEW_CTX ? gem_context_create(fd) : 0, + }; + int64_t old_prio; + + if (flags & USER) { + igt_debug("Dropping root privilege\n"); + igt_drop_root(); + } + + gem_context_get_param(fd, &arg); + old_prio = arg.value; + + for (unsigned i = 0; i < size; i++) { + int64_t prio = values[i]; + int expected = 0; + int err; + + arg.value = prio; + + if (flags & USER && + prio > I915_CONTEXT_DEFAULT_PRIORITY) + expected = -EPERM; + + if (prio < I915_CONTEXT_MIN_USER_PRIORITY || + prio > I915_CONTEXT_MAX_USER_PRIORITY) + expected = -EINVAL; + + err =__gem_context_set_param(fd, &arg); + igt_assert_f(err == expected, + "Priority requested %" PRId64 " with flags %x, expected result %d, returned %d\n", + prio, flags, expected, err); + + gem_context_get_param(fd, &arg); + if (!err) + old_prio = prio; + igt_assert_eq(arg.value, old_prio); + } + + arg.value = 0; + gem_context_set_param(fd, &arg); + + if (flags & NEW_CTX) + gem_context_destroy(fd, arg.ctx_id); + } + + igt_waitchildren(); + free(values); +} + igt_main { struct drm_i915_gem_context_param arg; @@ -38,6 +153,8 @@ igt_fixture { fd = drm_open_driver_render(DRIVER_INTEL); + + gem_require_contexts(fd); ctx = gem_context_create(fd); } @@ -136,11 +253,52 @@ gem_context_set_param(fd, &arg); } + arg.param = I915_CONTEXT_PARAM_PRIORITY; + + igt_subtest("set-priority-not-supported") { + igt_require(!gem_scheduler_has_ctx_priority(fd)); + + arg.ctx_id = ctx; + arg.size = 0; + + igt_assert_eq(__gem_context_set_param(fd, &arg), -ENODEV); + } + + igt_subtest_group { + igt_fixture { + igt_require(gem_scheduler_has_ctx_priority(fd)); + } + + igt_subtest("get-priority-new-ctx") { + struct drm_i915_gem_context_param local_arg = arg; + uint32_t local_ctx = gem_context_create(fd); + + local_arg.ctx_id = local_ctx; + + gem_context_get_param(fd, &local_arg); + igt_assert_eq(local_arg.value, I915_CONTEXT_DEFAULT_PRIORITY); + + gem_context_destroy(fd, local_ctx); + } + + igt_subtest("set-priority-invalid-size") { + struct drm_i915_gem_context_param local_arg = arg; + local_arg.ctx_id = ctx; + local_arg.value = 0; + local_arg.size = ~0; + + igt_assert_eq(__gem_context_set_param(fd, &local_arg), -EINVAL); + } + + igt_subtest("set-priority-range") + set_priority(fd); + } + /* NOTE: This testcase intentionally tests for the next free parameter * to catch ABI extensions. Don't "fix" this testcase without adding all * the tests for the new param first. */ - arg.param = I915_CONTEXT_PARAM_BANNABLE + 1; + arg.param = I915_CONTEXT_PARAM_PRIORITY + 1; igt_subtest("invalid-param-get") { arg.ctx_id = ctx; diff -Nru intel-gpu-tools-1.21/tests/gem_ctx_switch.c intel-gpu-tools-1.22/tests/gem_ctx_switch.c --- intel-gpu-tools-1.21/tests/gem_ctx_switch.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_ctx_switch.c 2018-03-09 14:22:59.000000000 +0000 @@ -45,19 +45,6 @@ #define INTERRUPTIBLE 1 -static int __gem_context_create(int fd, uint32_t *ctx_id) -{ - struct drm_i915_gem_context_create arg; - int ret = 0; - - memset(&arg, 0, sizeof(arg)); - if (drmIoctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &arg)) - ret = -errno; - - *ctx_id = arg.ctx_id; - return ret; -} - static double elapsed(const struct timespec *start, const struct timespec *end) { return ((end->tv_sec - start->tv_sec) + @@ -78,8 +65,7 @@ gem_require_ring(fd, e->exec_id | e->flags); - igt_require(__gem_context_create(fd, &contexts[0]) == 0); - for (n = 1; n < 64; n++) + for (n = 0; n < 64; n++) contexts[n] = gem_context_create(fd); memset(&obj, 0, sizeof(obj)); @@ -115,6 +101,13 @@ struct timespec start, now; unsigned int count = 0; + /* Warmup to bind all objects into each ctx before we begin */ + for (int i = 0; i < ARRAY_SIZE(contexts); i++) { + execbuf.rsvd1 = contexts[i]; + gem_execbuf(fd, &execbuf); + } + gem_sync(fd, handle); + clock_gettime(CLOCK_MONOTONIC, &start); do { igt_while_interruptible(flags & INTERRUPTIBLE) { @@ -140,6 +133,80 @@ gem_context_destroy(fd, contexts[n]); } +static void all(int fd, uint32_t handle, unsigned flags, int timeout) +{ + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_exec_object2 obj[2]; + unsigned int engine[16], e; + const char *name[16]; + uint32_t contexts[65]; + unsigned int nengine; + int n; + + nengine = 0; + for_each_physical_engine(fd, e) { + engine[nengine] = e; + name[nengine] = e__->name; + nengine++; + } + igt_require(nengine); + + for (n = 0; n < ARRAY_SIZE(contexts); n++) + contexts[n] = gem_context_create(fd); + + memset(obj, 0, sizeof(obj)); + obj[1].handle = handle; + + memset(&execbuf, 0, sizeof(execbuf)); + execbuf.buffers_ptr = to_user_pointer(obj + 1); + execbuf.buffer_count = 1; + execbuf.rsvd1 = contexts[0]; + execbuf.flags |= LOCAL_I915_EXEC_HANDLE_LUT; + execbuf.flags |= LOCAL_I915_EXEC_NO_RELOC; + igt_require(__gem_execbuf(fd, &execbuf) == 0); + gem_sync(fd, handle); + execbuf.buffers_ptr = to_user_pointer(obj); + execbuf.buffer_count = 2; + + for (int pot = 2; pot <= 64; pot *= 2) { + for (int nctx = pot - 1; nctx <= pot + 1; nctx++) { + igt_fork(child, nengine) { + struct timespec start, now; + unsigned int count = 0; + + obj[0].handle = gem_create(fd, 4096); + execbuf.flags |= engine[child]; + for (int loop = 0; loop < ARRAY_SIZE(contexts); loop++) { + execbuf.rsvd1 = contexts[loop]; + gem_execbuf(fd, &execbuf); + } + gem_sync(fd, obj[0].handle); + + clock_gettime(CLOCK_MONOTONIC, &start); + do { + for (int loop = 0; loop < 1024; loop++) { + execbuf.rsvd1 = contexts[loop % nctx]; + gem_execbuf(fd, &execbuf); + } + count += 1024; + clock_gettime(CLOCK_MONOTONIC, &now); + } while (elapsed(&start, &now) < timeout); + gem_sync(fd, obj[0].handle); + clock_gettime(CLOCK_MONOTONIC, &now); + gem_close(fd, obj[0].handle); + + igt_info("[%d:%d] %s: %'u cycles: %.3fus%s\n", + nctx, child, name[child], count, elapsed(&start, &now)*1e6 / count, + flags & INTERRUPTIBLE ? " (interruptible)" : ""); + } + igt_waitchildren(); + } + } + + for (n = 0; n < ARRAY_SIZE(contexts); n++) + gem_context_destroy(fd, contexts[n]); +} + igt_main { const int ncpus = sysconf(_SC_NPROCESSORS_ONLN); @@ -153,6 +220,8 @@ fd = drm_open_driver(DRIVER_INTEL); igt_require_gem(fd); + gem_require_contexts(fd); + light = gem_create(fd, 4096); gem_write(fd, light, 0, &bbe, sizeof(bbe)); @@ -180,6 +249,11 @@ single(fd, light, e, INTERRUPTIBLE, ncpus, 150); } + igt_subtest("basic-all-light") + all(fd, light, 0, 5); + igt_subtest("basic-all-heavy") + all(fd, heavy, 0, 5); + igt_fixture { igt_stop_hang_detector(); gem_close(fd, heavy); diff -Nru intel-gpu-tools-1.21/tests/gem_ctx_thrash.c intel-gpu-tools-1.22/tests/gem_ctx_thrash.c --- intel-gpu-tools-1.21/tests/gem_ctx_thrash.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_ctx_thrash.c 2018-03-09 14:22:59.000000000 +0000 @@ -86,33 +86,10 @@ return count; } -static int has_engine(int fd, const struct intel_execution_engine *e, uint32_t ctx) -{ - uint32_t bbe = MI_BATCH_BUFFER_END; - struct drm_i915_gem_execbuffer2 execbuf; - struct drm_i915_gem_exec_object2 exec; - int ret; - - memset(&exec, 0, sizeof(exec)); - exec.handle = gem_create(fd, 4096); - gem_write(fd, exec.handle, 0, &bbe, sizeof(bbe)); - - memset(&execbuf, 0, sizeof(execbuf)); - execbuf.buffers_ptr = to_user_pointer(&exec); - execbuf.buffer_count = 1; - execbuf.flags = e->exec_id | e->flags; - execbuf.rsvd1 = ctx; - ret = __gem_execbuf(fd, &execbuf); - gem_close(fd, exec.handle); - - return ret; -} - static void single(const char *name, bool all_engines) { struct drm_i915_gem_exec_object2 *obj; struct drm_i915_gem_relocation_entry *reloc; - const struct intel_execution_engine *e; unsigned engines[16]; uint64_t size; uint32_t *ctx, *map, scratch; @@ -124,26 +101,15 @@ igt_require_gem(fd); igt_require(gem_can_store_dword(fd, 0)); + gem_require_contexts(fd); + gen = intel_gen(intel_get_drm_devid(fd)); num_engines = 0; if (all_engines) { - for (e = intel_execution_engines; e->name; e++) { - if (e->exec_id == 0) - continue; - - if (has_engine(fd, e, 0)) - continue; - - if (e->exec_id == I915_EXEC_BSD) { - int is_bsd2 = e->flags != 0; - if (gem_has_bsd2(fd) != is_bsd2) - continue; - } - - igt_require(has_engine(fd, e, 1) == -ENOENT); - - engines[num_engines++] = e->exec_id | e->flags; + unsigned engine; + for_each_physical_engine(fd, engine) { + engines[num_engines++] = engine; if (num_engines == ARRAY_SIZE(engines)) break; } @@ -240,8 +206,7 @@ static void processes(void) { - const struct intel_execution_engine *e; - unsigned engines[16]; + unsigned engines[16], engine; int num_engines; struct rlimit rlim; unsigned num_ctx; @@ -251,20 +216,8 @@ fd = drm_open_driver(DRIVER_INTEL); num_engines = 0; - for (e = intel_execution_engines; e->name; e++) { - if (e->exec_id == 0) - continue; - - if (has_engine(fd, e, 0)) - continue; - - if (e->exec_id == I915_EXEC_BSD) { - int is_bsd2 = e->flags != 0; - if (gem_has_bsd2(fd) != is_bsd2) - continue; - } - - engines[num_engines++] = e->exec_id | e->flags; + for_each_physical_engine(fd, engine) { + engines[num_engines++] = engine; if (num_engines == ARRAY_SIZE(engines)) break; } @@ -371,6 +324,10 @@ struct thread data; data.fd = drm_open_driver_render(DRIVER_INTEL); + igt_require_gem(data.fd); + + gem_require_contexts(data.fd); + data.num_ctx = get_num_contexts(data.fd, false); data.all_ctx = malloc(data.num_ctx * sizeof(uint32_t)); igt_assert(data.all_ctx); diff -Nru intel-gpu-tools-1.21/tests/gem_eio.c intel-gpu-tools-1.22/tests/gem_eio.c --- intel-gpu-tools-1.21/tests/gem_eio.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_eio.c 2018-03-09 14:22:59.000000000 +0000 @@ -67,6 +67,8 @@ /* And just check the gpu is indeed running again */ igt_debug("Checking that the GPU recovered\n"); gem_test_engine(fd, -1); + + gem_quiescent_gpu(fd); } static void wedge_gpu(int fd) @@ -133,15 +135,17 @@ static int __gem_wait(int fd, uint32_t handle, int64_t timeout) { - struct drm_i915_gem_wait wait; - int err = 0; + struct drm_i915_gem_wait wait = { + .bo_handle = handle, + .timeout_ns = timeout, + }; + int err; - memset(&wait, 0, sizeof(wait)); - wait.bo_handle = handle; - wait.timeout_ns = timeout; + err = 0; if (drmIoctl(fd, DRM_IOCTL_I915_GEM_WAIT, &wait)) err = -errno; + errno = 0; return err; } @@ -149,6 +153,8 @@ { igt_hang_t hang; + igt_require_gem(fd); + /* If the request we wait on completes due to a hang (even for * that request), the user expects the return value to 0 (success). */ @@ -170,6 +176,9 @@ static void test_suspend(int fd, int state) { + /* Do a suspend first so that we don't skip inside the test */ + igt_system_suspend_autoresume(state, SUSPEND_TEST_DEVICES); + /* Check we can suspend when the driver is already wedged */ igt_require(i915_reset_control(false)); wedgeme(fd); @@ -182,12 +191,11 @@ static void test_inflight(int fd) { - struct drm_i915_gem_execbuffer2 execbuf; + const uint32_t bbe = MI_BATCH_BUFFER_END; struct drm_i915_gem_exec_object2 obj[2]; - uint32_t bbe = MI_BATCH_BUFFER_END; unsigned int engine; - int fence[64]; /* conservative estimate of ring size */ + igt_require_gem(fd); igt_require(gem_has_exec_fence(fd)); memset(obj, 0, sizeof(obj)); @@ -196,13 +204,17 @@ gem_write(fd, obj[1].handle, 0, &bbe, sizeof(bbe)); for_each_engine(fd, engine) { - igt_hang_t hang; + struct drm_i915_gem_execbuffer2 execbuf; + igt_spin_t *hang; + int fence[64]; /* conservative estimate of ring size */ + + gem_quiescent_gpu(fd); igt_debug("Starting %s on engine '%s'\n", __func__, e__->name); igt_require(i915_reset_control(false)); - hang = igt_hang_ring(fd, engine); - obj[0].handle = hang.handle; + hang = __igt_spin_batch_new(fd, 0, engine, 0); + obj[0].handle = hang->handle; memset(&execbuf, 0, sizeof(execbuf)); execbuf.buffers_ptr = to_user_pointer(obj); @@ -215,14 +227,13 @@ igt_assert(fence[n] != -1); } - igt_post_hang_ring(fd, hang); - igt_assert_eq(__gem_wait(fd, obj[1].handle, -1), 0); for (unsigned int n = 0; n < ARRAY_SIZE(fence); n++) { igt_assert_eq(sync_fence_status(fence[n]), -EIO); close(fence[n]); } + igt_spin_batch_free(fd, hang); igt_assert(i915_reset_control(true)); trigger_reset(fd); } @@ -234,8 +245,9 @@ struct drm_i915_gem_exec_object2 obj[2]; uint32_t bbe = MI_BATCH_BUFFER_END; int fence[64]; /* conservative estimate of ring size */ - igt_hang_t hang; + igt_spin_t *hang; + igt_require_gem(fd); igt_require(gem_has_exec_fence(fd)); igt_require(i915_reset_control(false)); @@ -244,8 +256,8 @@ obj[1].handle = gem_create(fd, 4096); gem_write(fd, obj[1].handle, 0, &bbe, sizeof(bbe)); - hang = igt_hang_ring(fd, 0); - obj[0].handle = hang.handle; + hang = __igt_spin_batch_new(fd, 0, 0, 0); + obj[0].handle = hang->handle; memset(&execbuf, 0, sizeof(execbuf)); execbuf.buffers_ptr = to_user_pointer(obj); @@ -261,44 +273,47 @@ igt_set_autoresume_delay(30); igt_system_suspend_autoresume(SUSPEND_STATE_MEM, SUSPEND_TEST_NONE); - igt_post_hang_ring(fd, hang); - igt_assert_eq(__gem_wait(fd, obj[1].handle, -1), 0); for (unsigned int n = 0; n < ARRAY_SIZE(fence); n++) { igt_assert_eq(sync_fence_status(fence[n]), -EIO); close(fence[n]); } + igt_spin_batch_free(fd, hang); igt_assert(i915_reset_control(true)); trigger_reset(fd); } -static uint32_t __gem_context_create(int fd) +static uint32_t context_create_safe(int i915) { - struct drm_i915_gem_context_create create; + struct drm_i915_gem_context_param param; - memset(&create, 0, sizeof(create)); - if (ioctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &create)) - return 0; + memset(¶m, 0, sizeof(param)); - return create.ctx_id; + param.ctx_id = gem_context_create(i915); + param.param = I915_CONTEXT_PARAM_BANNABLE; + gem_context_set_param(i915, ¶m); + + param.param = I915_CONTEXT_PARAM_NO_ERROR_CAPTURE; + param.value = 1; + gem_context_set_param(i915, ¶m); + + return param.ctx_id; } static void test_inflight_contexts(int fd) { - struct drm_i915_gem_execbuffer2 execbuf; struct drm_i915_gem_exec_object2 obj[2]; - uint32_t bbe = MI_BATCH_BUFFER_END; + const uint32_t bbe = MI_BATCH_BUFFER_END; unsigned int engine; uint32_t ctx[64]; - int fence[64]; + igt_require_gem(fd); igt_require(gem_has_exec_fence(fd)); + gem_require_contexts(fd); - ctx[0] = __gem_context_create(fd); - igt_require(ctx[0]); - for (unsigned int n = 1; n < ARRAY_SIZE(ctx); n++) - ctx[n] = gem_context_create(fd); + for (unsigned int n = 0; n < ARRAY_SIZE(ctx); n++) + ctx[n] = context_create_safe(fd); memset(obj, 0, sizeof(obj)); obj[0].flags = EXEC_OBJECT_WRITE; @@ -306,13 +321,17 @@ gem_write(fd, obj[1].handle, 0, &bbe, sizeof(bbe)); for_each_engine(fd, engine) { - igt_hang_t hang; + struct drm_i915_gem_execbuffer2 execbuf; + igt_spin_t *hang; + int fence[64]; + + gem_quiescent_gpu(fd); igt_debug("Starting %s on engine '%s'\n", __func__, e__->name); igt_require(i915_reset_control(false)); - hang = igt_hang_ring(fd, engine); - obj[0].handle = hang.handle; + hang = __igt_spin_batch_new(fd, 0, engine, 0); + obj[0].handle = hang->handle; memset(&execbuf, 0, sizeof(execbuf)); execbuf.buffers_ptr = to_user_pointer(obj); @@ -326,14 +345,13 @@ igt_assert(fence[n] != -1); } - igt_post_hang_ring(fd, hang); - igt_assert_eq(__gem_wait(fd, obj[1].handle, -1), 0); for (unsigned int n = 0; n < ARRAY_SIZE(fence); n++) { igt_assert_eq(sync_fence_status(fence[n]), -EIO); close(fence[n]); } + igt_spin_batch_free(fd, hang); igt_assert(i915_reset_control(true)); trigger_reset(fd); } @@ -344,20 +362,20 @@ static void test_inflight_external(int fd) { + const uint32_t bbe = MI_BATCH_BUFFER_END; struct drm_i915_gem_execbuffer2 execbuf; struct drm_i915_gem_exec_object2 obj; - uint32_t bbe = MI_BATCH_BUFFER_END; - igt_hang_t hang; - int timeline, fence; + igt_spin_t *hang; + uint32_t fence; + IGT_CORK_FENCE(cork); igt_require_sw_sync(); igt_require(gem_has_exec_fence(fd)); - timeline = sw_sync_timeline_create(); - fence = sw_sync_timeline_create_fence(timeline, 1); + fence = igt_cork_plug(&cork, fd); igt_require(i915_reset_control(false)); - hang = igt_hang_ring(fd, I915_EXEC_DEFAULT); + hang = __igt_spin_batch_new(fd, 0, 0, 0); memset(&obj, 0, sizeof(obj)); obj.handle = gem_create(fd, 4096); @@ -375,16 +393,18 @@ fence = execbuf.rsvd2 >> 32; igt_assert(fence != -1); - igt_post_hang_ring(fd, hang); /* wedged, with an unready batch */ - sw_sync_timeline_inc(timeline, 1); /* only now submit our batches */ + gem_sync(fd, hang->handle); /* wedged, with an unready batch */ + igt_assert(!gem_bo_busy(fd, hang->handle)); + igt_assert(gem_bo_busy(fd, obj.handle)); + igt_cork_unplug(&cork); /* only now submit our batches */ igt_assert_eq(__gem_wait(fd, obj.handle, -1), 0); igt_assert_eq(sync_fence_status(fence), -EIO); close(fence); + igt_spin_batch_free(fd, hang); igt_assert(i915_reset_control(true)); trigger_reset(fd); - close(timeline); } static void test_inflight_internal(int fd) @@ -394,15 +414,16 @@ uint32_t bbe = MI_BATCH_BUFFER_END; unsigned engine, nfence = 0; int fences[16]; - igt_hang_t hang; + igt_spin_t *hang; + igt_require_gem(fd); igt_require(gem_has_exec_fence(fd)); igt_require(i915_reset_control(false)); - hang = igt_hang_ring(fd, I915_EXEC_DEFAULT); + hang = __igt_spin_batch_new(fd, 0, 0, 0); memset(obj, 0, sizeof(obj)); - obj[0].handle = hang.handle; + obj[0].handle = hang->handle; obj[0].flags = EXEC_OBJECT_WRITE; obj[1].handle = gem_create(fd, 4096); gem_write(fd, obj[1].handle, 0, &bbe, sizeof(bbe)); @@ -420,14 +441,13 @@ nfence++; } - igt_post_hang_ring(fd, hang); /* wedged, with an unready batch */ - igt_assert_eq(__gem_wait(fd, obj[1].handle, -1), 0); while (nfence--) { igt_assert_eq(sync_fence_status(fences[nfence]), -EIO); close(fences[nfence]); } + igt_spin_batch_free(fd, hang); igt_assert(i915_reset_control(true)); trigger_reset(fd); } @@ -454,7 +474,8 @@ gem_submission_print_method(fd); igt_require_gem(fd); - igt_require_hang_ring(fd, I915_EXEC_DEFAULT); + + igt_allow_hang(fd, 0, 0); } igt_subtest("throttle") diff -Nru intel-gpu-tools-1.21/tests/gem_evict_alignment.c intel-gpu-tools-1.22/tests/gem_evict_alignment.c --- intel-gpu-tools-1.21/tests/gem_evict_alignment.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_evict_alignment.c 2018-03-09 14:22:59.000000000 +0000 @@ -61,7 +61,7 @@ struct drm_i915_gem_exec_object2 *obj; struct drm_i915_gem_execbuffer2 exec; uint32_t handle; - int n, ret, i=0; + int n, i=0; batch[i++] = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | @@ -121,10 +121,7 @@ i915_execbuffer2_set_context_id(exec, 0); exec.rsvd2 = 0; - ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec); - if (ret) - ret = errno; - igt_assert_eq(ret, error); + igt_assert_eq(__gem_execbuf(fd, &exec), -error); gem_close(fd, handle); free(obj); diff -Nru intel-gpu-tools-1.21/tests/gem_exec_async.c intel-gpu-tools-1.22/tests/gem_exec_async.c --- intel-gpu-tools-1.21/tests/gem_exec_async.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_exec_async.c 2018-03-09 14:22:59.000000000 +0000 @@ -88,6 +88,7 @@ #define BATCH 1 struct drm_i915_gem_relocation_entry reloc; struct drm_i915_gem_execbuffer2 execbuf; + unsigned int other; uint32_t *batch; int i; @@ -142,19 +143,14 @@ gem_close(fd, obj[BATCH].handle); i = 0; - for (const struct intel_execution_engine *e = intel_execution_engines; - e->name; e++) { - if (e->exec_id == 0 || e->exec_id == ring) + for_each_physical_engine(fd, other) { + if (other == ring) continue; - if (!gem_has_ring(fd, e->exec_id | e->flags)) + if (!gem_can_store_dword(fd, other)) continue; - if (!gem_can_store_dword(fd, e->exec_id | e->flags)) - continue; - - store_dword(fd, e->exec_id | e->flags, - obj[SCRATCH].handle, 4*i, i); + store_dword(fd, other, obj[SCRATCH].handle, 4*i, i); i++; } @@ -209,6 +205,7 @@ continue; igt_subtest_f("concurrent-writes-%s", e->name) { + igt_require(gem_ring_has_physical_engine(fd, e->exec_id | e->flags)); igt_require(gem_can_store_dword(fd, e->exec_id | e->flags)); one(fd, e->exec_id, e->flags); } diff -Nru intel-gpu-tools-1.21/tests/gem_exec_await.c intel-gpu-tools-1.22/tests/gem_exec_await.c --- intel-gpu-tools-1.21/tests/gem_exec_await.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_exec_await.c 2018-03-09 14:22:59.000000000 +0000 @@ -26,6 +26,7 @@ #include "igt_rand.h" #include "igt_sysfs.h" #include "igt_vgem.h" +#include "i915/gem_ring.h" #include #include @@ -44,26 +45,6 @@ (end->tv_nsec - start->tv_nsec)*1e-9); } -static bool ignore_engine(int fd, unsigned engine) -{ - if (engine == 0) - return true; - - if (gem_has_bsd2(fd) && engine == I915_EXEC_BSD) - return true; - - return false; -} - -static uint32_t __gem_context_create(int fd) -{ - struct drm_i915_gem_context_create arg; - - memset(&arg, 0, sizeof(arg)); - drmIoctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &arg); - return arg.ctx_id; -} - static void xchg_obj(void *array, unsigned i, unsigned j) { struct drm_i915_gem_exec_object2 *obj = array; @@ -98,12 +79,8 @@ double time; nengine = 0; - for_each_engine(fd, engine) { - if (ignore_engine(fd, engine)) - continue; - + for_each_physical_engine(fd, engine) engines[nengine++] = engine; - } igt_require(nengine); exec = calloc(nengine, sizeof(*exec)); @@ -130,8 +107,7 @@ LOCAL_I915_EXEC_HANDLE_LUT); if (flags & CONTEXTS) { - exec[e].execbuf.rsvd1 = __gem_context_create(fd); - igt_require(exec[e].execbuf.rsvd1); + exec[e].execbuf.rsvd1 = gem_context_create(fd); } exec[e].exec[0].handle = gem_create(fd, 4096); @@ -174,7 +150,7 @@ if (flags & CONTEXTS) { gem_context_destroy(fd, exec[e].execbuf.rsvd1); - exec[e].execbuf.rsvd1 = __gem_context_create(fd); + exec[e].execbuf.rsvd1 = gem_context_create(fd); } exec[e].reloc.presumed_offset = exec[e].exec[1].offset; @@ -247,94 +223,6 @@ free(exec); } -struct cork { - int device; - uint32_t handle; - uint32_t fence; -}; - -static void plug(int fd, struct cork *c) -{ - struct vgem_bo bo; - int dmabuf; - - c->device = drm_open_driver(DRIVER_VGEM); - - bo.width = bo.height = 1; - bo.bpp = 4; - vgem_create(c->device, &bo); - c->fence = vgem_fence_attach(c->device, &bo, VGEM_FENCE_WRITE); - - dmabuf = prime_handle_to_fd(c->device, bo.handle); - c->handle = prime_fd_to_handle(fd, dmabuf); - close(dmabuf); -} - -static void unplug(struct cork *c) -{ - vgem_fence_signal(c->device, c->fence); - close(c->device); -} - -static void alarm_handler(int sig) -{ -} - -static int __execbuf(int fd, struct drm_i915_gem_execbuffer2 *execbuf) -{ - return ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, execbuf); -} - -static unsigned int measure_ring_size(int fd) -{ - struct sigaction sa = { .sa_handler = alarm_handler }; - struct drm_i915_gem_exec_object2 obj[2]; - struct drm_i915_gem_execbuffer2 execbuf; - const uint32_t bbe = MI_BATCH_BUFFER_END; - unsigned int count, last; - struct itimerval itv; - struct cork c; - - memset(obj, 0, sizeof(obj)); - obj[1].handle = gem_create(fd, 4096); - gem_write(fd, obj[1].handle, 0, &bbe, sizeof(bbe)); - - plug(fd, &c); - obj[0].handle = c.handle; - - memset(&execbuf, 0, sizeof(execbuf)); - execbuf.buffers_ptr = to_user_pointer(obj); - execbuf.buffer_count = 2; - - sigaction(SIGALRM, &sa, NULL); - itv.it_interval.tv_sec = 0; - itv.it_interval.tv_usec = 100; - itv.it_value.tv_sec = 0; - itv.it_value.tv_usec = 1000; - setitimer(ITIMER_REAL, &itv, NULL); - - last = count = 0; - do { - if (__execbuf(fd, &execbuf) == 0) { - count++; - continue; - } - - if (last == count) - break; - - last = count; - } while (1); - - memset(&itv, 0, sizeof(itv)); - setitimer(ITIMER_REAL, &itv, NULL); - - unplug(&c); - gem_close(fd, obj[1].handle); - - return count; -} - igt_main { int ring_size = 0; @@ -346,7 +234,7 @@ igt_require_gem(device); gem_submission_print_method(device); - ring_size = measure_ring_size(device) - 10; + ring_size = gem_measure_ring_inflight(device, 0, 0) - 10; if (!gem_has_execlists(device)) ring_size /= 2; igt_info("Ring size: %d batches\n", ring_size); @@ -358,8 +246,10 @@ igt_subtest("wide-all") wide(device, ring_size, 20, 0); - igt_subtest("wide-contexts") + igt_subtest("wide-contexts") { + gem_require_contexts(device); wide(device, ring_size, 20, CONTEXTS); + } igt_fixture { igt_stop_hang_detector(); diff -Nru intel-gpu-tools-1.21/tests/gem_exec_bad_domains.c intel-gpu-tools-1.22/tests/gem_exec_bad_domains.c --- intel-gpu-tools-1.21/tests/gem_exec_bad_domains.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_exec_bad_domains.c 2018-03-09 14:22:59.000000000 +0000 @@ -95,7 +95,6 @@ struct drm_i915_gem_exec_object2 exec[2]; struct drm_i915_gem_relocation_entry reloc[1]; uint32_t handle, handle_target; - int ret; handle = gem_create(fd, 4096); handle_target = gem_create(fd, 4096); @@ -137,10 +136,7 @@ i915_execbuffer2_set_context_id(execbuf, 0); execbuf.rsvd2 = 0; - ret = drmIoctl(fd, - DRM_IOCTL_I915_GEM_EXECBUFFER2, - &execbuf); - igt_assert(ret != 0 && errno == EINVAL); + igt_assert_eq(__gem_execbuf(fd, &execbuf), -EINVAL); gem_close(fd, handle); gem_close(fd, handle_target); diff -Nru intel-gpu-tools-1.21/tests/gem_exec_blt.c intel-gpu-tools-1.22/tests/gem_exec_blt.c --- intel-gpu-tools-1.21/tests/gem_exec_blt.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_exec_blt.c 2018-03-09 14:22:59.000000000 +0000 @@ -228,12 +228,12 @@ execbuf.flags |= LOCAL_I915_EXEC_HANDLE_LUT; execbuf.flags |= LOCAL_I915_EXEC_NO_RELOC; - if (drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf)) { + if (__gem_execbuf(fd, &execbuf)) { len = gem_linear_blt(fd, buf, src, dst, object_size, reloc); igt_assert(len == execbuf.batch_len); gem_write(fd, handle, 0, buf, len); execbuf.flags = ring; - do_ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); + gem_execbuf(fd, &execbuf); } gem_sync(fd, handle); diff -Nru intel-gpu-tools-1.21/tests/gem_exec_capture.c intel-gpu-tools-1.22/tests/gem_exec_capture.c --- intel-gpu-tools-1.21/tests/gem_exec_capture.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_exec_capture.c 2018-03-09 14:22:59.000000000 +0000 @@ -22,6 +22,7 @@ */ #include "igt.h" +#include "igt_device.h" #include "igt_sysfs.h" #define LOCAL_OBJECT_CAPTURE (1 << 7) @@ -56,7 +57,7 @@ igt_assert(found); } -static void capture(int fd, int dir, unsigned ring) +static void __capture(int fd, int dir, unsigned ring, uint32_t target) { const int gen = intel_gen(intel_get_drm_devid(fd)); struct drm_i915_gem_exec_object2 obj[4]; @@ -71,7 +72,7 @@ memset(obj, 0, sizeof(obj)); obj[SCRATCH].handle = gem_create(fd, 4096); - obj[CAPTURE].handle = gem_create(fd, 4096); + obj[CAPTURE].handle = target; obj[CAPTURE].flags = LOCAL_OBJECT_CAPTURE; obj[NOCAPTURE].handle = gem_create(fd, 4096); @@ -141,6 +142,8 @@ execbuf.buffers_ptr = (uintptr_t)obj; execbuf.buffer_count = ARRAY_SIZE(obj); execbuf.flags = ring; + if (gen > 3 && gen < 6) + execbuf.flags |= I915_EXEC_SECURE; gem_execbuf(fd, &execbuf); /* Wait for the request to start */ @@ -156,10 +159,32 @@ gem_close(fd, obj[BATCH].handle); gem_close(fd, obj[NOCAPTURE].handle); - gem_close(fd, obj[CAPTURE].handle); gem_close(fd, obj[SCRATCH].handle); } +static void capture(int fd, int dir, unsigned ring) +{ + uint32_t handle; + + handle = gem_create(fd, 4096); + __capture(fd, dir, ring, handle); + gem_close(fd, handle); +} + +static void userptr(int fd, int dir) +{ + uint32_t handle; + void *ptr; + + igt_assert(posix_memalign(&ptr, 4096, 4096) == 0); + igt_require(__gem_userptr(fd, ptr, 4096, 0, 0, &handle) == 0); + + __capture(fd, dir, 0, handle); + + gem_close(fd, handle); + free(ptr); +} + static bool has_capture(int fd) { drm_i915_getparam_t gp; @@ -182,7 +207,14 @@ igt_skip_on_simulation(); igt_fixture { + int gen; + fd = drm_open_driver(DRIVER_INTEL); + + gen = intel_gen(intel_get_drm_devid(fd)); + if (gen > 3 && gen < 6) /* ctg and ilk need secure batches */ + igt_device_set_master(fd); + igt_require_gem(fd); gem_require_mmap_wc(fd); igt_require(has_capture(fd)); @@ -198,12 +230,19 @@ continue; igt_subtest_f("capture-%s", e->name) { - gem_require_ring(fd, e->exec_id | e->flags); + igt_require(gem_ring_has_physical_engine(fd, e->exec_id | e->flags)); igt_require(gem_can_store_dword(fd, e->exec_id | e->flags)); capture(fd, dir, e->exec_id | e->flags); } } + /* And check we can read from different types of objects */ + + igt_subtest_f("userptr") { + igt_require(gem_can_store_dword(fd, 0)); + userptr(fd, dir); + } + igt_fixture { close(dir); igt_disallow_hang(fd, hang); diff -Nru intel-gpu-tools-1.21/tests/gem_exec_create.c intel-gpu-tools-1.22/tests/gem_exec_create.c --- intel-gpu-tools-1.21/tests/gem_exec_create.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_exec_create.c 2018-03-09 14:22:59.000000000 +0000 @@ -54,17 +54,6 @@ (end->tv_nsec - start->tv_nsec)*1e-9); } -static bool ignore_engine(int fd, unsigned engine) -{ - if (engine == 0) - return true; - - if (gem_has_bsd2(fd) && engine == I915_EXEC_BSD) - return true; - - return false; -} - #define LEAK 0x1 static void all(int fd, unsigned flags, int timeout, int ncpus) @@ -77,12 +66,8 @@ unsigned engine; nengine = 0; - for_each_engine(fd, engine) { - if (ignore_engine(fd, engine)) - continue; - + for_each_physical_engine(fd, engine) engines[nengine++] = engine; - } igt_require(nengine); memset(&obj, 0, sizeof(obj)); diff -Nru intel-gpu-tools-1.21/tests/gem_exec_fence.c intel-gpu-tools-1.22/tests/gem_exec_fence.c --- intel-gpu-tools-1.21/tests/gem_exec_fence.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_exec_fence.c 2018-03-09 14:22:59.000000000 +0000 @@ -25,6 +25,7 @@ #include "igt_sysfs.h" #include "igt_vgem.h" #include "sw_sync.h" +#include "i915/gem_ring.h" #include #include @@ -273,7 +274,7 @@ igt_assert(fence != -1); i = 0; - for_each_engine(fd, engine) { + for_each_physical_engine(fd, engine) { if (!gem_can_store_dword(fd, engine)) continue; @@ -321,99 +322,20 @@ gem_execbuf(fd, &execbuf); } -struct cork { - int device; - uint32_t handle; - uint32_t fence; -}; - -static void plug(int fd, struct cork *c) -{ - struct vgem_bo bo; - int dmabuf; - - c->device = drm_open_driver(DRIVER_VGEM); - - bo.width = bo.height = 1; - bo.bpp = 4; - vgem_create(c->device, &bo); - c->fence = vgem_fence_attach(c->device, &bo, VGEM_FENCE_WRITE); - - dmabuf = prime_handle_to_fd(c->device, bo.handle); - c->handle = prime_fd_to_handle(fd, dmabuf); - close(dmabuf); -} - -static void unplug(int fd, struct cork *c) -{ - vgem_fence_signal(c->device, c->fence); - gem_close(fd, c->handle); - close(c->device); -} - static void alarm_handler(int sig) { } static int __execbuf(int fd, struct drm_i915_gem_execbuffer2 *execbuf) { - return ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, execbuf); -} - -static unsigned int measure_ring_size(int fd) -{ - struct sigaction sa = { .sa_handler = alarm_handler }; - struct drm_i915_gem_exec_object2 obj[2]; - struct drm_i915_gem_execbuffer2 execbuf; - const uint32_t bbe = MI_BATCH_BUFFER_END; - unsigned int count, last; - struct itimerval itv; - struct cork c; - - memset(obj, 0, sizeof(obj)); - obj[1].handle = gem_create(fd, 4096); - gem_write(fd, obj[1].handle, 0, &bbe, sizeof(bbe)); - - memset(&execbuf, 0, sizeof(execbuf)); - execbuf.buffers_ptr = to_user_pointer(&obj[1]); - execbuf.buffer_count = 1; - gem_execbuf(fd, &execbuf); - gem_sync(fd, obj[1].handle); - - plug(fd, &c); - obj[0].handle = c.handle; - - execbuf.buffers_ptr = to_user_pointer(obj); - execbuf.buffer_count = 2; - - sigaction(SIGALRM, &sa, NULL); - itv.it_interval.tv_sec = 0; - itv.it_interval.tv_usec = 100; - itv.it_value.tv_sec = 0; - itv.it_value.tv_usec = 1000; - setitimer(ITIMER_REAL, &itv, NULL); - - last = -1; - count = 0; - do { - if (__execbuf(fd, &execbuf) == 0) { - count++; - continue; - } - - if (last == count) - break; - - last = count; - } while (1); - - memset(&itv, 0, sizeof(itv)); - setitimer(ITIMER_REAL, &itv, NULL); + int err; - unplug(fd, &c); - gem_close(fd, obj[1].handle); + err = 0; + if (ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2_WR, execbuf)) + err = -errno; - return count; + errno = 0; + return err; } static void test_parallel(int fd, unsigned int master) @@ -430,15 +352,16 @@ uint32_t batch[16]; igt_spin_t *spin; unsigned engine; - struct cork c; + IGT_CORK_HANDLE(c); + uint32_t plug; int i, x = 0; - plug(fd, &c); + plug = igt_cork_plug(&c, fd); /* Fill the queue with many requests so that the next one has to * wait before it can be executed by the hardware. */ - spin = igt_spin_batch_new(fd, 0, master, c.handle); + spin = igt_spin_batch_new(fd, 0, master, plug); resubmit(fd, spin->handle, master, 16); /* Now queue the master request and its secondaries */ @@ -514,10 +437,7 @@ obj[BATCH].relocation_count = 1; /* Queue all secondaries */ - for_each_engine(fd, engine) { - if (engine == 0 || engine == I915_EXEC_BSD) - continue; - + for_each_physical_engine(fd, engine) { if (engine == master) continue; @@ -559,7 +479,8 @@ } /* Unblock the master */ - unplug(fd, &c); + igt_cork_unplug(&c); + gem_close(fd, plug); igt_spin_batch_end(spin); /* Wait for all secondaries to complete. If we used a regular fence @@ -586,6 +507,94 @@ gem_close(fd, handle[0]); } +static uint32_t batch_create(int fd) +{ + const uint32_t bbe = MI_BATCH_BUFFER_END; + uint32_t handle; + + handle = gem_create(fd, 4096); + gem_write(fd, handle, 0, &bbe, sizeof(bbe)); + + return handle; +} + +static inline uint32_t lower_32_bits(uint64_t x) +{ + return x & 0xffffffff; +} + +static inline uint32_t upper_32_bits(uint64_t x) +{ + return x >> 32; +} + +static void test_keep_in_fence(int fd, unsigned int engine, unsigned int flags) +{ + struct sigaction sa = { .sa_handler = alarm_handler }; + struct drm_i915_gem_exec_object2 obj = { + .handle = batch_create(fd), + }; + struct drm_i915_gem_execbuffer2 execbuf = { + .buffers_ptr = to_user_pointer(&obj), + .buffer_count = 1, + .flags = engine | LOCAL_EXEC_FENCE_OUT, + }; + unsigned long count, last; + struct itimerval itv; + igt_spin_t *spin; + int fence; + + spin = igt_spin_batch_new(fd, 0, engine, 0); + + gem_execbuf_wr(fd, &execbuf); + fence = upper_32_bits(execbuf.rsvd2); + + sigaction(SIGALRM, &sa, NULL); + itv.it_interval.tv_sec = 0; + itv.it_interval.tv_usec = 1000; + itv.it_value.tv_sec = 0; + itv.it_value.tv_usec = 10000; + setitimer(ITIMER_REAL, &itv, NULL); + + execbuf.flags |= LOCAL_EXEC_FENCE_IN; + execbuf.rsvd2 = fence; + + last = -1; + count = 0; + do { + int err = __execbuf(fd, &execbuf); + + igt_assert_eq(lower_32_bits(execbuf.rsvd2), fence); + + if (err == 0) { + close(fence); + + fence = upper_32_bits(execbuf.rsvd2); + execbuf.rsvd2 = fence; + + count++; + continue; + } + + igt_assert_eq(err, -EINTR); + igt_assert_eq(upper_32_bits(execbuf.rsvd2), 0); + + if (last == count) + break; + + last = count; + } while (1); + + memset(&itv, 0, sizeof(itv)); + setitimer(ITIMER_REAL, &itv, NULL); + + gem_close(fd, obj.handle); + close(fence); + + igt_spin_batch_free(fd, spin); + gem_quiescent_gpu(fd); +} + #define EXPIRED 0x10000 static void test_long_history(int fd, long ring_size, unsigned flags) { @@ -597,22 +606,15 @@ unsigned int nengine, n, s; unsigned long limit; int all_fences; - struct cork c; + IGT_CORK_HANDLE(c); limit = -1; if (!gem_uses_full_ppgtt(fd)) limit = ring_size / 3; nengine = 0; - for_each_engine(fd, engine) { - if (engine == 0) - continue; - - if (engine == I915_EXEC_BSD) - continue; - + for_each_physical_engine(fd, engine) engines[nengine++] = engine; - } igt_require(nengine); gem_quiescent_gpu(fd); @@ -632,8 +634,7 @@ execbuf.buffers_ptr = to_user_pointer(obj); execbuf.buffer_count = 2; - plug(fd, &c); - obj[0].handle = c.handle; + obj[0].handle = igt_cork_plug(&c, fd); igt_until_timeout(5) { execbuf.rsvd1 = gem_context_create(fd); @@ -661,7 +662,7 @@ if (!--limit) break; } - unplug(fd, &c); + igt_cork_unplug(&c); igt_info("History depth = %d\n", sync_fence_count(all_fences)); @@ -685,6 +686,7 @@ gem_sync(fd, obj[1].handle); gem_close(fd, obj[1].handle); + gem_close(fd, obj[0].handle); } static void test_fence_flip(int i915) @@ -698,7 +700,7 @@ int value = 0; memset(&gp, 0, sizeof(gp)); - gp.param = 50; /* I915_PARAM_HAS_EXEC_SUBMIT_FENCE */ + gp.param = 0xdeadbeef ^ 51; /* I915_PARAM_HAS_EXEC_SUBMIT_FENCE */ gp.value = &value; ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp, sizeof(gp)); @@ -1490,6 +1492,9 @@ igt_subtest_f("nb-await-%s", e->name) test_fence_await(i915, e->exec_id | e->flags, NONBLOCK); + igt_subtest_f("keep-in-fence-%s", e->name) + test_keep_in_fence(i915, e->exec_id | e->flags, 0); + if (e->exec_id && !(e->exec_id == I915_EXEC_BSD && !e->flags)) { igt_subtest_f("parallel-%s", e->name) { @@ -1528,22 +1533,22 @@ } } - igt_subtest("long-history") { - long ring_size = measure_ring_size(i915) - 1; - - igt_info("Ring size: %ld batches\n", ring_size); - igt_require(ring_size); + igt_subtest_group { + long ring_size = 0; - test_long_history(i915, ring_size, 0); - } + igt_fixture { + ring_size = gem_measure_ring_inflight(i915, 0, 0) - 1; + igt_info("Ring size: %ld batches\n", ring_size); + igt_require(ring_size); - igt_subtest("expired-history") { - long ring_size = measure_ring_size(i915) - 1; + gem_require_contexts(i915); + } - igt_info("Ring size: %ld batches\n", ring_size); - igt_require(ring_size); + igt_subtest("long-history") + test_long_history(i915, ring_size, 0); - test_long_history(i915, ring_size, EXPIRED); + igt_subtest("expired-history") + test_long_history(i915, ring_size, EXPIRED); } igt_subtest("flip") { diff -Nru intel-gpu-tools-1.21/tests/gem_exec_flush.c intel-gpu-tools-1.22/tests/gem_exec_flush.c --- intel-gpu-tools-1.21/tests/gem_exec_flush.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_exec_flush.c 2018-03-09 14:22:59.000000000 +0000 @@ -426,6 +426,11 @@ ptr = mmap(0, 64<<10, PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); break; + + default: + igt_assert(!"reachable"); + ptr = NULL; + break; } memset(&reloc, 0, sizeof(reloc)); diff -Nru intel-gpu-tools-1.21/tests/gem_exec_gttfill.c intel-gpu-tools-1.22/tests/gem_exec_gttfill.c --- intel-gpu-tools-1.21/tests/gem_exec_gttfill.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_exec_gttfill.c 2018-03-09 14:22:59.000000000 +0000 @@ -28,17 +28,6 @@ #define BATCH_SIZE (4096<<10) -static bool ignore_engine(int fd, unsigned engine) -{ - if (engine == 0) - return true; - - if (gem_has_bsd2(fd) && engine == I915_EXEC_BSD) - return true; - - return false; -} - static void xchg_u32(void *array, unsigned i, unsigned j) { uint32_t *u32 = array; @@ -126,10 +115,7 @@ nengine = 0; if (ring == 0) { - for_each_engine(fd, engine) { - if (ignore_engine(fd, engine)) - continue; - + for_each_physical_engine(fd, engine) { if (!gem_can_store_dword(fd, engine)) continue; diff -Nru intel-gpu-tools-1.21/tests/gem_exec_latency.c intel-gpu-tools-1.22/tests/gem_exec_latency.c --- intel-gpu-tools-1.21/tests/gem_exec_latency.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_exec_latency.c 2018-03-09 14:22:59.000000000 +0000 @@ -41,6 +41,7 @@ #include "igt_sysfs.h" #include "igt_vgem.h" +#include "i915/gem_ring.h" #define LOCAL_I915_EXEC_NO_RELOC (1<<11) #define LOCAL_I915_EXEC_HANDLE_LUT (1<<12) @@ -55,83 +56,6 @@ static unsigned int ring_size; -struct cork { - int device; - uint32_t handle; - uint32_t fence; -}; - -static void plug(int fd, struct cork *c) -{ - struct vgem_bo bo; - int dmabuf; - - c->device = drm_open_driver(DRIVER_VGEM); - - bo.width = bo.height = 1; - bo.bpp = 4; - vgem_create(c->device, &bo); - c->fence = vgem_fence_attach(c->device, &bo, VGEM_FENCE_WRITE); - - dmabuf = prime_handle_to_fd(c->device, bo.handle); - c->handle = prime_fd_to_handle(fd, dmabuf); - close(dmabuf); -} - -static void unplug(struct cork *c) -{ - vgem_fence_signal(c->device, c->fence); - close(c->device); -} - -static void alarm_handler(int sig) -{ -} - -static void set_timeout(int seconds) -{ - struct sigaction sa = { .sa_handler = alarm_handler }; - - sigaction(SIGALRM, seconds ? &sa : NULL, NULL); - alarm(seconds); -} - -static int __execbuf(int fd, struct drm_i915_gem_execbuffer2 *execbuf) -{ - return ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, execbuf); -} - -static unsigned int measure_ring_size(int fd) -{ - struct drm_i915_gem_exec_object2 obj[2]; - struct drm_i915_gem_execbuffer2 execbuf; - const uint32_t bbe = MI_BATCH_BUFFER_END; - unsigned int count; - struct cork c; - - memset(obj, 0, sizeof(obj)); - obj[1].handle = gem_create(fd, 4096); - gem_write(fd, obj[1].handle, 0, &bbe, sizeof(bbe)); - - plug(fd, &c); - obj[0].handle = c.handle; - - memset(&execbuf, 0, sizeof(execbuf)); - execbuf.buffers_ptr = to_user_pointer(obj); - execbuf.buffer_count = 2; - - count = 0; - set_timeout(1); - while (__execbuf(fd, &execbuf) == 0) - count++; - set_timeout(0); - - unplug(&c); - gem_close(fd, obj[1].handle); - - return count; -} - #define RCS_TIMESTAMP (0x2000 + 0x358) static void latency_on_ring(int fd, unsigned ring, const char *name, @@ -142,7 +66,7 @@ struct drm_i915_gem_exec_object2 obj[3]; struct drm_i915_gem_relocation_entry reloc; struct drm_i915_gem_execbuffer2 execbuf; - struct cork c; + IGT_CORK_HANDLE(c); volatile uint32_t *reg; unsigned repeats = ring_size; uint32_t start, end, *map, *results; @@ -206,8 +130,7 @@ } if (flags & CORK) { - plug(fd, &c); - obj[0].handle = c.handle; + obj[0].handle = igt_cork_plug(&c, fd); execbuf.buffers_ptr = to_user_pointer(&obj[0]); execbuf.buffer_count = 3; } @@ -228,7 +151,7 @@ igt_assert(reloc.presumed_offset == obj[1].offset); if (flags & CORK) - unplug(&c); + igt_cork_unplug(&c); gem_set_domain(fd, obj[1].handle, I915_GEM_DOMAIN_GTT, 0); gpu_latency = (results[repeats-1] - results[0]) / (double)(repeats-1); @@ -269,6 +192,8 @@ munmap(map, 64*1024); munmap(results, 4096); + if (flags & CORK) + gem_close(fd, obj[0].handle); gem_close(fd, obj[1].handle); gem_close(fd, obj[2].handle); } @@ -277,13 +202,13 @@ unsigned ring, const char *name, unsigned flags) { - const struct intel_execution_engine *e; const int gen = intel_gen(intel_get_drm_devid(fd)); const int has_64bit_reloc = gen >= 8; struct drm_i915_gem_exec_object2 obj[3]; struct drm_i915_gem_relocation_entry reloc; struct drm_i915_gem_execbuffer2 execbuf; const unsigned int repeats = ring_size / 2; + unsigned int other; uint32_t *map, *results; uint32_t ctx[2] = {}; int i, j; @@ -329,26 +254,19 @@ reloc.presumed_offset = obj[1].offset; reloc.target_handle = flags & CORK ? 1 : 0; - for (e = intel_execution_engines; e->name; e++) { + for_each_physical_engine(fd, other) { igt_spin_t *spin = NULL; - struct cork c; - - if (e->exec_id == 0) - continue; - - if (!gem_has_ring(fd, e->exec_id | e->flags)) - continue; + IGT_CORK_HANDLE(c); gem_set_domain(fd, obj[2].handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT); if (flags & PREEMPT) - spin = igt_spin_batch_new(fd, ctx[0], ring, 0); + spin = __igt_spin_batch_new(fd, ctx[0], ring, 0); if (flags & CORK) { - plug(fd, &c); - obj[0].handle = c.handle; + obj[0].handle = igt_cork_plug(&c, fd); execbuf.buffers_ptr = to_user_pointer(&obj[0]); execbuf.buffer_count = 3; } @@ -382,7 +300,7 @@ gem_execbuf(fd, &execbuf); execbuf.flags &= ~ENGINE_FLAGS; - execbuf.flags |= e->exec_id | e->flags; + execbuf.flags |= other; execbuf.batch_start_offset = 64 * (j + repeats); reloc.offset = @@ -408,18 +326,22 @@ } if (flags & CORK) - unplug(&c); + igt_cork_unplug(&c); gem_set_domain(fd, obj[1].handle, I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT); igt_spin_batch_free(fd, spin); igt_info("%s-%s delay: %.2f\n", - name, e->name, (results[2*repeats-1] - results[0]) / (double)repeats); + name, e__->name, + (results[2*repeats-1] - results[0]) / (double)repeats); } munmap(map, 64*1024); munmap(results, 4096); + + if (flags & CORK) + gem_close(fd, obj[0].handle); gem_close(fd, obj[1].handle); gem_close(fd, obj[2].handle); @@ -441,7 +363,7 @@ gem_submission_print_method(device); - ring_size = measure_ring_size(device); + ring_size = gem_measure_ring_inflight(device, 0, 0); igt_info("Ring size: %d batches\n", ring_size); igt_require(ring_size > 8); ring_size -= 8; /* leave some spare */ @@ -461,7 +383,7 @@ igt_subtest_group { igt_fixture { - gem_require_ring(device, e->exec_id | e->flags); + igt_require(gem_ring_has_physical_engine(device, e->exec_id | e->flags)); } igt_subtest_f("%s-dispatch", e->name) @@ -486,6 +408,7 @@ igt_subtest_group { igt_fixture { + gem_require_contexts(device); igt_require(gem_scheduler_has_preemption(device)); } diff -Nru intel-gpu-tools-1.21/tests/gem_exec_lut_handle.c intel-gpu-tools-1.22/tests/gem_exec_lut_handle.c --- intel-gpu-tools-1.21/tests/gem_exec_lut_handle.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_exec_lut_handle.c 2018-03-09 14:22:59.000000000 +0000 @@ -77,7 +77,7 @@ execbuf.buffer_count = 1; execbuf.flags = LOCAL_I915_EXEC_HANDLE_LUT; - return drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf) == 0; + return __gem_execbuf(fd, &execbuf) == 0; } #define ELAPSED(a,b) (1e6*((b)->tv_sec - (a)->tv_sec) + ((b)->tv_usec - (a)->tv_usec)) diff -Nru intel-gpu-tools-1.21/tests/gem_exec_nop.c intel-gpu-tools-1.22/tests/gem_exec_nop.c --- intel-gpu-tools-1.21/tests/gem_exec_nop.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_exec_nop.c 2018-03-09 14:22:59.000000000 +0000 @@ -188,17 +188,6 @@ assert_within_epsilon(n_headless, n_display, 0.1f); } -static bool ignore_engine(int fd, unsigned engine) -{ - if (engine == 0) - return true; - - if (gem_has_bsd2(fd) && engine == I915_EXEC_BSD) - return true; - - return false; -} - static void parallel(int fd, uint32_t handle, int timeout) { struct drm_i915_gem_execbuffer2 execbuf; @@ -212,10 +201,7 @@ sum = 0; nengine = 0; - for_each_engine(fd, engine) { - if (ignore_engine(fd, engine)) - continue; - + for_each_physical_engine(fd, engine) { engines[nengine] = engine; names[nengine] = e__->name; nengine++; @@ -277,10 +263,7 @@ const char *name; nengine = 0; - for_each_engine(fd, engine) { - if (ignore_engine(fd, engine)) - continue; - + for_each_physical_engine(fd, engine) { time = nop_on_ring(fd, handle, engine, 1, &count) / count; if (time > max) { name = e__->name; @@ -357,19 +340,6 @@ u[j] = tmp; } -static int __gem_context_create(int fd, uint32_t *ctx_id) -{ - struct drm_i915_gem_context_create arg; - int ret = 0; - - memset(&arg, 0, sizeof(arg)); - if (drmIoctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &arg)) - ret = -errno; - - *ctx_id = arg.ctx_id; - return ret; -} - static void sequential(int fd, uint32_t handle, unsigned flags, int timeout) { const int ncpus = flags & FORKED ? sysconf(_SC_NPROCESSORS_ONLN) : 1; @@ -381,17 +351,16 @@ double time, sum; unsigned n; + gem_require_contexts(fd); + results = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); igt_assert(results != MAP_FAILED); nengine = 0; sum = 0; - for_each_engine(fd, n) { + for_each_physical_engine(fd, n) { unsigned long count; - if (ignore_engine(fd, n)) - continue; - time = nop_on_ring(fd, handle, n, 1, &count) / count; sum += time; igt_debug("%s: %.3fus\n", e__->name, 1e6*time); @@ -520,12 +489,8 @@ nengine = 0; if (ring_id == -1) { - for_each_engine(fd, n) { - if (ignore_engine(fd, n)) - continue; - + for_each_physical_engine(fd, n) engines[nengine++] = n; - } } else { gem_require_ring(fd, ring_id); engines[nengine++] = ring_id; @@ -699,6 +664,7 @@ igt_subtest_group { igt_fixture { + gem_require_contexts(device); igt_require(gem_scheduler_has_ctx_priority(device)); igt_require(gem_scheduler_has_preemption(device)); } diff -Nru intel-gpu-tools-1.21/tests/gem_exec_parallel.c intel-gpu-tools-1.22/tests/gem_exec_parallel.c --- intel-gpu-tools-1.21/tests/gem_exec_parallel.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_exec_parallel.c 2018-03-09 14:22:59.000000000 +0000 @@ -55,33 +55,6 @@ munmap(map, 4096); } -static uint32_t __gem_context_create(int fd) -{ - struct drm_i915_gem_context_create arg; - - memset(&arg, 0, sizeof(arg)); - if (drmIoctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &arg) == 0) - gem_context_destroy(fd, arg.ctx_id); - - return arg.ctx_id; -} - -static void gem_require_context(int fd) -{ - igt_require(__gem_context_create(fd)); -} - -static bool ignore_engine(int fd, unsigned engine) -{ - if (engine == 0) - return true; - - if (!gem_can_store_dword(fd, engine)) - return true; - - return false; -} - #define CONTEXTS 0x1 #define FDS 0x2 @@ -189,15 +162,15 @@ int i; if (flags & CONTEXTS) - gem_require_context(fd); + gem_require_contexts(fd); if (flags & FDS) igt_require(gen > 5); nengine = 0; if (engine == -1) { - for_each_engine(fd, engine) { - if (!ignore_engine(fd, engine)) + for_each_physical_engine(fd, engine) { + if (gem_can_store_dword(fd, engine)) engines[nengine++] = engine; } } else { diff -Nru intel-gpu-tools-1.21/tests/gem_exec_params.c intel-gpu-tools-1.22/tests/gem_exec_params.c --- intel-gpu-tools-1.21/tests/gem_exec_params.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_exec_params.c 2018-03-09 14:22:59.000000000 +0000 @@ -233,10 +233,7 @@ } #define RUN_FAIL(expected_errno) do { \ - igt_assert(drmIoctl(fd, \ - DRM_IOCTL_I915_GEM_EXECBUFFER2, \ - &execbuf) == -1); \ - igt_assert_eq(errno, expected_errno); \ + igt_assert_eq(__gem_execbuf(fd, &execbuf), -expected_errno); \ } while(0) igt_subtest("no-bsd") { @@ -343,13 +340,16 @@ } igt_subtest("secure-non-master") { + igt_require(__igt_device_set_master(fd) == 0); /* Requires root privilege */ + igt_device_drop_master(fd); execbuf.flags = I915_EXEC_RENDER | I915_EXEC_SECURE; RUN_FAIL(EPERM); + igt_device_set_master(fd); - igt_assert(drmIoctl(fd, - DRM_IOCTL_I915_GEM_EXECBUFFER2, - &execbuf) == 0); + gem_execbuf(fd, &execbuf); + + igt_device_drop_master(fd); /* Only needs temporary master */ } /* HANDLE_LUT and NO_RELOC are already exercised by gem_exec_lut_handle, diff -Nru intel-gpu-tools-1.21/tests/gem_exec_reloc.c intel-gpu-tools-1.22/tests/gem_exec_reloc.c --- intel-gpu-tools-1.21/tests/gem_exec_reloc.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_exec_reloc.c 2018-03-09 14:22:59.000000000 +0000 @@ -258,7 +258,7 @@ nengine = 0; if (engine == -1) { - for_each_engine(fd, engine) { + for_each_physical_engine(fd, engine) { if (gem_can_store_dword(fd, engine)) engines[nengine++] = engine; } diff -Nru intel-gpu-tools-1.21/tests/gem_exec_reuse.c intel-gpu-tools-1.22/tests/gem_exec_reuse.c --- intel-gpu-tools-1.21/tests/gem_exec_reuse.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_exec_reuse.c 2018-03-09 14:22:59.000000000 +0000 @@ -56,19 +56,6 @@ gem_execbuf(n->fd, &execbuf); } -static int __gem_context_create(int fd, uint32_t *ctx_id) -{ - struct drm_i915_gem_context_create arg; - int ret = 0; - - memset(&arg, 0, sizeof(arg)); - if (drmIoctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &arg)) - ret = -errno; - - *ctx_id = arg.ctx_id; - return ret; -} - static int fls(uint64_t x) { int t; @@ -215,8 +202,9 @@ const unsigned int ncontexts = 1024; uint32_t contexts[ncontexts]; - igt_require(__gem_context_create(no.fd, &contexts[0]) == 0); - for (n = 1; n < ncontexts; n++) + gem_require_contexts(no.fd); + + for (n = 0; n < ncontexts; n++) contexts[n] = gem_context_create(no.fd); igt_until_timeout(timeout) { diff -Nru intel-gpu-tools-1.21/tests/gem_exec_schedule.c intel-gpu-tools-1.22/tests/gem_exec_schedule.c --- intel-gpu-tools-1.21/tests/gem_exec_schedule.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_exec_schedule.c 2018-03-09 14:22:59.000000000 +0000 @@ -32,6 +32,7 @@ #include "igt_vgem.h" #include "igt_rand.h" #include "igt_sysfs.h" +#include "i915/gem_ring.h" #define LO 0 #define HI 1 @@ -40,9 +41,12 @@ #define MAX_PRIO LOCAL_I915_CONTEXT_MAX_USER_PRIORITY #define MIN_PRIO LOCAL_I915_CONTEXT_MIN_USER_PRIORITY -#define BUSY_QLEN 8 #define MAX_ELSP_QLEN 16 +#define MAX_ENGINES 16 + +#define MAX_CONTEXTS 1024 + IGT_TEST_DESCRIPTION("Check that we can control the order of execution"); static void store_dword(int fd, uint32_t ctx, unsigned ring, @@ -99,35 +103,6 @@ gem_close(fd, obj[2].handle); } -struct cork { - int device; - uint32_t handle; - uint32_t fence; -}; - -static void plug(int fd, struct cork *c) -{ - struct vgem_bo bo; - int dmabuf; - - c->device = drm_open_driver(DRIVER_VGEM); - - bo.width = bo.height = 1; - bo.bpp = 4; - vgem_create(c->device, &bo); - c->fence = vgem_fence_attach(c->device, &bo, VGEM_FENCE_WRITE); - - dmabuf = prime_handle_to_fd(c->device, bo.handle); - c->handle = prime_fd_to_handle(fd, dmabuf); - close(dmabuf); -} - -static void unplug(struct cork *c) -{ - vgem_fence_signal(c->device, c->fence); - close(c->device); -} - static uint32_t create_highest_priority(int fd) { uint32_t ctx = gem_context_create(fd); @@ -142,9 +117,9 @@ return ctx; } -static void unplug_show_queue(int fd, struct cork *c, unsigned int engine) +static void unplug_show_queue(int fd, struct igt_cork *c, unsigned int engine) { - igt_spin_t *spin[BUSY_QLEN]; + igt_spin_t *spin[MAX_ELSP_QLEN]; for (int n = 0; n < ARRAY_SIZE(spin); n++) { uint32_t ctx = create_highest_priority(fd); @@ -152,7 +127,7 @@ gem_context_destroy(fd, ctx); } - unplug(c); /* batches will now be queued on the engine */ + igt_cork_unplug(c); /* batches will now be queued on the engine */ igt_debugfs_dump(fd, "i915_engine_info"); for (int n = 0; n < ARRAY_SIZE(spin); n++) @@ -162,19 +137,20 @@ static void fifo(int fd, unsigned ring) { - struct cork cork; - uint32_t scratch; + IGT_CORK_HANDLE(cork); + uint32_t scratch, plug; uint32_t *ptr; scratch = gem_create(fd, 4096); - plug(fd, &cork); + plug = igt_cork_plug(&cork, fd); /* Same priority, same timeline, final result will be the second eb */ - store_dword(fd, 0, ring, scratch, 0, 1, cork.handle, 0); - store_dword(fd, 0, ring, scratch, 0, 2, cork.handle, 0); + store_dword(fd, 0, ring, scratch, 0, 1, plug, 0); + store_dword(fd, 0, ring, scratch, 0, 2, plug, 0); unplug_show_queue(fd, &cork, ring); + gem_close(fd, plug); ptr = gem_mmap__gtt(fd, scratch, 4096, PROT_READ); gem_set_domain(fd, scratch, /* no write hazard lies! */ @@ -185,32 +161,21 @@ munmap(ptr, 4096); } -static bool ignore_engine(int fd, unsigned engine) -{ - if (engine == 0) - return true; - - if (gem_has_bsd2(fd) && engine == I915_EXEC_BSD) - return true; - - return false; -} - static void smoketest(int fd, unsigned ring, unsigned timeout) { const int ncpus = sysconf(_SC_NPROCESSORS_ONLN); - unsigned engines[16]; + unsigned engines[MAX_ENGINES]; unsigned nengine; unsigned engine; uint32_t scratch; uint32_t *ptr; nengine = 0; - for_each_engine(fd, engine) { - if (ignore_engine(fd, engine)) - continue; - - engines[nengine++] = engine; + if (ring == -1) { + for_each_physical_engine(fd, engine) + engines[nengine++] = engine; + } else { + engines[nengine++] = ring; } igt_require(nengine); @@ -262,8 +227,8 @@ static void reorder(int fd, unsigned ring, unsigned flags) #define EQUAL 1 { - struct cork cork; - uint32_t scratch; + IGT_CORK_HANDLE(cork); + uint32_t scratch, plug; uint32_t *ptr; uint32_t ctx[2]; @@ -274,15 +239,16 @@ gem_context_set_priority(fd, ctx[HI], flags & EQUAL ? MIN_PRIO : 0); scratch = gem_create(fd, 4096); - plug(fd, &cork); + plug = igt_cork_plug(&cork, fd); /* We expect the high priority context to be executed first, and * so the final result will be value from the low priority context. */ - store_dword(fd, ctx[LO], ring, scratch, 0, ctx[LO], cork.handle, 0); - store_dword(fd, ctx[HI], ring, scratch, 0, ctx[HI], cork.handle, 0); + store_dword(fd, ctx[LO], ring, scratch, 0, ctx[LO], plug, 0); + store_dword(fd, ctx[HI], ring, scratch, 0, ctx[HI], plug, 0); unplug_show_queue(fd, &cork, ring); + gem_close(fd, plug); gem_context_destroy(fd, ctx[LO]); gem_context_destroy(fd, ctx[HI]); @@ -301,10 +267,11 @@ static void promotion(int fd, unsigned ring) { - struct cork cork; + IGT_CORK_HANDLE(cork); uint32_t result, dep; uint32_t *ptr; uint32_t ctx[3]; + uint32_t plug; ctx[LO] = gem_context_create(fd); gem_context_set_priority(fd, ctx[LO], MIN_PRIO); @@ -318,15 +285,15 @@ result = gem_create(fd, 4096); dep = gem_create(fd, 4096); - plug(fd, &cork); + plug = igt_cork_plug(&cork, fd); /* Expect that HI promotes LO, so the order will be LO, HI, NOISE. * * fifo would be NOISE, LO, HI. * strict priority would be HI, NOISE, LO */ - store_dword(fd, ctx[NOISE], ring, result, 0, ctx[NOISE], cork.handle, 0); - store_dword(fd, ctx[LO], ring, result, 0, ctx[LO], cork.handle, 0); + store_dword(fd, ctx[NOISE], ring, result, 0, ctx[NOISE], plug, 0); + store_dword(fd, ctx[LO], ring, result, 0, ctx[LO], plug, 0); /* link LO <-> HI via a dependency on another buffer */ store_dword(fd, ctx[LO], ring, dep, 0, ctx[LO], 0, I915_GEM_DOMAIN_INSTRUCTION); @@ -335,6 +302,7 @@ store_dword(fd, ctx[HI], ring, result, 0, ctx[HI], 0, 0); unplug_show_queue(fd, &cork, ring); + gem_close(fd, plug); gem_context_destroy(fd, ctx[NOISE]); gem_context_destroy(fd, ctx[LO]); @@ -376,7 +344,7 @@ if (flags & HANG_LP) hang = igt_hang_ctx(fd, ctx[LO], ring, 0, NULL); - for (int n = 0; n < 16; n++) { + for (int n = 0; n < ARRAY_SIZE(spin); n++) { if (flags & NEW_CTX) { gem_context_destroy(fd, ctx[LO]); ctx[LO] = gem_context_create(fd); @@ -392,7 +360,7 @@ igt_assert(gem_bo_busy(fd, spin[0]->handle)); } - for (int n = 0; n < 16; n++) + for (int n = 0; n < ARRAY_SIZE(spin); n++) igt_spin_batch_free(fd, spin[n]); if (flags & HANG_LP) @@ -409,7 +377,7 @@ { uint32_t result = gem_create(fd, 4096); uint32_t *ptr = gem_mmap__gtt(fd, result, 4096, PROT_READ); - igt_spin_t *spin[MAX_ELSP_QLEN]; + igt_spin_t *spin[MAX_ENGINES]; unsigned int other; unsigned int n, i; uint32_t ctx[3]; @@ -433,7 +401,9 @@ gem_context_set_priority(fd, ctx[HI], MAX_PRIO); n = 0; - for_each_engine(fd, other) { + for_each_physical_engine(fd, other) { + igt_assert(n < ARRAY_SIZE(spin)); + spin[n] = __igt_spin_batch_new(fd, ctx[NOISE], other, 0); store_dword(fd, ctx[LO], other, result, (n + 1)*sizeof(uint32_t), n + 1, @@ -444,6 +414,7 @@ result, (n + 1)*sizeof(uint32_t), n + 1, 0, I915_GEM_DOMAIN_RENDER); + igt_debugfs_dump(fd, "i915_engine_info"); gem_set_domain(fd, result, I915_GEM_DOMAIN_GTT, 0); for (i = 0; i < n; i++) { @@ -486,7 +457,7 @@ n = 0; gem_context_set_priority(fd, ctx[HI], MIN_PRIO); - for_each_engine(fd, other) { + for_each_physical_engine(fd, other) { spin[n] = __igt_spin_batch_new(fd, ctx[NOISE], other, 0); store_dword(fd, ctx[HI], other, result, (n + 1)*sizeof(uint32_t), n + 1, @@ -525,7 +496,7 @@ ctx[HI] = gem_context_create(fd); gem_context_set_priority(fd, ctx[HI], MAX_PRIO); - for (int n = 0; n < 16; n++) { + for (int n = 0; n < ARRAY_SIZE(spin); n++) { ctx[LO] = gem_context_create(fd); gem_context_set_priority(fd, ctx[LO], MIN_PRIO); @@ -537,7 +508,7 @@ hang = igt_hang_ctx(fd, ctx[HI], ring, 0, NULL); igt_post_hang_ring(fd, hang); - for (int n = 0; n < 16; n++) { + for (int n = 0; n < ARRAY_SIZE(spin); n++) { /* Current behavior is to execute requests in order of submission. * This is subject to change as the scheduler evolve. The test should * be updated to reflect such changes. @@ -552,19 +523,19 @@ static void deep(int fd, unsigned ring) { #define XS 8 - const unsigned int nctx = MAX_PRIO - MIN_PRIO; - const unsigned size = ALIGN(4*nctx, 4096); + const unsigned int nreq = MAX_PRIO - MIN_PRIO; + const unsigned size = ALIGN(4*nreq, 4096); struct timespec tv = {}; - struct cork cork; + IGT_CORK_HANDLE(cork); + uint32_t plug; uint32_t result, dep[XS]; uint32_t expected = 0; uint32_t *ptr; uint32_t *ctx; - ctx = malloc(sizeof(*ctx) * nctx); - for (int n = 0; n < nctx; n++) { + ctx = malloc(sizeof(*ctx) * MAX_CONTEXTS); + for (int n = 0; n < MAX_CONTEXTS; n++) { ctx[n] = gem_context_create(fd); - gem_context_set_priority(fd, ctx[n], MAX_PRIO - nctx + n); } result = gem_create(fd, size); @@ -588,7 +559,7 @@ execbuf.buffers_ptr = to_user_pointer(obj); execbuf.buffer_count = XS + 2; execbuf.flags = ring; - for (int n = 0; n < nctx; n++) { + for (int n = 0; n < MAX_CONTEXTS; n++) { execbuf.rsvd1 = ctx[n]; gem_execbuf(fd, &execbuf); } @@ -596,25 +567,33 @@ gem_sync(fd, result); } - plug(fd, &cork); + plug = igt_cork_plug(&cork, fd); /* Create a deep dependency chain, with a few branches */ - for (int n = 0; n < nctx && igt_seconds_elapsed(&tv) < 8; n++) + for (int n = 0; n < nreq && igt_seconds_elapsed(&tv) < 8; n++) { + uint32_t context = ctx[n % MAX_CONTEXTS]; + gem_context_set_priority(fd, context, MAX_PRIO - nreq + n); + for (int m = 0; m < XS; m++) - store_dword(fd, ctx[n], ring, dep[m], 4*n, ctx[n], cork.handle, I915_GEM_DOMAIN_INSTRUCTION); + store_dword(fd, context, ring, dep[m], 4*n, context, plug, I915_GEM_DOMAIN_INSTRUCTION); + } + + for (int n = 0; n < nreq && igt_seconds_elapsed(&tv) < 6; n++) { + uint32_t context = ctx[n % MAX_CONTEXTS]; + gem_context_set_priority(fd, context, MAX_PRIO - nreq + n); - for (int n = 0; n < nctx && igt_seconds_elapsed(&tv) < 6; n++) { for (int m = 0; m < XS; m++) { - store_dword(fd, ctx[n], ring, result, 4*n, ctx[n], dep[m], 0); - store_dword(fd, ctx[n], ring, result, 4*m, ctx[n], 0, I915_GEM_DOMAIN_INSTRUCTION); + store_dword(fd, context, ring, result, 4*n, context, dep[m], 0); + store_dword(fd, context, ring, result, 4*m, context, 0, I915_GEM_DOMAIN_INSTRUCTION); } - expected = ctx[n]; + expected = context; } unplug_show_queue(fd, &cork, ring); + gem_close(fd, plug); igt_require(expected); /* too slow */ - for (int n = 0; n < nctx; n++) + for (int n = 0; n < MAX_CONTEXTS; n++) gem_context_destroy(fd, ctx[n]); for (int m = 0; m < XS; m++) { @@ -623,8 +602,8 @@ I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT); gem_close(fd, dep[m]); - for (int n = 0; n < nctx; n++) - igt_assert_eq_u32(ptr[n], ctx[n]); + for (int n = 0; n < nreq; n++) + igt_assert_eq_u32(ptr[n], ctx[n % MAX_CONTEXTS]); munmap(ptr, size); } @@ -654,111 +633,52 @@ return err; } -static unsigned int measure_ring_size(int fd, unsigned int ring) -{ - struct sigaction sa = { .sa_handler = alarm_handler }; - struct drm_i915_gem_exec_object2 obj[2]; - struct drm_i915_gem_execbuffer2 execbuf; - const uint32_t bbe = MI_BATCH_BUFFER_END; - unsigned int count, last; - struct itimerval itv; - struct cork c; - - memset(obj, 0, sizeof(obj)); - obj[1].handle = gem_create(fd, 4096); - gem_write(fd, obj[1].handle, 0, &bbe, sizeof(bbe)); - - memset(&execbuf, 0, sizeof(execbuf)); - execbuf.buffers_ptr = to_user_pointer(obj + 1); - execbuf.buffer_count = 1; - execbuf.flags = ring; - gem_execbuf(fd, &execbuf); - gem_sync(fd, obj[1].handle); - - plug(fd, &c); - obj[0].handle = c.handle; - - execbuf.buffers_ptr = to_user_pointer(obj); - execbuf.buffer_count = 2; - execbuf.rsvd1 = gem_context_create(fd); - - sigaction(SIGALRM, &sa, NULL); - itv.it_interval.tv_sec = 0; - itv.it_interval.tv_usec = 100; - itv.it_value.tv_sec = 0; - itv.it_value.tv_usec = 1000; - setitimer(ITIMER_REAL, &itv, NULL); - - last = -1; - count = 0; - do { - if (__execbuf(fd, &execbuf) == 0) { - count++; - continue; - } - - if (last == count) - break; - - last = count; - } while (1); - - memset(&itv, 0, sizeof(itv)); - setitimer(ITIMER_REAL, &itv, NULL); - - unplug(&c); - gem_close(fd, obj[1].handle); - gem_context_destroy(fd, execbuf.rsvd1); - - return count; -} - static void wide(int fd, unsigned ring) { -#define NCTX 4096 struct timespec tv = {}; - unsigned int ring_size = measure_ring_size(fd, ring); + unsigned int ring_size = gem_measure_ring_inflight(fd, ring, MEASURE_RING_NEW_CTX); - struct cork cork; + IGT_CORK_HANDLE(cork); + uint32_t plug; uint32_t result; uint32_t *ptr; uint32_t *ctx; unsigned int count; - ctx = malloc(sizeof(*ctx)*NCTX); - for (int n = 0; n < NCTX; n++) + ctx = malloc(sizeof(*ctx)*MAX_CONTEXTS); + for (int n = 0; n < MAX_CONTEXTS; n++) ctx[n] = gem_context_create(fd); - result = gem_create(fd, 4*NCTX); + result = gem_create(fd, 4*MAX_CONTEXTS); - plug(fd, &cork); + plug = igt_cork_plug(&cork, fd); /* Lots of in-order requests, plugged and submitted simultaneously */ for (count = 0; igt_seconds_elapsed(&tv) < 5 && count < ring_size; count++) { - for (int n = 0; n < NCTX; n++) { - store_dword(fd, ctx[n], ring, result, 4*n, ctx[n], cork.handle, I915_GEM_DOMAIN_INSTRUCTION); + for (int n = 0; n < MAX_CONTEXTS; n++) { + store_dword(fd, ctx[n], ring, result, 4*n, ctx[n], plug, I915_GEM_DOMAIN_INSTRUCTION); } } igt_info("Submitted %d requests over %d contexts in %.1fms\n", - count, NCTX, igt_nsec_elapsed(&tv) * 1e-6); + count, MAX_CONTEXTS, igt_nsec_elapsed(&tv) * 1e-6); unplug_show_queue(fd, &cork, ring); + gem_close(fd, plug); - for (int n = 0; n < NCTX; n++) + for (int n = 0; n < MAX_CONTEXTS; n++) gem_context_destroy(fd, ctx[n]); - ptr = gem_mmap__gtt(fd, result, 4*NCTX, PROT_READ); + ptr = gem_mmap__gtt(fd, result, 4*MAX_CONTEXTS, PROT_READ); gem_set_domain(fd, result, /* no write hazard lies! */ I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT); - for (int n = 0; n < NCTX; n++) + for (int n = 0; n < MAX_CONTEXTS; n++) igt_assert_eq_u32(ptr[n], ctx[n]); - munmap(ptr, 4*NCTX); + munmap(ptr, 4*MAX_CONTEXTS); gem_close(fd, result); free(ctx); -#undef NCTX } static void reorder_wide(int fd, unsigned ring) @@ -768,21 +688,20 @@ struct drm_i915_gem_exec_object2 obj[3]; struct drm_i915_gem_execbuffer2 execbuf; struct timespec tv = {}; - unsigned int ring_size = measure_ring_size(fd, ring); - struct cork cork; - uint32_t result, target; + unsigned int ring_size = gem_measure_ring_inflight(fd, ring, MEASURE_RING_NEW_CTX); + IGT_CORK_HANDLE(cork); + uint32_t result, target, plug; uint32_t *found, *expected; result = gem_create(fd, 4096); target = gem_create(fd, 4096); - - plug(fd, &cork); + plug = igt_cork_plug(&cork, fd); expected = gem_mmap__cpu(fd, target, 0, 4096, PROT_WRITE); gem_set_domain(fd, target, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU); memset(obj, 0, sizeof(obj)); - obj[0].handle = cork.handle; + obj[0].handle = plug; obj[1].handle = result; obj[2].relocs_ptr = to_user_pointer(&reloc); obj[2].relocation_count = 1; @@ -850,6 +769,7 @@ } unplug_show_queue(fd, &cork, ring); + gem_close(fd, plug); found = gem_mmap__gtt(fd, result, 4096, PROT_READ); gem_set_domain(fd, result, /* no write hazard lies! */ @@ -884,7 +804,7 @@ struct drm_i915_gem_exec_object2 obj[2]; unsigned int last, count; struct itimerval itv; - struct cork c; + IGT_CORK_HANDLE(c); bool *result; result = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); @@ -906,17 +826,16 @@ gem_sync(fd, obj[1].handle); /* Fill the low-priority ring */ - plug(fd, &c); - obj[0].handle = c.handle; + obj[0].handle = igt_cork_plug(&c, fd); execbuf.buffers_ptr = to_user_pointer(obj); execbuf.buffer_count = 2; sigaction(SIGALRM, &sa, NULL); itv.it_interval.tv_sec = 0; - itv.it_interval.tv_usec = 100; + itv.it_interval.tv_usec = 1000; itv.it_value.tv_sec = 0; - itv.it_value.tv_usec = 1000; + itv.it_value.tv_usec = 10000; setitimer(ITIMER_REAL, &itv, NULL); last = -1; @@ -981,7 +900,7 @@ igt_assert_f(result[2], "High priority child unable to submit within 10ms\n"); - unplug(&c); + igt_cork_unplug(&c); igt_waitchildren(); gem_context_destroy(fd, execbuf.rsvd1); @@ -1001,8 +920,11 @@ fd = drm_open_driver_master(DRIVER_INTEL); gem_submission_print_method(fd); gem_scheduler_print_capability(fd); + igt_require_gem(fd); gem_require_mmap_wc(fd); + gem_require_contexts(fd); + igt_fork_hang_detector(fd); } @@ -1013,7 +935,7 @@ continue; igt_subtest_f("fifo-%s", e->name) { - gem_require_ring(fd, e->exec_id | e->flags); + igt_require(gem_ring_has_physical_engine(fd, e->exec_id | e->flags)); igt_require(gem_can_store_dword(fd, e->exec_id) | e->flags); fifo(fd, e->exec_id | e->flags); } @@ -1030,13 +952,12 @@ smoketest(fd, -1, 30); for (e = intel_execution_engines; e->name; e++) { - /* default exec-id is purely symbolic */ if (e->exec_id == 0) continue; igt_subtest_group { igt_fixture { - gem_require_ring(fd, e->exec_id | e->flags); + igt_require(gem_ring_has_physical_engine(fd, e->exec_id | e->flags)); igt_require(gem_can_store_dword(fd, e->exec_id) | e->flags); } @@ -1113,9 +1034,12 @@ } for (e = intel_execution_engines; e->name; e++) { + if (e->exec_id == 0) + continue; + igt_subtest_group { igt_fixture { - gem_require_ring(fd, e->exec_id | e->flags); + igt_require(gem_ring_has_physical_engine(fd, e->exec_id | e->flags)); igt_require(gem_scheduler_has_preemption(fd)); } diff -Nru intel-gpu-tools-1.21/tests/gem_exec_store.c intel-gpu-tools-1.22/tests/gem_exec_store.c --- intel-gpu-tools-1.21/tests/gem_exec_store.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_exec_store.c 2018-03-09 14:22:59.000000000 +0000 @@ -220,7 +220,7 @@ nengine = 0; intel_detect_and_clear_missed_interrupts(fd); - for_each_engine(fd, engine) { + for_each_physical_engine(fd, engine) { if (!gem_can_store_dword(fd, engine)) continue; diff -Nru intel-gpu-tools-1.21/tests/gem_exec_suspend.c intel-gpu-tools-1.22/tests/gem_exec_suspend.c --- intel-gpu-tools-1.21/tests/gem_exec_suspend.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_exec_suspend.c 2018-03-09 14:22:59.000000000 +0000 @@ -62,25 +62,13 @@ munmap(map, 4096); } -static bool ignore_engine(int fd, unsigned engine) -{ - if (engine == 0) - return true; - - if (!gem_can_store_dword(fd, engine)) - return true; - - return false; -} - static void test_all(int fd, unsigned flags) { unsigned engine; - for_each_engine(fd, engine) { - if (!ignore_engine(fd, engine)) + for_each_physical_engine(fd, engine) + if (gem_can_store_dword(fd, engine)) run_test(fd, engine, flags & ~0xff); - } } static bool has_semaphores(int fd) @@ -118,8 +106,8 @@ * GPU is then unlikely to be active!) */ if (has_semaphores(fd)) { - for_each_engine(fd, engine) { - if (!ignore_engine(fd, engine)) + for_each_physical_engine(fd, engine) { + if (gem_can_store_dword(fd, engine)) engines[nengine++] = engine; } } else { diff -Nru intel-gpu-tools-1.21/tests/gem_exec_whisper.c intel-gpu-tools-1.22/tests/gem_exec_whisper.c --- intel-gpu-tools-1.21/tests/gem_exec_whisper.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_exec_whisper.c 2018-03-09 14:22:59.000000000 +0000 @@ -79,30 +79,6 @@ } } -static int __gem_context_create(int fd, uint32_t *ctx_id) -{ - struct drm_i915_gem_context_create arg; - int ret = 0; - - memset(&arg, 0, sizeof(arg)); - if (drmIoctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &arg)) - ret = -errno; - - *ctx_id = arg.ctx_id; - return ret; -} - -static bool ignore_engine(int fd, unsigned engine) -{ - if (engine == 0) - return true; - - if (!gem_can_store_dword(fd, engine)) - return true; - - return false; -} - #define CONTEXTS 0x1 #define FDS 0x2 #define INTERRUPTIBLE 0x4 @@ -230,8 +206,8 @@ nengine = 0; if (engine == -1) { - for_each_engine(fd, engine) { - if (!ignore_engine(fd, engine)) + for_each_physical_engine(fd, engine) { + if (gem_can_store_dword(fd, engine)) engines[nengine++] = engine; } } else { @@ -244,10 +220,8 @@ if (flags & FDS) igt_require(gen >= 6); - if (flags & CONTEXTS) { - igt_require(__gem_context_create(fd, &contexts[0]) == 0); - gem_context_destroy(fd, contexts[0]); - } + if (flags & CONTEXTS) + gem_require_contexts(fd); if (flags & HANG) init_hang(&hang); diff -Nru intel-gpu-tools-1.21/tests/gem_fenced_exec_thrash.c intel-gpu-tools-1.22/tests/gem_fenced_exec_thrash.c --- intel-gpu-tools-1.21/tests/gem_fenced_exec_thrash.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_fenced_exec_thrash.c 2018-03-09 14:22:59.000000000 +0000 @@ -25,17 +25,12 @@ * */ -#include "igt.h" #include -#include -#include #include -#include #include #include -#include - +#include "igt.h" IGT_TEST_DESCRIPTION("Test execbuf fence accounting."); @@ -45,7 +40,7 @@ #define BATCH_SIZE 4096 -#define MAX_FENCES 32 +#define MAX_FENCES 64 /* * Testcase: execbuf fence accounting @@ -59,53 +54,6 @@ * each command. */ -static drm_intel_bufmgr *bufmgr; -struct intel_batchbuffer *batch; -uint32_t devid; - -static void emit_dummy_load(void) -{ - int i; - uint32_t tile_flags = 0; - uint32_t tiling_mode = I915_TILING_X; - unsigned long pitch; - drm_intel_bo *dummy_bo; - - dummy_bo = drm_intel_bo_alloc_tiled(bufmgr, "tiled dummy_bo", 2048, 2048, - 4, &tiling_mode, &pitch, 0); - - if (IS_965(devid)) { - pitch /= 4; - tile_flags = XY_SRC_COPY_BLT_SRC_TILED | - XY_SRC_COPY_BLT_DST_TILED; - } - - for (i = 0; i < 5; i++) { - BLIT_COPY_BATCH_START(tile_flags); - OUT_BATCH((3 << 24) | /* 32 bits */ - (0xcc << 16) | /* copy ROP */ - pitch); - OUT_BATCH(0 << 16 | 1024); - OUT_BATCH((2048) << 16 | (2048)); - OUT_RELOC_FENCED(dummy_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); - OUT_BATCH(0 << 16 | 0); - OUT_BATCH(pitch); - OUT_RELOC_FENCED(dummy_bo, I915_GEM_DOMAIN_RENDER, 0, 0); - ADVANCE_BATCH(); - - if (batch->gen >= 6) { - BEGIN_BATCH(3, 0); - OUT_BATCH(XY_SETUP_CLIP_BLT_CMD); - OUT_BATCH(0); - OUT_BATCH(0); - ADVANCE_BATCH(); - } - } - intel_batchbuffer_flush(batch); - - drm_intel_bo_unreference(dummy_bo); -} - static uint32_t tiled_bo_create (int fd) { @@ -146,22 +94,14 @@ unsigned flags) { struct drm_i915_gem_execbuffer2 execbuf[2]; - struct drm_i915_gem_exec_object2 exec[2][2*MAX_FENCES+3]; - struct drm_i915_gem_relocation_entry reloc[2*MAX_FENCES+2]; + struct drm_i915_gem_exec_object2 exec[2][2*MAX_FENCES+1]; + struct drm_i915_gem_relocation_entry reloc[2*MAX_FENCES]; + unsigned long count; int i, n; - int loop = 1000; - - if (flags & BUSY_LOAD) { - bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); - batch = intel_batchbuffer_alloc(bufmgr, devid); - /* Takes forever otherwise. */ - loop = 50; - } - - if (flags & INTERRUPTIBLE) - igt_fork_signal_helper(); + igt_assert(2*num_fences+1 <= ARRAY_SIZE(exec[0])); + igt_assert(2*num_fences <= ARRAY_SIZE(reloc)); memset(execbuf, 0, sizeof(execbuf)); memset(exec, 0, sizeof(exec)); @@ -186,16 +126,25 @@ execbuf[i].batch_len = 2*sizeof(uint32_t); } - do { - if (flags & BUSY_LOAD) - emit_dummy_load(); - - igt_assert_eq(__gem_execbuf(fd, &execbuf[0]), -expected_errno); - igt_assert_eq(__gem_execbuf(fd, &execbuf[1]), -expected_errno); - } while (--loop); + count = 0; + igt_until_timeout(2) { + for (i = 0; i < 2; i++) { + igt_spin_t *spin = NULL; + + if (flags & BUSY_LOAD) + spin = __igt_spin_batch_new(fd, 0, 0, 0); + + igt_while_interruptible(flags & INTERRUPTIBLE) { + igt_assert_eq(__gem_execbuf(fd, &execbuf[i]), + -expected_errno); + } - if (flags & INTERRUPTIBLE) - igt_stop_signal_helper(); + igt_spin_batch_free(fd, spin); + gem_quiescent_gpu(fd); + } + count++; + } + igt_info("Completed %lu cycles\n", count); /* Cleanup */ for (n = 0; n < 2*num_fences; n++) @@ -203,28 +152,25 @@ for (i = 0; i < 2; i++) gem_close(fd, exec[i][2*num_fences].handle); - - if (flags & BUSY_LOAD) { - intel_batchbuffer_free(batch); - drm_intel_bufmgr_destroy(bufmgr); - } } -int fd; -int num_fences; - igt_main { + uint32_t devid = 0; + unsigned int num_fences = 0; + int fd = -1; + igt_skip_on_simulation(); igt_fixture { fd = drm_open_driver(DRIVER_INTEL); igt_require_gem(fd); + num_fences = gem_available_fences(fd); igt_assert(num_fences > 4); - devid = intel_get_drm_devid(fd); - igt_assert(num_fences <= MAX_FENCES); + + devid = intel_get_drm_devid(fd); } igt_subtest("2-spare-fences") diff -Nru intel-gpu-tools-1.21/tests/gem_fence_thrash.c intel-gpu-tools-1.22/tests/gem_fence_thrash.c --- intel-gpu-tools-1.21/tests/gem_fence_thrash.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_fence_thrash.c 2018-03-09 14:22:59.000000000 +0000 @@ -107,75 +107,16 @@ return NULL; } -#if defined(__x86_64__) && !defined(__clang__) - -#pragma GCC push_options -#pragma GCC target("sse4.1") - -#include - -#define MOVNT 512 - -__attribute__((noinline)) -static void copy_wc_page(void *dst, void *src) -{ - if (igt_x86_features() & SSE4_1) { - __m128i *S = (__m128i *)src; - __m128i *D = (__m128i *)dst; - - for (int i = 0; i < PAGE_SIZE/CACHELINE; i++) { - __m128i tmp[4]; - - tmp[0] = _mm_stream_load_si128(S++); - tmp[1] = _mm_stream_load_si128(S++); - tmp[2] = _mm_stream_load_si128(S++); - tmp[3] = _mm_stream_load_si128(S++); - - _mm_store_si128(D++, tmp[0]); - _mm_store_si128(D++, tmp[1]); - _mm_store_si128(D++, tmp[2]); - _mm_store_si128(D++, tmp[3]); - } - } else - memcpy(dst, src, PAGE_SIZE); -} - -static void copy_wc_cacheline(void *dst, void *src) -{ - if (igt_x86_features() & SSE4_1) { - __m128i *S = (__m128i *)src; - __m128i *D = (__m128i *)dst; - __m128i tmp[4]; - - tmp[0] = _mm_stream_load_si128(S++); - tmp[1] = _mm_stream_load_si128(S++); - tmp[2] = _mm_stream_load_si128(S++); - tmp[3] = _mm_stream_load_si128(S++); - - _mm_store_si128(D++, tmp[0]); - _mm_store_si128(D++, tmp[1]); - _mm_store_si128(D++, tmp[2]); - _mm_store_si128(D++, tmp[3]); - } else - memcpy(dst, src, CACHELINE); -} - -#pragma GCC pop_options - -#else - static void copy_wc_page(void *dst, const void *src) { - memcpy(dst, src, PAGE_SIZE); + igt_memcpy_from_wc(dst, src, PAGE_SIZE); } static void copy_wc_cacheline(void *dst, const void *src) { - memcpy(dst, src, CACHELINE); + igt_memcpy_from_wc(dst, src, CACHELINE); } -#endif - static void _bo_write_verify(struct test *t) { diff -Nru intel-gpu-tools-1.21/tests/gem_gtt_hog.c intel-gpu-tools-1.22/tests/gem_gtt_hog.c --- intel-gpu-tools-1.21/tests/gem_gtt_hog.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_gtt_hog.c 2018-03-09 14:22:59.000000000 +0000 @@ -113,7 +113,7 @@ gem_pwrite.data_ptr = to_user_pointer(buf); if (drmIoctl(data->fd, DRM_IOCTL_I915_GEM_PWRITE, &gem_pwrite) == 0) { while (loops--) - drmIoctl(data->fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); + gem_execbuf(data->fd, &execbuf); } drmIoctl(data->fd, DRM_IOCTL_GEM_CLOSE, &create.handle); diff -Nru intel-gpu-tools-1.21/tests/gem_linear_blits.c intel-gpu-tools-1.22/tests/gem_linear_blits.c --- intel-gpu-tools-1.21/tests/gem_linear_blits.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_linear_blits.c 2018-03-09 14:22:59.000000000 +0000 @@ -215,6 +215,8 @@ free(handle); } +#define MAX_32b ((1ull << 32) - 4096) + int main(int argc, char **argv) { int fd = 0; @@ -230,20 +232,28 @@ run_test(fd, 2); igt_subtest("normal") { - int count; + uint64_t count; - count = 3 * gem_aperture_size(fd) / (1024*1024) / 2; + count = gem_aperture_size(fd); + if (count >> 32) + count = MAX_32b; + count = 3 * count / (1024*1024) / 2; igt_require(count > 1); intel_require_memory(count, sizeof(linear), CHECK_RAM); + run_test(fd, count); } igt_subtest("interruptible") { - int count; + uint64_t count; - count = 3 * gem_aperture_size(fd) / (1024*1024) / 2; + count = gem_aperture_size(fd); + if (count >> 32) + count = MAX_32b; + count = 3 * count / (1024*1024) / 2; igt_require(count > 1); intel_require_memory(count, sizeof(linear), CHECK_RAM); + igt_fork_signal_helper(); run_test(fd, count); igt_stop_signal_helper(); diff -Nru intel-gpu-tools-1.21/tests/gem_lut_handle.c intel-gpu-tools-1.22/tests/gem_lut_handle.c --- intel-gpu-tools-1.21/tests/gem_lut_handle.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_lut_handle.c 2018-03-09 14:22:59.000000000 +0000 @@ -84,12 +84,7 @@ i915_execbuffer2_set_context_id(execbuf, 0); execbuf.rsvd2 = 0; - if (drmIoctl(fd, - DRM_IOCTL_I915_GEM_EXECBUFFER2, - &execbuf)) - return -errno; - - return 0; + return __gem_execbuf(fd, &execbuf); } static int many_exec(int fd, uint32_t batch, int num_exec, int num_reloc, unsigned flags) @@ -156,11 +151,7 @@ i915_execbuffer2_set_context_id(execbuf, 0); execbuf.rsvd2 = 0; - ret = drmIoctl(fd, - DRM_IOCTL_I915_GEM_EXECBUFFER2, - &execbuf); - if (ret < 0) - ret = -errno; + ret = __gem_execbuf(fd, &execbuf); for (n = 0; n < num_exec; n++) gem_close(fd, gem_exec[n].handle); diff -Nru intel-gpu-tools-1.21/tests/gem_mmap_gtt.c intel-gpu-tools-1.22/tests/gem_mmap_gtt.c --- intel-gpu-tools-1.21/tests/gem_mmap_gtt.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_mmap_gtt.c 2018-03-09 14:22:59.000000000 +0000 @@ -529,45 +529,10 @@ munmap(linear_pattern, PAGE_SIZE); } -#if defined(__x86_64__) && !defined(__clang__) -#define MOVNT 512 - -#pragma GCC push_options -#pragma GCC target("sse4.1") - -#include -__attribute__((noinline)) -static void copy_wc_page(void *dst, void *src) -{ - if (igt_x86_features() & SSE4_1) { - __m128i *S = (__m128i *)src; - __m128i *D = (__m128i *)dst; - - for (int i = 0; i < PAGE_SIZE/64; i++) { - __m128i tmp[4]; - - tmp[0] = _mm_stream_load_si128(S++); - tmp[1] = _mm_stream_load_si128(S++); - tmp[2] = _mm_stream_load_si128(S++); - tmp[3] = _mm_stream_load_si128(S++); - - _mm_store_si128(D++, tmp[0]); - _mm_store_si128(D++, tmp[1]); - _mm_store_si128(D++, tmp[2]); - _mm_store_si128(D++, tmp[3]); - } - } else - memcpy(dst, src, PAGE_SIZE); -} - -#pragma GCC pop_options - -#else static void copy_wc_page(void *dst, const void *src) { - memcpy(dst, src, PAGE_SIZE); + igt_memcpy_from_wc(dst, src, PAGE_SIZE); } -#endif static unsigned int tile_row_size(int tiling, unsigned int stride) { diff -Nru intel-gpu-tools-1.21/tests/gem_mocs_settings.c intel-gpu-tools-1.22/tests/gem_mocs_settings.c --- intel-gpu-tools-1.21/tests/gem_mocs_settings.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_mocs_settings.c 2018-03-09 14:22:59.000000000 +0000 @@ -453,6 +453,9 @@ flags & MOCS_NON_DEFAULT_CTX ? "-ctx": "", flags & MOCS_DIRTY_VALUES ? "-dirty" : "", e->name) { + if (flags & (MOCS_NON_DEFAULT_CTX | MOCS_DIRTY_VALUES)) + gem_require_contexts(fd); + run_test(fd, e->exec_id | e->flags, flags, mode); } } diff -Nru intel-gpu-tools-1.21/tests/gem_pwrite_pread.c intel-gpu-tools-1.22/tests/gem_pwrite_pread.c --- intel-gpu-tools-1.21/tests/gem_pwrite_pread.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_pwrite_pread.c 2018-03-09 14:22:59.000000000 +0000 @@ -100,7 +100,7 @@ while (loops--) { gem_write(fd, src, 0, buf, len); - do_ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); + gem_execbuf(fd, &execbuf); gem_read(fd, dst, 0, buf, len); } @@ -120,7 +120,7 @@ I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT); memcpy(src_ptr, buf, len); - do_ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); + gem_execbuf(fd, &execbuf); gem_set_domain(fd, dst, I915_GEM_DOMAIN_GTT, 0); memcpy(buf, dst_ptr, len); @@ -145,7 +145,7 @@ I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU); memcpy(src_ptr, buf, len); - do_ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); + gem_execbuf(fd, &execbuf); gem_set_domain(fd, dst, I915_GEM_DOMAIN_CPU, 0); memcpy(buf, dst_ptr, len); @@ -167,7 +167,7 @@ gem_write(fd, src, 0, buf, len); memset(buf, 0, len); - do_ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); + gem_execbuf(fd, &execbuf); gem_read(fd, dst, 0, buf, len); gem_close(fd, exec[2].handle); @@ -189,7 +189,7 @@ for (i = 0; i < len/4; i++) src_ptr[i] = i; - do_ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); + gem_execbuf(fd, &execbuf); gem_close(fd, exec[2].handle); gem_set_domain(fd, dst, I915_GEM_DOMAIN_GTT, 0); @@ -213,7 +213,7 @@ for (i = 0; i < len/4; i++) src_ptr[i] = i; - do_ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); + gem_execbuf(fd, &execbuf); gem_close(fd, exec[2].handle); gem_set_domain(fd, dst, I915_GEM_DOMAIN_CPU, 0); diff -Nru intel-gpu-tools-1.21/tests/gem_request_retire.c intel-gpu-tools-1.22/tests/gem_request_retire.c --- intel-gpu-tools-1.21/tests/gem_request_retire.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_request_retire.c 2018-03-09 14:22:59.000000000 +0000 @@ -227,7 +227,8 @@ igt_fixture { fd = drm_open_driver(DRIVER_INTEL); igt_require_gem(fd); - igt_assert(fd >= 0); + + gem_require_contexts(fd); } igt_subtest("retire-vma-not-inactive") diff -Nru intel-gpu-tools-1.21/tests/gem_reset_stats.c intel-gpu-tools-1.22/tests/gem_reset_stats.c --- intel-gpu-tools-1.21/tests/gem_reset_stats.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_reset_stats.c 2018-03-09 14:22:59.000000000 +0000 @@ -114,7 +114,10 @@ static void check_context(const struct intel_execution_engine *e) { int fd = drm_open_driver(DRIVER_INTEL); + + gem_require_contexts(fd); igt_require(has_engine(fd, gem_context_create(fd), e)); + close(fd); } @@ -605,10 +608,7 @@ c2 = get_reset_count(fd, ctx); - if (ctx == 0) - igt_assert(c2 == -EPERM); - else - igt_assert(c2 == 0); + igt_assert(c2 == 0); } igt_waitchildren(); @@ -644,10 +644,11 @@ const uint32_t bad = rand() + 1; if (ctx == 0) { - if (cap == root) - igt_assert_eq(_test_params(fd, ctx, 0, 0), 0); - else - igt_assert_eq(_test_params(fd, ctx, 0, 0), -EPERM); + igt_assert_eq(_test_params(fd, ctx, 0, 0), 0); + + if (cap != root) { + igt_assert(get_reset_count(fd, ctx) == 0); + } } igt_assert_eq(_test_params(fd, ctx, 0, bad), -EINVAL); diff -Nru intel-gpu-tools-1.21/tests/gem_ringfill.c intel-gpu-tools-1.22/tests/gem_ringfill.c --- intel-gpu-tools-1.21/tests/gem_ringfill.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_ringfill.c 2018-03-09 14:22:59.000000000 +0000 @@ -35,6 +35,7 @@ #include "igt_device.h" #include "igt_gt.h" #include "igt_vgem.h" +#include "i915/gem_ring.h" #include #include @@ -237,100 +238,6 @@ run_test(fd, ring, 0, 0); } -struct cork { - int device; - uint32_t handle; - uint32_t fence; -}; - -static void plug(int fd, struct cork *c) -{ - struct vgem_bo bo; - int dmabuf; - - c->device = drm_open_driver(DRIVER_VGEM); - - bo.width = bo.height = 1; - bo.bpp = 4; - vgem_create(c->device, &bo); - c->fence = vgem_fence_attach(c->device, &bo, VGEM_FENCE_WRITE); - - dmabuf = prime_handle_to_fd(c->device, bo.handle); - c->handle = prime_fd_to_handle(fd, dmabuf); - close(dmabuf); -} - -static void unplug(struct cork *c) -{ - vgem_fence_signal(c->device, c->fence); - close(c->device); -} - -static void alarm_handler(int sig) -{ -} - -static int __execbuf(int fd, struct drm_i915_gem_execbuffer2 *execbuf) -{ - return ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, execbuf); -} - -static unsigned int measure_ring_size(int fd) -{ - struct sigaction sa = { .sa_handler = alarm_handler }; - struct drm_i915_gem_exec_object2 obj[2]; - struct drm_i915_gem_execbuffer2 execbuf; - const uint32_t bbe = MI_BATCH_BUFFER_END; - unsigned int count, last; - struct itimerval itv; - struct cork c; - - memset(obj, 0, sizeof(obj)); - obj[1].handle = gem_create(fd, 4096); - gem_write(fd, obj[1].handle, 0, &bbe, sizeof(bbe)); - - memset(&execbuf, 0, sizeof(execbuf)); - execbuf.buffers_ptr = to_user_pointer(obj + 1); - execbuf.buffer_count = 1; - gem_execbuf(fd, &execbuf); - gem_sync(fd, obj[1].handle); - - plug(fd, &c); - obj[0].handle = c.handle; - - execbuf.buffers_ptr = to_user_pointer(obj); - execbuf.buffer_count = 2; - - sigaction(SIGALRM, &sa, NULL); - itv.it_interval.tv_sec = 0; - itv.it_interval.tv_usec = 100; - itv.it_value.tv_sec = 0; - itv.it_value.tv_usec = 1000; - setitimer(ITIMER_REAL, &itv, NULL); - - last = -1; - count = 0; - do { - if (__execbuf(fd, &execbuf) == 0) { - count++; - continue; - } - - if (last == count) - break; - - last = count; - } while (1); - - memset(&itv, 0, sizeof(itv)); - setitimer(ITIMER_REAL, &itv, NULL); - - unplug(&c); - gem_close(fd, obj[1].handle); - - return count; -} - igt_main { const struct { @@ -365,7 +272,7 @@ master = true; } - ring_size = measure_ring_size(fd); + ring_size = gem_measure_ring_inflight(fd, 0, 0); igt_info("Ring size: %d batches\n", ring_size); igt_require(ring_size); } diff -Nru intel-gpu-tools-1.21/tests/gem_ring_sync_loop.c intel-gpu-tools-1.22/tests/gem_ring_sync_loop.c --- intel-gpu-tools-1.21/tests/gem_ring_sync_loop.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_ring_sync_loop.c 2018-03-09 14:22:59.000000000 +0000 @@ -48,7 +48,7 @@ int i; nengine = 0; - for_each_engine(fd, engine) + for_each_physical_engine(fd, engine) engines[nengine++] = engine; igt_require(nengine); diff -Nru intel-gpu-tools-1.21/tests/gem_softpin.c intel-gpu-tools-1.22/tests/gem_softpin.c --- intel-gpu-tools-1.21/tests/gem_softpin.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_softpin.c 2018-03-09 14:22:59.000000000 +0000 @@ -302,11 +302,11 @@ /* Find a hole */ memset(object, 0, sizeof(object)); - object[0].handle = gem_create(fd, 3*4096); + object[0].handle = gem_create(fd, 5*4096); gem_write(fd, object[0].handle, 0, &bbe, sizeof(bbe)); gem_execbuf(fd, &execbuf); gem_close(fd, object[0].handle); - hole = object[0].offset; + hole = object[0].offset + 4096; /* Create a snoop + uncached pair */ object[0].handle = gem_create(fd, 4096); diff -Nru intel-gpu-tools-1.21/tests/gem_spin_batch.c intel-gpu-tools-1.22/tests/gem_spin_batch.c --- intel-gpu-tools-1.21/tests/gem_spin_batch.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_spin_batch.c 2018-03-09 14:22:59.000000000 +0000 @@ -41,7 +41,7 @@ struct timespec itv = { }; uint64_t elapsed; - spin = igt_spin_batch_new(fd, 0, engine, 0); + spin = __igt_spin_batch_new(fd, 0, engine, 0); while ((elapsed = igt_nsec_elapsed(&tv)) >> 30 < timeout_sec) { igt_spin_t *next = __igt_spin_batch_new(fd, 0, engine, 0); @@ -64,7 +64,6 @@ loops, (long long)elapsed, (long)(elapsed / timeout_100ms)); assert_within_epsilon(timeout_100ms * loops, elapsed, MAX_ERROR); - igt_assert_eq(intel_detect_and_clear_missed_interrupts(fd), 0); } static void spin_exit_handler(int sig) @@ -76,10 +75,7 @@ { unsigned engine; - for_each_engine(fd, engine) { - if (engine == 0) - continue; - + for_each_physical_engine(fd, engine) { igt_fork(child, 1) { igt_install_exit_handler(spin_exit_handler); spin(fd, engine, timeout_sec); @@ -104,15 +100,18 @@ } for (e = intel_execution_engines; e->name; e++) { - if (e->exec_id == 0) - continue; - - igt_subtest_f("basic-%s", e->name) + igt_subtest_f("basic-%s", e->name) { + intel_detect_and_clear_missed_interrupts(fd); spin(fd, e->exec_id, 3); + igt_assert_eq(intel_detect_and_clear_missed_interrupts(fd), 0); + } } - igt_subtest("spin-each") + igt_subtest("spin-each") { + intel_detect_and_clear_missed_interrupts(fd); spin_on_all_engines(fd, 3); + igt_assert_eq(intel_detect_and_clear_missed_interrupts(fd), 0); + } igt_fixture { igt_stop_hang_detector(); diff -Nru intel-gpu-tools-1.21/tests/gem_sync.c intel-gpu-tools-1.22/tests/gem_sync.c --- intel-gpu-tools-1.21/tests/gem_sync.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_sync.c 2018-03-09 14:22:59.000000000 +0000 @@ -86,23 +86,9 @@ int num_engines = 0; if (ring == ~0u) { - const struct intel_execution_engine *e; - - for (e = intel_execution_engines; e->name; e++) { - if (e->exec_id == 0) - continue; - - if (!gem_has_ring(fd, e->exec_id | e->flags)) - continue; - - if (e->exec_id == I915_EXEC_BSD) { - int is_bsd2 = e->flags != 0; - if (gem_has_bsd2(fd) != is_bsd2) - continue; - } - - names[num_engines] = e->name; - engines[num_engines++] = e->exec_id | e->flags; + for_each_physical_engine(fd, ring) { + names[num_engines] = e__->name; + engines[num_engines++] = ring; if (num_engines == ARRAY_SIZE(engines)) break; } @@ -153,6 +139,45 @@ } static void +idle_ring(int fd, unsigned ring, int timeout) +{ + const uint32_t bbe = MI_BATCH_BUFFER_END; + struct drm_i915_gem_exec_object2 object; + struct drm_i915_gem_execbuffer2 execbuf; + double start, elapsed; + unsigned long cycles; + + gem_require_ring(fd, ring); + + memset(&object, 0, sizeof(object)); + object.handle = gem_create(fd, 4096); + gem_write(fd, object.handle, 0, &bbe, sizeof(bbe)); + + memset(&execbuf, 0, sizeof(execbuf)); + execbuf.buffers_ptr = to_user_pointer(&object); + execbuf.buffer_count = 1; + execbuf.flags = ring; + gem_execbuf(fd, &execbuf); + gem_sync(fd, object.handle); + + intel_detect_and_clear_missed_interrupts(fd); + start = gettime(); + cycles = 0; + do { + do { + gem_execbuf(fd, &execbuf); + gem_quiescent_gpu(fd); + } while (++cycles & 1023); + } while ((elapsed = gettime() - start) < timeout); + igt_assert_eq(intel_detect_and_clear_missed_interrupts(fd), 0); + + igt_info("Completed %ld cycles: %.3f us\n", + cycles, elapsed*1e6/cycles); + + gem_close(fd, object.handle); +} + +static void store_ring(int fd, unsigned ring, int num_children, int timeout) { const int gen = intel_gen(intel_get_drm_devid(fd)); @@ -161,26 +186,12 @@ int num_engines = 0; if (ring == ~0u) { - const struct intel_execution_engine *e; - - for (e = intel_execution_engines; e->name; e++) { - if (e->exec_id == 0) - continue; - - if (!gem_has_ring(fd, e->exec_id | e->flags)) - continue; - - if (!gem_can_store_dword(fd, e->exec_id | e->flags)) + for_each_physical_engine(fd, ring) { + if (!gem_can_store_dword(fd, ring)) continue; - if (e->exec_id == I915_EXEC_BSD) { - int is_bsd2 = e->flags != 0; - if (gem_has_bsd2(fd) != is_bsd2) - continue; - } - - names[num_engines] = e->name; - engines[num_engines++] = e->exec_id | e->flags; + names[num_engines] = e__->name; + engines[num_engines++] = ring; if (num_engines == ARRAY_SIZE(engines)) break; } @@ -463,31 +474,17 @@ intel_detect_and_clear_missed_interrupts(fd); if (ring == ~0u) { - const struct intel_execution_engine *e; - - for (e = intel_execution_engines; e->name; e++) { - if (e->exec_id == 0) + for_each_physical_engine(fd, ring) { + if (!gem_can_store_dword(fd, ring)) continue; - if (!gem_has_ring(fd, e->exec_id | e->flags)) - continue; - - if (!gem_can_store_dword(fd, e->exec_id | e->flags)) - continue; - - if (e->exec_id == I915_EXEC_BSD) { - int is_bsd2 = e->flags != 0; - if (gem_has_bsd2(fd) != is_bsd2) - continue; - } - igt_fork(child, 1) __store_many(fd, - e->exec_id | e->flags, + ring, timeout, &shared[n]); - names[n++] = e->name; + names[n++] = e__->name; } igt_waitchildren(); } else { @@ -508,24 +505,11 @@ static void sync_all(int fd, int num_children, int timeout) { - const struct intel_execution_engine *e; - unsigned engines[16]; + unsigned engines[16], engine; int num_engines = 0; - for (e = intel_execution_engines; e->name; e++) { - if (e->exec_id == 0) - continue; - - if (!gem_has_ring(fd, e->exec_id | e->flags)) - continue; - - if (e->exec_id == I915_EXEC_BSD) { - int is_bsd2 = e->flags != 0; - if (gem_has_bsd2(fd) != is_bsd2) - continue; - } - - engines[num_engines++] = e->exec_id | e->flags; + for_each_physical_engine(fd, engine) { + engines[num_engines++] = engine; if (num_engines == ARRAY_SIZE(engines)) break; } @@ -573,27 +557,15 @@ store_all(int fd, int num_children, int timeout) { const int gen = intel_gen(intel_get_drm_devid(fd)); - const struct intel_execution_engine *e; unsigned engines[16]; int num_engines = 0; + unsigned int ring; - for (e = intel_execution_engines; e->name; e++) { - if (e->exec_id == 0) + for_each_physical_engine(fd, ring) { + if (!gem_can_store_dword(fd, ring)) continue; - if (!gem_has_ring(fd, e->exec_id | e->flags)) - continue; - - if (!gem_can_store_dword(fd, e->exec_id)) - continue; - - if (e->exec_id == I915_EXEC_BSD) { - int is_bsd2 = e->flags != 0; - if (gem_has_bsd2(fd) != is_bsd2) - continue; - } - - engines[num_engines++] = e->exec_id | e->flags; + engines[num_engines++] = ring; if (num_engines == ARRAY_SIZE(engines)) break; } @@ -698,23 +670,9 @@ uint32_t ctx[2]; if (ring == ~0u) { - const struct intel_execution_engine *e; - - for (e = intel_execution_engines; e->name; e++) { - if (e->exec_id == 0) - continue; - - if (!gem_has_ring(fd, e->exec_id | e->flags)) - continue; - - if (e->exec_id == I915_EXEC_BSD) { - int is_bsd2 = e->flags != 0; - if (gem_has_bsd2(fd) != is_bsd2) - continue; - } - - names[num_engines] = e->name; - engines[num_engines++] = e->exec_id | e->flags; + for_each_physical_engine(fd, ring) { + names[num_engines] = e__->name; + engines[num_engines++] = ring; if (num_engines == ARRAY_SIZE(engines)) break; } @@ -802,6 +760,8 @@ for (e = intel_execution_engines; e->name; e++) { igt_subtest_f("%s", e->name) sync_ring(fd, e->exec_id | e->flags, 1, 150); + igt_subtest_f("idle-%s", e->name) + idle_ring(fd, e->exec_id | e->flags, 150); igt_subtest_f("store-%s", e->name) store_ring(fd, e->exec_id | e->flags, 1, 150); igt_subtest_f("many-%s", e->name) @@ -839,6 +799,7 @@ igt_subtest_group { igt_fixture { + gem_require_contexts(fd); igt_require(gem_scheduler_has_ctx_priority(fd)); igt_require(gem_scheduler_has_preemption(fd)); } diff -Nru intel-gpu-tools-1.21/tests/gem_tiled_blits.c intel-gpu-tools-1.22/tests/gem_tiled_blits.c --- intel-gpu-tools-1.21/tests/gem_tiled_blits.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_tiled_blits.c 2018-03-09 14:22:59.000000000 +0000 @@ -192,6 +192,8 @@ free(bo); } +#define MAX_32b ((1ull << 32) - 4096) + int fd; int main(int argc, char **argv) @@ -212,9 +214,12 @@ run_test(2); igt_subtest("normal") { - int count; + uint64_t count; - count = 3 * gem_aperture_size(fd) / (1024*1024) / 2; + count = gem_aperture_size(fd); + if (count >> 32) + count = MAX_32b; + count = 3 * count / (1024*1024) / 2; count += (count & 1) == 0; intel_require_memory(count, 1024*1024, CHECK_RAM); @@ -222,9 +227,12 @@ } igt_subtest("interruptible") { - int count; + uint64_t count; - count = 3 * gem_aperture_size(fd) / (1024*1024) / 2; + count = gem_aperture_size(fd); + if (count >> 32) + count = MAX_32b; + count = 3 * count / (1024*1024) / 2; count += (count & 1) == 0; intel_require_memory(count, 1024*1024, CHECK_RAM); diff -Nru intel-gpu-tools-1.21/tests/gem_tiled_fence_blits.c intel-gpu-tools-1.22/tests/gem_tiled_fence_blits.c --- intel-gpu-tools-1.21/tests/gem_tiled_fence_blits.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_tiled_fence_blits.c 2018-03-09 14:22:59.000000000 +0000 @@ -98,16 +98,20 @@ } } -static void run_test (int fd, int count) +static void run_test(int fd, int count) { - drm_intel_bo *bo[4096]; - uint32_t bo_start_val[4096]; + drm_intel_bo **bo; + uint32_t *bo_start_val; uint32_t start = 0; int i; count |= 1; igt_info("Using %d 1MiB buffers\n", count); + bo = malloc(count * sizeof(*bo)); + bo_start_val = malloc(count * sizeof(*bo_start_val)); + igt_assert(bo && bo_start_val); + bufmgr = drm_intel_bufmgr_gem_init(fd, 4096); drm_intel_bufmgr_gem_enable_reuse(bufmgr); batch = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd)); @@ -158,11 +162,16 @@ intel_batchbuffer_free(batch); drm_intel_bufmgr_destroy(bufmgr); + + free(bo_start_val); + free(bo); } +#define MAX_32b ((1ull << 32) - 4096) + igt_main { - int fd, count; + int fd; igt_fixture { fd = drm_open_driver(DRIVER_INTEL); @@ -177,7 +186,12 @@ igt_skip_on_simulation(); igt_subtest("normal") { - count = 3 * gem_aperture_size(fd) / (bo_size) / 2; + uint64_t count; + + count = gem_aperture_size(fd); + if (count >> 32) + count = MAX_32b; + count = 3 * count / bo_size / 2; intel_require_memory(count, bo_size, CHECK_RAM); run_test(fd, count); } diff -Nru intel-gpu-tools-1.21/tests/gem_tiled_pread_pwrite.c intel-gpu-tools-1.22/tests/gem_tiled_pread_pwrite.c --- intel-gpu-tools-1.21/tests/gem_tiled_pread_pwrite.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_tiled_pread_pwrite.c 2018-03-09 14:22:59.000000000 +0000 @@ -100,45 +100,10 @@ return handle; } -#if defined(__x86_64__) && !defined(__clang__) -#define MOVNT 512 - -#pragma GCC push_options -#pragma GCC target("sse4.1") - -#include -__attribute__((noinline)) -static void copy_wc_page(void *dst, void *src) -{ - if (igt_x86_features() & SSE4_1) { - __m128i *S = (__m128i *)src; - __m128i *D = (__m128i *)dst; - - for (int i = 0; i < PAGE_SIZE/64; i++) { - __m128i tmp[4]; - - tmp[0] = _mm_stream_load_si128(S++); - tmp[1] = _mm_stream_load_si128(S++); - tmp[2] = _mm_stream_load_si128(S++); - tmp[3] = _mm_stream_load_si128(S++); - - _mm_store_si128(D++, tmp[0]); - _mm_store_si128(D++, tmp[1]); - _mm_store_si128(D++, tmp[2]); - _mm_store_si128(D++, tmp[3]); - } - } else - memcpy(dst, src, PAGE_SIZE); -} - -#pragma GCC pop_options - -#else static void copy_wc_page(void *dst, const void *src) { - memcpy(dst, src, PAGE_SIZE); + igt_memcpy_from_wc(dst, src, PAGE_SIZE); } -#endif igt_simple_main { diff -Nru intel-gpu-tools-1.21/tests/gem_wait.c intel-gpu-tools-1.22/tests/gem_wait.c --- intel-gpu-tools-1.21/tests/gem_wait.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_wait.c 2018-03-09 14:22:59.000000000 +0000 @@ -69,51 +69,15 @@ #define AWAIT 4 #define WRITE 8 -struct cork { - int device; - uint32_t handle; - uint32_t fence; -}; - -static struct cork plug(int fd, unsigned flags) -{ - struct cork c; - struct vgem_bo bo; - int dmabuf; - - if ((flags & (WRITE | AWAIT)) == 0) - return (struct cork){0}; - - c.device = drm_open_driver(DRIVER_VGEM); - - bo.width = bo.height = 1; - bo.bpp = 4; - vgem_create(c.device, &bo); - c.fence = vgem_fence_attach(c.device, &bo, VGEM_FENCE_WRITE); - - dmabuf = prime_handle_to_fd(c.device, bo.handle); - c.handle = prime_fd_to_handle(fd, dmabuf); - close(dmabuf); - - return c; -} - -static void unplug(struct cork *c) -{ - if (!c->device) - return; - - vgem_fence_signal(c->device, c->fence); - close(c->device); -} - static void basic(int fd, unsigned engine, unsigned flags) { - struct cork cork = plug(fd, flags); - igt_spin_t *spin = igt_spin_batch_new(fd, 0, engine, cork.handle); + IGT_CORK_HANDLE(cork); + uint32_t plug = + flags & (WRITE | AWAIT) ? igt_cork_plug(&cork, fd) : 0; + igt_spin_t *spin = igt_spin_batch_new(fd, 0, engine, plug); struct drm_i915_gem_wait wait = { - flags & WRITE ? cork.handle : spin->handle - }; + flags & WRITE ? plug : spin->handle + }; igt_assert_eq(__gem_wait(fd, &wait), -ETIME); @@ -127,7 +91,9 @@ timeout = 1; } - unplug(&cork); + if (flags & (WRITE | AWAIT)) + igt_cork_unplug(&cork); + igt_assert_eq(__gem_wait(fd, &wait), -ETIME); while (__gem_wait(fd, &wait) == -ETIME) @@ -137,7 +103,9 @@ igt_assert_eq(__gem_wait(fd, &wait), -ETIME); igt_assert_eq_s64(wait.timeout_ns, 0); - unplug(&cork); + if (flags & (WRITE | AWAIT)) + igt_cork_unplug(&cork); + wait.timeout_ns = 0; igt_assert_eq(__gem_wait(fd, &wait), -ETIME); @@ -157,6 +125,8 @@ igt_assert(wait.timeout_ns == 0); } + if (plug) + gem_close(fd, plug); igt_spin_batch_free(fd, spin); } diff -Nru intel-gpu-tools-1.21/tests/gem_workarounds.c intel-gpu-tools-1.22/tests/gem_workarounds.c --- intel-gpu-tools-1.21/tests/gem_workarounds.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gem_workarounds.c 2018-03-09 14:22:59.000000000 +0000 @@ -182,8 +182,11 @@ if (flags & FD) fd = reopen(fd); - if (flags & CONTEXT) + + if (flags & CONTEXT) { + gem_require_contexts(fd); ctx = gem_context_create(fd); + } igt_assert_eq(workaround_fail_count(fd, ctx), 0); diff -Nru intel-gpu-tools-1.21/tests/gen3_mixed_blits.c intel-gpu-tools-1.22/tests/gen3_mixed_blits.c --- intel-gpu-tools-1.21/tests/gen3_mixed_blits.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gen3_mixed_blits.c 2018-03-09 14:22:59.000000000 +0000 @@ -88,7 +88,6 @@ struct drm_i915_gem_execbuffer2 exec; uint32_t handle; uint32_t tiling_bits; - int ret; /* invariant state */ *b++ = (_3DSTATE_AA_CMD | @@ -310,12 +309,7 @@ i915_execbuffer2_set_context_id(exec, 0); exec.rsvd2 = 0; - ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec); - while (ret && errno == EBUSY) { - drmCommandNone(fd, DRM_I915_GEM_THROTTLE); - ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec); - } - igt_assert_eq(ret, 0); + gem_execbuf(fd, &exec); gem_close(fd, handle); } @@ -327,7 +321,6 @@ struct drm_i915_gem_exec_object2 obj[3]; struct drm_i915_gem_execbuffer2 exec; uint32_t handle; - int ret; *b++ = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | @@ -388,12 +381,7 @@ i915_execbuffer2_set_context_id(exec, 0); exec.rsvd2 = 0; - ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec); - while (ret && errno == EBUSY) { - drmCommandNone(fd, DRM_I915_GEM_THROTTLE); - ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec); - } - igt_assert_eq(ret, 0); + gem_execbuf(fd, &exec); gem_close(fd, handle); } diff -Nru intel-gpu-tools-1.21/tests/gen3_render_linear_blits.c intel-gpu-tools-1.22/tests/gen3_render_linear_blits.c --- intel-gpu-tools-1.21/tests/gen3_render_linear_blits.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gen3_render_linear_blits.c 2018-03-09 14:22:59.000000000 +0000 @@ -85,7 +85,6 @@ struct drm_i915_gem_exec_object2 obj[3]; struct drm_i915_gem_execbuffer2 exec; uint32_t handle; - int ret; /* invariant state */ *b++ = (_3DSTATE_AA_CMD | @@ -280,12 +279,7 @@ i915_execbuffer2_set_context_id(exec, 0); exec.rsvd2 = 0; - ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec); - while (ret && errno == EBUSY) { - drmCommandNone(fd, DRM_I915_GEM_THROTTLE); - ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec); - } - igt_assert_eq(ret, 0); + gem_execbuf(fd, &exec); gem_close(fd, handle); } diff -Nru intel-gpu-tools-1.21/tests/gen3_render_mixed_blits.c intel-gpu-tools-1.22/tests/gen3_render_mixed_blits.c --- intel-gpu-tools-1.21/tests/gen3_render_mixed_blits.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gen3_render_mixed_blits.c 2018-03-09 14:22:59.000000000 +0000 @@ -87,7 +87,6 @@ struct drm_i915_gem_execbuffer2 exec; uint32_t handle; uint32_t tiling_bits; - int ret; /* invariant state */ *b++ = (_3DSTATE_AA_CMD | @@ -293,12 +292,7 @@ i915_execbuffer2_set_context_id(exec, 0); exec.rsvd2 = 0; - ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec); - while (ret && errno == EBUSY) { - drmCommandNone(fd, DRM_I915_GEM_THROTTLE); - ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec); - } - igt_assert_eq(ret, 0); + gem_execbuf(fd, &exec); gem_close(fd, handle); } diff -Nru intel-gpu-tools-1.21/tests/gen3_render_tiledx_blits.c intel-gpu-tools-1.22/tests/gen3_render_tiledx_blits.c --- intel-gpu-tools-1.21/tests/gen3_render_tiledx_blits.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gen3_render_tiledx_blits.c 2018-03-09 14:22:59.000000000 +0000 @@ -84,7 +84,6 @@ struct drm_i915_gem_exec_object2 obj[3]; struct drm_i915_gem_execbuffer2 exec; uint32_t handle; - int ret; /* invariant state */ *b++ = (_3DSTATE_AA_CMD | @@ -280,12 +279,7 @@ i915_execbuffer2_set_context_id(exec, 0); exec.rsvd2 = 0; - ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec); - while (ret && errno == EBUSY) { - drmCommandNone(fd, DRM_I915_GEM_THROTTLE); - ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec); - } - igt_assert_eq(ret, 0); + gem_execbuf(fd, &exec); gem_close(fd, handle); } diff -Nru intel-gpu-tools-1.21/tests/gen3_render_tiledy_blits.c intel-gpu-tools-1.22/tests/gen3_render_tiledy_blits.c --- intel-gpu-tools-1.21/tests/gen3_render_tiledy_blits.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gen3_render_tiledy_blits.c 2018-03-09 14:22:59.000000000 +0000 @@ -84,7 +84,6 @@ struct drm_i915_gem_exec_object2 obj[3]; struct drm_i915_gem_execbuffer2 exec; uint32_t handle; - int ret; /* invariant state */ *b++ = (_3DSTATE_AA_CMD | @@ -280,12 +279,7 @@ i915_execbuffer2_set_context_id(exec, 0); exec.rsvd2 = 0; - ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec); - while (ret && errno == EBUSY) { - drmCommandNone(fd, DRM_I915_GEM_THROTTLE); - ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec); - } - igt_assert_eq(ret, 0); + gem_execbuf(fd, &exec); gem_close(fd, handle); } diff -Nru intel-gpu-tools-1.21/tests/gen7_forcewake_mt.c intel-gpu-tools-1.22/tests/gen7_forcewake_mt.c --- intel-gpu-tools-1.21/tests/gen7_forcewake_mt.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/gen7_forcewake_mt.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,204 +0,0 @@ -/* - * Copyright © 2014 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. - * - * Authors: - * Chris Wilson - * - */ - -/* - * Testcase: Exercise a suspect workaround required for FORCEWAKE_MT - * - */ - -#include "igt.h" -#include -#include -#include - -#include "drm.h" - -IGT_TEST_DESCRIPTION("Exercise a suspect workaround required for" - " FORCEWAKE_MT."); - -#define FORCEWAKE_MT 0xa188 - -struct thread { - pthread_t thread; - void *mmio; - int fd; - int bit; -}; - -static const struct pci_id_match match[] = { - INTEL_IVB_D_IDS(NULL), - INTEL_IVB_M_IDS(NULL), - - INTEL_HSW_IDS(NULL), - - { 0, 0, 0 }, -}; - -static struct pci_device *__igfx_get(void) -{ - struct pci_device *dev; - - if (pci_system_init()) - return 0; - - dev = pci_device_find_by_slot(0, 0, 2, 0); - if (dev == NULL || dev->vendor_id != 0x8086) { - struct pci_device_iterator *iter; - - iter = pci_id_match_iterator_create(match); - if (!iter) - return 0; - - dev = pci_device_next(iter); - pci_iterator_destroy(iter); - } - - return dev; -} - -static void *igfx_get_mmio(void) -{ - struct pci_device *pci = __igfx_get(); - void *mmio = NULL; - int error; - - igt_skip_on(pci == NULL); - igt_skip_on(intel_gen(pci->device_id) != 7); - - error = pci_device_probe(pci); - igt_assert_eq(error, 0); - - error = pci_device_map_range(pci, - pci->regions[0].base_addr, - 2*1024*1024, - PCI_DEV_MAP_FLAG_WRITABLE, - &mmio); - igt_assert_eq(error, 0); - igt_assert(mmio != NULL); - - return mmio; -} - -static void *thread(void *arg) -{ - struct thread *t = arg; - uint32_t *forcewake_mt = (uint32_t *)((char *)t->mmio + FORCEWAKE_MT); - uint32_t bit = 1 << t->bit; - - while (1) { - *forcewake_mt = bit << 16 | bit; - igt_assert(*forcewake_mt & bit); - *forcewake_mt = bit << 16; - igt_assert((*forcewake_mt & bit) == 0); - } - - return NULL; -} - -#define MI_STORE_REGISTER_MEM (0x24<<23) - -igt_simple_main -{ - struct thread t[16]; - int i; - - t[0].fd = drm_open_driver(DRIVER_INTEL); - t[0].mmio = igfx_get_mmio(); - - for (i = 2; i < 16; i++) { - t[i] = t[0]; - t[i].bit = i; - pthread_create(&t[i].thread, NULL, thread, &t[i]); - } - - sleep(2); - - for (i = 0; i < 1000; i++) { - uint32_t *p; - struct drm_i915_gem_execbuffer2 execbuf; - struct drm_i915_gem_exec_object2 exec[2]; - struct drm_i915_gem_relocation_entry reloc[2]; - uint32_t b[] = { - MI_LOAD_REGISTER_IMM, - FORCEWAKE_MT, - 2 << 16 | 2, - MI_STORE_REGISTER_MEM | 1, - FORCEWAKE_MT, - 0, // to be patched - MI_LOAD_REGISTER_IMM, - FORCEWAKE_MT, - 2 << 16, - MI_STORE_REGISTER_MEM | 1, - FORCEWAKE_MT, - 1 * sizeof(uint32_t), // to be patched - MI_BATCH_BUFFER_END, - 0 - }; - - memset(exec, 0, sizeof(exec)); - exec[1].handle = gem_create(t[0].fd, 4096); - exec[1].relocation_count = 2; - exec[1].relocs_ptr = (uintptr_t)reloc; - gem_write(t[0].fd, exec[1].handle, 0, b, sizeof(b)); - exec[0].handle = gem_create(t[0].fd, 4096); - - reloc[0].offset = 5 * sizeof(uint32_t); - reloc[0].delta = 0; - reloc[0].target_handle = exec[0].handle; - reloc[0].read_domains = I915_GEM_DOMAIN_RENDER; - reloc[0].write_domain = I915_GEM_DOMAIN_RENDER; - reloc[0].presumed_offset = 0; - - reloc[1].offset = 11 * sizeof(uint32_t); - reloc[1].delta = 1 * sizeof(uint32_t); - reloc[1].target_handle = exec[0].handle; - reloc[1].read_domains = I915_GEM_DOMAIN_RENDER; - reloc[1].write_domain = I915_GEM_DOMAIN_RENDER; - reloc[1].presumed_offset = 0; - - memset(&execbuf, 0, sizeof(execbuf)); - execbuf.buffers_ptr = (uintptr_t)&exec; - execbuf.buffer_count = 2; - execbuf.batch_len = sizeof(b); - execbuf.flags = I915_EXEC_SECURE; - - gem_execbuf(t[0].fd, &execbuf); - gem_sync(t[0].fd, exec[1].handle); - - p = gem_mmap__gtt(t[0].fd, exec[0].handle, 4096, PROT_READ); - - igt_info("[%d]={ %08x %08x }\n", i, p[0], p[1]); - igt_assert(p[0] & 2); - igt_assert((p[1] & 2) == 0); - - munmap(p, 4096); - gem_close(t[0].fd, exec[0].handle); - gem_close(t[0].fd, exec[1].handle); - - usleep(1000); - } -} diff -Nru intel-gpu-tools-1.21/tests/intel-ci/meson.build intel-gpu-tools-1.22/tests/intel-ci/meson.build --- intel-gpu-tools-1.21/tests/intel-ci/meson.build 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/intel-ci/meson.build 2018-03-09 14:22:59.000000000 +0000 @@ -5,4 +5,4 @@ 'README', ] -install_data(sources : intelci_files, install_dir : pkgdatadir) +install_data(sources : intelci_files, install_dir : datadir) diff -Nru intel-gpu-tools-1.21/tests/kms_atomic.c intel-gpu-tools-1.22/tests/kms_atomic.c --- intel-gpu-tools-1.21/tests/kms_atomic.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/kms_atomic.c 2018-03-09 14:22:59.000000000 +0000 @@ -264,20 +264,13 @@ static uint32_t plane_get_igt_format(igt_plane_t *plane) { drmModePlanePtr plane_kms; - const uint32_t *igt_formats; - int num_igt_formats; int i; plane_kms = plane->drm_plane; - igt_get_all_cairo_formats(&igt_formats, &num_igt_formats); - for (i = 0; i < num_igt_formats; i++) { - int j; - - for (j = 0; j < plane_kms->count_formats; j++) { - if (plane_kms->formats[j] == igt_formats[i]) - return plane_kms->formats[j]; - } + for (i = 0; i < plane_kms->count_formats; i++) { + if (igt_fb_supported_format(plane_kms->formats[i])) + return plane_kms->formats[i]; } return 0; @@ -485,6 +478,10 @@ igt_plane_set_prop_value(plane, IGT_PLANE_FB_ID, pipe->values[IGT_CRTC_MODE_ID]); plane_commit_atomic_err(plane, ATOMIC_RELAX_NONE, EINVAL); + /* Valid, but invalid because CRTC_ID is set. */ + igt_plane_set_prop_value(plane, IGT_PLANE_FB_ID, 0); + plane_commit_atomic_err(plane, ATOMIC_RELAX_NONE, EINVAL); + igt_plane_set_fb(plane, fb); plane_commit(plane, COMMIT_ATOMIC, ATOMIC_RELAX_NONE); @@ -501,6 +498,10 @@ igt_plane_set_prop_value(plane, IGT_PLANE_CRTC_ID, pipe->values[IGT_CRTC_MODE_ID]); plane_commit_atomic_err(plane, ATOMIC_RELAX_NONE, EINVAL); + /* Valid, but invalid because FB_ID is set. */ + igt_plane_set_prop_value(plane, IGT_PLANE_CRTC_ID, 0); + plane_commit_atomic_err(plane, ATOMIC_RELAX_NONE, EINVAL); + igt_plane_set_fb(plane, fb); plane_commit(plane, COMMIT_ATOMIC, ATOMIC_RELAX_NONE); diff -Nru intel-gpu-tools-1.21/tests/kms_atomic_transition.c intel-gpu-tools-1.22/tests/kms_atomic_transition.c --- intel-gpu-tools-1.21/tests/kms_atomic_transition.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/kms_atomic_transition.c 2018-03-09 14:22:59.000000000 +0000 @@ -410,7 +410,8 @@ mode = igt_output_get_mode(output); override_mode = *mode; - override_mode.flags |= DRM_MODE_FLAG_HSKEW; + /* try to force a modeset */ + override_mode.flags ^= DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NHSYNC; igt_create_fb(display->drm_fd, mode->hdisplay, mode->vdisplay, DRM_FORMAT_XRGB8888, LOCAL_DRM_FORMAT_MOD_NONE, &fb); diff -Nru intel-gpu-tools-1.21/tests/kms_ccs.c intel-gpu-tools-1.22/tests/kms_ccs.c --- intel-gpu-tools-1.21/tests/kms_ccs.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/kms_ccs.c 2018-03-09 14:22:59.000000000 +0000 @@ -53,12 +53,11 @@ typedef struct { int drm_fd; igt_display_t display; - struct igt_fb fb; - struct igt_fb fb_sprite; igt_output_t *output; enum pipe pipe; enum test_flags flags; igt_plane_t *plane; + igt_pipe_crc_t *pipe_crc; } data_t; #define RED 0x00ff0000 @@ -131,7 +130,7 @@ return (struct local_drm_format_modifier *)(((char *)blob) + blob->modifiers_offset); } -static void plane_require_ccs(data_t *data, igt_plane_t *plane, uint32_t format) +static bool plane_has_format_with_ccs(data_t *data, igt_plane_t *plane, uint32_t format) { drmModePropertyBlobPtr blob; struct local_drm_format_modifier_blob *blob_data; @@ -162,8 +161,8 @@ } } - igt_skip_on_f(fmt_idx == -1, - "Format 0x%x not supported by plane\n", format); + if (fmt_idx == -1) + return false; modifiers = modifiers_ptr(blob_data); last_mod = &modifiers[blob_data->count_modifiers]; @@ -178,12 +177,10 @@ if (modifiers[i].formats & (1UL << (fmt_idx - modifiers[i].offset))) - return; - - igt_skip("i915 CCS modifier not supported for format\n"); + return true; } - igt_skip("i915 CCS modifier not supported by kernel for plane\n"); + return false; } static void render_fb(data_t *data, uint32_t gem_handle, unsigned int size, @@ -386,12 +383,14 @@ fb->domain = 0; } -static void try_config(data_t *data, enum test_fb_flags fb_flags) +static bool try_config(data_t *data, enum test_fb_flags fb_flags, + igt_crc_t *crc) { igt_display_t *display = &data->display; igt_plane_t *primary; drmModeModeInfo *drm_mode = igt_output_get_mode(data->output); enum igt_commit_style commit; + struct igt_fb fb, fb_sprite; int ret; if (data->display.is_atomic) @@ -401,30 +400,32 @@ primary = igt_output_get_plane_type(data->output, DRM_PLANE_TYPE_PRIMARY); - plane_require_ccs(data, primary, DRM_FORMAT_XRGB8888); + if (!plane_has_format_with_ccs(data, primary, DRM_FORMAT_XRGB8888)) + return false; if (data->plane && fb_flags & FB_COMPRESSED) { - plane_require_ccs(data, data->plane, DRM_FORMAT_XRGB8888); - generate_fb(data, &data->fb, drm_mode->hdisplay, + if (!plane_has_format_with_ccs(data, data->plane, DRM_FORMAT_XRGB8888)) + return false; + generate_fb(data, &fb, drm_mode->hdisplay, drm_mode->vdisplay, (fb_flags & ~FB_COMPRESSED) | FB_HAS_PLANE); - generate_fb(data, &data->fb_sprite, 256, 256, fb_flags); + generate_fb(data, &fb_sprite, 256, 256, fb_flags); } else { - generate_fb(data, &data->fb, drm_mode->hdisplay, + generate_fb(data, &fb, drm_mode->hdisplay, drm_mode->vdisplay, fb_flags); } if (data->flags & TEST_FAIL_ON_ADDFB2) - return; + return true; igt_plane_set_position(primary, 0, 0); igt_plane_set_size(primary, drm_mode->hdisplay, drm_mode->vdisplay); - igt_plane_set_fb(primary, &data->fb); + igt_plane_set_fb(primary, &fb); if (data->plane && fb_flags & FB_COMPRESSED) { igt_plane_set_position(data->plane, 0, 0); igt_plane_set_size(data->plane, 256, 256); - igt_plane_set_fb(data->plane, &data->fb_sprite); + igt_plane_set_fb(data->plane, &fb_sprite); } if (data->flags & TEST_ROTATE_180) @@ -433,28 +434,40 @@ igt_plane_set_rotation(primary, IGT_ROTATION_90); ret = igt_display_try_commit2(display, commit); - if (data->flags & TEST_BAD_ROTATION_90) + if (data->flags & TEST_BAD_ROTATION_90) { igt_assert_eq(ret, -EINVAL); - else + } else { igt_assert_eq(ret, 0); + if (crc) + igt_pipe_crc_collect_crc(data->pipe_crc, crc); + } + igt_debug_wait_for_keypress("ccs"); if (data->plane && fb_flags & FB_COMPRESSED) { igt_plane_set_position(data->plane, 0, 0); igt_plane_set_size(data->plane, 0, 0); igt_plane_set_fb(data->plane, NULL); - igt_remove_fb(display->drm_fd, &data->fb_sprite); + igt_remove_fb(display->drm_fd, &fb_sprite); } + + igt_plane_set_fb(primary, NULL); + igt_plane_set_rotation(primary, IGT_ROTATION_0); + igt_display_commit2(display, commit); + + if (data->flags & TEST_CRC) + igt_remove_fb(data->drm_fd, &fb); + + return true; } -static void test_output(data_t *data) +static int test_output(data_t *data) { igt_display_t *display = &data->display; - igt_plane_t *primary; igt_crc_t crc, ref_crc; - igt_pipe_crc_t *pipe_crc; enum test_fb_flags fb_flags = 0; + int valid_tests = 0; igt_display_require_output_on_pipe(display, data->pipe); @@ -466,44 +479,35 @@ igt_output_set_pipe(data->output, data->pipe); if (data->flags & TEST_CRC) { - pipe_crc = igt_pipe_crc_new(data->drm_fd, data->pipe, INTEL_PIPE_CRC_SOURCE_AUTO); - - try_config(data, fb_flags | FB_COMPRESSED); - igt_pipe_crc_collect_crc(pipe_crc, &ref_crc); - - try_config(data, fb_flags); - igt_pipe_crc_collect_crc(pipe_crc, &crc); + data->pipe_crc = igt_pipe_crc_new(data->drm_fd, data->pipe, INTEL_PIPE_CRC_SOURCE_AUTO); - igt_assert_crc_equal(&crc, &ref_crc); + if (try_config(data, fb_flags | FB_COMPRESSED, &ref_crc) && + try_config(data, fb_flags, &crc)) { + igt_assert_crc_equal(&crc, &ref_crc); + valid_tests++; + } - igt_pipe_crc_free(pipe_crc); - pipe_crc = NULL; + igt_pipe_crc_free(data->pipe_crc); + data->pipe_crc = NULL; } if (data->flags & TEST_BAD_PIXEL_FORMAT || data->flags & TEST_BAD_ROTATION_90 || data->flags & TEST_NO_AUX_BUFFER || data->flags & TEST_BAD_CCS_HANDLE) { - try_config(data, fb_flags | FB_COMPRESSED); + valid_tests += try_config(data, fb_flags | FB_COMPRESSED, NULL); } if (data->flags & TEST_BAD_AUX_STRIDE) { - try_config(data, fb_flags | FB_COMPRESSED | FB_MISALIGN_AUX_STRIDE); - try_config(data, fb_flags | FB_COMPRESSED | FB_SMALL_AUX_STRIDE); - try_config(data, fb_flags | FB_COMPRESSED | FB_ZERO_AUX_STRIDE); + valid_tests += try_config(data, fb_flags | FB_COMPRESSED | FB_MISALIGN_AUX_STRIDE , NULL); + valid_tests += try_config(data, fb_flags | FB_COMPRESSED | FB_SMALL_AUX_STRIDE , NULL); + valid_tests += try_config(data, fb_flags | FB_COMPRESSED | FB_ZERO_AUX_STRIDE , NULL); } - primary = igt_output_get_plane_type(data->output, DRM_PLANE_TYPE_PRIMARY); - igt_plane_set_fb(primary, NULL); - igt_plane_set_rotation(primary, IGT_ROTATION_0); - if (!display->is_atomic) - igt_display_commit2(display, COMMIT_UNIVERSAL); - igt_output_set_pipe(data->output, PIPE_ANY); igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY); - if (data->flags & TEST_CRC) - igt_remove_fb(data->drm_fd, &data->fb); + return valid_tests; } static data_t data; @@ -524,52 +528,53 @@ for_each_pipe_static(pipe) { const char *pipe_name = kmstest_pipe_name(pipe); - int sprite_idx = 0; data.pipe = pipe; data.flags = TEST_BAD_PIXEL_FORMAT; igt_subtest_f("pipe-%s-bad-pixel-format", pipe_name) - test_output(&data); + igt_require(test_output(&data)); data.flags = TEST_BAD_ROTATION_90; igt_subtest_f("pipe-%s-bad-rotation-90", pipe_name) - test_output(&data); + igt_require(test_output(&data)); data.flags = TEST_CRC; igt_subtest_f("pipe-%s-crc-primary-basic", pipe_name) - test_output(&data); + igt_require(test_output(&data)); data.flags = TEST_CRC | TEST_ROTATE_180; igt_subtest_f("pipe-%s-crc-primary-rotation-180", pipe_name) - test_output(&data); + igt_require(test_output(&data)); data.flags = TEST_CRC; igt_subtest_f("pipe-%s-crc-sprite-planes-basic", pipe_name) { + int valid_tests = 0; igt_display_require_output_on_pipe(&data.display, data.pipe); for_each_plane_on_pipe(&data.display, data.pipe, data.plane) { if (data.plane->type == DRM_PLANE_TYPE_PRIMARY) continue; - sprite_idx++; - test_output(&data); + valid_tests += test_output(&data); } + + igt_require(valid_tests); } data.plane = NULL; data.flags = TEST_NO_AUX_BUFFER; igt_subtest_f("pipe-%s-missing-ccs-buffer", pipe_name) - test_output(&data); + igt_require(test_output(&data)); data.flags = TEST_BAD_CCS_HANDLE; igt_subtest_f("pipe-%s-ccs-on-another-bo", pipe_name) - test_output(&data); + igt_require(test_output(&data)); data.flags = TEST_BAD_AUX_STRIDE; igt_subtest_f("pipe-%s-bad-aux-stride", pipe_name) - test_output(&data); + igt_require(test_output(&data)); } igt_fixture diff -Nru intel-gpu-tools-1.21/tests/kms_chv_cursor_fail.c intel-gpu-tools-1.22/tests/kms_chv_cursor_fail.c --- intel-gpu-tools-1.21/tests/kms_chv_cursor_fail.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/kms_chv_cursor_fail.c 2018-03-09 14:22:59.000000000 +0000 @@ -60,15 +60,6 @@ EDGE_BOTTOM = 0x8, }; -static void cursor_disable(data_t *data) -{ - igt_output_t *output = data->output; - igt_plane_t *cursor; - - cursor = igt_output_get_plane_type(output, DRM_PLANE_TYPE_CURSOR); - igt_plane_set_fb(cursor, NULL); -} - static void create_cursor_fb(data_t *data, int cur_w, int cur_h) { cairo_t *cr; @@ -87,8 +78,7 @@ else igt_paint_color_alpha(cr, 0, 0, data->fb.width, data->fb.height, 0.0, 0.0, 0.0, 0.0); - igt_assert(cairo_status(cr) == 0); - cairo_destroy(cr); + igt_put_cairo_ctx(data->drm_fd, &data->fb, cr); } static void cursor_move(data_t *data, int x, int y, int i) @@ -124,7 +114,7 @@ dx = (ex - sx)/XSTEP; - igt_pipe_crc_start(data->pipe_crc); + igt_pipe_crc_drain(data->pipe_crc); i = 0; @@ -155,7 +145,6 @@ } n = igt_pipe_crc_get_crcs(data->pipe_crc, NCRC, &crc); - igt_pipe_crc_stop(data->pipe_crc); if (!data->colored) { igt_debug("Checking CRCs: "); @@ -226,15 +215,27 @@ } } +static void cleanup_crtc(data_t *data) +{ + igt_display_t *display = &data->display; + + igt_display_reset(display); + igt_pipe_crc_free(data->pipe_crc); + data->pipe_crc = NULL; + + igt_remove_fb(data->drm_fd, &data->primary_fb); +} + static void prepare_crtc(data_t *data) { drmModeModeInfo *mode; igt_display_t *display = &data->display; igt_plane_t *primary; + cleanup_crtc(data); + /* select the pipe we want to use */ igt_output_set_pipe(data->output, data->pipe); - cursor_disable(data); mode = igt_output_get_mode(data->output); igt_create_pattern_fb(data->drm_fd, mode->hdisplay, mode->vdisplay, @@ -251,37 +252,12 @@ data->jump_y = (mode->vdisplay - data->curh) / 2; /* create the pipe_crc object for this pipe */ - if (data->pipe_crc) - igt_pipe_crc_free(data->pipe_crc); - data->pipe_crc = igt_pipe_crc_new_nonblock(data->drm_fd, data->pipe, INTEL_PIPE_CRC_SOURCE_AUTO); - /* make sure cursor is disabled */ - cursor_disable(data); - igt_wait_for_vblank(data->drm_fd, data->pipe); - /* get reference crc w/o cursor */ - igt_pipe_crc_collect_crc(data->pipe_crc, &data->ref_crc); - igt_pipe_crc_collect_crc(data->pipe_crc, &data->ref_crc); - igt_pipe_crc_collect_crc(data->pipe_crc, &data->ref_crc); -} - -static void cleanup_crtc(data_t *data) -{ - igt_display_t *display = &data->display; - igt_plane_t *primary; - - igt_pipe_crc_free(data->pipe_crc); - data->pipe_crc = NULL; - - igt_remove_fb(data->drm_fd, &data->primary_fb); - - primary = igt_output_get_plane_type(data->output, DRM_PLANE_TYPE_PRIMARY); - igt_plane_set_fb(primary, NULL); - - igt_output_set_pipe(data->output, PIPE_ANY); - igt_display_commit(display); + igt_pipe_crc_start(data->pipe_crc); + igt_assert(igt_pipe_crc_get_single(data->pipe_crc, &data->ref_crc)); } static void test_crtc(data_t *data, unsigned int edges) @@ -289,6 +265,8 @@ igt_display_t *display = &data->display; int valid_tests = 0; + cleanup_crtc(data); + create_cursor_fb(data, data->curw, data->curh); for_each_valid_output_on_pipe(display, data->pipe, data->output) { @@ -307,9 +285,6 @@ igt_subtest_name(), kmstest_pipe_name(data->pipe), igt_output_name(data->output)); - - /* cleanup what prepare_crtc() has done */ - cleanup_crtc(data); } igt_remove_fb(data->drm_fd, &data->fb); diff -Nru intel-gpu-tools-1.21/tests/kms_color.c intel-gpu-tools-1.22/tests/kms_color.c --- intel-gpu-tools-1.21/tests/kms_color.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/kms_color.c 2018-03-09 14:22:59.000000000 +0000 @@ -86,7 +86,7 @@ colors[i].b); } - cairo_destroy(cr); + igt_put_cairo_ctx(data->drm_fd, fb, cr); } static void paint_rectangles(data_t *data, @@ -103,7 +103,7 @@ colors[i].r, colors[i].g, colors[i].b); } - cairo_destroy(cr); + igt_put_cairo_ctx(data->drm_fd, fb, cr); } static double *generate_table(uint32_t lut_size, double exp) diff -Nru intel-gpu-tools-1.21/tests/kms_concurrent.c intel-gpu-tools-1.22/tests/kms_concurrent.c --- intel-gpu-tools-1.21/tests/kms_concurrent.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/kms_concurrent.c 2018-03-09 14:22:59.000000000 +0000 @@ -148,8 +148,7 @@ rect_w[i], rect_h[i], 0.0, 0.0, 0.0); } - igt_assert(cairo_status(cr) == 0); - cairo_destroy(cr); + igt_put_cairo_ctx(data->drm_fd, &data->fb[primary->index], cr); } static void diff -Nru intel-gpu-tools-1.21/tests/kms_crtc_background_color.c intel-gpu-tools-1.22/tests/kms_crtc_background_color.c --- intel-gpu-tools-1.21/tests/kms_crtc_background_color.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/kms_crtc_background_color.c 2018-03-09 14:22:59.000000000 +0000 @@ -69,7 +69,7 @@ b = (double) ((background & 0xFF0000) >> 16) / 255.0; igt_paint_color_alpha(cr, 0, 0, w, h, r, g, b, alpha); - cairo_destroy(cr); + igt_put_cairo_ctx(data->gfx_fd, &data->fb, cr); } static void prepare_crtc(data_t *data, igt_output_t *output, enum pipe pipe, diff -Nru intel-gpu-tools-1.21/tests/kms_cursor_crc.c intel-gpu-tools-1.22/tests/kms_cursor_crc.c --- intel-gpu-tools-1.21/tests/kms_cursor_crc.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/kms_cursor_crc.c 2018-03-09 14:22:59.000000000 +0000 @@ -141,13 +141,16 @@ igt_pipe_crc_t *pipe_crc = data->pipe_crc; igt_crc_t crc, ref_crc; igt_plane_t *cursor; - cairo_t *cr = igt_get_cairo_ctx(data->drm_fd, &data->primary_fb); + cairo_t *cr; int ret = 0; igt_print_activity(); /* Hardware test */ + cr = igt_get_cairo_ctx(data->drm_fd, &data->primary_fb); igt_paint_test_pattern(cr, data->screenw, data->screenh); + igt_put_cairo_ctx(data->drm_fd, &data->primary_fb, cr); + cursor_enable(data); cursor = igt_output_get_plane_type(data->output, DRM_PLANE_TYPE_CURSOR); igt_plane_set_position(cursor, x, y); @@ -190,7 +193,9 @@ igt_display_commit(display); /* Now render the same in software and collect crc */ + cr = igt_get_cairo_ctx(data->drm_fd, &data->primary_fb); draw_cursor(cr, x, y, data->curw, data->curh); + igt_put_cairo_ctx(data->drm_fd, &data->primary_fb, cr); igt_display_commit(display); igt_wait_for_vblank(data->drm_fd, data->pipe); @@ -198,20 +203,25 @@ igt_assert_crc_equal(&crc, &ref_crc); /* Clear screen afterwards */ + cr = igt_get_cairo_ctx(data->drm_fd, &data->primary_fb); igt_paint_color(cr, 0, 0, data->screenw, data->screenh, 0.0, 0.0, 0.0); + igt_put_cairo_ctx(data->drm_fd, &data->primary_fb, cr); } static void do_fail_test(data_t *data, int x, int y, int expect) { igt_display_t *display = &data->display; igt_plane_t *cursor; - cairo_t *cr = igt_get_cairo_ctx(data->drm_fd, &data->primary_fb); + cairo_t *cr; int ret; igt_print_activity(); /* Hardware test */ + cr = igt_get_cairo_ctx(data->drm_fd, &data->primary_fb); igt_paint_test_pattern(cr, data->screenw, data->screenh); + igt_put_cairo_ctx(data->drm_fd, &data->primary_fb, cr); + cursor_enable(data); cursor = igt_output_get_plane_type(data->output, DRM_PLANE_TYPE_CURSOR); igt_plane_set_position(cursor, x, y); @@ -446,7 +456,7 @@ cr = igt_get_cairo_ctx(data->drm_fd, &data->fb); draw_cursor(cr, 0, 0, cur_w, cur_h); - igt_assert(cairo_status(cr) == 0); + igt_put_cairo_ctx(data->drm_fd, &data->fb, cr); } static bool has_nonsquare_cursors(uint32_t devid) @@ -486,6 +496,7 @@ /* Use a solid white rectangle as the cursor */ cr = igt_get_cairo_ctx(data->drm_fd, &data->fb); igt_paint_color_alpha(cr, 0, 0, cursor_max_size, cursor_max_size, 1.0, 1.0, 1.0, 1.0); + igt_put_cairo_ctx(data->drm_fd, &data->fb, cr); /* Hardware test loop */ cursor_enable(data); @@ -501,16 +512,20 @@ } cursor_disable(data); /* Software test loop */ - cr = igt_get_cairo_ctx(data->drm_fd, &data->primary_fb); for (i = 0, size = cursor_max_size; size >= 64; size /= 2, i++) { /* Now render the same in software and collect crc */ + cr = igt_get_cairo_ctx(data->drm_fd, &data->primary_fb); igt_paint_color_alpha(cr, 0, 0, size, size, 1.0, 1.0, 1.0, 1.0); + igt_put_cairo_ctx(data->drm_fd, &data->primary_fb, cr); + igt_display_commit(display); igt_wait_for_vblank(data->drm_fd, data->pipe); igt_pipe_crc_collect_crc(pipe_crc, &ref_crc); /* Clear screen afterwards */ + cr = igt_get_cairo_ctx(data->drm_fd, &data->primary_fb); igt_paint_color(cr, 0, 0, data->screenw, data->screenh, 0.0, 0.0, 0.0); + igt_put_cairo_ctx(data->drm_fd, &data->primary_fb, cr); igt_assert_crc_equal(&crc[i], &ref_crc); } } diff -Nru intel-gpu-tools-1.21/tests/kms_cursor_legacy.c intel-gpu-tools-1.22/tests/kms_cursor_legacy.c --- intel-gpu-tools-1.21/tests/kms_cursor_legacy.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/kms_cursor_legacy.c 2018-03-09 14:22:59.000000000 +0000 @@ -1276,7 +1276,7 @@ enum pipe pipe = find_connected_pipe(display, false); igt_pipe_t *pipe_connected = &display->pipes[pipe]; igt_plane_t *plane_primary = igt_pipe_get_plane_type(pipe_connected, DRM_PLANE_TYPE_PRIMARY); - igt_crc_t crcs[2]; + igt_crc_t crcs[2], test_crc; if (atomic) igt_require(display->is_atomic); @@ -1290,7 +1290,7 @@ igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY); - pipe_crc = igt_pipe_crc_new_nonblock(display->drm_fd, pipe, INTEL_PIPE_CRC_SOURCE_AUTO); + pipe_crc = igt_pipe_crc_new(display->drm_fd, pipe, INTEL_PIPE_CRC_SOURCE_AUTO); set_cursor_on_pipe(display, pipe, &cursor_fb); igt_display_commit2(display, COMMIT_UNIVERSAL); @@ -1322,9 +1322,6 @@ /* Disable cursor, and immediately queue a flip. Check if resulting crc is correct. */ for (int i = 1; i >= 0; i--) { igt_spin_t *spin; - igt_crc_t *received_crcs = NULL; - int ncrcs; - static const int max_crcs = 8; spin = igt_spin_batch_new(display->drm_fd, 0, 0, fb_info[1].gem_handle); @@ -1336,7 +1333,8 @@ igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start); - ncrcs = igt_pipe_crc_get_crcs(pipe_crc, max_crcs, &received_crcs); + igt_pipe_crc_drain(pipe_crc); + igt_pipe_crc_get_single(pipe_crc, &test_crc); igt_spin_batch_free(display->drm_fd, spin); @@ -1349,16 +1347,7 @@ igt_plane_set_fb(plane_primary, &fb_info[0]); igt_display_commit2(display, COMMIT_UNIVERSAL); - /* - * We collect the crc nonblockingly, and should have at least 1 - * but not so many crcs that we overflow. Last CRC is the only - * one we care about here. Other CRCs may have been from before - * the cursor update and can contain garbage. - */ - igt_assert(ncrcs > 0 && ncrcs < max_crcs); - - igt_assert_crc_equal(&crcs[i], &received_crcs[ncrcs - 1]); - free(received_crcs); + igt_assert_crc_equal(&crcs[i], &test_crc); } igt_remove_fb(display->drm_fd, &fb_info[1]); diff -Nru intel-gpu-tools-1.21/tests/kms_draw_crc.c intel-gpu-tools-1.22/tests/kms_draw_crc.c --- intel-gpu-tools-1.21/tests/kms_draw_crc.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/kms_draw_crc.c 2018-03-09 14:22:59.000000000 +0000 @@ -163,7 +163,7 @@ format, modifier, 0, NULL, &stride, NULL); ret = __kms_addfb(drm_fd, gem_handle, 64, 64, - stride, format, modifier, + stride, format, modifier, NULL, LOCAL_DRM_MODE_FB_MODIFIERS, &fb_id); drmModeRmFB(drm_fd, fb_id); gem_close(drm_fd, gem_handle); diff -Nru intel-gpu-tools-1.21/tests/kms_fbcon_fbt.c intel-gpu-tools-1.22/tests/kms_fbcon_fbt.c --- intel-gpu-tools-1.21/tests/kms_fbcon_fbt.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/kms_fbcon_fbt.c 2018-03-09 14:22:59.000000000 +0000 @@ -87,6 +87,9 @@ char buf[128]; igt_debugfs_read(fd, "i915_fbc_status", buf); + if (*buf == '\0') /* !HAS_FBC -> -ENODEV*/ + return false; + return !strstr(buf, "FBC unsupported on this chipset\n"); } @@ -162,6 +165,9 @@ char buf[256]; igt_debugfs_read(fd, "i915_edp_psr_status", buf); + if (*buf == '\0') /* !HAS_PSR -> -ENODEV*/ + return false; + return strstr(buf, "Sink_Support: yes\n"); } diff -Nru intel-gpu-tools-1.21/tests/kms_flip.c intel-gpu-tools-1.22/tests/kms_flip.c --- intel-gpu-tools-1.21/tests/kms_flip.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/kms_flip.c 2018-03-09 14:22:59.000000000 +0000 @@ -45,8 +45,7 @@ #include "igt_stats.h" #define TEST_DPMS (1 << 0) -#define TEST_WITH_DUMMY_BCS (1 << 1) -#define TEST_WITH_DUMMY_RCS (1 << 2) + #define TEST_PAN (1 << 3) #define TEST_MODESET (1 << 4) #define TEST_CHECK_TS (1 << 5) @@ -73,7 +72,7 @@ #define TEST_SUSPEND (1 << 26) #define TEST_TS_CONT (1 << 27) #define TEST_BO_TOOBIG (1 << 28) -#define TEST_HANG_ONCE (1 << 29) + #define TEST_BASIC (1 << 30) #define EVENT_FLIP (1 << 0) @@ -668,8 +667,6 @@ struct vblank_reply vbl_reply; unsigned int target_seq; igt_hang_t hang; - igt_spin_t *spin_rcs = 0; - igt_spin_t *spin_bcs = 0; target_seq = o->vblank_state.seq_step; /* Absolute waits only works once we have a frame counter. */ @@ -691,20 +688,6 @@ if (!(o->flags & TEST_SINGLE_BUFFER)) o->current_fb_id = !o->current_fb_id; - if (o->flags & TEST_WITH_DUMMY_BCS) { - spin_bcs = __igt_spin_batch_new(drm_fd, 0, I915_EXEC_BLT, - o->fb_info[o->current_fb_id].gem_handle); - igt_spin_batch_set_timeout(spin_bcs, - NSEC_PER_SEC); - } - - if (o->flags & TEST_WITH_DUMMY_RCS) { - spin_rcs = __igt_spin_batch_new(drm_fd, 0, I915_EXEC_RENDER, - o->fb_info[o->current_fb_id].gem_handle); - igt_spin_batch_set_timeout(spin_rcs, - NSEC_PER_SEC); - } - if (o->flags & TEST_FB_RECREATE) recreate_fb(o); new_fb_id = o->fb_ids[o->current_fb_id]; @@ -809,10 +792,6 @@ completed_events = EVENT_VBLANK; } } - if (spin_rcs) - igt_spin_batch_free(drm_fd, spin_rcs); - if (spin_bcs) - igt_spin_batch_free(drm_fd, spin_bcs); if (do_flip && (o->flags & TEST_EBUSY)) igt_assert(do_page_flip(o, new_fb_id, true) == -EBUSY); @@ -997,8 +976,7 @@ cairo_set_source_rgb(cr, 1, 1, 1); cairo_fill(cr); - igt_assert(!cairo_status(cr)); - cairo_destroy(cr); + igt_put_cairo_ctx(drm_fd, fb, cr); } static int @@ -1065,10 +1043,6 @@ evctx.vblank_handler = vblank_handler; evctx.page_flip_handler = page_flip_handler; - /* make timeout lax with the dummy load */ - if (o->flags & (TEST_WITH_DUMMY_BCS | TEST_WITH_DUMMY_RCS)) - timeout.tv_sec *= 60; - FD_ZERO(&fds); FD_SET(drm_fd, &fds); do { @@ -1096,16 +1070,8 @@ static unsigned event_loop(struct test_output *o, unsigned duration_ms) { unsigned long start, end; - igt_hang_t hang; int count = 0; - if (o->flags & (TEST_WITH_DUMMY_BCS | TEST_WITH_DUMMY_RCS)) - igt_require_gem(drm_fd); - - memset(&hang, 0, sizeof(hang)); - if (o->flags & TEST_HANG_ONCE) - hang = hang_gpu(drm_fd); - start = gettime_us(); while (1) { @@ -1125,8 +1091,6 @@ end = gettime_us(); - unhang_gpu(drm_fd, hang); - /* Flush any remaining events */ if (o->pending_events) wait_for_events(o); @@ -1368,8 +1332,7 @@ igt_info("\n%s: PASSED\n\n", test_name); out: - if (o->fb_ids[2]) - igt_remove_fb(drm_fd, &o->fb_info[2]); + igt_remove_fb(drm_fd, &o->fb_info[2]); igt_remove_fb(drm_fd, &o->fb_info[1]); igt_remove_fb(drm_fd, &o->fb_info[0]); @@ -1562,7 +1525,6 @@ int flags; const char *name; } tests[] = { - { 30, TEST_VBLANK, "wf_vblank" }, { 30, TEST_VBLANK | TEST_CHECK_TS, "wf_vblank-ts-check" }, { 30, TEST_VBLANK | TEST_VBLANK_BLOCK | TEST_CHECK_TS, "blocking-wf_vblank" }, @@ -1570,16 +1532,6 @@ "absolute-wf_vblank" }, { 30, TEST_VBLANK | TEST_VBLANK_BLOCK | TEST_VBLANK_ABSOLUTE, "blocking-absolute-wf_vblank" }, - { 60, TEST_VBLANK | TEST_DPMS | TEST_EINVAL, "wf_vblank-vs-dpms" }, - { 60, TEST_VBLANK | TEST_DPMS | TEST_WITH_DUMMY_BCS, - "blt-wf_vblank-vs-dpms" }, - { 60, TEST_VBLANK | TEST_DPMS | TEST_WITH_DUMMY_RCS, - "rcs-wf_vblank-vs-dpms" }, - { 60, TEST_VBLANK | TEST_MODESET | TEST_EINVAL, "wf_vblank-vs-modeset" }, - { 60, TEST_VBLANK | TEST_MODESET | TEST_WITH_DUMMY_BCS, - "blt-wf_vblank-vs-modeset" }, - { 60, TEST_VBLANK | TEST_MODESET | TEST_WITH_DUMMY_RCS, - "rcs-wf_vblank-vs-modeset" }, { 10, TEST_FLIP | TEST_BASIC, "plain-flip" }, { 30, TEST_FLIP | TEST_EBUSY , "busy-flip" }, { 30, TEST_FLIP | TEST_FENCE_STRESS , "flip-vs-fences" }, @@ -1589,8 +1541,6 @@ { 30, TEST_FLIP | TEST_RMFB | TEST_MODESET , "flip-vs-rmfb" }, { 20, TEST_FLIP | TEST_DPMS | TEST_EINVAL | TEST_BASIC, "flip-vs-dpms" }, { 30, TEST_FLIP | TEST_PAN, "flip-vs-panning" }, - { 60, TEST_FLIP | TEST_PAN | TEST_WITH_DUMMY_BCS, "blt-flip-vs-panning" }, - { 60, TEST_FLIP | TEST_PAN | TEST_WITH_DUMMY_RCS, "render-flip-vs-panning" }, { 20, TEST_FLIP | TEST_MODESET | TEST_EINVAL | TEST_BASIC, "flip-vs-modeset" }, { 30, TEST_FLIP | TEST_VBLANK_EXPIRED_SEQ, "flip-vs-expired-vblank" }, @@ -1603,7 +1553,6 @@ TEST_CHECK_TS, "flip-vs-blocking-wf-vblank" }, { 30, TEST_FLIP | TEST_MODESET | TEST_HANG | TEST_NOEVENT, "flip-vs-modeset-vs-hang" }, { 30, TEST_FLIP | TEST_PAN | TEST_HANG, "flip-vs-panning-vs-hang" }, - { 30, TEST_VBLANK | TEST_HANG_ONCE, "vblank-vs-hang" }, { 1, TEST_FLIP | TEST_EINVAL | TEST_FB_BAD_TILING, "flip-vs-bad-tiling" }, { 1, TEST_DPMS_OFF | TEST_MODESET | TEST_FLIP, @@ -1614,11 +1563,6 @@ { 0, TEST_ENOENT | TEST_NOEVENT, "nonexisting-fb" }, { 10, TEST_DPMS_OFF | TEST_DPMS | TEST_VBLANK_RACE, "dpms-vs-vblank-race" }, { 10, TEST_MODESET | TEST_VBLANK_RACE, "modeset-vs-vblank-race" }, - { 10, TEST_VBLANK | TEST_DPMS | TEST_RPM | TEST_TS_CONT, "vblank-vs-dpms-rpm" }, - { 10, TEST_VBLANK | TEST_MODESET | TEST_RPM | TEST_TS_CONT, "vblank-vs-modeset-rpm" }, - { 0, TEST_VBLANK | TEST_DPMS | TEST_SUSPEND | TEST_TS_CONT, "vblank-vs-dpms-suspend" }, - { 0, TEST_VBLANK | TEST_MODESET | TEST_SUSPEND | TEST_TS_CONT, "vblank-vs-modeset-suspend" }, - { 0, TEST_VBLANK | TEST_SUSPEND | TEST_TS_CONT, "vblank-vs-suspend" }, { 0, TEST_BO_TOOBIG | TEST_NO_2X_OUTPUT, "bo-too-big" }, }; int i; diff -Nru intel-gpu-tools-1.21/tests/kms_force_connector_basic.c intel-gpu-tools-1.22/tests/kms_force_connector_basic.c --- intel-gpu-tools-1.21/tests/kms_force_connector_basic.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/kms_force_connector_basic.c 2018-03-09 14:22:59.000000000 +0000 @@ -86,29 +86,39 @@ opt_handler, NULL); igt_fixture { + unsigned vga_connector_id = 0; + drm_fd = drm_open_driver_master(DRIVER_INTEL); res = drmModeGetResources(drm_fd); igt_assert(res); /* find the vga connector */ for (int i = 0; i < res->count_connectors; i++) { - vga_connector = drmModeGetConnectorCurrent(drm_fd, res->connectors[i]); if (vga_connector->connector_type == DRM_MODE_CONNECTOR_VGA) { - start_n_modes = vga_connector->count_modes; - start_connection = vga_connector->connection; - break; + /* Ensure that no override was left in place. */ + kmstest_force_connector(drm_fd, + vga_connector, + FORCE_CONNECTOR_UNSPECIFIED); + + /* Only use the first VGA connector. */ + if (!vga_connector_id) + vga_connector_id = res->connectors[i]; } drmModeFreeConnector(vga_connector); - - vga_connector = NULL; } - igt_require(vga_connector); + igt_require(vga_connector_id); + + /* Reacquire status after clearing any previous overrides */ + vga_connector = drmModeGetConnector(drm_fd, vga_connector_id); igt_skip_on(vga_connector->connection == DRM_MODE_CONNECTED); + + start_n_modes = vga_connector->count_modes; + start_connection = vga_connector->connection; } igt_subtest("force-load-detect") { diff -Nru intel-gpu-tools-1.21/tests/kms_frontbuffer_tracking.c intel-gpu-tools-1.22/tests/kms_frontbuffer_tracking.c --- intel-gpu-tools-1.21/tests/kms_frontbuffer_tracking.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/kms_frontbuffer_tracking.c 2018-03-09 14:22:59.000000000 +0000 @@ -34,7 +34,7 @@ IGT_TEST_DESCRIPTION("Test the Kernel's frontbuffer tracking mechanism and " - "its related features: FBC and PSR"); + "its related features: FBC, PSR and DRRS"); /* * One of the aspects of this test is that, for every subtest, we try different @@ -105,8 +105,9 @@ FEATURE_NONE = 0, FEATURE_FBC = 1, FEATURE_PSR = 2, - FEATURE_COUNT = 4, - FEATURE_DEFAULT = 4, + FEATURE_DRRS = 4, + FEATURE_COUNT = 8, + FEATURE_DEFAULT = 8, } feature; /* Possible pixel formats. We just use FORMAT_DEFAULT for most tests and @@ -182,6 +183,13 @@ .can_test = false, }; +#define MAX_DRRS_STATUS_BUF_LEN 256 + +struct { + bool can_test; +} drrs = { + .can_test = false, +}; #define SINK_CRC_SIZE 12 typedef struct { @@ -541,7 +549,6 @@ { uint32_t format; unsigned int size, stride; - int bpp; uint64_t tiling_for_size; switch (pformat) { @@ -576,13 +583,12 @@ * the same size regardless of tiling since we want to properly exercise * the Kernel's specific tiling-checking code paths without accidentally * hitting size-checking ones first. */ - bpp = igt_drm_format_to_bpp(format); if (plane == PLANE_CUR) tiling_for_size = LOCAL_DRM_FORMAT_MOD_NONE; else tiling_for_size = opt.tiling; - igt_calc_fb_size(drm.fd, width, height, bpp, tiling_for_size, &size, + igt_calc_fb_size(drm.fd, width, height, format, tiling_for_size, &size, &stride); igt_create_fb_with_bo_size(drm.fd, width, height, format, tiling, fb, @@ -790,22 +796,21 @@ buf[len] = '\0'; } -#define debugfs_read(p, arr) __debugfs_read(p, arr, sizeof(arr)) - -static bool fbc_is_enabled(void) +static int __debugfs_write(const char *param, char *buf, int len) { - char buf[128]; - - debugfs_read("i915_fbc_status", buf); - return strstr(buf, "FBC enabled\n"); + return igt_sysfs_write(drm.debugfs, param, buf, len - 1); } -static void fbc_print_status(void) +#define debugfs_read(p, arr) __debugfs_read(p, arr, sizeof(arr)) +#define debugfs_write(p, arr) __debugfs_write(p, arr, sizeof(arr)) + +static bool fbc_is_enabled(int lvl) { char buf[128]; debugfs_read("i915_fbc_status", buf); - igt_info("FBC status:\n%s\n", buf); + igt_log(IGT_LOG_DOMAIN, lvl, "fbc_is_enabled()?\n%s", buf); + return strstr(buf, "FBC enabled\n"); } static bool psr_is_enabled(void) @@ -825,6 +830,68 @@ igt_info("PSR status:\n%s\n", buf); } +static void drrs_set(unsigned int val) +{ + char buf[2]; + int ret; + + igt_debug("Manually %sabling DRRS. %u\n", val ? "en" : "dis", val); + snprintf(buf, sizeof(buf), "%d", val); + ret = debugfs_write("i915_drrs_ctl", buf); + + /* + * drrs_enable() is called on DRRS capable platform only, + * whereas drrs_disable() is called on all platforms. + * So handle the failure of debugfs_write only for drrs_enable(). + */ + if (val) + igt_assert_f(ret == (sizeof(buf) - 1), "debugfs_write failed"); +} + +static bool is_drrs_high(void) +{ + char buf[MAX_DRRS_STATUS_BUF_LEN]; + + debugfs_read("i915_drrs_status", buf); + return strstr(buf, "DRRS_HIGH_RR"); +} + +static bool is_drrs_low(void) +{ + char buf[MAX_DRRS_STATUS_BUF_LEN]; + + debugfs_read("i915_drrs_status", buf); + return strstr(buf, "DRRS_LOW_RR"); +} + +static bool is_drrs_supported(void) +{ + char buf[MAX_DRRS_STATUS_BUF_LEN]; + + debugfs_read("i915_drrs_status", buf); + return strstr(buf, "DRRS Supported: Yes"); +} + +static bool is_drrs_inactive(void) +{ + char buf[MAX_DRRS_STATUS_BUF_LEN]; + + debugfs_read("i915_drrs_status", buf); + + if (strstr(buf, "DRRS_State: ")) + return false; + + return true; +} + +static void drrs_print_status(void) +{ + char buf[MAX_DRRS_STATUS_BUF_LEN]; + + debugfs_read("i915_drrs_status", buf); + igt_info("DRRS STATUS :\n%s\n", buf); +} + static struct timespec fbc_get_last_action(void) { struct timespec ret = { 0, 0 }; @@ -927,7 +994,7 @@ static bool fbc_wait_until_enabled(void) { - return igt_wait(fbc_is_enabled(), 2000, 1); + return igt_wait(fbc_is_enabled(IGT_LOG_DEBUG), 2000, 1); } static bool psr_wait_until_enabled(void) @@ -935,10 +1002,22 @@ return igt_wait(psr_is_enabled(), 5000, 1); } +static bool psr_wait_until_disabled(void) +{ + return igt_wait(!psr_is_enabled(), 5000, 1); +} + +static bool drrs_wait_until_rr_switch_to_low(void) +{ + return igt_wait(is_drrs_low(), 5000, 1); +} + #define fbc_enable() igt_set_module_param_int("enable_fbc", 1) #define fbc_disable() igt_set_module_param_int("enable_fbc", 0) #define psr_enable() igt_set_module_param_int("enable_psr", 1) #define psr_disable() igt_set_module_param_int("enable_psr", 0) +#define drrs_enable() drrs_set(1) +#define drrs_disable() drrs_set(0) static void get_sink_crc(sink_crc_t *crc, bool mandatory) { @@ -1184,6 +1263,7 @@ fbc_disable(); psr_disable(); + drrs_disable(); } static void *busy_thread_func(void *data) @@ -1513,6 +1593,9 @@ char buf[128]; debugfs_read("i915_fbc_status", buf); + if (*buf == '\0') + return false; + return !strstr(buf, "FBC unsupported on this chipset\n"); } @@ -1555,6 +1638,9 @@ char buf[256]; debugfs_read("i915_edp_psr_status", buf); + if (*buf == '\0') /* !HAS_PSR -> -ENODEV*/ + return false; + return strstr(buf, "Sink_Support: yes\n"); } @@ -1577,6 +1663,22 @@ { } +static void setup_drrs(void) +{ + if (get_connector(prim_mode_params.connector_id)->connector_type != + DRM_MODE_CONNECTOR_eDP) { + igt_info("Can't test DRRS: no usable eDP screen.\n"); + return; + } + + if (!is_drrs_supported()) { + igt_info("Can't test DRRS: Not supported.\n"); + return; + } + + drrs.can_test = true; +} + static void setup_environment(void) { setup_drm(); @@ -1584,6 +1686,7 @@ setup_fbc(); setup_psr(); + setup_drrs(); setup_crcs(); } @@ -1662,6 +1765,11 @@ #define ASSERT_PSR_ENABLED (1 << 6) #define ASSERT_PSR_DISABLED (1 << 7) +#define DRRS_ASSERT_FLAGS (7 << 8) +#define ASSERT_DRRS_HIGH (1 << 8) +#define ASSERT_DRRS_LOW (1 << 9) +#define ASSERT_DRRS_INACTIVE (1 << 10) + static int adjust_assertion_flags(const struct test_mode *t, int flags) { if (!(flags & DONT_ASSERT_FEATURE_STATUS)) { @@ -1669,12 +1777,17 @@ flags |= ASSERT_FBC_ENABLED; if (!(flags & ASSERT_PSR_DISABLED)) flags |= ASSERT_PSR_ENABLED; + if (!((flags & ASSERT_DRRS_LOW) || + (flags & ASSERT_DRRS_INACTIVE))) + flags |= ASSERT_DRRS_HIGH; } if ((t->feature & FEATURE_FBC) == 0) flags &= ~FBC_ASSERT_FLAGS; if ((t->feature & FEATURE_PSR) == 0) flags &= ~PSR_ASSERT_FLAGS; + if ((t->feature & FEATURE_DRRS) == 0) + flags &= ~DRRS_ASSERT_FLAGS; return flags; } @@ -1706,12 +1819,29 @@ return; } + if (flags & ASSERT_DRRS_HIGH) { + if (!is_drrs_high()) { + drrs_print_status(); + igt_assert_f(false, "DRRS HIGH\n"); + } + } else if (flags & ASSERT_DRRS_LOW) { + if (!drrs_wait_until_rr_switch_to_low()) { + drrs_print_status(); + igt_assert_f(false, "DRRS LOW\n"); + } + } else if (flags & ASSERT_DRRS_INACTIVE) { + if (!is_drrs_inactive()) { + drrs_print_status(); + igt_assert_f(false, "DRRS INACTIVE\n"); + } + } + if (flags & ASSERT_FBC_ENABLED) { igt_require(!fbc_not_enough_stolen()); igt_require(!fbc_stride_not_supported()); if (!fbc_wait_until_enabled()) { - fbc_print_status(); - igt_assert_f(fbc_is_enabled(), "FBC disabled\n"); + igt_assert_f(fbc_is_enabled(IGT_LOG_WARN), + "FBC disabled\n"); } if (opt.fbc_check_compression) @@ -1723,10 +1853,13 @@ if (flags & ASSERT_PSR_ENABLED) { if (!psr_wait_until_enabled()) { psr_print_status(); - igt_assert_f(psr_is_enabled(), "PSR disabled\n"); + igt_assert_f(psr_is_enabled(), "PSR still disabled\n"); } } else if (flags & ASSERT_PSR_DISABLED) { - igt_assert(!psr_wait_until_enabled()); + if (!psr_wait_until_disabled()) { + psr_print_status(); + igt_assert_f(!psr_is_enabled(), "PSR still enabled\n"); + } } } @@ -1833,6 +1966,8 @@ fbc_enable(); if (t->feature & FEATURE_PSR) psr_enable(); + if (t->feature & FEATURE_DRRS) + drrs_enable(); } static void check_test_requirements(const struct test_mode *t) @@ -1852,6 +1987,18 @@ "Can't test PSR without sink CRCs\n"); } + if (t->feature & FEATURE_DRRS) + igt_require_f(drrs.can_test, + "Can't test DRRS with the current outputs\n"); + + /* + * In kernel, When PSR is enabled, DRRS will be disabled. So If a test + * case needs DRRS + PSR enabled, that will be skipped. + */ + igt_require_f(!((t->feature & FEATURE_PSR) && + (t->feature & FEATURE_DRRS)), + "Can't test PSR and DRRS together\n"); + if (opt.only_pipes != PIPE_COUNT) igt_require(t->pipes == opt.only_pipes); } @@ -1973,7 +2120,7 @@ unset_all_crtcs(); do_assertions(ASSERT_FBC_DISABLED | ASSERT_PSR_DISABLED | - DONT_ASSERT_CRC); + DONT_ASSERT_CRC | ASSERT_DRRS_INACTIVE); enable_prim_screen_and_wait(t); set_cursor_for_test(t, &prim_mode_params); @@ -2065,6 +2212,13 @@ if (op_disables_psr(t, t->method)) assertions |= ASSERT_PSR_DISABLED; + /* + * On FBS_INDIVIDUAL, write to offscreen plane will not touch the + * current frambuffer. Hence assert for DRRS_LOW. + */ + if ((t->fbs == FBS_INDIVIDUAL) && (t->screen == SCREEN_OFFSCREEN)) + assertions |= ASSERT_DRRS_LOW; + prepare_subtest(t, pattern); target = pick_target(t, params); @@ -2273,7 +2427,11 @@ sleep(2); update_wanted_crc(t, &pattern->crcs[t->format][r]); - do_assertions(0); + + if (t->feature & FEATURE_DRRS) + do_assertions(ASSERT_DRRS_LOW); + else + do_assertions(0); } } @@ -2882,14 +3040,14 @@ sleep(5); igt_system_suspend_autoresume(SUSPEND_STATE_MEM, SUSPEND_TEST_NONE); sleep(5); - do_assertions(0); + do_assertions(ASSERT_DRRS_LOW); unset_all_crtcs(); sleep(5); igt_system_suspend_autoresume(SUSPEND_STATE_MEM, SUSPEND_TEST_NONE); sleep(5); do_assertions(ASSERT_FBC_DISABLED | ASSERT_PSR_DISABLED | - DONT_ASSERT_CRC); + DONT_ASSERT_CRC | ASSERT_DRRS_INACTIVE); set_mode_for_params(params); do_assertions(0); @@ -3371,6 +3529,14 @@ return "psr"; case FEATURE_FBC | FEATURE_PSR: return "fbcpsr"; + case FEATURE_DRRS: + return "drrs"; + case FEATURE_FBC | FEATURE_DRRS: + return "fbcdrrs"; + case FEATURE_PSR | FEATURE_DRRS: + return "psrdrrs"; + case FEATURE_FBC | FEATURE_PSR | FEATURE_DRRS: + return "fbcpsrdrrs"; default: igt_assert(false); } @@ -3635,7 +3801,7 @@ tilingchange_subtest(&t); } - if (t.feature & FEATURE_PSR) + if ((t.feature & FEATURE_PSR) || (t.feature & FEATURE_DRRS)) igt_subtest_f("%s-slowdraw", feature_str(t.feature)) slow_draw_subtest(&t); diff -Nru intel-gpu-tools-1.21/tests/kms_mmap_write_crc.c intel-gpu-tools-1.22/tests/kms_mmap_write_crc.c --- intel-gpu-tools-1.21/tests/kms_mmap_write_crc.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/kms_mmap_write_crc.c 2018-03-09 14:22:59.000000000 +0000 @@ -92,7 +92,7 @@ cr = igt_get_cairo_ctx(data->drm_fd, fb); igt_paint_test_pattern(cr, fb->width, fb->height); - cairo_destroy(cr); + igt_put_cairo_ctx(data->drm_fd, fb, cr); /* flip to it to make it UC/WC and fully flushed */ igt_plane_set_fb(data->primary, fb); @@ -135,7 +135,7 @@ * fully flushed */ cr = igt_get_cairo_ctx(data->drm_fd, fb); igt_paint_test_pattern(cr, fb->width, fb->height); - cairo_destroy(cr); + igt_put_cairo_ctx(data->drm_fd, fb, cr); igt_plane_set_fb(data->primary, fb); igt_display_commit(display); diff -Nru intel-gpu-tools-1.21/tests/kms_panel_fitting.c intel-gpu-tools-1.22/tests/kms_panel_fitting.c --- intel-gpu-tools-1.21/tests/kms_panel_fitting.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/kms_panel_fitting.c 2018-03-09 14:22:59.000000000 +0000 @@ -32,15 +32,8 @@ int drm_fd; igt_display_t display; - int image_w; - int image_h; - struct igt_fb fb1; struct igt_fb fb2; - struct igt_fb fb3; - int fb_id1; - int fb_id2; - int fb_id3; igt_plane_t *plane1; igt_plane_t *plane2; @@ -58,18 +51,14 @@ igt_output_set_pipe(output, pipe); /* before allocating, free if any older fb */ - if (data->fb_id1) { - igt_remove_fb(data->drm_fd, &data->fb1); - data->fb_id1 = 0; - } + igt_remove_fb(data->drm_fd, &data->fb1); /* allocate fb for plane 1 */ - data->fb_id1 = igt_create_pattern_fb(data->drm_fd, - mode->hdisplay, mode->vdisplay, - DRM_FORMAT_XRGB8888, - LOCAL_DRM_FORMAT_MOD_NONE, - &data->fb1); - igt_assert(data->fb_id1); + igt_create_pattern_fb(data->drm_fd, + mode->hdisplay, mode->vdisplay, + DRM_FORMAT_XRGB8888, + LOCAL_DRM_FORMAT_MOD_NONE, + &data->fb1); /* * We always set the primary plane to actually enable the pipe as @@ -91,18 +80,8 @@ { igt_display_t *display = &data->display; - if (data->fb_id1) { - igt_remove_fb(data->drm_fd, &data->fb1); - data->fb_id1 = 0; - } - if (data->fb_id2) { - igt_remove_fb(data->drm_fd, &data->fb2); - data->fb_id2 = 0; - } - if (data->fb_id3) { - igt_remove_fb(data->drm_fd, &data->fb3); - data->fb_id3 = 0; - } + igt_remove_fb(data->drm_fd, &data->fb1); + igt_remove_fb(data->drm_fd, &data->fb2); if (plane->type != DRM_PLANE_TYPE_PRIMARY) { igt_plane_t *primary; @@ -121,7 +100,6 @@ { igt_display_t *display = &d->display; igt_output_t *output; - cairo_surface_t *image; enum pipe pipe; int valid_tests = 0; @@ -146,18 +124,11 @@ mode = igt_output_get_mode(output); native_mode = *mode; - /* allocate fb2 with image size */ - image = igt_cairo_image_surface_create_from_png(FILE_NAME); - igt_assert(cairo_surface_status(image) == CAIRO_STATUS_SUCCESS); - d->image_w = cairo_image_surface_get_width(image); - d->image_h = cairo_image_surface_get_height(image); - cairo_surface_destroy(image); - - d->fb_id2 = igt_create_image_fb(d->drm_fd, 0, 0, - DRM_FORMAT_XRGB8888, - LOCAL_DRM_FORMAT_MOD_NONE, - FILE_NAME, &d->fb2); - igt_assert(d->fb_id2); + /* allocate fb2 with image */ + igt_create_image_fb(d->drm_fd, 0, 0, + DRM_FORMAT_XRGB8888, + LOCAL_DRM_FORMAT_MOD_NONE, + FILE_NAME, &d->fb2); /* Set up display to enable panel fitting */ mode->hdisplay = 640; diff -Nru intel-gpu-tools-1.21/tests/kms_plane.c intel-gpu-tools-1.22/tests/kms_plane.c --- intel-gpu-tools-1.21/tests/kms_plane.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/kms_plane.c 2018-03-09 14:22:59.000000000 +0000 @@ -138,8 +138,7 @@ igt_paint_color(cr, 0, 0, mode->hdisplay, mode->vdisplay, 0.0, 1.0, 0.0); igt_paint_color(cr, rect_x, rect_y, rect_w, rect_h, 0.0, 0.0, 0.0); - igt_assert(cairo_status(cr) == 0); - cairo_destroy(cr); + igt_put_cairo_ctx(data->drm_fd, fb, cr); } enum { @@ -279,8 +278,7 @@ mode->hdisplay, mode->vdisplay, 0.0, 0.0, 1.0); - igt_assert(cairo_status(cr) == 0); - cairo_destroy(cr); + igt_put_cairo_ctx(data->drm_fd, fb, cr); } enum { @@ -368,20 +366,6 @@ igt_skip_on(connected_outs == 0); } -static bool can_draw(uint32_t drm_format) -{ - const uint32_t *drm_formats; - int format_count, i; - - igt_get_all_cairo_formats(&drm_formats, &format_count); - - for (i = 0; i < format_count; i++) - if (drm_formats[i] == drm_format) - return true; - - return false; -} - static void test_format_plane(data_t *data, enum pipe pipe, igt_output_t *output, igt_plane_t *plane) { @@ -422,7 +406,7 @@ for (i = 0; i < plane->drm_plane->count_formats; i++) { format = plane->drm_plane->formats[i]; - if (!can_draw(format)) + if (!igt_fb_supported_format(format)) continue; igt_debug("Testing format 0x%x on %s.%u\n", @@ -436,8 +420,7 @@ 0.0, 1.0, 0.0); if (width >= 164 && height >= 164) igt_paint_color(cr, 100, 100, 64, 64, 0.0, 0.0, 0.0); - igt_assert(cairo_status(cr) == 0); - cairo_destroy(cr); + igt_put_cairo_ctx(data->drm_fd, &fb, cr); igt_plane_set_fb(plane, &fb); igt_display_commit2(&data->display, COMMIT_UNIVERSAL); diff -Nru intel-gpu-tools-1.21/tests/kms_plane_lowres.c intel-gpu-tools-1.22/tests/kms_plane_lowres.c --- intel-gpu-tools-1.21/tests/kms_plane_lowres.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/kms_plane_lowres.c 2018-03-09 14:22:59.000000000 +0000 @@ -126,23 +126,6 @@ } static void -display_commit_mode(igt_display_t *display, igt_pipe_crc_t *pipe_crc, - enum pipe pipe, int flags, igt_crc_t *out_crc) -{ - char buf[256]; - int ret; - - ret = igt_display_try_commit_atomic(display, flags, NULL); - igt_skip_on(ret != 0); - - igt_set_timeout(1, "Stuck on page flip"); - ret = read(display->drm_fd, buf, sizeof(buf)); - igt_assert(ret >= 0); - - igt_pipe_crc_collect_crc(pipe_crc, out_crc); -} - -static void check_mode(drmModeModeInfo *mode1, drmModeModeInfo *mode2) { igt_assert_eq(mode1->hdisplay, mode2->hdisplay); @@ -151,7 +134,7 @@ } static drmModeModeInfo * -test_setup(data_t *data, enum pipe pipe, uint64_t modifier, int flags, +test_setup(data_t *data, enum pipe pipe, uint64_t modifier, igt_output_t *output) { drmModeModeInfo *mode; @@ -211,13 +194,12 @@ drmModeModeInfo mode_lowres; drmModeModeInfo *mode1, *mode2, *mode3; int ret; - int flags = DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_ALLOW_MODESET; igt_pipe_crc_t *pipe_crc; igt_info("Testing connector %s using pipe %s\n", igt_output_name(output), kmstest_pipe_name(pipe)); - mode1 = test_setup(data, pipe, modifier, flags, output); + mode1 = test_setup(data, pipe, modifier, output); mode_lowres = get_lowres_mode(data->drm_fd, mode1); @@ -225,8 +207,8 @@ igt_skip_on(ret != 0); pipe_crc = igt_pipe_crc_new(data->drm_fd, pipe, INTEL_PIPE_CRC_SOURCE_AUTO); - - igt_pipe_crc_collect_crc(pipe_crc, &crc_hires1); + igt_pipe_crc_start(pipe_crc); + igt_pipe_crc_get_single(pipe_crc, &crc_hires1); igt_assert_plane_visible(data->drm_fd, pipe, true); @@ -238,7 +220,9 @@ check_mode(&mode_lowres, mode2); - display_commit_mode(&data->display, pipe_crc, pipe, flags, &crc_lowres); + igt_display_commit2(&data->display, COMMIT_ATOMIC); + igt_pipe_crc_drain(pipe_crc); + igt_pipe_crc_get_single(pipe_crc, &crc_lowres); igt_assert_plane_visible(data->drm_fd, pipe, false); @@ -250,7 +234,10 @@ check_mode(mode1, mode3); - display_commit_mode(&data->display, pipe_crc, pipe, flags, &crc_hires2); + igt_display_commit2(&data->display, COMMIT_ATOMIC); + + igt_pipe_crc_drain(pipe_crc); + igt_pipe_crc_get_single(pipe_crc, &crc_hires2); igt_assert_plane_visible(data->drm_fd, pipe, true); diff -Nru intel-gpu-tools-1.21/tests/kms_plane_multiple.c intel-gpu-tools-1.22/tests/kms_plane_multiple.c --- intel-gpu-tools-1.21/tests/kms_plane_multiple.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/kms_plane_multiple.c 2018-03-09 14:22:59.000000000 +0000 @@ -173,8 +173,7 @@ rect_w[i], rect_h[i], 0.0, 0.0, 0.0); } - igt_assert(cairo_status(cr) == 0); - cairo_destroy(cr); + igt_put_cairo_ctx(data->drm_fd, &data->fb[primary->index], cr); } diff -Nru intel-gpu-tools-1.21/tests/kms_plane_scaling.c intel-gpu-tools-1.22/tests/kms_plane_scaling.c --- intel-gpu-tools-1.21/tests/kms_plane_scaling.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/kms_plane_scaling.c 2018-03-09 14:22:59.000000000 +0000 @@ -38,14 +38,7 @@ int image_w; int image_h; - int num_scalers; - - struct igt_fb fb1; - struct igt_fb fb2; - struct igt_fb fb3; - int fb_id1; - int fb_id2; - int fb_id3; + struct igt_fb fb[4]; igt_plane_t *plane1; igt_plane_t *plane2; @@ -53,80 +46,178 @@ igt_plane_t *plane4; } data_t; -#define FILE_NAME "1080p-left.png" +static int get_num_scalers(uint32_t devid, enum pipe pipe) +{ + igt_require(intel_gen(devid) >= 9); + + if (intel_gen(devid) >= 10) + return 2; + else if (pipe != PIPE_C) + return 2; + else + return 1; +} + +static void cleanup_fbs(data_t *data) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(data->fb); i++) + igt_remove_fb(data->drm_fd, &data->fb[i]); +} + +static void cleanup_crtc(data_t *data) +{ + igt_display_reset(&data->display); + igt_pipe_crc_free(data->pipe_crc); + data->pipe_crc = NULL; + + cleanup_fbs(data); +} static void prepare_crtc(data_t *data, igt_output_t *output, enum pipe pipe, - igt_plane_t *plane, drmModeModeInfo *mode, enum igt_commit_style s) + igt_plane_t *plane, drmModeModeInfo *mode) { igt_display_t *display = &data->display; + cleanup_crtc(data); + igt_output_set_pipe(output, pipe); /* create the pipe_crc object for this pipe */ - igt_pipe_crc_free(data->pipe_crc); data->pipe_crc = igt_pipe_crc_new(data->drm_fd, pipe, INTEL_PIPE_CRC_SOURCE_AUTO); - /* before allocating, free if any older fb */ - if (data->fb_id1) { - igt_remove_fb(data->drm_fd, &data->fb1); - data->fb_id1 = 0; - } - /* allocate fb for plane 1 */ - data->fb_id1 = igt_create_pattern_fb(data->drm_fd, - mode->hdisplay, mode->vdisplay, - DRM_FORMAT_XRGB8888, - LOCAL_I915_FORMAT_MOD_X_TILED, /* tiled */ - &data->fb1); - igt_assert(data->fb_id1); - - /* - * We always set the primary plane to actually enable the pipe as - * there's no way (that works) to light up a pipe with only a sprite - * plane enabled at the moment. - */ + igt_create_pattern_fb(data->drm_fd, mode->hdisplay, mode->vdisplay, + DRM_FORMAT_XRGB8888, + LOCAL_I915_FORMAT_MOD_X_TILED, /* tiled */ + &data->fb[0]); + + igt_plane_set_fb(plane, &data->fb[0]); + if (plane->type != DRM_PLANE_TYPE_PRIMARY) { igt_plane_t *primary; + int ret; + /* Do we succeed without enabling the primary plane? */ + ret = igt_display_try_commit2(display, COMMIT_ATOMIC); + if (!ret) + return; + + /* + * Fallback: set the primary plane to actually enable the pipe. + * Some drivers always require the primary plane to be enabled. + */ primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY); - igt_plane_set_fb(primary, &data->fb1); + igt_plane_set_fb(primary, &data->fb[0]); } + igt_display_commit2(display, COMMIT_ATOMIC); +} - igt_plane_set_fb(plane, &data->fb1); - igt_display_commit2(display, s); +static void check_scaling_pipe_plane_rot(data_t *d, igt_plane_t *plane, + uint32_t pixel_format, + uint64_t tiling, enum pipe pipe, + igt_output_t *output, + igt_rotation_t rot) +{ + igt_display_t *display = &d->display; + int width, height; + drmModeModeInfo *mode; + + cleanup_crtc(d); + + igt_output_set_pipe(output, pipe); + mode = igt_output_get_mode(output); + + /* create buffer in the range of min and max source side limit.*/ + width = height = 9; + igt_create_color_fb(display->drm_fd, width, height, + pixel_format, tiling, 0.0, 1.0, 0.0, &d->fb[0]); + igt_plane_set_fb(plane, &d->fb[0]); + + /* Check min to full resolution upscaling */ + igt_fb_set_position(&d->fb[0], plane, 0, 0); + igt_fb_set_size(&d->fb[0], plane, width, height); + igt_plane_set_position(plane, 0, 0); + igt_plane_set_size(plane, mode->hdisplay, mode->vdisplay); + igt_plane_set_rotation(plane, rot); + igt_display_commit2(display, COMMIT_ATOMIC); + + igt_plane_set_fb(plane, NULL); + igt_plane_set_position(plane, 0, 0); } -static void cleanup_crtc(data_t *data, igt_output_t *output, igt_plane_t *plane) +static const igt_rotation_t rotations[] = { + IGT_ROTATION_0, + IGT_ROTATION_90, + IGT_ROTATION_180, + IGT_ROTATION_270, +}; + +static bool can_rotate(unsigned format) { - igt_display_t *display = &data->display; + if (format == DRM_FORMAT_C8 || + format == DRM_FORMAT_RGB565) + return false; - igt_pipe_crc_free(data->pipe_crc); - data->pipe_crc = NULL; + return true; +} + +static void test_scaler_with_rotation_pipe(data_t *d, enum pipe pipe, + igt_output_t *output) +{ + igt_display_t *display = &d->display; + igt_plane_t *plane; - if (data->fb_id1) { - igt_remove_fb(data->drm_fd, &data->fb1); - data->fb_id1 = 0; - } - if (data->fb_id2) { - igt_remove_fb(data->drm_fd, &data->fb2); - data->fb_id2 = 0; - } - if (data->fb_id3) { - igt_remove_fb(data->drm_fd, &data->fb3); - data->fb_id3 = 0; + igt_output_set_pipe(output, pipe); + for_each_plane_on_pipe(display, pipe, plane) { + if (plane->type == DRM_PLANE_TYPE_CURSOR) + continue; + + for (int i = 0; i < ARRAY_SIZE(rotations); i++) { + igt_rotation_t rot = rotations[i]; + for (int j = 0; j < plane->drm_plane->count_formats; j++) { + unsigned format = plane->drm_plane->formats[j]; + if (igt_fb_supported_format(format) && can_rotate(format)) + check_scaling_pipe_plane_rot(d, plane, format, + LOCAL_I915_FORMAT_MOD_Y_TILED, + pipe, output, rot); + } + } } +} - if (plane->type != DRM_PLANE_TYPE_PRIMARY) { - igt_plane_t *primary; +static const uint64_t tilings[] = { + LOCAL_DRM_FORMAT_MOD_NONE, + LOCAL_I915_FORMAT_MOD_X_TILED, + LOCAL_I915_FORMAT_MOD_Y_TILED, + LOCAL_I915_FORMAT_MOD_Yf_TILED +}; - primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY); - igt_plane_set_fb(primary, NULL); - } +static void test_scaler_with_pixel_format_pipe(data_t *d, enum pipe pipe, igt_output_t *output) +{ + igt_display_t *display = &d->display; + igt_plane_t *plane; - igt_plane_set_fb(plane, NULL); - igt_output_set_pipe(output, PIPE_ANY); + igt_output_set_pipe(output, pipe); - igt_display_commit2(display, COMMIT_UNIVERSAL); + for_each_plane_on_pipe(display, pipe, plane) { + if (plane->type == DRM_PLANE_TYPE_CURSOR) + continue; + + for (int i = 0; i < ARRAY_SIZE(tilings); i++) { + uint64_t tiling = tilings[i]; + + for (int j = 0; j < plane->drm_plane->count_formats; j++) { + uint32_t format = plane->drm_plane->formats[j]; + + if (igt_fb_supported_format(format)) + check_scaling_pipe_plane_rot(d, plane, + format, tiling, + pipe, output, IGT_ROTATION_0); + } + } + } } /* does iterative scaling on plane2 */ @@ -134,185 +225,347 @@ { igt_display_t *display = &d->display; - if (mode->hdisplay >= d->fb2.width) { + if (mode->hdisplay >= d->fb[1].width) { int w, h; /* fixed fb */ - igt_fb_set_position(&d->fb2, d->plane2, 0, 0); - igt_fb_set_size(&d->fb2, d->plane2, d->fb2.width, d->fb2.height); + igt_fb_set_position(&d->fb[1], d->plane2, 0, 0); + igt_fb_set_size(&d->fb[1], d->plane2, d->fb[1].width, d->fb[1].height); igt_plane_set_position(d->plane2, 0, 0); /* adjust plane size */ - for (w = d->fb2.width; w <= mode->hdisplay; w+=10) { - h = w * d->fb2.height / d->fb2.width; + for (w = d->fb[1].width; w <= mode->hdisplay; w+=10) { + h = w * d->fb[1].height / d->fb[1].width; igt_plane_set_size(d->plane2, w, h); - igt_display_commit2(display, COMMIT_UNIVERSAL); + igt_display_commit2(display, COMMIT_ATOMIC); } } else { int w, h; /* fixed plane */ igt_plane_set_position(d->plane2, 0, 0); igt_plane_set_size(d->plane2, mode->hdisplay, mode->vdisplay); - igt_fb_set_position(&d->fb2, d->plane2, 0, 0); + igt_fb_set_position(&d->fb[1], d->plane2, 0, 0); /* adjust fb size */ - for (w = mode->hdisplay; w <= d->fb2.width; w+=10) { - h = w * mode->hdisplay / mode->vdisplay; - igt_fb_set_size(&d->fb2, d->plane2, w, h); - igt_display_commit2(display, COMMIT_UNIVERSAL); + for (w = mode->hdisplay; w <= d->fb[1].width; w+=10) { + /* Source coordinates must not be clipped. */ + h = min(w * mode->hdisplay / mode->vdisplay, d->fb[1].height); + igt_fb_set_size(&d->fb[1], d->plane2, w, h); + igt_display_commit2(display, COMMIT_ATOMIC); } } } -static void test_plane_scaling(data_t *d) +static void +test_plane_scaling_on_pipe(data_t *d, enum pipe pipe, igt_output_t *output) { igt_display_t *display = &d->display; - igt_output_t *output; - enum pipe pipe; - int valid_tests = 0; + drmModeModeInfo *mode; int primary_plane_scaling = 0; /* For now */ - igt_require(d->num_scalers); + mode = igt_output_get_mode(output); - for_each_pipe_with_valid_output(display, pipe, output) { - drmModeModeInfo *mode; + /* Set up display with plane 1 */ + d->plane1 = &display->pipes[pipe].planes[0]; + prepare_crtc(d, output, pipe, d->plane1, mode); + + igt_create_color_pattern_fb(display->drm_fd, 600, 600, + DRM_FORMAT_XRGB8888, + LOCAL_I915_FORMAT_MOD_X_TILED, /* tiled */ + .5, .5, .5, &d->fb[1]); + + igt_create_pattern_fb(d->drm_fd, + mode->hdisplay, mode->vdisplay, + DRM_FORMAT_XRGB8888, + LOCAL_I915_FORMAT_MOD_X_TILED, /* tiled */ + &d->fb[2]); + + if (primary_plane_scaling) { + /* Primary plane upscaling */ + igt_fb_set_position(&d->fb[0], d->plane1, 100, 100); + igt_fb_set_size(&d->fb[0], d->plane1, 500, 500); + igt_plane_set_position(d->plane1, 0, 0); + igt_plane_set_size(d->plane1, mode->hdisplay, mode->vdisplay); + igt_display_commit2(display, COMMIT_ATOMIC); + + /* Primary plane 1:1 no scaling */ + igt_fb_set_position(&d->fb[0], d->plane1, 0, 0); + igt_fb_set_size(&d->fb[0], d->plane1, d->fb[0].width, d->fb[0].height); + igt_plane_set_position(d->plane1, 0, 0); + igt_plane_set_size(d->plane1, mode->hdisplay, mode->vdisplay); + igt_display_commit2(display, COMMIT_ATOMIC); + } - igt_output_set_pipe(output, pipe); + /* Set up fb[1]->plane2 mapping. */ + d->plane2 = igt_output_get_plane(output, 1); + igt_plane_set_fb(d->plane2, &d->fb[1]); + + /* 2nd plane windowed */ + igt_fb_set_position(&d->fb[1], d->plane2, 100, 100); + igt_fb_set_size(&d->fb[1], d->plane2, d->fb[1].width-200, d->fb[1].height-200); + igt_plane_set_position(d->plane2, 100, 100); + igt_plane_set_size(d->plane2, mode->hdisplay-200, mode->vdisplay-200); + igt_display_commit2(display, COMMIT_ATOMIC); + + iterate_plane_scaling(d, mode); + + /* 2nd plane up scaling */ + igt_fb_set_position(&d->fb[1], d->plane2, 100, 100); + igt_fb_set_size(&d->fb[1], d->plane2, 500, 500); + igt_plane_set_position(d->plane2, 10, 10); + igt_plane_set_size(d->plane2, mode->hdisplay-20, mode->vdisplay-20); + igt_display_commit2(display, COMMIT_ATOMIC); + + /* 2nd plane downscaling */ + igt_fb_set_position(&d->fb[1], d->plane2, 0, 0); + igt_fb_set_size(&d->fb[1], d->plane2, d->fb[1].width, d->fb[1].height); + igt_plane_set_position(d->plane2, 10, 10); + + /* Downscale (10/9)x of original image */ + igt_plane_set_size(d->plane2, (d->fb[1].width * 10)/9, (d->fb[1].height * 10)/9); + igt_display_commit2(display, COMMIT_ATOMIC); + + if (primary_plane_scaling) { + /* Primary plane up scaling */ + igt_fb_set_position(&d->fb[0], d->plane1, 100, 100); + igt_fb_set_size(&d->fb[0], d->plane1, 500, 500); + igt_plane_set_position(d->plane1, 0, 0); + igt_plane_set_size(d->plane1, mode->hdisplay, mode->vdisplay); + igt_display_commit2(display, COMMIT_ATOMIC); + } - mode = igt_output_get_mode(output); + /* Set up fb[2]->plane3 mapping. */ + d->plane3 = igt_output_get_plane(output, 2); + igt_plane_set_fb(d->plane3, &d->fb[2]); + + if(d->plane3->type == DRM_PLANE_TYPE_CURSOR) { + igt_debug("Plane-3 doesnt exist on pipe %s\n", kmstest_pipe_name(pipe)); + return; + } - /* allocate fb2 with image size */ - d->fb_id2 = igt_create_image_fb(d->drm_fd, 0, 0, - DRM_FORMAT_XRGB8888, - LOCAL_I915_FORMAT_MOD_X_TILED, /* tiled */ - FILE_NAME, &d->fb2); - igt_assert(d->fb_id2); - - d->fb_id3 = igt_create_pattern_fb(d->drm_fd, - mode->hdisplay, mode->vdisplay, - DRM_FORMAT_XRGB8888, - LOCAL_I915_FORMAT_MOD_X_TILED, /* tiled */ - &d->fb3); - igt_assert(d->fb_id3); - - /* Set up display with plane 1 */ - d->plane1 = igt_output_get_plane(output, 0); - prepare_crtc(d, output, pipe, d->plane1, mode, COMMIT_UNIVERSAL); - - if (primary_plane_scaling) { - /* Primary plane upscaling */ - igt_fb_set_position(&d->fb1, d->plane1, 100, 100); - igt_fb_set_size(&d->fb1, d->plane1, 500, 500); - igt_plane_set_position(d->plane1, 0, 0); - igt_plane_set_size(d->plane1, mode->hdisplay, mode->vdisplay); - igt_display_commit2(display, COMMIT_UNIVERSAL); - - /* Primary plane 1:1 no scaling */ - igt_fb_set_position(&d->fb1, d->plane1, 0, 0); - igt_fb_set_size(&d->fb1, d->plane1, d->fb1.width, d->fb1.height); - igt_plane_set_position(d->plane1, 0, 0); - igt_plane_set_size(d->plane1, mode->hdisplay, mode->vdisplay); - igt_display_commit2(display, COMMIT_UNIVERSAL); - } + /* 3rd plane windowed - no scaling */ + igt_fb_set_position(&d->fb[2], d->plane3, 100, 100); + igt_fb_set_size(&d->fb[2], d->plane3, d->fb[2].width-300, d->fb[2].height-300); + igt_plane_set_position(d->plane3, 100, 100); + igt_plane_set_size(d->plane3, mode->hdisplay-300, mode->vdisplay-300); + igt_display_commit2(display, COMMIT_ATOMIC); + + /* Switch scaler from plane 2 to plane 3 */ + igt_fb_set_position(&d->fb[1], d->plane2, 100, 100); + igt_fb_set_size(&d->fb[1], d->plane2, d->fb[1].width-200, d->fb[1].height-200); + igt_plane_set_position(d->plane2, 100, 100); + igt_plane_set_size(d->plane2, d->fb[1].width-200, d->fb[1].height-200); + + igt_fb_set_position(&d->fb[2], d->plane3, 100, 100); + igt_fb_set_size(&d->fb[2], d->plane3, d->fb[2].width-400, d->fb[2].height-400); + igt_plane_set_position(d->plane3, 10, 10); + igt_plane_set_size(d->plane3, mode->hdisplay-300, mode->vdisplay-300); + igt_display_commit2(display, COMMIT_ATOMIC); + + if (primary_plane_scaling) { + /* Switch scaler from plane 1 to plane 2 */ + igt_fb_set_position(&d->fb[0], d->plane1, 0, 0); + igt_fb_set_size(&d->fb[0], d->plane1, d->fb[0].width, d->fb[0].height); + igt_plane_set_position(d->plane1, 0, 0); + igt_plane_set_size(d->plane1, mode->hdisplay, mode->vdisplay); - /* Set up fb2->plane2 mapping. */ - d->plane2 = igt_output_get_plane(output, 1); - igt_plane_set_fb(d->plane2, &d->fb2); - - /* 2nd plane windowed */ - igt_fb_set_position(&d->fb2, d->plane2, 100, 100); - igt_fb_set_size(&d->fb2, d->plane2, d->fb2.width-200, d->fb2.height-200); + igt_fb_set_position(&d->fb[1], d->plane2, 100, 100); + igt_fb_set_size(&d->fb[1], d->plane2, d->fb[1].width-500,d->fb[1].height-500); igt_plane_set_position(d->plane2, 100, 100); igt_plane_set_size(d->plane2, mode->hdisplay-200, mode->vdisplay-200); - igt_display_commit2(display, COMMIT_UNIVERSAL); + igt_display_commit2(display, COMMIT_ATOMIC); + } +} - iterate_plane_scaling(d, mode); +static void +__test_scaler_with_clipping_clamping_scenario(data_t *d, drmModeModeInfo *mode, + uint32_t f1, uint32_t f2) +{ + cleanup_fbs(d); - /* 2nd plane up scaling */ - igt_fb_set_position(&d->fb2, d->plane2, 100, 100); - igt_fb_set_size(&d->fb2, d->plane2, 500, 500); - igt_plane_set_position(d->plane2, 10, 10); - igt_plane_set_size(d->plane2, mode->hdisplay-20, mode->vdisplay-20); - igt_display_commit2(display, COMMIT_UNIVERSAL); - - /* 2nd plane downscaling */ - igt_fb_set_position(&d->fb2, d->plane2, 0, 0); - igt_fb_set_size(&d->fb2, d->plane2, d->fb2.width, d->fb2.height); - igt_plane_set_position(d->plane2, 10, 10); - igt_plane_set_size(d->plane2, 500, 500 * d->fb2.height/d->fb2.width); - igt_display_commit2(display, COMMIT_UNIVERSAL); - - if (primary_plane_scaling) { - /* Primary plane up scaling */ - igt_fb_set_position(&d->fb1, d->plane1, 100, 100); - igt_fb_set_size(&d->fb1, d->plane1, 500, 500); - igt_plane_set_position(d->plane1, 0, 0); - igt_plane_set_size(d->plane1, mode->hdisplay, mode->vdisplay); - igt_display_commit2(display, COMMIT_UNIVERSAL); - } + igt_create_pattern_fb(d->drm_fd, + mode->hdisplay, mode->vdisplay, f1, + LOCAL_I915_FORMAT_MOD_X_TILED, &d->fb[1]); + + igt_create_pattern_fb(d->drm_fd, + mode->hdisplay, mode->vdisplay, f2, + LOCAL_I915_FORMAT_MOD_Y_TILED, &d->fb[2]); + + igt_plane_set_fb(d->plane1, &d->fb[1]); + igt_plane_set_fb(d->plane2, &d->fb[2]); + + igt_fb_set_position(&d->fb[1], d->plane1, 0, 0); + igt_fb_set_size(&d->fb[1], d->plane1, 300, 300); + igt_plane_set_position(d->plane1, 100, 400); + igt_fb_set_position(&d->fb[2], d->plane2, 0, 0); + igt_fb_set_size(&d->fb[2], d->plane2, 400, 400); + igt_plane_set_position(d->plane2, 100, 100); + + /* scaled window size is outside the modeset area.*/ + igt_plane_set_size(d->plane1, mode->hdisplay + 200, + mode->vdisplay + 200); + igt_plane_set_size(d->plane2, mode->hdisplay + 100, + mode->vdisplay + 100); + igt_display_commit2(&d->display, COMMIT_ATOMIC); +} - /* Set up fb3->plane3 mapping. */ - d->plane3 = igt_output_get_plane(output, 2); - igt_plane_set_fb(d->plane3, &d->fb3); - - /* 3rd plane windowed - no scaling */ - igt_fb_set_position(&d->fb3, d->plane3, 100, 100); - igt_fb_set_size(&d->fb3, d->plane3, d->fb3.width-300, d->fb3.height-300); - igt_plane_set_position(d->plane3, 100, 100); - igt_plane_set_size(d->plane3, mode->hdisplay-300, mode->vdisplay-300); - igt_display_commit2(display, COMMIT_UNIVERSAL); - - /* Switch scaler from plane 2 to plane 3 */ - igt_fb_set_position(&d->fb2, d->plane2, 100, 100); - igt_fb_set_size(&d->fb2, d->plane2, d->fb2.width-200, d->fb2.height-200); - igt_plane_set_position(d->plane2, 100, 100); - igt_plane_set_size(d->plane2, d->fb2.width-200, d->fb2.height-200); +static void +test_scaler_with_clipping_clamping_scenario(data_t *d, enum pipe pipe, igt_output_t *output) +{ + drmModeModeInfo *mode; - igt_fb_set_position(&d->fb3, d->plane3, 100, 100); - igt_fb_set_size(&d->fb3, d->plane3, d->fb3.width-400, d->fb3.height-400); - igt_plane_set_position(d->plane3, 10, 10); - igt_plane_set_size(d->plane3, mode->hdisplay-300, mode->vdisplay-300); - igt_display_commit2(display, COMMIT_UNIVERSAL); - - if (primary_plane_scaling) { - /* Switch scaler from plane 1 to plane 2 */ - igt_fb_set_position(&d->fb1, d->plane1, 0, 0); - igt_fb_set_size(&d->fb1, d->plane1, d->fb1.width, d->fb1.height); - igt_plane_set_position(d->plane1, 0, 0); - igt_plane_set_size(d->plane1, mode->hdisplay, mode->vdisplay); - - igt_fb_set_position(&d->fb2, d->plane2, 100, 100); - igt_fb_set_size(&d->fb2, d->plane2, d->fb2.width-500,d->fb2.height-500); - igt_plane_set_position(d->plane2, 100, 100); - igt_plane_set_size(d->plane2, mode->hdisplay-200, mode->vdisplay-200); - igt_display_commit2(display, COMMIT_UNIVERSAL); + igt_require(get_num_scalers(d->devid, pipe) >= 2); + + mode = igt_output_get_mode(output); + d->plane1 = &d->display.pipes[pipe].planes[0]; + d->plane2 = &d->display.pipes[pipe].planes[1]; + prepare_crtc(d, output, pipe, d->plane1, mode); + + for (int i = 0; i < d->plane1->drm_plane->count_formats; i++) { + unsigned f1 = d->plane1->drm_plane->formats[i]; + if (!igt_fb_supported_format(f1)) + continue; + + for (int j = 0; j < d->plane2->drm_plane->count_formats; j++) { + unsigned f2 = d->plane2->drm_plane->formats[j]; + + if (!igt_fb_supported_format(f2)) + continue; + + __test_scaler_with_clipping_clamping_scenario(d, mode, f1, f2); } + } +} - /* back to single plane mode */ - igt_plane_set_fb(d->plane2, NULL); - igt_plane_set_fb(d->plane3, NULL); - igt_display_commit2(display, COMMIT_UNIVERSAL); +static void find_connected_pipe(igt_display_t *display, bool second, enum pipe *pipe, igt_output_t **output) +{ + enum pipe first = PIPE_NONE; + igt_output_t *first_output = NULL; + bool found = false; + + for_each_pipe_with_valid_output(display, *pipe, *output) { + if (first == *pipe || *output == first_output) + continue; + + if (second) { + first = *pipe; + first_output = *output; + second = false; + continue; + } - valid_tests++; - cleanup_crtc(d, output, d->plane1); + return; } - igt_require_f(valid_tests, "no valid crtc/connector combinations found\n"); + + if (first_output) + igt_require_f(found, "No second valid output found\n"); + else + igt_require_f(found, "No valid outputs found\n"); } -igt_simple_main +static void test_scaler_with_multi_pipe_plane(data_t *d) +{ + igt_display_t *display = &d->display; + igt_output_t *output1, *output2; + drmModeModeInfo *mode1, *mode2; + enum pipe pipe1, pipe2; + + cleanup_crtc(d); + + find_connected_pipe(display, false, &pipe1, &output1); + find_connected_pipe(display, true, &pipe2, &output2); + + igt_skip_on(!output1 || !output2); + + igt_output_set_pipe(output1, pipe1); + igt_output_set_pipe(output2, pipe2); + + d->plane1 = igt_output_get_plane(output1, 0); + d->plane2 = get_num_scalers(d->devid, pipe1) >= 2 ? igt_output_get_plane(output1, 1) : NULL; + d->plane3 = igt_output_get_plane(output2, 0); + d->plane4 = get_num_scalers(d->devid, pipe2) >= 2 ? igt_output_get_plane(output2, 1) : NULL; + + mode1 = igt_output_get_mode(output1); + mode2 = igt_output_get_mode(output2); + + igt_create_pattern_fb(d->drm_fd, 600, 600, + DRM_FORMAT_XRGB8888, + LOCAL_I915_FORMAT_MOD_Y_TILED, &d->fb[0]); + + igt_create_pattern_fb(d->drm_fd, 500, 500, + DRM_FORMAT_XRGB8888, + LOCAL_I915_FORMAT_MOD_Y_TILED, &d->fb[1]); + + igt_create_pattern_fb(d->drm_fd, 700, 700, + DRM_FORMAT_XRGB8888, + LOCAL_I915_FORMAT_MOD_Y_TILED, &d->fb[2]); + + igt_create_pattern_fb(d->drm_fd, 400, 400, + DRM_FORMAT_XRGB8888, + LOCAL_I915_FORMAT_MOD_Y_TILED, &d->fb[3]); + + igt_plane_set_fb(d->plane1, &d->fb[0]); + if (d->plane2) + igt_plane_set_fb(d->plane2, &d->fb[1]); + igt_plane_set_fb(d->plane3, &d->fb[2]); + if (d->plane4) + igt_plane_set_fb(d->plane4, &d->fb[3]); + igt_display_commit2(display, COMMIT_ATOMIC); + + /* Upscaling Primary */ + igt_plane_set_size(d->plane1, mode1->hdisplay, mode1->vdisplay); + igt_plane_set_size(d->plane3, mode2->hdisplay, mode2->vdisplay); + igt_display_commit2(display, COMMIT_ATOMIC); + + /* Upscaling Sprites */ + igt_plane_set_size(d->plane2 ?: d->plane1, mode1->hdisplay, mode1->vdisplay); + igt_plane_set_size(d->plane4 ?: d->plane3, mode2->hdisplay, mode2->vdisplay); + igt_display_commit2(display, COMMIT_ATOMIC); +} + +igt_main { data_t data = {}; + enum pipe pipe; igt_skip_on_simulation(); + igt_fixture { + data.drm_fd = drm_open_driver(DRIVER_INTEL); + igt_require_pipe_crc(data.drm_fd); + igt_display_init(&data.display, data.drm_fd); + data.devid = intel_get_drm_devid(data.drm_fd); + igt_require(data.display.is_atomic); + } + + for_each_pipe_static(pipe) igt_subtest_group { + igt_output_t *output; - data.drm_fd = drm_open_driver(DRIVER_INTEL); - igt_require_pipe_crc(data.drm_fd); - igt_display_init(&data.display, data.drm_fd); - data.devid = intel_get_drm_devid(data.drm_fd); + igt_fixture { + igt_display_require_output_on_pipe(&data.display, pipe); - data.num_scalers = intel_gen(data.devid) >= 9 ? 2 : 0; + igt_require(get_num_scalers(data.devid, pipe) > 0); + } + + igt_subtest_f("pipe-%s-plane-scaling", kmstest_pipe_name(pipe)) + for_each_valid_output_on_pipe(&data.display, pipe, output) + test_plane_scaling_on_pipe(&data, pipe, output); + + igt_subtest_f("pipe-%s-scaler-with-pixel-format", kmstest_pipe_name(pipe)) + for_each_valid_output_on_pipe(&data.display, pipe, output) + test_scaler_with_pixel_format_pipe(&data, pipe, output); + + igt_subtest_f("pipe-%s-scaler-with-rotation", kmstest_pipe_name(pipe)) + for_each_valid_output_on_pipe(&data.display, pipe, output) + test_scaler_with_rotation_pipe(&data, pipe, output); + + igt_subtest_f("pipe-%s-scaler-with-clipping-clamping", kmstest_pipe_name(pipe)) + for_each_valid_output_on_pipe(&data.display, pipe, output) + test_scaler_with_clipping_clamping_scenario(&data, pipe, output); + } - test_plane_scaling(&data); + igt_subtest_f("2x-scaler-multi-pipe") + test_scaler_with_multi_pipe_plane(&data); - igt_display_fini(&data.display); + igt_fixture + igt_display_fini(&data.display); } diff -Nru intel-gpu-tools-1.21/tests/kms_psr_sink_crc.c intel-gpu-tools-1.22/tests/kms_psr_sink_crc.c --- intel-gpu-tools-1.21/tests/kms_psr_sink_crc.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/kms_psr_sink_crc.c 2018-03-09 14:22:59.000000000 +0000 @@ -91,7 +91,7 @@ cr = igt_get_cairo_ctx(data->drm_fd, &data->fb_white); igt_paint_color_alpha(cr, 0, 0, 64, 64, 1.0, 1.0, 1.0, 1.0); - igt_assert(cairo_status(cr) == 0); + igt_put_cairo_ctx(data->drm_fd, &data->fb_white, cr); } diff -Nru intel-gpu-tools-1.21/tests/kms_render.c intel-gpu-tools-1.22/tests/kms_render.c --- intel-gpu-tools-1.21/tests/kms_render.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/kms_render.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,253 +0,0 @@ -/* - * 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 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. - * - * Authors: - * Imre Deak - */ -#include "config.h" - -#include "igt.h" -#include -#include -#include -#include -#include - -#include "intel_bufmgr.h" - -drmModeRes *resources; -int drm_fd; - -enum test_flags { - TEST_DIRECT_RENDER = 0x01, - TEST_GPU_BLIT = 0x02, -}; - -static int paint_fb(struct igt_fb *fb, const char *test_name, - const char *mode_format_str, const char *cconf_str) -{ - cairo_t *cr; - - cr = igt_get_cairo_ctx(drm_fd, fb); - - igt_paint_color_gradient(cr, 0, 0, fb->width, fb->height, 1, 1, 1); - igt_paint_test_pattern(cr, fb->width, fb->height); - - cairo_move_to(cr, fb->width / 2, fb->height / 2); - cairo_set_font_size(cr, 36); - igt_cairo_printf_line(cr, align_hcenter, 10, "%s", test_name); - igt_cairo_printf_line(cr, align_hcenter, 10, "%s", mode_format_str); - igt_cairo_printf_line(cr, align_hcenter, 10, "%s", cconf_str); - - cairo_destroy(cr); - - return 0; -} - -static void gpu_blit(struct igt_fb *dst_fb, struct igt_fb *src_fb) -{ - drm_intel_bo *dst_bo; - drm_intel_bo *src_bo; - int bpp; - static drm_intel_bufmgr *bufmgr; - struct intel_batchbuffer *batch; - uint32_t devid; - - igt_require_intel(drm_fd); - igt_require_gem(drm_fd); - - bufmgr = drm_intel_bufmgr_gem_init(drm_fd, 4096); - devid = intel_get_drm_devid(drm_fd); - batch = intel_batchbuffer_alloc(bufmgr, devid); - - igt_assert(dst_fb->drm_format == src_fb->drm_format); - igt_assert(src_fb->drm_format == DRM_FORMAT_RGB565 || - igt_drm_format_to_bpp(src_fb->drm_format) != 16); - bpp = igt_drm_format_to_bpp(src_fb->drm_format); - dst_bo = gem_handle_to_libdrm_bo(bufmgr, drm_fd, "destination", - dst_fb->gem_handle); - igt_assert(dst_bo); - src_bo = gem_handle_to_libdrm_bo(bufmgr, drm_fd, "source", - src_fb->gem_handle); - igt_assert(src_bo); - - intel_blt_copy(batch, - src_bo, 0, 0, src_fb->width * bpp / 8, - dst_bo, 0, 0, dst_fb->width * bpp / 8, - src_fb->width, src_fb->height, bpp); - intel_batchbuffer_flush(batch); - gem_quiescent_gpu(drm_fd); - - drm_intel_bo_unreference(src_bo); - drm_intel_bo_unreference(dst_bo); -} - -static int test_format(const char *test_name, - struct kmstest_connector_config *cconf, - drmModeModeInfo *mode, uint32_t format, - enum test_flags flags) -{ - int width; - int height; - struct igt_fb fb[2]; - char *mode_format_str; - char *cconf_str; - int ret; - - ret = asprintf(&mode_format_str, "%s @ %dHz / %s", - mode->name, mode->vrefresh, igt_format_str(format)); - igt_assert_lt(0, ret); - ret = asprintf(&cconf_str, "pipe %s, encoder %s, connector %s", - kmstest_pipe_name(cconf->pipe), - kmstest_encoder_type_str(cconf->encoder->encoder_type), - kmstest_connector_type_str(cconf->connector->connector_type)); - igt_assert_lt(0, ret); - - igt_info("Beginning test %s with %s on %s\n", - test_name, mode_format_str, cconf_str); - - width = mode->hdisplay; - height = mode->vdisplay; - - if (!igt_create_fb(drm_fd, width, height, format, - LOCAL_DRM_FORMAT_MOD_NONE, &fb[0])) - goto err1; - - if (!igt_create_fb(drm_fd, width, height, format, - LOCAL_DRM_FORMAT_MOD_NONE, &fb[1])) - goto err2; - - if (drmModeSetCrtc(drm_fd, cconf->crtc->crtc_id, fb[0].fb_id, - 0, 0, &cconf->connector->connector_id, 1, - mode)) - goto err2; - do_or_die(drmModePageFlip(drm_fd, cconf->crtc->crtc_id, fb[0].fb_id, - 0, NULL)); - sleep(2); - - if (flags & TEST_DIRECT_RENDER) { - paint_fb(&fb[0], test_name, mode_format_str, cconf_str); - } else if (flags & TEST_GPU_BLIT) { - paint_fb(&fb[1], test_name, mode_format_str, cconf_str); - gpu_blit(&fb[0], &fb[1]); - } - sleep(5); - - igt_info("Test %s with %s on %s: PASSED\n", - test_name, mode_format_str, cconf_str); - free(mode_format_str); - free(cconf_str); - - igt_remove_fb(drm_fd, &fb[1]); - igt_remove_fb(drm_fd, &fb[0]); - - return 0; - -err2: - igt_remove_fb(drm_fd, &fb[0]); -err1: - igt_info("Test %s with %s on %s: SKIPPED\n", - test_name, mode_format_str, cconf_str); - free(mode_format_str); - free(cconf_str); - - return -1; -} - -static void test_connector(const char *test_name, - struct kmstest_connector_config *cconf, - enum test_flags flags) -{ - const uint32_t *formats; - int format_count; - int i; - - igt_get_all_cairo_formats(&formats, &format_count); - for (i = 0; i < format_count; i++) { - if (is_i915_device(drm_fd) - && intel_gen(intel_get_drm_devid(drm_fd)) < 4 - && formats[i] == DRM_FORMAT_XRGB2101010) { - igt_info("gen2/3 don't support 10bpc, skipping\n"); - continue; - } - - test_format(test_name, - cconf, &cconf->connector->modes[0], - formats[i], flags); - } -} - -static int run_test(const char *test_name, enum test_flags flags) -{ - int i; - - resources = drmModeGetResources(drm_fd); - igt_assert(resources); - - /* Find any connected displays */ - for (i = 0; i < resources->count_connectors; i++) { - uint32_t connector_id; - int j; - - connector_id = resources->connectors[i]; - for (j = 0; j < resources->count_crtcs; j++) { - struct kmstest_connector_config cconf; - - if (!kmstest_get_connector_config(drm_fd, connector_id, - 1 << j, &cconf)) - continue; - - test_connector(test_name, &cconf, flags); - - kmstest_free_connector_config(&cconf); - } - } - - drmModeFreeResources(resources); - - return 1; -} - -igt_main -{ - struct { - enum test_flags flags; - const char *name; - } tests[] = { - { TEST_DIRECT_RENDER, "direct-render" }, - { TEST_GPU_BLIT, "gpu-blit" }, - }; - int i; - - igt_skip_on_simulation(); - - igt_fixture { - drm_fd = drm_open_driver_master(DRIVER_ANY); - - kmstest_set_vt_graphics_mode(); - } - - for (i = 0; i < ARRAY_SIZE(tests); i++) { - igt_subtest(tests[i].name) - run_test(tests[i].name, tests[i].flags); - } - - igt_fixture - close(drm_fd); -} diff -Nru intel-gpu-tools-1.21/tests/kms_rotation_crc.c intel-gpu-tools-1.22/tests/kms_rotation_crc.c --- intel-gpu-tools-1.21/tests/kms_rotation_crc.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/kms_rotation_crc.c 2018-03-09 14:22:59.000000000 +0000 @@ -33,7 +33,6 @@ struct igt_fb fb; struct igt_fb fb_reference; struct igt_fb fb_unrotated; - struct igt_fb fb_modeset; struct igt_fb fb_flip; igt_crc_t ref_crc; igt_crc_t flip_crc; @@ -43,7 +42,6 @@ int pos_y; uint32_t override_fmt; uint64_t override_tiling; - bool flips; int devid; } data_t; @@ -120,71 +118,45 @@ igt_paint_color(cr, 0, h / 2, w / 2, h / 2, RGB_COLOR(bl)); igt_paint_color(cr, w / 2, h / 2, w / 2, h / 2, RGB_COLOR(br)); - cairo_destroy(cr); + igt_put_cairo_ctx(data->gfx_fd, fb, cr); } -static void prepare_crtc(data_t *data, igt_output_t *output, enum pipe pipe, - igt_plane_t *plane, enum igt_commit_style commit) +static void remove_fbs(data_t *data) { - drmModeModeInfo *mode; - unsigned int w, h; - uint64_t tiling = data->override_tiling ?: LOCAL_DRM_FORMAT_MOD_NONE; - uint32_t pixel_format = data->override_fmt ?: DRM_FORMAT_XRGB8888; - igt_display_t *display = &data->display; - igt_plane_t *primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY); + igt_remove_fb(data->gfx_fd, &data->fb); + igt_remove_fb(data->gfx_fd, &data->fb_reference); + igt_remove_fb(data->gfx_fd, &data->fb_unrotated); + igt_remove_fb(data->gfx_fd, &data->fb_flip); +} - igt_output_set_pipe(output, pipe); - igt_plane_set_rotation(plane, IGT_ROTATION_0); +static void cleanup_crtc(data_t *data) +{ + igt_display_t *display = &data->display; - /* create the pipe_crc object for this pipe */ igt_pipe_crc_free(data->pipe_crc); - data->pipe_crc = igt_pipe_crc_new(data->gfx_fd, pipe, INTEL_PIPE_CRC_SOURCE_AUTO); - - mode = igt_output_get_mode(output); - - w = mode->hdisplay; - h = mode->vdisplay; - - igt_create_fb(data->gfx_fd, w, h, pixel_format, tiling, &data->fb_modeset); - - /* - * With igt_display_commit2 and COMMIT_UNIVERSAL, we call just the - * setplane without a modeset. So, to be able to call - * igt_display_commit and ultimately setcrtc to do the first modeset, - * we create an fb covering the crtc and call commit - * - * It's also a good idea to set a primary fb on the primary plane - * regardless, to force a underrun when watermarks are allocated - * incorrectly for other planes. - */ - igt_plane_set_fb(primary, &data->fb_modeset); - - if (commit < COMMIT_ATOMIC) { - igt_plane_clear_prop_changed(primary, IGT_PLANE_ROTATION); - igt_display_commit(display); - - if (plane->type == DRM_PLANE_TYPE_PRIMARY) - igt_plane_set_prop_changed(primary, IGT_PLANE_ROTATION); - } + data->pipe_crc = NULL; - igt_plane_set_fb(plane, NULL); + remove_fbs(data); - igt_display_commit2(display, commit); + igt_display_reset(display); } -static void remove_fbs(data_t *data) +static void prepare_crtc(data_t *data, igt_output_t *output, enum pipe pipe, + igt_plane_t *plane) { - if (!data->fb.fb_id) - return; + igt_display_t *display = &data->display; - igt_remove_fb(data->gfx_fd, &data->fb); - igt_remove_fb(data->gfx_fd, &data->fb_reference); - igt_remove_fb(data->gfx_fd, &data->fb_unrotated); + cleanup_crtc(data); - if (data->fb_flip.fb_id) - igt_remove_fb(data->gfx_fd, &data->fb_flip); + igt_output_set_pipe(output, pipe); + igt_plane_set_rotation(plane, IGT_ROTATION_0); - data->fb_flip.fb_id = data->fb.fb_id = 0; + /* create the pipe_crc object for this pipe */ + igt_pipe_crc_free(data->pipe_crc); + + igt_display_commit2(display, COMMIT_ATOMIC); + data->pipe_crc = igt_pipe_crc_new(data->gfx_fd, pipe, INTEL_PIPE_CRC_SOURCE_AUTO); + igt_pipe_crc_start(data->pipe_crc); } enum rectangle_type { @@ -196,7 +168,7 @@ }; static void prepare_fbs(data_t *data, igt_output_t *output, - igt_plane_t *plane, enum rectangle_type rect) + igt_plane_t *plane, enum rectangle_type rect, uint32_t format) { drmModeModeInfo *mode; igt_display_t *display = &data->display; @@ -205,12 +177,7 @@ uint32_t pixel_format = data->override_fmt ?: DRM_FORMAT_XRGB8888; const float flip_opacity = 0.75; - if (data->fb.fb_id) { - igt_plane_set_fb(plane, NULL); - igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_UNIVERSAL); - - remove_fbs(data); - } + remove_fbs(data); igt_plane_set_rotation(plane, IGT_ROTATION_0); @@ -260,19 +227,25 @@ /* * Create a reference software rotated flip framebuffer. */ - if (data->flips) { - igt_create_fb(data->gfx_fd, ref_w, ref_h, pixel_format, tiling, - &data->fb_flip); - paint_squares(data, data->rotation, &data->fb_flip, - flip_opacity); - igt_plane_set_fb(plane, &data->fb_flip); - if (plane->type != DRM_PLANE_TYPE_CURSOR) - igt_plane_set_position(plane, data->pos_x, data->pos_y); - igt_display_commit2(display, - display->is_atomic ? - COMMIT_ATOMIC : COMMIT_UNIVERSAL); - igt_pipe_crc_collect_crc(data->pipe_crc, &data->flip_crc); - } + igt_create_fb(data->gfx_fd, ref_w, ref_h, pixel_format, tiling, + &data->fb_flip); + paint_squares(data, data->rotation, &data->fb_flip, + flip_opacity); + igt_plane_set_fb(plane, &data->fb_flip); + if (plane->type != DRM_PLANE_TYPE_CURSOR) + igt_plane_set_position(plane, data->pos_x, data->pos_y); + igt_display_commit2(display, COMMIT_ATOMIC); + igt_pipe_crc_drain(data->pipe_crc); + igt_pipe_crc_get_single(data->pipe_crc, &data->flip_crc); + + /* + * Prepare the non-rotated flip fb. + */ + igt_remove_fb(data->gfx_fd, &data->fb_flip); + igt_create_fb(data->gfx_fd, w, h, pixel_format, tiling, + &data->fb_flip); + paint_squares(data, IGT_ROTATION_0, &data->fb_flip, + flip_opacity); /* * Create a reference CRC for a software-rotated fb. @@ -284,9 +257,10 @@ igt_plane_set_fb(plane, &data->fb_reference); if (plane->type != DRM_PLANE_TYPE_CURSOR) igt_plane_set_position(plane, data->pos_x, data->pos_y); - igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_UNIVERSAL); + igt_display_commit2(display, COMMIT_ATOMIC); - igt_pipe_crc_collect_crc(data->pipe_crc, &data->ref_crc); + igt_pipe_crc_drain(data->pipe_crc); + igt_pipe_crc_get_single(data->pipe_crc, &data->ref_crc); /* * Prepare the non-rotated reference fb. @@ -297,7 +271,7 @@ igt_plane_set_rotation(plane, IGT_ROTATION_0); if (plane->type != DRM_PLANE_TYPE_CURSOR) igt_plane_set_position(plane, data->pos_x, data->pos_y); - igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_UNIVERSAL); + igt_display_commit2(display, COMMIT_ATOMIC); /* * Prepare the plane with an non-rotated fb let the hw rotate it. @@ -308,47 +282,6 @@ if (plane->type != DRM_PLANE_TYPE_CURSOR) igt_plane_set_position(plane, data->pos_x, data->pos_y); - - /* - * Prepare the non-rotated flip fb. - */ - if (data->flips) { - igt_remove_fb(data->gfx_fd, &data->fb_flip); - igt_create_fb(data->gfx_fd, w, h, pixel_format, tiling, - &data->fb_flip); - paint_squares(data, IGT_ROTATION_0, &data->fb_flip, - flip_opacity); - } - -} - -static void cleanup_crtc(data_t *data, igt_output_t *output, igt_plane_t *plane) -{ - igt_display_t *display = &data->display; - - igt_pipe_crc_free(data->pipe_crc); - data->pipe_crc = NULL; - - remove_fbs(data); - - igt_remove_fb(data->gfx_fd, &data->fb_modeset); - - /* XXX: see the note in prepare_crtc() */ - if (plane->type != DRM_PLANE_TYPE_PRIMARY) { - igt_plane_t *primary; - - primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY); - igt_plane_set_fb(primary, NULL); - } - - igt_plane_set_fb(plane, NULL); - igt_plane_set_rotation(plane, IGT_ROTATION_0); - - igt_display_commit2(display, COMMIT_UNIVERSAL); - - igt_output_set_pipe(output, PIPE_ANY); - - igt_display_commit(display); } static void wait_for_pageflip(int fd) @@ -368,31 +301,77 @@ igt_assert(drmHandleEvent(fd, &evctx) == 0); } -static void __test_plane_rotation(data_t *data, int plane_type, bool test_bad_format) +static void test_single_case(data_t *data, enum pipe pipe, + igt_output_t *output, igt_plane_t *plane, + enum rectangle_type rect, + uint32_t format, bool test_bad_format) { igt_display_t *display = &data->display; - igt_output_t *output; - enum pipe pipe; - int valid_tests = 0; igt_crc_t crc_output; - enum igt_commit_style commit = COMMIT_LEGACY; int ret; - if (data->flips && plane_type != DRM_PLANE_TYPE_PRIMARY) - igt_require(data->display.is_atomic); + igt_debug("Testing case %i on pipe %s, format %s\n", rect, kmstest_pipe_name(pipe), igt_format_str(format)); + prepare_fbs(data, output, plane, rect, format); + + igt_plane_set_rotation(plane, data->rotation); + if (data->rotation & (IGT_ROTATION_90 | IGT_ROTATION_270)) + igt_plane_set_size(plane, data->fb.height, data->fb.width); + + ret = igt_display_try_commit2(display, COMMIT_ATOMIC); + if (test_bad_format) { + igt_assert_eq(ret, -EINVAL); + return; + } + + /* Verify commit was ok. */ + igt_assert_eq(ret, 0); + + /* Check CRC */ + igt_pipe_crc_drain(data->pipe_crc); + igt_pipe_crc_get_single(data->pipe_crc, &crc_output); + igt_assert_crc_equal(&data->ref_crc, &crc_output); + + /* + * If flips are requested flip to a different fb and + * check CRC against that one as well. + */ + if (data->fb_flip.fb_id) { + igt_plane_set_fb(plane, &data->fb_flip); + if (data->rotation == IGT_ROTATION_90 || data->rotation == IGT_ROTATION_270) + igt_plane_set_size(plane, data->fb.height, data->fb.width); + + if (plane->type != DRM_PLANE_TYPE_PRIMARY) { + igt_display_commit_atomic(display, DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK, NULL); + } else { + ret = drmModePageFlip(data->gfx_fd, + output->config.crtc->crtc_id, + data->fb_flip.fb_id, + DRM_MODE_PAGE_FLIP_EVENT, + NULL); + igt_assert_eq(ret, 0); + } + wait_for_pageflip(data->gfx_fd); + igt_pipe_crc_drain(data->pipe_crc); + igt_pipe_crc_get_single(data->pipe_crc, &crc_output); + igt_assert_crc_equal(&data->flip_crc, + &crc_output); + } +} - if (plane_type == DRM_PLANE_TYPE_PRIMARY || plane_type == DRM_PLANE_TYPE_CURSOR) - commit = COMMIT_UNIVERSAL; +static void test_plane_rotation(data_t *data, int plane_type, bool test_bad_format) +{ + igt_display_t *display = &data->display; + igt_output_t *output; + enum pipe pipe; if (plane_type == DRM_PLANE_TYPE_CURSOR) igt_require(display->has_cursor_plane); - if (data->display.is_atomic) - commit = COMMIT_ATOMIC; + igt_display_require_output(display); for_each_pipe_with_valid_output(display, pipe, output) { igt_plane_t *plane; - int i; + int i, j; if (IS_CHERRYVIEW(data->devid) && pipe != PIPE_B) continue; @@ -402,7 +381,7 @@ plane = igt_output_get_plane_type(output, plane_type); igt_require(igt_plane_has_prop(plane, IGT_PLANE_ROTATION)); - prepare_crtc(data, output, pipe, plane, commit); + prepare_crtc(data, output, pipe, plane); for (i = 0; i < num_rectangle_types; i++) { /* Unsupported on i915 */ @@ -415,171 +394,47 @@ i != rectangle && intel_gen(intel_get_drm_devid(data->gfx_fd)) < 9) continue; - igt_debug("Testing case %i on pipe %s\n", i, kmstest_pipe_name(pipe)); - prepare_fbs(data, output, plane, i); + if (!data->override_fmt) { + for (j = 0; j < plane->drm_plane->count_formats; j++) { + uint32_t format = plane->drm_plane->formats[j]; - igt_plane_set_rotation(plane, data->rotation); - if (data->rotation & (IGT_ROTATION_90 | IGT_ROTATION_270)) - igt_plane_set_size(plane, data->fb.height, data->fb.width); - - ret = igt_display_try_commit2(display, commit); - if (test_bad_format && (data->override_fmt || data->override_tiling)) { - igt_assert_eq(ret, -EINVAL); - continue; - } - - /* Verify commit was ok. */ - igt_assert_eq(ret, 0); + if (!igt_fb_supported_format(format)) + continue; - /* Check CRC */ - igt_pipe_crc_collect_crc(data->pipe_crc, &crc_output); - igt_assert_crc_equal(&data->ref_crc, &crc_output); - - /* - * If flips are requested flip to a different fb and - * check CRC against that one as well. - */ - if (data->flips) { - igt_plane_set_fb(plane, &data->fb_flip); - if (data->rotation == IGT_ROTATION_90 || data->rotation == IGT_ROTATION_270) - igt_plane_set_size(plane, data->fb.height, data->fb.width); - - if (plane_type != DRM_PLANE_TYPE_PRIMARY) { - igt_display_commit_atomic(display, DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK, NULL); - } else { - ret = drmModePageFlip(data->gfx_fd, - output->config.crtc->crtc_id, - data->fb_flip.fb_id, - DRM_MODE_PAGE_FLIP_EVENT, - NULL); - igt_assert_eq(ret, 0); + test_single_case(data, pipe, output, plane, i, + format, test_bad_format); } - wait_for_pageflip(data->gfx_fd); - igt_pipe_crc_collect_crc(data->pipe_crc, - &crc_output); - igt_assert_crc_equal(&data->flip_crc, - &crc_output); + } else { + test_single_case(data, pipe, output, plane, i, + data->override_fmt, test_bad_format); } } - - valid_tests++; - cleanup_crtc(data, output, plane); } - igt_require_f(valid_tests, "no valid crtc/connector combinations found\n"); -} - -static inline void test_bad_plane_rotation(data_t *data, int plane_type) -{ - __test_plane_rotation(data, plane_type, true); -} - -static inline void test_plane_rotation(data_t *data, int plane_type) -{ - __test_plane_rotation(data, plane_type, false); -} - -static void test_plane_rotation_ytiled_obj(data_t *data, - igt_output_t *output, - int plane_type) -{ - igt_display_t *display = &data->display; - uint64_t tiling = LOCAL_I915_FORMAT_MOD_Y_TILED; - uint32_t format = DRM_FORMAT_XRGB8888; - int bpp = igt_drm_format_to_bpp(format); - enum igt_commit_style commit = COMMIT_LEGACY; - int fd = data->gfx_fd; - igt_plane_t *plane; - drmModeModeInfo *mode; - unsigned int stride, size, w, h; - uint32_t gem_handle; - int ret; - - plane = igt_output_get_plane_type(output, plane_type); - igt_require(igt_plane_has_prop(plane, IGT_PLANE_ROTATION)); - - if (plane_type == DRM_PLANE_TYPE_PRIMARY || plane_type == DRM_PLANE_TYPE_CURSOR) - commit = COMMIT_UNIVERSAL; - - if (plane_type == DRM_PLANE_TYPE_CURSOR) - igt_require(display->has_cursor_plane); - - if (data->display.is_atomic) - commit = COMMIT_ATOMIC; - - mode = igt_output_get_mode(output); - w = mode->hdisplay; - h = mode->vdisplay; - - for (stride = 512; stride < (w * bpp / 8); stride *= 2) - ; - for (size = 1024*1024; size < stride * h; size *= 2) - ; - - gem_handle = gem_create(fd, size); - ret = __gem_set_tiling(fd, gem_handle, I915_TILING_Y, stride); - igt_assert_eq(ret, 0); - - do_or_die(__kms_addfb(fd, gem_handle, w, h, stride, - format, tiling, LOCAL_DRM_MODE_FB_MODIFIERS, - &data->fb.fb_id)); - data->fb.width = w; - data->fb.height = h; - data->fb.gem_handle = gem_handle; - - igt_plane_set_fb(plane, NULL); - igt_display_commit(display); - - igt_plane_set_rotation(plane, data->rotation); - igt_plane_set_fb(plane, &data->fb); - igt_plane_set_size(plane, h, w); - - ret = igt_display_try_commit2(display, commit); - - igt_output_set_pipe(output, PIPE_NONE); - - kmstest_restore_vt_mode(); - igt_remove_fb(fd, &data->fb); - igt_assert_eq(ret, 0); } static void test_plane_rotation_exhaust_fences(data_t *data, + enum pipe pipe, igt_output_t *output, - int plane_type) + igt_plane_t *plane) { igt_display_t *display = &data->display; uint64_t tiling = LOCAL_I915_FORMAT_MOD_Y_TILED; uint32_t format = DRM_FORMAT_XRGB8888; - int bpp = igt_drm_format_to_bpp(format); - enum igt_commit_style commit = COMMIT_LEGACY; int fd = data->gfx_fd; - igt_plane_t *plane; drmModeModeInfo *mode; - data_t data2[MAX_FENCES+1] = {}; + struct igt_fb fb[MAX_FENCES+1] = {}; unsigned int stride, size, w, h; - uint32_t gem_handle; uint64_t total_aperture_size, total_fbs_size; - int i, ret; + int i; - plane = igt_output_get_plane_type(output, plane_type); igt_require(igt_plane_has_prop(plane, IGT_PLANE_ROTATION)); - if (plane_type == DRM_PLANE_TYPE_PRIMARY || plane_type == DRM_PLANE_TYPE_CURSOR) - commit = COMMIT_UNIVERSAL; - - if (plane_type == DRM_PLANE_TYPE_CURSOR) - igt_require(display->has_cursor_plane); - - if (data->display.is_atomic) - commit = COMMIT_ATOMIC; - + prepare_crtc(data, output, pipe, plane); mode = igt_output_get_mode(output); w = mode->hdisplay; h = mode->vdisplay; - for (stride = 512; stride < (w * bpp / 8); stride *= 2) - ; - for (size = 1024*1024; size < stride * h; size *= 2) - ; + igt_calc_fb_size(fd, w, h, format, tiling, &size, &stride); /* * Make sure there is atleast 90% of the available GTT space left @@ -589,68 +444,20 @@ total_aperture_size = gem_available_aperture_size(fd); igt_require(total_fbs_size < total_aperture_size * 0.9); - igt_plane_set_fb(plane, NULL); - igt_display_commit(display); - for (i = 0; i < MAX_FENCES + 1; i++) { - gem_handle = gem_create(fd, size); - ret = __gem_set_tiling(fd, gem_handle, I915_TILING_Y, stride); - if (ret) { - igt_warn("failed to set tiling\n"); - goto err_alloc; - } + igt_create_fb(fd, w, h, format, tiling, &fb[i]); - ret = (__kms_addfb(fd, gem_handle, w, h, stride, - format, tiling, LOCAL_DRM_MODE_FB_MODIFIERS, - &data2[i].fb.fb_id)); - if (ret) { - igt_warn("failed to create framebuffer\n"); - goto err_alloc; - } - - data2[i].fb.width = w; - data2[i].fb.height = h; - data2[i].fb.gem_handle = gem_handle; - - igt_plane_set_fb(plane, &data2[i].fb); + igt_plane_set_fb(plane, &fb[i]); igt_plane_set_rotation(plane, IGT_ROTATION_0); - - ret = igt_display_try_commit2(display, commit); - if (ret) { - igt_warn("failed to commit unrotated fb\n"); - goto err_commit; - } + igt_display_commit2(display, COMMIT_ATOMIC); igt_plane_set_rotation(plane, IGT_ROTATION_90); igt_plane_set_size(plane, h, w); - - igt_display_commit2(display, commit); - if (ret) { - igt_warn("failed to commit hardware rotated fb: %i\n", ret); - goto err_commit; - } + igt_display_commit2(display, COMMIT_ATOMIC); } -err_alloc: - if (ret) - gem_close(fd, gem_handle); - - i--; -err_commit: - igt_plane_set_fb(plane, NULL); - igt_plane_set_rotation(plane, IGT_ROTATION_0); - - if (commit < COMMIT_ATOMIC) - igt_display_commit2(display, commit); - - igt_output_set_pipe(output, PIPE_NONE); - igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY); - - for (; i >= 0; i--) - igt_remove_fb(fd, &data2[i].fb); - - kmstest_restore_vt_mode(); - igt_assert_eq(ret, 0); + for (i = 0; i < MAX_FENCES + 1; i++) + igt_remove_fb(fd, &fb[i]); } static const char *plane_test_str(unsigned plane) @@ -697,63 +504,37 @@ } } -static const char *flip_test_str(unsigned flips) -{ - if (flips) - return "-flip"; - else - return ""; -} - igt_main { struct rot_subtest { unsigned plane; igt_rotation_t rot; - bool flips; } *subtest, subtests[] = { - { DRM_PLANE_TYPE_PRIMARY, IGT_ROTATION_90, 0 }, - { DRM_PLANE_TYPE_PRIMARY, IGT_ROTATION_180, 0 }, - { DRM_PLANE_TYPE_PRIMARY, IGT_ROTATION_270, 0 }, - { DRM_PLANE_TYPE_PRIMARY, IGT_ROTATION_90, 1 }, - { DRM_PLANE_TYPE_PRIMARY, IGT_ROTATION_180, 1 }, - { DRM_PLANE_TYPE_PRIMARY, IGT_ROTATION_270, 1 }, - { DRM_PLANE_TYPE_OVERLAY, IGT_ROTATION_90, 0 }, - { DRM_PLANE_TYPE_OVERLAY, IGT_ROTATION_180, 0 }, - { DRM_PLANE_TYPE_OVERLAY, IGT_ROTATION_270, 0 }, - { DRM_PLANE_TYPE_OVERLAY, IGT_ROTATION_90, 1 }, - { DRM_PLANE_TYPE_OVERLAY, IGT_ROTATION_180, 1 }, - { DRM_PLANE_TYPE_OVERLAY, IGT_ROTATION_270, 1 }, - { DRM_PLANE_TYPE_CURSOR, IGT_ROTATION_180, 0 }, - { 0, 0, 0} + { DRM_PLANE_TYPE_PRIMARY, IGT_ROTATION_90 }, + { DRM_PLANE_TYPE_PRIMARY, IGT_ROTATION_180 }, + { DRM_PLANE_TYPE_PRIMARY, IGT_ROTATION_270 }, + { DRM_PLANE_TYPE_OVERLAY, IGT_ROTATION_90 }, + { DRM_PLANE_TYPE_OVERLAY, IGT_ROTATION_180 }, + { DRM_PLANE_TYPE_OVERLAY, IGT_ROTATION_270 }, + { DRM_PLANE_TYPE_CURSOR, IGT_ROTATION_180 }, + { 0, 0} }; struct reflect_x { uint64_t tiling; igt_rotation_t rot; - bool flips; } *reflect_x, reflect_x_subtests[] = { - { LOCAL_I915_FORMAT_MOD_X_TILED, IGT_ROTATION_0, 0 }, - { LOCAL_I915_FORMAT_MOD_X_TILED, IGT_ROTATION_180, 0 }, - { LOCAL_I915_FORMAT_MOD_Y_TILED, IGT_ROTATION_0, 0 }, - { LOCAL_I915_FORMAT_MOD_Y_TILED, IGT_ROTATION_90, 0 }, - { LOCAL_I915_FORMAT_MOD_Y_TILED, IGT_ROTATION_180, 0 }, - { LOCAL_I915_FORMAT_MOD_Y_TILED, IGT_ROTATION_270, 0 }, - { LOCAL_I915_FORMAT_MOD_Yf_TILED, IGT_ROTATION_0, 0 }, - { LOCAL_I915_FORMAT_MOD_Yf_TILED, IGT_ROTATION_90, 0 }, - { LOCAL_I915_FORMAT_MOD_Yf_TILED, IGT_ROTATION_180, 0 }, - { LOCAL_I915_FORMAT_MOD_Yf_TILED, IGT_ROTATION_270, 0 }, - { LOCAL_I915_FORMAT_MOD_X_TILED, IGT_ROTATION_0, 1 }, - { LOCAL_I915_FORMAT_MOD_X_TILED, IGT_ROTATION_180, 1 }, - { LOCAL_I915_FORMAT_MOD_Y_TILED, IGT_ROTATION_0, 1 }, - { LOCAL_I915_FORMAT_MOD_Y_TILED, IGT_ROTATION_90, 1 }, - { LOCAL_I915_FORMAT_MOD_Y_TILED, IGT_ROTATION_180, 1 }, - { LOCAL_I915_FORMAT_MOD_Y_TILED, IGT_ROTATION_270, 1 }, - { LOCAL_I915_FORMAT_MOD_Yf_TILED, IGT_ROTATION_0, 1 }, - { LOCAL_I915_FORMAT_MOD_Yf_TILED, IGT_ROTATION_90, 1 }, - { LOCAL_I915_FORMAT_MOD_Yf_TILED, IGT_ROTATION_180, 1 }, - { LOCAL_I915_FORMAT_MOD_Yf_TILED, IGT_ROTATION_270, 1 }, - { 0, 0, 0 } + { LOCAL_I915_FORMAT_MOD_X_TILED, IGT_ROTATION_0 }, + { LOCAL_I915_FORMAT_MOD_X_TILED, IGT_ROTATION_180 }, + { LOCAL_I915_FORMAT_MOD_Y_TILED, IGT_ROTATION_0 }, + { LOCAL_I915_FORMAT_MOD_Y_TILED, IGT_ROTATION_90 }, + { LOCAL_I915_FORMAT_MOD_Y_TILED, IGT_ROTATION_180 }, + { LOCAL_I915_FORMAT_MOD_Y_TILED, IGT_ROTATION_270 }, + { LOCAL_I915_FORMAT_MOD_Yf_TILED, IGT_ROTATION_0 }, + { LOCAL_I915_FORMAT_MOD_Yf_TILED, IGT_ROTATION_90 }, + { LOCAL_I915_FORMAT_MOD_Yf_TILED, IGT_ROTATION_180 }, + { LOCAL_I915_FORMAT_MOD_Yf_TILED, IGT_ROTATION_270 }, + { 0, 0 } }; data_t data = {}; @@ -774,16 +555,14 @@ } for (subtest = subtests; subtest->rot; subtest++) { - igt_subtest_f("%s-rotation-%s%s", + igt_subtest_f("%s-rotation-%s", plane_test_str(subtest->plane), - rot_test_str(subtest->rot), - flip_test_str(subtest->flips)) { + rot_test_str(subtest->rot)) { igt_require(!(subtest->rot & (IGT_ROTATION_90 | IGT_ROTATION_270)) || gen >= 9); data.rotation = subtest->rot; - data.flips = subtest->flips; - test_plane_rotation(&data, subtest->plane); + test_plane_rotation(&data, subtest->plane, false); } } @@ -792,78 +571,57 @@ data.rotation = IGT_ROTATION_90; data.pos_x = 100, data.pos_y = 0; - test_plane_rotation(&data, DRM_PLANE_TYPE_OVERLAY); + test_plane_rotation(&data, DRM_PLANE_TYPE_OVERLAY, false); } + data.pos_x = 0, + data.pos_y = 0; igt_subtest_f("bad-pixel-format") { igt_require(gen >= 9); - data.pos_x = 0, - data.pos_y = 0; data.rotation = IGT_ROTATION_90; data.override_fmt = DRM_FORMAT_RGB565; - test_bad_plane_rotation(&data, DRM_PLANE_TYPE_PRIMARY); + test_plane_rotation(&data, DRM_PLANE_TYPE_PRIMARY, true); } + data.override_fmt = 0; igt_subtest_f("bad-tiling") { igt_require(gen >= 9); - data.override_fmt = 0; data.rotation = IGT_ROTATION_90; - data.override_tiling = LOCAL_DRM_FORMAT_MOD_NONE; - test_bad_plane_rotation(&data, DRM_PLANE_TYPE_PRIMARY); - } - - igt_subtest_f("primary-rotation-90-Y-tiled") { - enum pipe pipe; - igt_output_t *output; - int valid_tests = 0; - - igt_require(gen >= 9); - data.rotation = IGT_ROTATION_90; - - for_each_pipe_with_valid_output(&data.display, pipe, output) { - igt_output_set_pipe(output, pipe); - - test_plane_rotation_ytiled_obj(&data, output, DRM_PLANE_TYPE_PRIMARY); - - valid_tests++; - break; - } - - igt_require_f(valid_tests, "no valid crtc/connector combinations found\n"); + data.override_tiling = LOCAL_I915_FORMAT_MOD_X_TILED; + test_plane_rotation(&data, DRM_PLANE_TYPE_PRIMARY, true); } + data.override_tiling = 0; for (reflect_x = reflect_x_subtests; reflect_x->tiling; reflect_x++) { - igt_subtest_f("primary-%s-reflect-x-%s%s", + igt_subtest_f("primary-%s-reflect-x-%s", tiling_test_str(reflect_x->tiling), - rot_test_str(reflect_x->rot), - flip_test_str(reflect_x->flips)) { + rot_test_str(reflect_x->rot)) { igt_require(gen >= 10 || (IS_CHERRYVIEW(data.devid) && reflect_x->rot == IGT_ROTATION_0 && reflect_x->tiling == LOCAL_I915_FORMAT_MOD_X_TILED)); data.rotation = (IGT_REFLECT_X | reflect_x->rot); data.override_tiling = reflect_x->tiling; - data.flips = reflect_x->flips; - test_plane_rotation(&data, DRM_PLANE_TYPE_PRIMARY); + test_plane_rotation(&data, DRM_PLANE_TYPE_PRIMARY, false); } } + /* + * exhaust-fences should be last test, if it fails we may OOM in + * the following subtests otherwise. + */ igt_subtest_f("exhaust-fences") { enum pipe pipe; igt_output_t *output; - int valid_tests = 0; igt_require(gen >= 9); + igt_display_require_output(&data.display); for_each_pipe_with_valid_output(&data.display, pipe, output) { - igt_output_set_pipe(output, pipe); + igt_plane_t *primary = &data.display.pipes[pipe].planes[0]; - test_plane_rotation_exhaust_fences(&data, output, DRM_PLANE_TYPE_PRIMARY); - - valid_tests++; + test_plane_rotation_exhaust_fences(&data, pipe, output, primary); break; } - - igt_require_f(valid_tests, "no valid crtc/connector combinations found\n"); } igt_fixture { diff -Nru intel-gpu-tools-1.21/tests/kms_setmode.c intel-gpu-tools-1.22/tests/kms_setmode.c --- intel-gpu-tools-1.21/tests/kms_setmode.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/kms_setmode.c 2018-03-09 14:22:59.000000000 +0000 @@ -161,7 +161,7 @@ crtc_str[i]); } - cairo_destroy(cr); + igt_put_cairo_ctx(drm_fd, fb, cr); return 0; } @@ -361,6 +361,9 @@ int i; for (i = 0; i < crtc_count; i++) { + igt_remove_fb(drm_fd, &crtcs[i].fb_info); + drmModeSetCrtc(drm_fd, crtcs[i].crtc_id, 0, 0, 0, NULL, 0, NULL); + free(crtcs[i].cconfs); } } @@ -577,15 +580,6 @@ if (ret == 0 && tconf->flags & TEST_TIMINGS) check_timings(crtcs[0].crtc_idx, &crtcs[0].mode); - for (i = 0; i < crtc_count; i++) { - if (crtcs[i].fb_info.fb_id) { - drmModeSetCrtc(drm_fd, crtcs[i].crtc_id, 0, 0, 0, NULL, - 0, NULL); - drmModeRmFB(drm_fd, crtcs[i].fb_info.fb_id); - crtcs[i].fb_info.fb_id = 0; - } - } - return; } diff -Nru intel-gpu-tools-1.21/tests/kms_vblank.c intel-gpu-tools-1.22/tests/kms_vblank.c --- intel-gpu-tools-1.21/tests/kms_vblank.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/kms_vblank.c 2018-03-09 14:22:59.000000000 +0000 @@ -51,9 +51,14 @@ igt_output_t *output; enum pipe pipe; unsigned int flags; -#define IDLE 1 -#define BUSY 2 -#define FORKED 4 +#define IDLE 0x1 +#define BUSY 0x2 +#define FORKED 0x4 +#define NOHANG 0x8 +#define MODESET 0x10 +#define DPMS 0x20 +#define SUSPEND 0x40 +#define RPM 0x80 } data_t; static double elapsed(const struct timespec *start, @@ -69,6 +74,8 @@ igt_display_t *display = &data->display; igt_plane_t *primary; + igt_display_reset(display); + /* select the pipe we want to use */ igt_output_set_pipe(output, data->pipe); @@ -90,16 +97,7 @@ static void cleanup_crtc(data_t *data, int fd, igt_output_t *output) { - igt_display_t *display = &data->display; - igt_plane_t *primary; - igt_remove_fb(fd, &data->primary_fb); - - primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY); - igt_plane_set_fb(primary, NULL); - - igt_output_set_pipe(output, PIPE_ANY); - igt_display_commit(display); } static int wait_vblank(int fd, union drm_wait_vblank *vbl) @@ -113,54 +111,62 @@ return err; } -static void run_test(data_t *data, int fd, void (*testfunc)(data_t *, int, int)) +static void run_test(data_t *data, void (*testfunc)(data_t *, int, int)) { - int nchildren = - data->flags & FORKED ? sysconf(_SC_NPROCESSORS_ONLN) : 1; igt_display_t *display = &data->display; - igt_output_t *output; - enum pipe p; + igt_output_t *output = data->output; + int fd = display->drm_fd; + igt_hang_t hang; - for_each_pipe_with_valid_output(display, p, output) { - data->pipe = p; - prepare_crtc(data, fd, output); + prepare_crtc(data, fd, output); - igt_info("Beginning %s on pipe %s, connector %s (%d threads)\n", - igt_subtest_name(), - kmstest_pipe_name(data->pipe), - igt_output_name(output), - nchildren); - - if (data->flags & BUSY) { - union drm_wait_vblank vbl; - - memset(&vbl, 0, sizeof(vbl)); - vbl.request.type = - DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT; - vbl.request.type |= kmstest_get_vbl_flag(data->pipe); - vbl.request.sequence = 120 + 12; - igt_assert_eq(wait_vblank(fd, &vbl), 0); - } + if (data->flags & RPM) + igt_require(igt_setup_runtime_pm()); + + igt_info("Beginning %s on pipe %s, connector %s\n", + igt_subtest_name(), kmstest_pipe_name(data->pipe), + igt_output_name(output)); + + if (!(data->flags & NOHANG)) + hang = igt_hang_ring(fd, I915_EXEC_DEFAULT); + + if (data->flags & BUSY) { + union drm_wait_vblank vbl; + + memset(&vbl, 0, sizeof(vbl)); + vbl.request.type = + DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT; + vbl.request.type |= kmstest_get_vbl_flag(data->pipe); + vbl.request.sequence = 120 + 12; + igt_assert_eq(wait_vblank(fd, &vbl), 0); + } + + if (data->flags & FORKED) { + int nchildren = sysconf(_SC_NPROCESSORS_ONLN); + + igt_debug("Spawning %d threads\n", nchildren); igt_fork(child, nchildren) testfunc(data, fd, nchildren); igt_waitchildren(); + } else + testfunc(data, fd, 1); - if (data->flags & BUSY) { - struct drm_event_vblank buf; - igt_assert_eq(read(fd, &buf, sizeof(buf)), sizeof(buf)); - } + if (data->flags & BUSY) { + struct drm_event_vblank buf; + igt_assert_eq(read(fd, &buf, sizeof(buf)), sizeof(buf)); + } - igt_assert(poll(&(struct pollfd){fd, POLLIN}, 1, 0) == 0); + igt_assert(poll(&(struct pollfd){fd, POLLIN}, 1, 0) == 0); - igt_info("\n%s on pipe %s, connector %s: PASSED\n\n", - igt_subtest_name(), - kmstest_pipe_name(data->pipe), - igt_output_name(output)); + if (!(data->flags & NOHANG)) + igt_post_hang_ring(fd, hang); - /* cleanup what prepare_crtc() has done */ - cleanup_crtc(data, fd, output); - } + igt_info("\n%s on pipe %s, connector %s: PASSED\n\n", + igt_subtest_name(), kmstest_pipe_name(data->pipe), igt_output_name(output)); + + /* cleanup what prepare_crtc() has done */ + cleanup_crtc(data, fd, output); } static void crtc_id_subtest(data_t *data, int fd) @@ -315,20 +321,87 @@ elapsed(&start, &end, count)); } -igt_main +static int get_vblank(int fd, enum pipe pipe, unsigned flags) +{ + union drm_wait_vblank vbl; + + memset(&vbl, 0, sizeof(vbl)); + vbl.request.type = DRM_VBLANK_RELATIVE | kmstest_get_vbl_flag(pipe) | flags; + do_or_die(igt_ioctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbl)); + + return vbl.reply.sequence; +} + +static void vblank_ts_cont(data_t *data, int fd, int nchildren) +{ + igt_display_t *display = &data->display; + igt_output_t *output = data->output; + int seq1, seq2; + union drm_wait_vblank vbl; + + seq1 = get_vblank(fd, data->pipe, 0); + + if (data->flags & DPMS) { + igt_output_set_prop_value(output, IGT_CONNECTOR_DPMS, DRM_MODE_DPMS_OFF); + igt_display_commit(display); + } + + if (data->flags & MODESET) { + igt_output_set_pipe(output, PIPE_NONE); + igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY); + } + + if (data->flags & RPM) + igt_assert(igt_wait_for_pm_status(IGT_RUNTIME_PM_STATUS_SUSPENDED)); + + if (data->flags & SUSPEND) + igt_system_suspend_autoresume(SUSPEND_STATE_MEM, + SUSPEND_TEST_NONE); + + if (data->flags & (MODESET | DPMS)) { + /* Attempting to do a vblank while disabled should return -EINVAL */ + memset(&vbl, 0, sizeof(vbl)); + vbl.request.type = DRM_VBLANK_RELATIVE; + vbl.request.type |= kmstest_get_vbl_flag(data->pipe); + igt_assert_eq(wait_vblank(fd, &vbl), -EINVAL); + } + + if (data->flags & DPMS) { + igt_output_set_prop_value(output, IGT_CONNECTOR_DPMS, DRM_MODE_DPMS_ON); + igt_display_commit(display); + } + + if (data->flags & MODESET) { + igt_output_set_pipe(output, data->pipe); + igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY); + } + + seq2 = get_vblank(fd, data->pipe, 0); + + igt_debug("testing ts continuity: Current frame %u, old frame %u\n", seq2, seq1); + + igt_assert_f(seq2 - seq1 >= 0, "unexpected vblank seq %u, should be >= %u\n", seq2, seq1); + igt_assert_f(seq2 - seq1 <= 150, "unexpected vblank seq %u, should be < %u\n", seq2, seq1 + 150); +} + +static void run_subtests_for_pipe(data_t *data) { - int fd; - data_t data; const struct { const char *name; void (*func)(data_t *, int, int); unsigned int valid; } funcs[] = { - { "accuracy", accuracy, IDLE }, + /* + * GPU reset recovery may disable irqs or reset display, so + * accuracy tests will fail in the hang case, disable this test. + */ + { "accuracy", accuracy, IDLE | NOHANG }, { "query", vblank_query, IDLE | FORKED | BUSY }, { "wait", vblank_wait, IDLE | FORKED | BUSY }, + { "ts-continuation", vblank_ts_cont, IDLE | SUSPEND | MODESET | DPMS | RPM }, { } }, *f; + const struct { const char *name; unsigned int flags; @@ -337,9 +410,52 @@ { "forked", IDLE | FORKED }, { "busy", BUSY }, { "forked-busy", BUSY | FORKED }, + { "dpms-rpm", DPMS | RPM | NOHANG }, + { "dpms-suspend", DPMS | SUSPEND | NOHANG}, + { "suspend", SUSPEND | NOHANG }, + { "modeset", MODESET }, + { "modeset-rpm", MODESET | RPM | NOHANG}, { } }, *m; + igt_fixture + igt_display_require_output_on_pipe(&data->display, data->pipe); + + for (f = funcs; f->name; f++) { + for (m = modes; m->name; m++) { + if (m->flags & ~(f->valid | NOHANG)) + continue; + + igt_subtest_f("pipe-%s-%s-%s", + kmstest_pipe_name(data->pipe), + f->name, m->name) { + for_each_valid_output_on_pipe(&data->display, data->pipe, data->output) { + data->flags = m->flags | NOHANG; + run_test(data, f->func); + } + } + + /* Skip the -hang version if NOHANG flag is set */ + if (f->valid & NOHANG || m->flags & NOHANG) + continue; + + igt_subtest_f("pipe-%s-%s-%s-hang", + kmstest_pipe_name(data->pipe), + f->name, m->name) { + for_each_valid_output_on_pipe(&data->display, data->pipe, data->output) { + data->flags = m->flags; + run_test(data, f->func); + } + } + } + } +} + +igt_main +{ + int fd; + data_t data; + igt_skip_on_simulation(); igt_fixture { @@ -352,15 +468,7 @@ igt_subtest("crtc-id") crtc_id_subtest(&data, fd); - for (f = funcs; f->name; f++) { - for (m = modes; m->name; m++) { - if (m->flags & ~f->valid) - continue; - - igt_subtest_f("%s-%s", f->name, m->name) { - data.flags = m->flags; - run_test(&data, fd, f->func); - } - } - } + for_each_pipe_static(data.pipe) + igt_subtest_group + run_subtests_for_pipe(&data); } diff -Nru intel-gpu-tools-1.21/tests/Makefile.am intel-gpu-tools-1.22/tests/Makefile.am --- intel-gpu-tools-1.21/tests/Makefile.am 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/Makefile.am 2018-03-09 14:22:59.000000000 +0000 @@ -126,8 +126,6 @@ gem_tiled_swapping_LDADD = $(LDADD) -lpthread prime_self_import_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS) prime_self_import_LDADD = $(LDADD) -lpthread -gen7_forcewake_mt_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS) -gen7_forcewake_mt_LDADD = $(LDADD) -lpthread gem_userptr_blits_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS) gem_userptr_blits_LDADD = $(LDADD) -lpthread perf_pmu_LDADD = $(LDADD) $(top_builddir)/lib/libigt_perf.la @@ -149,6 +147,8 @@ audio_CFLAGS = $(AM_CFLAGS) $(ALSA_CFLAGS) audio_LDADD = $(LDADD) $(ALSA_LIBS) +testdisplay_CFLAGS = $(AM_CFLAGS) $(GLIB_CFLAGS) + amdgpu_amd_basic_CFLAGS = $(AM_CFLAGS) $(DRM_AMDGPU_CFLAGS) amdgpu_amd_basic_LDADD = $(LDADD) $(DRM_AMDGPU_LIBS) amdgpu_amd_cs_nop_CFLAGS = $(AM_CFLAGS) $(DRM_AMDGPU_CFLAGS) diff -Nru intel-gpu-tools-1.21/tests/Makefile.sources intel-gpu-tools-1.22/tests/Makefile.sources --- intel-gpu-tools-1.21/tests/Makefile.sources 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/Makefile.sources 2018-03-09 14:22:59.000000000 +0000 @@ -9,6 +9,7 @@ vc4_dmabuf_poll \ vc4_lookup_fail \ vc4_label_bo \ + vc4_purgeable_bo \ vc4_tiling \ vc4_wait_bo \ vc4_wait_seqno \ @@ -57,6 +58,7 @@ gem_ctx_bad_exec \ gem_ctx_create \ gem_ctx_exec \ + gem_ctx_isolation \ gem_ctx_param \ gem_ctx_switch \ gem_ctx_thrash \ @@ -164,7 +166,6 @@ gen3_render_mixed_blits \ gen3_render_tiledx_blits \ gen3_render_tiledy_blits \ - gen7_forcewake_mt \ gvt_basic \ kms_3d \ kms_addfb_basic \ @@ -202,7 +203,6 @@ kms_properties \ kms_psr_sink_crc \ kms_pwrite_crc \ - kms_render \ kms_rmfb \ kms_rotation_crc \ kms_setmode \ diff -Nru intel-gpu-tools-1.21/tests/meson.build intel-gpu-tools-1.22/tests/meson.build --- intel-gpu-tools-1.21/tests/meson.build 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/meson.build 2018-03-09 14:22:59.000000000 +0000 @@ -35,6 +35,7 @@ 'gem_ctx_bad_exec', 'gem_ctx_create', 'gem_ctx_exec', + 'gem_ctx_isolation', 'gem_ctx_param', 'gem_ctx_switch', 'gem_ctx_thrash', @@ -142,7 +143,6 @@ 'gen3_render_mixed_blits', 'gen3_render_tiledx_blits', 'gen3_render_tiledy_blits', - 'gen7_forcewake_mt', 'gvt_basic', 'kms_3d', 'kms_addfb_basic', @@ -180,7 +180,6 @@ 'kms_properties', 'kms_psr_sink_crc', 'kms_pwrite_crc', - 'kms_render', 'kms_rmfb', 'kms_rotation_crc', 'kms_setmode', @@ -213,6 +212,7 @@ 'vc4_dmabuf_poll', 'vc4_label_bo', 'vc4_lookup_fail', + 'vc4_purgeable_bo', 'vc4_tiling', 'vc4_wait_bo', 'vc4_wait_seqno', @@ -255,8 +255,6 @@ test_deps += alsa endif -libexecdir = join_paths(get_option('prefix'), get_option('libexecdir'), 'intel-gpu-tools') - test_executables = [] foreach prog : test_progs @@ -278,8 +276,6 @@ install : true) test_progs += 'testdisplay' -pkgdatadir = join_paths(get_option('prefix'), get_option('datadir'), 'intel-gpu-tools') - gen_testlist = find_program('generate_testlist.sh') test_list = custom_target('testlist', output : 'test-list.txt', @@ -318,6 +314,6 @@ '1080p-right.png', 'pass.png', ] -install_data(sources : image_files, install_dir : pkgdatadir) +install_data(sources : image_files, install_dir : datadir) subdir('intel-ci') diff -Nru intel-gpu-tools-1.21/tests/perf.c intel-gpu-tools-1.22/tests/perf.c --- intel-gpu-tools-1.21/tests/perf.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/perf.c 2018-03-09 14:22:59.000000000 +0000 @@ -210,25 +210,6 @@ return gen8_oa_formats[format]; } -static bool -timestamp_delta_within(uint32_t delta, - uint32_t expected_delta, - uint32_t margin) -{ - return delta >= (expected_delta - margin) && - delta <= (expected_delta + margin); -} - -static bool -double_value_within(double value, - double expected, - double percent_margin) -{ - return value >= (expected - expected * percent_margin / 100.0) && - value <= (expected + expected * percent_margin / 100.0); - -} - static void __perf_close(int fd) { @@ -473,12 +454,11 @@ return false; /* TODO */ } else if (IS_GEN8(devid)) { return report[0] & (1ul << 25); - } else if (IS_GEN9(devid)) { + } else if (AT_LEAST_GEN(devid, 9)) { return report[0] & (1ul << 16); } - /* Need to update this function for newer Gen. */ - igt_assert(!"reached"); + igt_assert(!"Please update this function for newer Gen"); } static uint32_t @@ -489,17 +469,6 @@ return report[2]; } -static double -oa_reports_tick_per_period(uint32_t *report0, uint32_t *report1) -{ - if (intel_gen(devid) < 8) - return 0.0; - - /* Measure the number GPU tick delta to timestamp delta. */ - return (double) (report1[3] - report0[3]) / - (double) (report1[1] - report0[1]); -} - static void scratch_buf_memset(drm_intel_bo *bo, int width, int height, uint32_t color) { @@ -558,51 +527,6 @@ } } -static uint32_t -i915_get_one_gpu_timestamp(void) -{ - const bool r64b = intel_gen(devid) >= 8; - struct drm_i915_gem_execbuffer2 execbuf; - struct drm_i915_gem_exec_object2 obj[2]; - struct drm_i915_gem_relocation_entry reloc; - uint32_t batch[16]; - uint32_t timestamp; - int i; - - memset(obj, 0, sizeof(obj)); - obj[0].handle = gem_create(drm_fd, 4096); - obj[1].handle = gem_create(drm_fd, 4096); - obj[1].relocs_ptr = to_user_pointer(&reloc); - obj[1].relocation_count = 1; - - i = 0; - batch[i++] = 0x24 << 23 | (1 + r64b); /* SRM */ - batch[i++] = 0x2358; /* RCS0 timestamp */ - reloc.target_handle = obj[0].handle; - reloc.presumed_offset = obj[0].offset; - reloc.offset = i * sizeof(batch[0]); - reloc.delta = 0; - reloc.read_domains = I915_GEM_DOMAIN_RENDER; - reloc.write_domain = I915_GEM_DOMAIN_RENDER; - batch[i++] = reloc.delta; - if (r64b) - batch[i++] = 0; - batch[i] = MI_BATCH_BUFFER_END; - gem_write(drm_fd, obj[1].handle, 0, batch, sizeof(batch)); - - memset(&execbuf, 0, sizeof(execbuf)); - execbuf.buffers_ptr = to_user_pointer(obj); - execbuf.buffer_count = 2; - execbuf.batch_len = 4096; - gem_execbuf(drm_fd, &execbuf); - gem_close(drm_fd, obj[1].handle); - - gem_read(drm_fd, obj[0].handle, 0, ×tamp, sizeof(timestamp)); - gem_close(drm_fd, obj[0].handle); - - return timestamp; -} - static void hsw_sanity_check_render_basic_reports(uint32_t *oa_report0, uint32_t *oa_report1, enum drm_i915_oa_format fmt) @@ -1758,302 +1682,105 @@ * test can fail due to buffer overflows if it wasn't possible to * keep up, so we don't start from an exponent of zero... */ - for (int exponent = 5; exponent < 18; exponent++) { - uint64_t expected_timestamp_delta; - uint32_t time_delta; - int n_tested = 0; - int n_time_delta_matches = 0; - - /* The exponent is effectively selecting a bit in the timestamp - * to trigger reports on and so in practice we expect the raw - * timestamp deltas for periodic reports to exactly match the - * value of next bit. - */ - expected_timestamp_delta = 2UL << exponent; + for (int exponent = 5; exponent < 20; exponent++) { + uint64_t properties[] = { + /* Include OA reports in samples */ + DRM_I915_PERF_PROP_SAMPLE_OA, true, - for (int j = 0; n_tested < 10 && j < 100; j++) { - uint64_t properties[] = { - /* Include OA reports in samples */ - DRM_I915_PERF_PROP_SAMPLE_OA, true, - - /* OA unit configuration */ - DRM_I915_PERF_PROP_OA_METRICS_SET, test_metric_set_id, - DRM_I915_PERF_PROP_OA_FORMAT, test_oa_format, - DRM_I915_PERF_PROP_OA_EXPONENT, exponent, - }; - struct drm_i915_perf_open_param param = { - .flags = I915_PERF_FLAG_FD_CLOEXEC, - .num_properties = ARRAY_SIZE(properties) / 2, - .properties_ptr = to_user_pointer(properties), - }; - int ret; - uint64_t average_timestamp_delta; - uint32_t n_reports = 0; - uint32_t n_idle_reports = 0; - uint32_t n_reads = 0; - uint64_t first_timestamp = 0; - bool check_first_timestamp = true; - struct drm_i915_perf_record_header *header; - uint64_t delta_delta; - struct { - uint32_t report[64]; - } reports[30]; - struct { - uint8_t *buf; - size_t len; - } reads[1000]; - double error; - double tick_per_period; - - igt_debug("ITER %d: testing OA exponent %d," - " expected ts delta = %"PRIu64" (%"PRIu64"ns/%.2fus/%.2fms)\n", - j, exponent, - expected_timestamp_delta, - oa_exponent_to_ns(exponent), - oa_exponent_to_ns(exponent) / 1000.0, - oa_exponent_to_ns(exponent) / (1000.0 * 1000.0)); - - stream_fd = __perf_open(drm_fd, ¶m, true /* prevent_pm */); - - /* Right after opening the OA stream, read a - * first timestamp as way to filter previously - * scheduled work that would have configured - * the OA unit at a different period. */ - first_timestamp = i915_get_one_gpu_timestamp(); - - while (n_reads < ARRAY_SIZE(reads) && - n_reports < ARRAY_SIZE(reports)) { - const size_t buf_size = 1024 * 1024; - uint8_t *buf = reads[n_reads++].buf = calloc(1, buf_size); - - while ((ret = read(stream_fd, buf, buf_size)) < 0 && - errno == EINTR) - ; - - /* We should never have no data. */ - igt_assert(ret > 0); - reads[n_reads - 1].len = ret; - - igt_debug(" > read %i bytes\n", ret); - - for (int offset = 0; - offset < ret && n_reports < ARRAY_SIZE(reports); - offset += header->size) { - uint32_t *report; - double previous_tick_per_period; - - header = (void *)(buf + offset); - - if (header->type == DRM_I915_PERF_RECORD_OA_BUFFER_LOST) { - igt_assert(!"reached"); - break; - } + /* OA unit configuration */ + DRM_I915_PERF_PROP_OA_METRICS_SET, test_metric_set_id, + DRM_I915_PERF_PROP_OA_FORMAT, test_oa_format, + DRM_I915_PERF_PROP_OA_EXPONENT, exponent, + }; + struct drm_i915_perf_open_param param = { + .flags = I915_PERF_FLAG_FD_CLOEXEC, + .num_properties = ARRAY_SIZE(properties) / 2, + .properties_ptr = to_user_pointer(properties), + }; + uint64_t expected_timestamp_delta = 2ULL << exponent; + size_t format_size = get_oa_format(test_oa_format).size; + size_t sample_size = (sizeof(struct drm_i915_perf_record_header) + + format_size); + int max_reports = MAX_OA_BUF_SIZE / format_size; + int buf_size = sample_size * max_reports * 1.5; + uint8_t *buf = calloc(1, buf_size); + int ret, n_timer_reports = 0; + uint32_t matches = 0; + struct { + uint32_t report[64]; + } timer_reports[30]; + + igt_debug("testing OA exponent %d," + " expected ts delta = %"PRIu64" (%"PRIu64"ns/%.2fus/%.2fms)\n", + exponent, expected_timestamp_delta, + oa_exponent_to_ns(exponent), + oa_exponent_to_ns(exponent) / 1000.0, + oa_exponent_to_ns(exponent) / (1000.0 * 1000.0)); - if (header->type == DRM_I915_PERF_RECORD_OA_REPORT_LOST) { - n_reports = 0; - n_idle_reports = 0; - for (int r = 0; r < n_reads; r++) - free(reads[r].buf); - n_reads = 0; - break; - } + stream_fd = __perf_open(drm_fd, ¶m, true /* prevent_pm */); - if (header->type != DRM_I915_PERF_RECORD_SAMPLE) - continue; + while (n_timer_reports < ARRAY_SIZE(timer_reports)) { + struct drm_i915_perf_record_header *header; - report = (void *)(header + 1); + while ((ret = read(stream_fd, buf, buf_size)) < 0 && + errno == EINTR) + ; - /* Skip anything before the first - * timestamp, it might not be at the - * right periodic exponent. */ - if (check_first_timestamp && - report[1] < first_timestamp) { - igt_debug(" > Dropping ts=%u (prior %"PRIu64")\n", - report[1], first_timestamp); - continue; - } + /* igt_debug(" > read %i bytes\n", ret); */ - /* Once we've passed the first - * timestamp, no need to check. */ - check_first_timestamp = false; - - if (!oa_report_ctx_is_valid(report)) - n_idle_reports++; - - /* We only measure timestamps between - * periodic reports. */ - if (!oa_report_is_periodic(exponent, report)) - continue; - - igt_debug(" > write %i timestamp=%u\n", n_reports, report[1]); - memcpy(reports[n_reports].report, report, - sizeof(reports[n_reports].report)); - n_reports++; - - previous_tick_per_period = tick_per_period; - - if (n_reports > 1) { - tick_per_period = - oa_reports_tick_per_period(reports[n_reports - 2].report, - reports[n_reports - 1].report); - - /* Dismiss the series of report - * if we notice clock frequency - * changes. */ - if (!double_value_within(tick_per_period, - previous_tick_per_period, 5)) { - igt_debug("Noticed clock frequency change at ts=%u (%f / %f), " - "dropping reports and trying again\n", - report[1], previous_tick_per_period, tick_per_period); - n_reports = 0; - n_idle_reports = 0; - for (int r = 0; r < n_reads; r++) - free(reads[r].buf); - n_reads = 0; - break; - } - } - } - } + /* We should never have no data. */ + igt_assert(ret > 0); - __perf_close(stream_fd); - igt_debug("closed stream\n"); + for (int offset = 0; + offset < ret && n_timer_reports < ARRAY_SIZE(timer_reports); + offset += header->size) { + uint32_t *report; - igt_assert_eq(n_reports, ARRAY_SIZE(reports)); + header = (void *)(buf + offset); - average_timestamp_delta = 0; - for (int i = 0; i < (n_reports - 1); i++) { - /* XXX: calculating with u32 arithmetic to account for overflow */ - uint32_t u32_delta = reports[i + 1].report[1] - reports[i].report[1]; + if (header->type == DRM_I915_PERF_RECORD_OA_BUFFER_LOST) { + igt_assert(!"reached"); + break; + } - average_timestamp_delta += u32_delta; - } - average_timestamp_delta /= (n_reports - 1); + if (header->type == DRM_I915_PERF_RECORD_OA_REPORT_LOST) + igt_debug("report loss\n"); - if (average_timestamp_delta > expected_timestamp_delta) - delta_delta = average_timestamp_delta - expected_timestamp_delta; - else - delta_delta = expected_timestamp_delta - average_timestamp_delta; - error = (delta_delta / (double)expected_timestamp_delta) * 100.0; - - time_delta = timebase_scale(average_timestamp_delta); - - igt_debug(" > Avg. time delta = %"PRIu32"(ns)," - " n idle reports = %u, n reads = %u, error=%f\n", - time_delta, n_idle_reports, n_reads, error); - if (error > 5) { - uint32_t *rpt = NULL, *last = NULL, *last_periodic = NULL; - - igt_debug(" > More than 5%% error: avg_ts_delta = %"PRIu64", delta_delta = %"PRIu64", " - "expected_delta = %"PRIu64", first_timestamp = %"PRIu64"\n", - average_timestamp_delta, delta_delta, expected_timestamp_delta, first_timestamp); - for (int i = 0; i < (n_reports - 1); i++) { - /* XXX: calculating with u32 arithmetic to account for overflow */ - uint32_t u32_delta = - reports[i + 1].report[1] - reports[i].report[1]; + if (header->type != DRM_I915_PERF_RECORD_SAMPLE) + continue; - if (u32_delta > expected_timestamp_delta) - delta_delta = u32_delta - expected_timestamp_delta; - else - delta_delta = expected_timestamp_delta - u32_delta; - error = (delta_delta / (double)expected_timestamp_delta) * 100.0; + report = (void *)(header + 1); - igt_debug(" > ts=%u-%u timestamp delta from %2d to %2d = %-8u (error = %u%%, ctx_id = %x)\n", - reports[i + 1].report[1], reports[i].report[1], - i, i + 1, u32_delta, (unsigned)error, - oa_report_get_ctx_id(reports[i + 1].report)); - } - for (int r = 0; r < n_reads; r++) { - igt_debug(" > read\n"); - for (int offset = 0; - offset < reads[r].len; - offset += header->size) { - /* Just a random counter, - * helpful to notice - * inconsistency in debug. - */ - int counter_print = 13; - uint64_t a0 = 0, aN = 0; - double local_period = 0; - - header = (void *) &reads[r].buf[offset]; - - if (header->type != DRM_I915_PERF_RECORD_SAMPLE) { - igt_debug(" > loss\n"); - continue; - } - - rpt = (void *)(header + 1); - - if (last) { - a0 = gen8_read_40bit_a_counter(rpt, test_oa_format, 0) - - gen8_read_40bit_a_counter(last, test_oa_format, 0); - aN = gen8_read_40bit_a_counter(rpt, test_oa_format, counter_print) - - gen8_read_40bit_a_counter(last, test_oa_format, counter_print); - } - - if (last_periodic && - intel_gen(devid) >= 8 && - oa_report_is_periodic(exponent, rpt)) { - local_period = - ((uint64_t) rpt[3] - last_periodic[3]) / - ((uint64_t) rpt[1] - last_periodic[1]); - } - - igt_debug(" > report ts=%u" - " ts_delta_last=%8u ts_delta_last_periodic=%8u is_timer=%i ctx_id=%8x gpu_ticks=%u period=%.2f A0=%"PRIu64" A%i=%"PRIu64"\n", - rpt[1], - (last != NULL) ? (rpt[1] - last[1]) : 0, - (last_periodic != NULL) ? (rpt[1] - last_periodic[1]) : 0, - oa_report_is_periodic(exponent, rpt), - oa_report_get_ctx_id(rpt), - (last != NULL) ? (rpt[3] - last[3]) : 0, - local_period, - a0, counter_print, aN); - - last = rpt; - if (oa_report_is_periodic(exponent, rpt)) - last_periodic = rpt; - } - } + if (!oa_report_is_periodic(exponent, report)) + continue; - igt_assert(!"reached"); + memcpy(timer_reports[n_timer_reports].report, report, + sizeof(timer_reports[n_timer_reports].report)); + n_timer_reports++; } + } - if (timestamp_delta_within(average_timestamp_delta, - expected_timestamp_delta, - expected_timestamp_delta * 0.05)) { - igt_debug(" > timestamp delta matching %"PRIu64"ns ~= expected %"PRIu64"! :)\n", - timebase_scale(average_timestamp_delta), - timebase_scale(expected_timestamp_delta)); - n_time_delta_matches++; - } else { - igt_debug(" > timestamp delta mismatch: %"PRIu64"ns != expected %"PRIu64"ns\n", - timebase_scale(average_timestamp_delta), - timebase_scale(expected_timestamp_delta)); - igt_assert(average_timestamp_delta < - (expected_timestamp_delta * 2)); - } + __perf_close(stream_fd); - n_tested++; + igt_debug("report%04i ts=%08x hw_id=0x%08x\n", 0, + timer_reports[0].report[1], + oa_report_get_ctx_id(timer_reports[0].report)); + for (int i = 1; i < n_timer_reports; i++) { + uint32_t delta = + timer_reports[i].report[1] - timer_reports[i - 1].report[1]; + + igt_debug("report%04i ts=%08x hw_id=0x%08x delta=%u %s\n", i, + timer_reports[i].report[1], + oa_report_get_ctx_id(timer_reports[i].report), + delta, delta == expected_timestamp_delta ? "" : "******"); - for (int r = 0; r < n_reads; r++) - free(reads[r].buf); + matches += expected_timestamp_delta <= delta; } - if (n_tested < 10) - igt_debug("Too many test iterations had to be skipped\n"); - igt_assert_eq(n_tested, 10); - - igt_debug("Number of iterations with expected timestamp delta = %d\n", - n_time_delta_matches); - - /* The HW doesn't give us any strict guarantee that the - * timestamps are exactly aligned with the exponent mask but - * in practice it seems very rare for that not to be the case - * so it a useful sanity check to assert quite strictly... - */ - igt_assert(n_time_delta_matches >= 9); + igt_debug("matches=%u/%u\n", matches, n_timer_reports - 1); + + /* Allow for a couple of errors. */ + igt_assert_lte(n_timer_reports - 3, matches); } load_helper_stop(); @@ -2646,7 +2373,6 @@ uint32_t n_periodic_reports; uint32_t first_timestamp = 0, last_timestamp = 0; uint32_t last_periodic_report[64]; - double tick_per_period; do_ioctl(stream_fd, I915_PERF_IOCTL_ENABLE, 0); @@ -2700,7 +2426,6 @@ for (int offset = 0; offset < len; offset += header->size) { uint32_t *report; - double previous_tick_per_period; header = (void *) (buf + offset); report = (void *) (header + 1); @@ -2711,41 +2436,22 @@ break; case DRM_I915_PERF_RECORD_SAMPLE: igt_debug(" > report ts=%u" - " ts_delta_last_periodic=%8u is_timer=%i ctx_id=%8x gpu_ticks=%u nb_periodic=%u\n", + " ts_delta_last_periodic=%8u is_timer=%i ctx_id=%8x nb_periodic=%u\n", report[1], n_periodic_reports > 0 ? report[1] - last_periodic_report[1] : 0, oa_report_is_periodic(oa_exponent, report), oa_report_get_ctx_id(report), - n_periodic_reports > 0 ? report[3] - last_periodic_report[3] : 0, n_periodic_reports); if (first_timestamp == 0) first_timestamp = report[1]; last_timestamp = report[1]; - previous_tick_per_period = tick_per_period; - - if (n_periodic_reports > 1 && - oa_report_is_periodic(oa_exponent, report)) { - tick_per_period = - oa_reports_tick_per_period(last_periodic_report, - report); - - if (!double_value_within(previous_tick_per_period, - tick_per_period, 5)) - igt_debug("clock change!\n"); - + if (oa_report_is_periodic(oa_exponent, report)) { memcpy(last_periodic_report, report, sizeof(last_periodic_report)); + n_periodic_reports++; } - - /* We want to measure only the periodic - * reports, ctx-switch might inflate the - * content of the buffer and skew or - * measurement. - */ - n_periodic_reports += - oa_report_is_periodic(oa_exponent, report); break; case DRM_I915_PERF_RECORD_OA_BUFFER_LOST: igt_assert(!"unexpected overflow"); @@ -2814,7 +2520,6 @@ struct drm_i915_perf_record_header *header; uint32_t first_timestamp = 0, last_timestamp = 0; uint32_t last_periodic_report[64]; - double tick_per_period; /* Giving enough time for an overflow might help catch whether * the OA unit has been enabled even if the driver might at @@ -2851,7 +2556,6 @@ for (int offset = 0; offset < len; offset += header->size) { uint32_t *report; - double previous_tick_per_period; header = (void *) (buf + offset); report = (void *) (header + 1); @@ -2864,38 +2568,27 @@ first_timestamp = report[1]; last_timestamp = report[1]; - previous_tick_per_period = tick_per_period; - - if (n_periodic_reports > 0 && - oa_report_is_periodic(oa_exponent, report)) { - tick_per_period = - oa_reports_tick_per_period(last_periodic_report, - report); - - if (!double_value_within(tick_per_period, - previous_tick_per_period, 5)) - igt_debug("clock change!\n"); - - igt_debug(" > report ts=%u" - " ts_delta_last_periodic=%8u is_timer=%i ctx_id=%8x gpu_ticks=%u nb_periodic=%u\n", - report[1], - report[1] - last_periodic_report[1], - oa_report_is_periodic(oa_exponent, report), - oa_report_get_ctx_id(report), - report[3] - last_periodic_report[3], - n_periodic_reports); + igt_debug(" > report ts=%8x" + " ts_delta_last_periodic=%s%8u" + " is_timer=%i ctx_id=0x%8x\n", + report[1], + oa_report_is_periodic(oa_exponent, report) ? " " : "*", + n_periodic_reports > 0 ? (report[1] - last_periodic_report[1]) : 0, + oa_report_is_periodic(oa_exponent, report), + oa_report_get_ctx_id(report)); + if (oa_report_is_periodic(oa_exponent, report)) { memcpy(last_periodic_report, report, sizeof(last_periodic_report)); - } - /* We want to measure only the periodic - * reports, ctx-switch might inflate the - * content of the buffer and skew or - * measurement. - */ - n_periodic_reports += - oa_report_is_periodic(oa_exponent, report); + /* We want to measure only the + * periodic reports, ctx-switch + * might inflate the content of + * the buffer and skew or + * measurement. + */ + n_periodic_reports++; + } break; case DRM_I915_PERF_RECORD_OA_BUFFER_LOST: igt_assert(!"unexpected overflow"); diff -Nru intel-gpu-tools-1.21/tests/perf_pmu.c intel-gpu-tools-1.22/tests/perf_pmu.c --- intel-gpu-tools-1.21/tests/perf_pmu.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/perf_pmu.c 2018-03-09 14:22:59.000000000 +0000 @@ -35,11 +35,13 @@ #include #include #include +#include #include "igt.h" #include "igt_core.h" #include "igt_perf.h" #include "igt_sysfs.h" +#include "igt_pm.h" #include "sw_sync.h" IGT_TEST_DESCRIPTION("Test the i915 pmu perf interface"); @@ -72,23 +74,47 @@ static void init(int gem_fd, const struct intel_execution_engine2 *e, uint8_t sample) { - int fd; - - fd = open_pmu(__I915_PMU_ENGINE(e->class, e->instance, sample)); + int fd, err = 0; + bool exists; - close(fd); + errno = 0; + fd = perf_i915_open(__I915_PMU_ENGINE(e->class, e->instance, sample)); + if (fd < 0) + err = errno; + + exists = gem_has_engine(gem_fd, e->class, e->instance); + if (intel_gen(intel_get_drm_devid(gem_fd)) < 6 && + sample == I915_SAMPLE_SEMA) + exists = false; + + if (exists) { + igt_assert_eq(err, 0); + igt_assert_fd(fd); + close(fd); + } else { + igt_assert_lt(fd, 0); + igt_assert_eq(err, ENODEV); + } } -static uint64_t pmu_read_single(int fd) +static uint64_t __pmu_read_single(int fd, uint64_t *ts) { uint64_t data[2]; igt_assert_eq(read(fd, data, sizeof(data)), sizeof(data)); + if (ts) + *ts = data[1]; + return data[0]; } -static void pmu_read_multi(int fd, unsigned int num, uint64_t *val) +static uint64_t pmu_read_single(int fd) +{ + return __pmu_read_single(fd, NULL); +} + +static uint64_t pmu_read_multi(int fd, unsigned int num, uint64_t *val) { uint64_t buf[2 + num]; unsigned int i; @@ -97,13 +123,20 @@ for (i = 0; i < num; i++) val[i] = buf[2 + i]; + + return buf[1]; } +#define __assert_within_epsilon(x, ref, tol_up, tol_down) \ + igt_assert_f((double)(x) <= (1.0 + (tol_up)) * (double)(ref) && \ + (double)(x) >= (1.0 - (tol_down)) * (double)(ref), \ + "'%s' != '%s' (%f not within +%f%%/-%f%% tolerance of %f)\n",\ + #x, #ref, (double)(x), \ + (tol_up) * 100.0, (tol_down) * 100.0, \ + (double)(ref)) + #define assert_within_epsilon(x, ref, tolerance) \ - igt_assert_f((double)(x) <= (1.0 + (tolerance)) * (double)(ref) && \ - (double)(x) >= (1.0 - (tolerance)) * (double)(ref), \ - "'%s' != '%s' (%f not within %f%% tolerance of %f)\n",\ - #x, #ref, (double)(x), (tolerance) * 100.0, (double)(ref)) + __assert_within_epsilon(x, ref, tolerance, tolerance) /* * Helper for cases where we assert on time spent sleeping (directly or @@ -130,8 +163,29 @@ return gem_class_instance_to_eb_flags(gem_fd, e->class, e->instance); } +#define TEST_BUSY (1) +#define FLAG_SYNC (2) +#define TEST_TRAILING_IDLE (4) +#define TEST_RUNTIME_PM (8) +#define FLAG_LONG (16) +#define FLAG_HANG (32) + +static void end_spin(int fd, igt_spin_t *spin, unsigned int flags) +{ + if (!spin) + return; + + igt_spin_batch_end(spin); + + if (flags & FLAG_SYNC) + gem_sync(fd, spin->handle); + + if (flags & TEST_TRAILING_IDLE) + usleep(batch_duration_ns / 5000); +} + static void -single(int gem_fd, const struct intel_execution_engine2 *e, bool busy) +single(int gem_fd, const struct intel_execution_engine2 *e, unsigned int flags) { unsigned long slept; igt_spin_t *spin; @@ -140,20 +194,46 @@ fd = open_pmu(I915_PMU_ENGINE_BUSY(e->class, e->instance)); - if (busy) + if (flags & TEST_BUSY) spin = igt_spin_batch_new(gem_fd, 0, e2ring(gem_fd, e), 0); else spin = NULL; + val = pmu_read_single(fd); slept = measured_usleep(batch_duration_ns / 1000); - igt_spin_batch_end(spin); + if (flags & TEST_TRAILING_IDLE) + end_spin(gem_fd, spin, flags); + val = pmu_read_single(fd) - val; - val = pmu_read_single(fd); + if (flags & FLAG_HANG) + igt_force_gpu_reset(gem_fd); + else + end_spin(gem_fd, spin, FLAG_SYNC); + + assert_within_epsilon(val, flags & TEST_BUSY ? slept : 0.f, tolerance); + + /* Check for idle after hang. */ + if (flags & FLAG_HANG) { + /* Sleep for a bit for reset unwind to settle. */ + usleep(500e3); + /* + * Ensure batch was executing before reset, meaning it must be + * idle by now. Unless it did not even manage to start before we + * triggered the reset, in which case the idleness check below + * might fail. The latter is very unlikely since there are two + * sleeps during which it had an opportunity to start. + */ + igt_assert(!gem_bo_busy(gem_fd, spin->handle)); + val = pmu_read_single(fd); + slept = measured_usleep(batch_duration_ns / 1000); + val = pmu_read_single(fd) - val; + + assert_within_epsilon(val, 0, tolerance); + } igt_spin_batch_free(gem_fd, spin); close(fd); - assert_within_epsilon(val, busy ? slept : 0.f, tolerance); gem_quiescent_gpu(gem_fd); } @@ -161,8 +241,8 @@ busy_start(int gem_fd, const struct intel_execution_engine2 *e) { unsigned long slept; + uint64_t val, ts[2]; igt_spin_t *spin; - uint64_t val; int fd; /* @@ -181,13 +261,15 @@ fd = open_pmu(I915_PMU_ENGINE_BUSY(e->class, e->instance)); + val = __pmu_read_single(fd, &ts[0]); slept = measured_usleep(batch_duration_ns / 1000); - val = pmu_read_single(fd); + val = __pmu_read_single(fd, &ts[1]) - val; + igt_debug("slept=%lu perf=%"PRIu64"\n", slept, ts[1] - ts[0]); igt_spin_batch_free(gem_fd, spin); close(fd); - assert_within_epsilon(val, slept, tolerance); + assert_within_epsilon(val, ts[1] - ts[0], tolerance); gem_quiescent_gpu(gem_fd); } @@ -200,8 +282,8 @@ busy_double_start(int gem_fd, const struct intel_execution_engine2 *e) { unsigned long slept; + uint64_t val, val2, ts[2]; igt_spin_t *spin[2]; - uint64_t val, val2; uint32_t ctx; int fd; @@ -228,8 +310,10 @@ */ fd = open_pmu(I915_PMU_ENGINE_BUSY(e->class, e->instance)); + val = __pmu_read_single(fd, &ts[0]); slept = measured_usleep(batch_duration_ns / 1000); - val = pmu_read_single(fd); + val = __pmu_read_single(fd, &ts[1]) - val; + igt_debug("slept=%lu perf=%"PRIu64"\n", slept, ts[1] - ts[0]); igt_spin_batch_end(spin[0]); igt_spin_batch_end(spin[1]); @@ -241,7 +325,7 @@ usleep(batch_duration_ns / 1000); val2 = pmu_read_single(fd) - val2; - igt_info("busy=%lu idle=%lu\n", val, val2); + igt_info("busy=%"PRIu64" idle=%"PRIu64"\n", val, val2); igt_spin_batch_free(gem_fd, spin[0]); igt_spin_batch_free(gem_fd, spin[1]); @@ -250,13 +334,13 @@ gem_context_destroy(gem_fd, ctx); - assert_within_epsilon(val, slept, tolerance); + assert_within_epsilon(val, ts[1] - ts[0], tolerance); igt_assert_eq(val2, 0); gem_quiescent_gpu(gem_fd); } -static void log_busy(int fd, unsigned int num_engines, uint64_t *val) +static void log_busy(unsigned int num_engines, uint64_t *val) { char buf[1024]; int rem = sizeof(buf); @@ -277,14 +361,15 @@ static void busy_check_all(int gem_fd, const struct intel_execution_engine2 *e, - const unsigned int num_engines) + const unsigned int num_engines, unsigned int flags) { const struct intel_execution_engine2 *e_; + uint64_t tval[2][num_engines]; + unsigned int busy_idx = 0, i; uint64_t val[num_engines]; int fd[num_engines]; unsigned long slept; igt_spin_t *spin; - unsigned int busy_idx, i; i = 0; fd[0] = -1; @@ -302,15 +387,21 @@ igt_assert_eq(i, num_engines); spin = igt_spin_batch_new(gem_fd, 0, e2ring(gem_fd, e), 0); + pmu_read_multi(fd[0], num_engines, tval[0]); slept = measured_usleep(batch_duration_ns / 1000); - igt_spin_batch_end(spin); - - pmu_read_multi(fd[0], num_engines, val); - log_busy(fd[0], num_engines, val); + if (flags & TEST_TRAILING_IDLE) + end_spin(gem_fd, spin, flags); + pmu_read_multi(fd[0], num_engines, tval[1]); + end_spin(gem_fd, spin, FLAG_SYNC); igt_spin_batch_free(gem_fd, spin); close(fd[0]); + for (i = 0; i < num_engines; i++) + val[i] = tval[1][i] - tval[0][i]; + + log_busy(num_engines, val); + assert_within_epsilon(val[busy_idx], slept, tolerance); for (i = 0; i < num_engines; i++) { if (i == busy_idx) @@ -321,18 +412,32 @@ } static void +__submit_spin_batch(int gem_fd, + struct drm_i915_gem_exec_object2 *obj, + const struct intel_execution_engine2 *e) +{ + struct drm_i915_gem_execbuffer2 eb = { + .buffer_count = 1, + .buffers_ptr = to_user_pointer(obj), + .flags = e2ring(gem_fd, e), + }; + + gem_execbuf(gem_fd, &eb); +} + +static void most_busy_check_all(int gem_fd, const struct intel_execution_engine2 *e, - const unsigned int num_engines) + const unsigned int num_engines, unsigned int flags) { + struct drm_i915_gem_exec_object2 obj = {}; const struct intel_execution_engine2 *e_; + uint64_t tval[2][num_engines]; uint64_t val[num_engines]; int fd[num_engines]; unsigned long slept; igt_spin_t *spin = NULL; unsigned int idle_idx, i; - gem_require_engine(gem_fd, e->class, e->instance); - i = 0; for_each_engine_class_instance(fd, e_) { if (!gem_has_engine(gem_fd, e_->class, e_->instance)) @@ -341,18 +446,11 @@ if (e == e_) { idle_idx = i; } else if (spin) { - struct drm_i915_gem_exec_object2 obj = { - .handle = spin->handle - }; - struct drm_i915_gem_execbuffer2 eb = { - .buffer_count = 1, - .buffers_ptr = to_user_pointer(&obj), - .flags = e2ring(gem_fd, e_), - }; - gem_execbuf(gem_fd, &eb); + __submit_spin_batch(gem_fd, &obj, e_); } else { spin = igt_spin_batch_new(gem_fd, 0, e2ring(gem_fd, e_), 0); + obj.handle = spin->handle; } val[i++] = I915_PMU_ENGINE_BUSY(e_->class, e_->instance); @@ -363,15 +461,21 @@ for (i = 0; i < num_engines; i++) fd[i] = open_group(val[i], fd[0]); + pmu_read_multi(fd[0], num_engines, tval[0]); slept = measured_usleep(batch_duration_ns / 1000); - igt_spin_batch_end(spin); - - pmu_read_multi(fd[0], num_engines, val); - log_busy(fd[0], num_engines, val); + if (flags & TEST_TRAILING_IDLE) + end_spin(gem_fd, spin, flags); + pmu_read_multi(fd[0], num_engines, tval[1]); + end_spin(gem_fd, spin, FLAG_SYNC); igt_spin_batch_free(gem_fd, spin); close(fd[0]); + for (i = 0; i < num_engines; i++) + val[i] = tval[1][i] - tval[0][i]; + + log_busy(num_engines, val); + for (i = 0; i < num_engines; i++) { if (i == idle_idx) assert_within_epsilon(val[i], 0.0f, tolerance); @@ -382,9 +486,12 @@ } static void -all_busy_check_all(int gem_fd, const unsigned int num_engines) +all_busy_check_all(int gem_fd, const unsigned int num_engines, + unsigned int flags) { + struct drm_i915_gem_exec_object2 obj = {}; const struct intel_execution_engine2 *e; + uint64_t tval[2][num_engines]; uint64_t val[num_engines]; int fd[num_engines]; unsigned long slept; @@ -397,18 +504,11 @@ continue; if (spin) { - struct drm_i915_gem_exec_object2 obj = { - .handle = spin->handle - }; - struct drm_i915_gem_execbuffer2 eb = { - .buffer_count = 1, - .buffers_ptr = to_user_pointer(&obj), - .flags = e2ring(gem_fd, e), - }; - gem_execbuf(gem_fd, &eb); + __submit_spin_batch(gem_fd, &obj, e); } else { spin = igt_spin_batch_new(gem_fd, 0, e2ring(gem_fd, e), 0); + obj.handle = spin->handle; } val[i++] = I915_PMU_ENGINE_BUSY(e->class, e->instance); @@ -419,48 +519,58 @@ for (i = 0; i < num_engines; i++) fd[i] = open_group(val[i], fd[0]); + pmu_read_multi(fd[0], num_engines, tval[0]); slept = measured_usleep(batch_duration_ns / 1000); - igt_spin_batch_end(spin); - - pmu_read_multi(fd[0], num_engines, val); - log_busy(fd[0], num_engines, val); + if (flags & TEST_TRAILING_IDLE) + end_spin(gem_fd, spin, flags); + pmu_read_multi(fd[0], num_engines, tval[1]); + end_spin(gem_fd, spin, FLAG_SYNC); igt_spin_batch_free(gem_fd, spin); close(fd[0]); for (i = 0; i < num_engines; i++) + val[i] = tval[1][i] - tval[0][i]; + + log_busy(num_engines, val); + + for (i = 0; i < num_engines; i++) assert_within_epsilon(val[i], slept, tolerance); gem_quiescent_gpu(gem_fd); } static void -no_sema(int gem_fd, const struct intel_execution_engine2 *e, bool busy) +no_sema(int gem_fd, const struct intel_execution_engine2 *e, unsigned int flags) { igt_spin_t *spin; - uint64_t val[2]; + uint64_t val[2][2]; int fd; fd = open_group(I915_PMU_ENGINE_SEMA(e->class, e->instance), -1); open_group(I915_PMU_ENGINE_WAIT(e->class, e->instance), fd); - if (busy) { + if (flags & TEST_BUSY) spin = igt_spin_batch_new(gem_fd, 0, e2ring(gem_fd, e), 0); - igt_spin_batch_set_timeout(spin, batch_duration_ns); - } else { - usleep(batch_duration_ns / 1000); - } + else + spin = NULL; - if (busy) - gem_sync(gem_fd, spin->handle); + pmu_read_multi(fd, 2, val[0]); + measured_usleep(batch_duration_ns / 1000); + if (flags & TEST_TRAILING_IDLE) + end_spin(gem_fd, spin, flags); + pmu_read_multi(fd, 2, val[1]); - pmu_read_multi(fd, 2, val); + val[0][0] = val[1][0] - val[0][0]; + val[0][1] = val[1][1] - val[0][1]; - if (busy) + if (spin) { + end_spin(gem_fd, spin, FLAG_SYNC); igt_spin_batch_free(gem_fd, spin); + } close(fd); - assert_within_epsilon(val[0], 0.0f, tolerance); - assert_within_epsilon(val[1], 0.0f, tolerance); + assert_within_epsilon(val[0][0], 0.0f, tolerance); + assert_within_epsilon(val[0][1], 0.0f, tolerance); } #define MI_INSTR(opcode, flags) (((opcode) << 23) | (flags)) @@ -469,7 +579,8 @@ #define MI_SEMAPHORE_SAD_GTE_SDD (1<<12) static void -sema_wait(int gem_fd, const struct intel_execution_engine2 *e) +sema_wait(int gem_fd, const struct intel_execution_engine2 *e, + unsigned int flags) { struct drm_i915_gem_relocation_entry reloc[2] = {}; struct drm_i915_gem_exec_object2 obj[2] = {}; @@ -478,7 +589,7 @@ unsigned long slept; uint32_t *obj_ptr; uint32_t batch[16]; - uint64_t val[2]; + uint64_t val[2], ts[2]; int fd; igt_require(intel_gen(intel_get_drm_devid(gem_fd)) >= 8); @@ -536,17 +647,25 @@ fd = open_pmu(I915_PMU_ENGINE_SEMA(e->class, e->instance)); + val[0] = pmu_read_single(fd); + gem_execbuf(gem_fd, &eb); do { /* wait for the batch to start executing */ usleep(5e3); } while (!obj_ptr[1]); - usleep(5e3); /* wait for the register sampling */ - val[0] = pmu_read_single(fd); + igt_assert_f(igt_wait(pmu_read_single(fd) != val[0], 10, 1), + "sampling failed to start withing 10ms"); + + val[0] = __pmu_read_single(fd, &ts[0]); slept = measured_usleep(batch_duration_ns / 1000); - val[1] = pmu_read_single(fd); - igt_debug("slept %.3fms, sampled %.3fms\n", - slept*1e-6, (val[1] - val[0])*1e-6); + if (flags & TEST_TRAILING_IDLE) + obj_ptr[0] = 1; + val[1] = __pmu_read_single(fd, &ts[1]); + igt_debug("slept %.3fms (perf %.3fms), sampled %.3fms\n", + slept * 1e-6, + (ts[1] - ts[0]) * 1e-6, + (val[1] - val[0]) * 1e-6); obj_ptr[0] = 1; gem_sync(gem_fd, bb_handle); @@ -749,11 +868,13 @@ multi_client(int gem_fd, const struct intel_execution_engine2 *e) { uint64_t config = I915_PMU_ENGINE_BUSY(e->class, e->instance); - unsigned int slept; + unsigned long slept[2]; + uint64_t val[2], ts[2], perf_slept[2]; igt_spin_t *spin; - uint64_t val[2]; int fd[2]; + gem_quiescent_gpu(gem_fd); + fd[0] = open_pmu(config); /* @@ -764,21 +885,26 @@ fd[1] = open_pmu(config); spin = igt_spin_batch_new(gem_fd, 0, e2ring(gem_fd, e), 0); - igt_spin_batch_set_timeout(spin, 2 * batch_duration_ns); - slept = measured_usleep(batch_duration_ns / 1000); - val[1] = pmu_read_single(fd[1]); + val[0] = val[1] = __pmu_read_single(fd[0], &ts[0]); + slept[1] = measured_usleep(batch_duration_ns / 1000); + val[1] = __pmu_read_single(fd[1], &ts[1]) - val[1]; + perf_slept[1] = ts[1] - ts[0]; + igt_debug("slept=%lu perf=%"PRIu64"\n", slept[1], perf_slept[1]); close(fd[1]); - gem_sync(gem_fd, spin->handle); - - val[0] = pmu_read_single(fd[0]); + slept[0] = measured_usleep(batch_duration_ns / 1000) + slept[1]; + val[0] = __pmu_read_single(fd[0], &ts[1]) - val[0]; + perf_slept[0] = ts[1] - ts[0]; + igt_debug("slept=%lu perf=%"PRIu64"\n", slept[0], perf_slept[0]); + igt_spin_batch_end(spin); + gem_sync(gem_fd, spin->handle); igt_spin_batch_free(gem_fd, spin); close(fd[0]); - assert_within_epsilon(val[0], 2 * batch_duration_ns, tolerance); - assert_within_epsilon(val[1], slept, tolerance); + assert_within_epsilon(val[0], perf_slept[0], tolerance); + assert_within_epsilon(val[1], perf_slept[1], tolerance); } /** @@ -858,19 +984,30 @@ static void cpu_hotplug(int gem_fd) { - struct timespec start = { }; - igt_spin_t *spin; - uint64_t val, ref; - int fd; + igt_spin_t *spin[2]; + uint64_t ts[2]; + uint64_t val; + int link[2]; + int fd, ret; + int cur = 0; + char buf; + igt_skip_on(IS_BROXTON(intel_get_drm_devid(gem_fd))); igt_require(cpu0_hotplug_support()); - fd = perf_i915_open(I915_PMU_ENGINE_BUSY(I915_ENGINE_CLASS_RENDER, 0)); - igt_assert(fd >= 0); + fd = open_pmu(I915_PMU_ENGINE_BUSY(I915_ENGINE_CLASS_RENDER, 0)); - spin = igt_spin_batch_new(gem_fd, 0, I915_EXEC_RENDER, 0); + /* + * Create two spinners so test can ensure shorter gaps in engine + * busyness as it is terminating one and re-starting the other. + */ + spin[0] = igt_spin_batch_new(gem_fd, 0, I915_EXEC_RENDER, 0); + spin[1] = __igt_spin_batch_new(gem_fd, 0, I915_EXEC_RENDER, 0); + + val = __pmu_read_single(fd, &ts[0]); - igt_nsec_elapsed(&start); + ret = pipe2(link, O_NONBLOCK); + igt_assert_eq(ret, 0); /* * Toggle online status of all the CPUs in a child process and ensure @@ -879,40 +1016,94 @@ igt_fork(child, 1) { int cpu = 0; + close(link[0]); + for (;;) { char name[128]; int cpufd; - sprintf(name, "/sys/devices/system/cpu/cpu%d/online", - cpu); + igt_assert_lt(snprintf(name, sizeof(name), + "/sys/devices/system/cpu/cpu%d/online", + cpu), sizeof(name)); cpufd = open(name, O_WRONLY); if (cpufd == -1) { igt_assert(cpu > 0); + /* + * Signal parent that we cycled through all + * CPUs and we are done. + */ + igt_assert_eq(write(link[1], "*", 1), 1); + break; + } + + /* Offline followed by online a CPU. */ + + ret = write(cpufd, "0", 2); + if (ret < 0) { + /* + * If we failed to offline a CPU we don't want + * to proceed. + */ + igt_warn("Failed to offline cpu%u! (%d)\n", + cpu, errno); + igt_assert_eq(write(link[1], "s", 1), 1); break; } - igt_assert_eq(write(cpufd, "0", 2), 2); usleep(1e6); - igt_assert_eq(write(cpufd, "1", 2), 2); + ret = write(cpufd, "1", 2); + if (ret < 0) { + /* + * Failed to bring a CPU back online is fatal + * for the sanity of a test run so stop further + * testing. + */ + igt_warn("Failed to online cpu%u! (%d)\n", + cpu, errno); + igt_fatal_error(); + } close(cpufd); cpu++; } } - igt_waitchildren(); + close(link[1]); - igt_spin_batch_end(spin); - gem_sync(gem_fd, spin->handle); + /* + * Very long batches can be declared as GPU hangs so emit shorter ones + * until the CPU core shuffler finishes one loop. + */ + for (;;) { + usleep(500e3); + end_spin(gem_fd, spin[cur], 0); + + /* Check if the child is signaling completion. */ + ret = read(link[0], &buf, 1); + if ( ret == 1 || (ret < 0 && errno != EAGAIN)) + break; - ref = igt_nsec_elapsed(&start); - val = pmu_read_single(fd); + igt_spin_batch_free(gem_fd, spin[cur]); + spin[cur] = __igt_spin_batch_new(gem_fd, 0, I915_EXEC_RENDER, + 0); + cur ^= 1; + } - igt_spin_batch_free(gem_fd, spin); + val = __pmu_read_single(fd, &ts[1]) - val; + + end_spin(gem_fd, spin[0], FLAG_SYNC); + end_spin(gem_fd, spin[1], FLAG_SYNC); + igt_spin_batch_free(gem_fd, spin[0]); + igt_spin_batch_free(gem_fd, spin[1]); + igt_waitchildren(); close(fd); + close(link[0]); - assert_within_epsilon(val, ref, tolerance); + /* Skip if child signals a problem with offlining a CPU. */ + igt_skip_on(buf == 's'); + + assert_within_epsilon(val, ts[1] - ts[0], tolerance); } static void @@ -1026,9 +1217,8 @@ test_frequency(int gem_fd) { uint32_t min_freq, max_freq, boost_freq; - uint64_t val[2], start[2]; + uint64_t val[2], start[2], slept; double min[2], max[2]; - unsigned long slept; igt_spin_t *spin; int fd, sysfs; @@ -1059,11 +1249,11 @@ gem_quiescent_gpu(gem_fd); /* Idle to be sure the change takes effect */ spin = igt_spin_batch_new(gem_fd, 0, I915_EXEC_RENDER, 0); - pmu_read_multi(fd, 2, start); - slept = measured_usleep(batch_duration_ns / 1000); + slept = pmu_read_multi(fd, 2, start); + measured_usleep(batch_duration_ns / 1000); + slept = pmu_read_multi(fd, 2, val) - slept; - pmu_read_multi(fd, 2, val); min[0] = 1e9*(val[0] - start[0]) / slept; min[1] = 1e9*(val[1] - start[1]) / slept; @@ -1085,11 +1275,11 @@ gem_quiescent_gpu(gem_fd); spin = igt_spin_batch_new(gem_fd, 0, I915_EXEC_RENDER, 0); - pmu_read_multi(fd, 2, start); - slept = measured_usleep(batch_duration_ns / 1000); + slept = pmu_read_multi(fd, 2, start); + measured_usleep(batch_duration_ns / 1000); + slept = pmu_read_multi(fd, 2, val) - slept; - pmu_read_multi(fd, 2, val); max[0] = 1e9*(val[0] - start[0]) / slept; max[1] = 1e9*(val[1] - start[1]) / slept; @@ -1109,8 +1299,13 @@ min[0], min[1]); igt_info("Max frequency: requested %.1f, actual %.1f\n", max[0], max[1]); + assert_within_epsilon(min[0], min_freq, tolerance); - assert_within_epsilon(max[0], max_freq, tolerance); + /* + * On thermally throttled devices we cannot be sure maximum frequency + * can be reached so use larger tolerance downards. + */ + __assert_within_epsilon(max[0], max_freq, tolerance, 0.15f); } static bool wait_for_rc6(int fd) @@ -1135,24 +1330,51 @@ } static void -test_rc6(int gem_fd) +test_rc6(int gem_fd, unsigned int flags) { int64_t duration_ns = 2e9; - uint64_t idle, busy, prev; - unsigned int slept; + uint64_t idle, busy, prev, ts[2]; + unsigned long slept; int fd, fw; + gem_quiescent_gpu(gem_fd); + fd = open_pmu(I915_PMU_RC6_RESIDENCY); - gem_quiescent_gpu(gem_fd); + if (flags & TEST_RUNTIME_PM) { + drmModeRes *res; + + res = drmModeGetResources(gem_fd); + igt_assert(res); + + /* force all connectors off */ + kmstest_set_vt_graphics_mode(); + kmstest_unset_all_crtcs(gem_fd, res); + drmModeFreeResources(res); + + igt_require(igt_setup_runtime_pm()); + igt_require(igt_wait_for_pm_status(IGT_RUNTIME_PM_STATUS_SUSPENDED)); + + /* + * Sleep for a bit to see if once woken up estimated RC6 hasn't + * drifted to far in advance of real RC6. + */ + if (flags & FLAG_LONG) { + pmu_read_single(fd); + sleep(5); + pmu_read_single(fd); + } + } + igt_require(wait_for_rc6(fd)); - /* Go idle and check full RC6. */ - prev = pmu_read_single(fd); + /* While idle check full RC6. */ + prev = __pmu_read_single(fd, &ts[0]); slept = measured_usleep(duration_ns / 1000); - idle = pmu_read_single(fd); + idle = __pmu_read_single(fd, &ts[1]); + igt_debug("slept=%lu perf=%"PRIu64"\n", slept, ts[1] - ts[0]); - assert_within_epsilon(idle - prev, slept, tolerance); + assert_within_epsilon(idle - prev, ts[1] - ts[0], tolerance); /* Wake up device and check no RC6. */ fw = igt_open_forcewake_handle(gem_fd); @@ -1169,6 +1391,209 @@ assert_within_epsilon(busy - prev, 0.0, tolerance); } +static void +test_enable_race(int gem_fd, const struct intel_execution_engine2 *e) +{ + uint64_t config = I915_PMU_ENGINE_BUSY(e->class, e->instance); + struct igt_helper_process engine_load = { }; + const uint32_t bbend = MI_BATCH_BUFFER_END; + struct drm_i915_gem_exec_object2 obj = { }; + struct drm_i915_gem_execbuffer2 eb = { }; + int fd; + + igt_require(gem_has_execlists(gem_fd)); + igt_require(gem_has_engine(gem_fd, e->class, e->instance)); + + obj.handle = gem_create(gem_fd, 4096); + gem_write(gem_fd, obj.handle, 0, &bbend, sizeof(bbend)); + + eb.buffer_count = 1; + eb.buffers_ptr = to_user_pointer(&obj); + eb.flags = e2ring(gem_fd, e); + + /* + * This test is probabilistic so run in a few times to increase the + * chance of hitting the race. + */ + igt_until_timeout(10) { + /* + * Defeat the busy stats delayed disable, we need to guarantee + * we are the first PMU user. + */ + gem_quiescent_gpu(gem_fd); + sleep(2); + + /* Apply interrupt-heavy load on the engine. */ + igt_fork_helper(&engine_load) { + for (;;) + gem_execbuf(gem_fd, &eb); + } + + /* Wait a bit to allow engine load to start. */ + usleep(500e3); + + /* Enable the PMU. */ + fd = open_pmu(config); + + /* Stop load and close the PMU. */ + igt_stop_helper(&engine_load); + close(fd); + } + + /* Cleanup. */ + gem_close(gem_fd, obj.handle); + gem_quiescent_gpu(gem_fd); +} + +static double __error(double val, double ref) +{ + igt_assert(ref > 1e-5 /* smallval */); + return (100.0 * val / ref) - 100.0; +} + +static void __rearm_spin_batch(igt_spin_t *spin) +{ + const uint32_t mi_arb_chk = 0x5 << 23; + + *spin->batch = mi_arb_chk; + __sync_synchronize(); +} + +#define div_round_up(a, b) (((a) + (b) - 1) / (b)) + +static void +accuracy(int gem_fd, const struct intel_execution_engine2 *e, + unsigned long target_busy_pct) +{ + const unsigned int min_test_loops = 7; + const unsigned long min_test_us = 1e6; + unsigned long busy_us = 2500; + unsigned long idle_us = 100 * (busy_us - target_busy_pct * + busy_us / 100) / target_busy_pct; + unsigned long pwm_calibration_us; + unsigned long test_us; + double busy_r, expected; + uint64_t val[2]; + uint64_t ts[2]; + int link[2]; + int fd; + + /* Sampling platforms cannot reach the high accuracy criteria. */ + igt_require(gem_has_execlists(gem_fd)); + + while (idle_us < 2500) { + busy_us *= 2; + idle_us *= 2; + } + + pwm_calibration_us = min_test_loops * (busy_us + idle_us); + while (pwm_calibration_us < min_test_us) + pwm_calibration_us += busy_us + idle_us; + test_us = min_test_loops * (idle_us + busy_us); + while (test_us < min_test_us) + test_us += busy_us + idle_us; + + igt_info("calibration=%luus, test=%luus; ratio=%.2f%% (%luus/%luus)\n", + pwm_calibration_us, test_us, + (double)busy_us / (busy_us + idle_us) * 100.0, + busy_us, idle_us); + + assert_within_epsilon((double)busy_us / (busy_us + idle_us), + (double)target_busy_pct / 100.0, tolerance); + + igt_assert(pipe(link) == 0); + + /* Emit PWM pattern on the engine from a child. */ + igt_fork(child, 1) { + struct sched_param rt = { .sched_priority = 99 }; + const unsigned long timeout[] = { + pwm_calibration_us * 1000, test_us * 2 * 1000 + }; + struct drm_i915_gem_exec_object2 obj = {}; + uint64_t total_busy_ns = 0, total_idle_ns = 0; + igt_spin_t *spin; + int ret; + + /* We need the best sleep accuracy we can get. */ + ret = sched_setscheduler(0, + SCHED_FIFO | SCHED_RESET_ON_FORK, + &rt); + if (ret) + igt_warn("Failed to set scheduling policy!\n"); + + /* Allocate our spin batch and idle it. */ + spin = igt_spin_batch_new(gem_fd, 0, e2ring(gem_fd, e), 0); + obj.handle = spin->handle; + __submit_spin_batch(gem_fd, &obj, e); /* record its location */ + igt_spin_batch_end(spin); + gem_sync(gem_fd, obj.handle); + obj.flags |= EXEC_OBJECT_PINNED; + + /* 1st pass is calibration, second pass is the test. */ + for (int pass = 0; pass < ARRAY_SIZE(timeout); pass++) { + uint64_t busy_ns = -total_busy_ns; + uint64_t idle_ns = -total_idle_ns; + struct timespec test_start = { }; + + igt_nsec_elapsed(&test_start); + do { + struct timespec t_busy = { }; + unsigned int target_idle_us; + + igt_nsec_elapsed(&t_busy); + + /* Restart the spinbatch. */ + __rearm_spin_batch(spin); + __submit_spin_batch(gem_fd, &obj, e); + measured_usleep(busy_us); + igt_spin_batch_end(spin); + gem_sync(gem_fd, obj.handle); + + total_busy_ns += igt_nsec_elapsed(&t_busy); + + target_idle_us = + (100 * total_busy_ns / target_busy_pct - (total_busy_ns + total_idle_ns)) / 1000; + total_idle_ns += measured_usleep(target_idle_us); + } while (igt_nsec_elapsed(&test_start) < timeout[pass]); + + busy_ns += total_busy_ns; + idle_ns += total_idle_ns; + + expected = (double)busy_ns / (busy_ns + idle_ns); + igt_info("%u: busy %"PRIu64"us, idle %"PRIu64"us: %.2f%% (target: %lu%%)\n", + pass, busy_ns / 1000, idle_ns / 1000, + 100 * expected, target_busy_pct); + write(link[1], &expected, sizeof(expected)); + } + + igt_spin_batch_free(gem_fd, spin); + } + + /* Let the child run. */ + read(link[0], &expected, sizeof(expected)); + assert_within_epsilon(expected, target_busy_pct/100., 0.05); + + /* Collect engine busyness for an interesting part of child runtime. */ + fd = open_pmu(I915_PMU_ENGINE_BUSY(e->class, e->instance)); + val[0] = __pmu_read_single(fd, &ts[0]); + read(link[0], &expected, sizeof(expected)); + val[1] = __pmu_read_single(fd, &ts[1]); + close(fd); + + close(link[1]); + close(link[0]); + + igt_waitchildren(); + + busy_r = (double)(val[1] - val[0]) / (ts[1] - ts[0]); + + igt_info("error=%.2f%% (%.2f%% vs %.2f%%)\n", + __error(busy_r, expected), 100 * busy_r, 100 * expected); + + assert_within_epsilon(busy_r, expected, 0.15); + assert_within_epsilon(1 - busy_r, 1 - expected, 0.15); +} + igt_main { const unsigned int num_other_metrics = @@ -1197,8 +1622,11 @@ invalid_init(); for_each_engine_class_instance(fd, e) { + const unsigned int pct[] = { 2, 50, 98 }; + /** - * Test that a single engine metric can be initialized. + * Test that a single engine metric can be initialized or it + * is correctly rejected. */ igt_subtest_f("init-busy-%s", e->name) init(fd, e, I915_SAMPLE_BUSY); @@ -1209,46 +1637,112 @@ igt_subtest_f("init-sema-%s", e->name) init(fd, e, I915_SAMPLE_SEMA); - /** - * Test that engines show no load when idle. - */ - igt_subtest_f("idle-%s", e->name) - single(fd, e, false); - - /** - * Test that a single engine reports load correctly. - */ - igt_subtest_f("busy-%s", e->name) - single(fd, e, true); - - /** - * Test that when one engine is loaded other report no load. - */ - igt_subtest_f("busy-check-all-%s", e->name) - busy_check_all(fd, e, num_engines); - - /** - * Test that when all except one engine are loaded all loads - * are correctly reported. - */ - igt_subtest_f("most-busy-check-all-%s", e->name) - most_busy_check_all(fd, e, num_engines); + igt_subtest_group { + igt_fixture { + gem_require_engine(fd, e->class, e->instance); + } - /** - * Test that semphore counters report no activity on idle - * or busy engines. - */ - igt_subtest_f("idle-no-semaphores-%s", e->name) - no_sema(fd, e, false); + /** + * Test that engines show no load when idle. + */ + igt_subtest_f("idle-%s", e->name) + single(fd, e, 0); + + /** + * Test that a single engine reports load correctly. + */ + igt_subtest_f("busy-%s", e->name) + single(fd, e, TEST_BUSY); + igt_subtest_f("busy-idle-%s", e->name) + single(fd, e, TEST_BUSY | TEST_TRAILING_IDLE); + + /** + * Test that when one engine is loaded other report no + * load. + */ + igt_subtest_f("busy-check-all-%s", e->name) + busy_check_all(fd, e, num_engines, TEST_BUSY); + igt_subtest_f("busy-idle-check-all-%s", e->name) + busy_check_all(fd, e, num_engines, + TEST_BUSY | TEST_TRAILING_IDLE); + + /** + * Test that when all except one engine are loaded all + * loads are correctly reported. + */ + igt_subtest_f("most-busy-check-all-%s", e->name) + most_busy_check_all(fd, e, num_engines, + TEST_BUSY); + igt_subtest_f("most-busy-idle-check-all-%s", e->name) + most_busy_check_all(fd, e, num_engines, + TEST_BUSY | + TEST_TRAILING_IDLE); + + /** + * Test that semphore counters report no activity on + * idle or busy engines. + */ + igt_subtest_f("idle-no-semaphores-%s", e->name) + no_sema(fd, e, 0); + + igt_subtest_f("busy-no-semaphores-%s", e->name) + no_sema(fd, e, TEST_BUSY); + + igt_subtest_f("busy-idle-no-semaphores-%s", e->name) + no_sema(fd, e, TEST_BUSY | TEST_TRAILING_IDLE); + + /** + * Test that semaphore waits are correctly reported. + */ + igt_subtest_f("semaphore-wait-%s", e->name) + sema_wait(fd, e, TEST_BUSY); + + igt_subtest_f("semaphore-wait-idle-%s", e->name) + sema_wait(fd, e, + TEST_BUSY | TEST_TRAILING_IDLE); + + /** + * Check that two perf clients do not influence each + * others observations. + */ + igt_subtest_f("multi-client-%s", e->name) + multi_client(fd, e); + + /** + * Check that reported usage is correct when PMU is + * enabled after the batch is running. + */ + igt_subtest_f("busy-start-%s", e->name) + busy_start(fd, e); + + /** + * Check that reported usage is correct when PMU is + * enabled after two batches are running. + */ + igt_subtest_f("busy-double-start-%s", e->name) { + gem_require_contexts(fd); + busy_double_start(fd, e); + } - igt_subtest_f("busy-no-semaphores-%s", e->name) - no_sema(fd, e, true); + /** + * Check that the PMU can be safely enabled in face of + * interrupt-heavy engine load. + */ + igt_subtest_f("enable-race-%s", e->name) + test_enable_race(fd, e); + + /** + * Check engine busyness accuracy is as expected. + */ + for (i = 0; i < ARRAY_SIZE(pct); i++) { + igt_subtest_f("busy-accuracy-%u-%s", + pct[i], e->name) + accuracy(fd, e, pct[i]); + } - /** - * Test that semaphore waits are correctly reported. - */ - igt_subtest_f("semaphore-wait-%s", e->name) - sema_wait(fd, e); + igt_subtest_f("busy-hang-%s", e->name) + single(fd, e, TEST_BUSY | FLAG_HANG); + } /** * Test that event waits are correctly reported. @@ -1256,27 +1750,6 @@ if (e->class == I915_ENGINE_CLASS_RENDER) igt_subtest_f("event-wait-%s", e->name) event_wait(fd, e); - - /** - * Check that two perf clients do not influence each others - * observations. - */ - igt_subtest_f("multi-client-%s", e->name) - multi_client(fd, e); - - /** - * Check that reported usage is correct when PMU is enabled - * after the batch is running. - */ - igt_subtest_f("busy-start-%s", e->name) - busy_start(fd, e); - - /** - * Check that reported usage is correct when PMU is enabled - * after two batches are running. - */ - igt_subtest_f("busy-double-start-%s", e->name) - busy_double_start(fd, e); } /** @@ -1284,7 +1757,10 @@ * correctly reported. */ igt_subtest("all-busy-check-all") - all_busy_check_all(fd, num_engines); + all_busy_check_all(fd, num_engines, TEST_BUSY); + igt_subtest("all-busy-idle-check-all") + all_busy_check_all(fd, num_engines, + TEST_BUSY | TEST_TRAILING_IDLE); /** * Test that non-engine counters can be initialized and read. Apart @@ -1323,13 +1799,19 @@ * Test RC6 residency reporting. */ igt_subtest("rc6") - test_rc6(fd); + test_rc6(fd, 0); + + igt_subtest("rc6-runtime-pm") + test_rc6(fd, TEST_RUNTIME_PM); + + igt_subtest("rc6-runtime-pm-long") + test_rc6(fd, TEST_RUNTIME_PM | FLAG_LONG); /** * Check render nodes are counted. */ igt_subtest_group { - int render_fd; + int render_fd = -1; igt_fixture { render_fd = drm_open_driver_render(DRIVER_INTEL); @@ -1339,8 +1821,20 @@ } for_each_engine_class_instance(fd, e) { - igt_subtest_f("render-node-busy-%s", e->name) - single(fd, e, true); + igt_subtest_group { + igt_fixture { + gem_require_engine(render_fd, + e->class, + e->instance); + } + + igt_subtest_f("render-node-busy-%s", e->name) + single(fd, e, TEST_BUSY); + igt_subtest_f("render-node-busy-idle-%s", + e->name) + single(fd, e, + TEST_BUSY | TEST_TRAILING_IDLE); + } } igt_fixture { diff -Nru intel-gpu-tools-1.21/tests/pm_rc6_residency.c intel-gpu-tools-1.22/tests/pm_rc6_residency.c --- intel-gpu-tools-1.21/tests/pm_rc6_residency.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/pm_rc6_residency.c 2018-03-09 14:22:59.000000000 +0000 @@ -60,6 +60,15 @@ return enabled; } +static bool has_rc6_residency(const char *name) +{ + unsigned long residency; + char path[128]; + + sprintf(path, "power/%s_residency_ms", name); + return igt_sysfs_scanf(sysfs, path, "%lu", &residency) == 1; +} + static unsigned long read_rc6_residency(const char *name) { unsigned long residency; @@ -129,15 +138,15 @@ */ read_residencies(devid, mask, &end); igt_debug("time=%d: rc6=(%d, %d), rc6p=%d, rc6pp=%d\n", - end.duration, end.rc6, end.media_rc6, end.rc6p, end.rc6pp); + end.duration, end.rc6, end.media_rc6, end.rc6p, end.rc6pp); for (retry = 0; retry < 2; retry++) { start = end; sleep(SLEEP_DURATION); read_residencies(devid, mask, &end); igt_debug("time=%d: rc6=(%d, %d), rc6p=%d, rc6pp=%d\n", - end.duration, - end.rc6, end.media_rc6, end.rc6p, end.rc6pp); + end.duration, + end.rc6, end.media_rc6, end.rc6p, end.rc6pp); if (end.rc6 >= start.rc6 && end.media_rc6 >= start.media_rc6 && @@ -171,9 +180,9 @@ unsigned long start, now; /* First wait for roughly an RC6 Evaluation Interval */ - usleep(160 * 1000); + usleep(160 * 1000); - /* Then poll for RC6 to start ticking */ + /* Then poll for RC6 to start ticking */ now = read_rc6_residency("rc6"); do { start = now; @@ -201,6 +210,8 @@ devid = intel_get_drm_devid(fd); sysfs = igt_sysfs_open(fd, NULL); + igt_require(has_rc6_residency("rc6")); + /* Make sure rc6 counters are running */ igt_drop_caches_set(fd, DROP_IDLE); igt_require(wait_for_rc6()); diff -Nru intel-gpu-tools-1.21/tests/pm_rpm.c intel-gpu-tools-1.22/tests/pm_rpm.c --- intel-gpu-tools-1.21/tests/pm_rpm.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/pm_rpm.c 2018-03-09 14:22:59.000000000 +0000 @@ -1116,7 +1116,7 @@ execbuf.flags = I915_EXEC_BLT; i915_execbuffer2_set_context_id(execbuf, 0); - do_ioctl(drm_fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); + gem_execbuf(drm_fd, &execbuf); *presumed_dst_offset = relocs[0].presumed_offset; @@ -1257,7 +1257,7 @@ i915_execbuffer2_set_context_id(execbuf, 0); for (i = 0; i < rounds; i++) { - do_ioctl(drm_fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); + gem_execbuf(drm_fd, &execbuf); if (wait_flags & WAIT_STATUS) igt_assert(wait_for_suspended()); @@ -1387,7 +1387,7 @@ igt_assert(wait_for_suspended()); for (i = 0; i < 20; i++) { - do_ioctl(drm_fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); + gem_execbuf(drm_fd, &execbuf); igt_assert(wait_for_suspended()); } diff -Nru intel-gpu-tools-1.21/tests/pm_rps.c intel-gpu-tools-1.22/tests/pm_rps.c --- intel-gpu-tools-1.21/tests/pm_rps.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/pm_rps.c 2018-03-09 14:22:59.000000000 +0000 @@ -221,6 +221,8 @@ return; } + igt_require_gem(drm_fd); + lh.exit = false; lh.load = load; @@ -233,7 +235,7 @@ igt_debug("Applying %s load...\n", lh.load ? "high" : "low"); - spin[0] = igt_spin_batch_new(drm_fd, 0, 0, 0); + spin[0] = __igt_spin_batch_new(drm_fd, 0, 0, 0); if (lh.load == HIGH) spin[1] = __igt_spin_batch_new(drm_fd, 0, 0, 0); while (!lh.exit) { @@ -434,6 +436,7 @@ wait += IDLE_WAIT_TIMESTEP_MSEC; } while (wait < IDLE_WAIT_TIMEOUT_MSEC); + igt_debugfs_dump(drm_fd, "i915_rps_boost_info"); igt_assert_eq(freqs[CUR], freqs[RPn]); igt_debug("Required %d msec to reach cur=idle\n", wait); } @@ -457,6 +460,7 @@ wait += LOADED_WAIT_TIMESTEP_MSEC; } while (wait < LOADED_WAIT_TIMEOUT_MSEC); + igt_debugfs_dump(drm_fd, "i915_rps_boost_info"); igt_assert_lte(freqs[MAX], freqs[CUR]); igt_debug("Required %d msec to reach cur=max\n", wait); } @@ -484,15 +488,31 @@ wait += STABILIZE_WAIT_TIMESTEP_MSEC; } while (wait < STABILIZE_WAIT_TIMEOUT_MSEC); + igt_debugfs_dump(drm_fd, "i915_rps_boost_info"); igt_debug("Waited %d msec to stabilize cur\n", wait); } +static void resubmit_batch(int fd, uint32_t handle, int count) +{ + struct drm_i915_gem_exec_object2 obj = { + .handle = handle + }; + struct drm_i915_gem_execbuffer2 eb = { + .buffer_count = 1, + .buffers_ptr = to_user_pointer(&obj), + }; + while (count--) + gem_execbuf(fd, &eb); +} + static void boost_freq(int fd, int *boost_freqs) { int64_t timeout = 1; igt_spin_t *load; load = igt_spin_batch_new(fd, 0, 0, 0); + resubmit_batch(fd, load->handle, 16); + /* Waiting will grant us a boost to maximum */ gem_wait(fd, load->handle, &timeout); diff -Nru intel-gpu-tools-1.21/tests/pm_sseu.c intel-gpu-tools-1.22/tests/pm_sseu.c --- intel-gpu-tools-1.21/tests/pm_sseu.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/pm_sseu.c 2018-03-09 14:22:59.000000000 +0000 @@ -104,6 +104,14 @@ *last = pos - 1; } +static bool +dbg_has_line(const char *first, const char *last, const char *name) +{ + char *pos = strstr(first, name); + + return pos != NULL && pos < last; +} + static int dbg_get_int(const char *first, const char *last, const char *name) { @@ -154,12 +162,21 @@ memset(stat, 0, sizeof(*stat)); dbg_get_status_section("SSEU Device Info", &first, &last); + for (char *tmp = first; tmp < last; tmp++) + igt_debug("%c", *tmp); + igt_debug("\n"); stat->info.slice_total = dbg_get_int(first, last, "Available Slice Total:"); stat->info.subslice_total = dbg_get_int(first, last, "Available Subslice Total:"); - stat->info.subslice_per = - dbg_get_int(first, last, "Available Subslice Per Slice:"); + /* Dealing with a change in 4.17. */ + if (dbg_has_line(first, last, "Available Subslice Per Slice:")) { + stat->info.subslice_per = + dbg_get_int(first, last, "Available Subslice Per Slice:"); + } else { + stat->info.subslice_per = + dbg_get_int(first, last, "Available Slice0 subslices:"); + } stat->info.eu_total = dbg_get_int(first, last, "Available EU Total:"); stat->info.eu_per = @@ -172,12 +189,21 @@ dbg_get_bool(first, last, "Has EU Power Gating:"); dbg_get_status_section("SSEU Device Status", &first, &last); + for (char *tmp = first; tmp < last; tmp++) + igt_debug("%c", *tmp); + igt_debug("\n"); stat->hw.slice_total = dbg_get_int(first, last, "Enabled Slice Total:"); stat->hw.subslice_total = dbg_get_int(first, last, "Enabled Subslice Total:"); - stat->hw.subslice_per = - dbg_get_int(first, last, "Enabled Subslice Per Slice:"); + /* Dealing with a change in 4.17. */ + if (dbg_has_line(first, last, "Enabled Subslice Per Slice:")) { + stat->hw.subslice_per = + dbg_get_int(first, last, "Enabled Subslice Per Slice:"); + } else { + stat->hw.subslice_per = + dbg_get_int(first, last, "Enabled Slice0 subslices:"); + } stat->hw.eu_total = dbg_get_int(first, last, "Enabled EU Total:"); stat->hw.eu_per = diff -Nru intel-gpu-tools-1.21/tests/prime_mmap_coherency.c intel-gpu-tools-1.22/tests/prime_mmap_coherency.c --- intel-gpu-tools-1.21/tests/prime_mmap_coherency.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/prime_mmap_coherency.c 2018-03-09 14:22:59.000000000 +0000 @@ -101,6 +101,8 @@ drm_intel_bo_unreference(bo_1); munmap(ptr_cpu, width * height); + close(dma_buf_fd); + return stale; } @@ -169,6 +171,9 @@ drm_intel_bo_unreference(bo_2); munmap(ptr_cpu, width * height); + close(dma_buf2_fd); + close(dma_buf_fd); + return stale; } diff -Nru intel-gpu-tools-1.21/tests/prime_vgem.c intel-gpu-tools-1.22/tests/prime_vgem.c --- intel-gpu-tools-1.21/tests/prime_vgem.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/prime_vgem.c 2018-03-09 14:22:59.000000000 +0000 @@ -723,7 +723,7 @@ do_or_die(__kms_addfb(i915, handle[i], bo[i].width, bo[i].height, bo[i].pitch, - DRM_FORMAT_XRGB8888, I915_TILING_NONE, + DRM_FORMAT_XRGB8888, I915_TILING_NONE, NULL, LOCAL_DRM_MODE_FB_MODIFIERS, &fb_id[i])); igt_assert(fb_id[i]); } diff -Nru intel-gpu-tools-1.21/tests/syncobj_basic.c intel-gpu-tools-1.22/tests/syncobj_basic.c --- intel-gpu-tools-1.21/tests/syncobj_basic.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/syncobj_basic.c 2018-03-09 14:22:59.000000000 +0000 @@ -187,7 +187,7 @@ igt_main { - int fd; + int fd = -1; igt_fixture { fd = drm_open_driver(DRIVER_ANY); diff -Nru intel-gpu-tools-1.21/tests/syncobj_wait.c intel-gpu-tools-1.22/tests/syncobj_wait.c --- intel-gpu-tools-1.21/tests/syncobj_wait.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/syncobj_wait.c 2018-03-09 14:22:59.000000000 +0000 @@ -317,7 +317,7 @@ { uint32_t syncobj = syncobj_create(fd, 0); uint32_t flags = flags_for_test_flags(test_flags); - int timeline; + int timeline = -1; if (test_flags & (WAIT_SUBMITTED | WAIT_SIGNALED)) timeline = syncobj_attach_sw_sync(fd, syncobj); @@ -336,6 +336,8 @@ } syncobj_destroy(fd, syncobj); + if (timeline != -1) + close(timeline); } static void @@ -343,7 +345,7 @@ { uint32_t syncobj = syncobj_create(fd, 0); uint32_t flags = flags_for_test_flags(test_flags); - int timeline; + int timeline = -1; timer_t timer; if (test_flags & WAIT_FOR_SUBMIT) { @@ -360,7 +362,7 @@ timer_delete(timer); - if (!(test_flags & WAIT_FOR_SUBMIT)) + if (timeline != -1) close(timeline); syncobj_destroy(fd, syncobj); @@ -614,7 +616,7 @@ uint32_t syncobjs[8]; enum syncobj_stage stage[8]; int i, j, timelines[8]; - uint32_t first_signaled, num_signaled; + uint32_t first_signaled = -1, num_signaled = 0; pthread_t thread; for (i = 0; i < 8; i++) { @@ -757,7 +759,7 @@ igt_main { - int fd; + int fd = -1; igt_fixture { fd = drm_open_driver(DRIVER_ANY); diff -Nru intel-gpu-tools-1.21/tests/testdisplay.c intel-gpu-tools-1.22/tests/testdisplay.c --- intel-gpu-tools-1.21/tests/testdisplay.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/testdisplay.c 2018-03-09 14:22:59.000000000 +0000 @@ -227,9 +227,7 @@ cairo_set_source_rgb(cr, .8, .8, .8); cairo_fill(cr); - igt_assert(!cairo_status(cr)); - - cairo_destroy(cr); + igt_put_cairo_ctx(drm_fd, fb_info, cr); } static void paint_image(cairo_t *cr, const char *file) @@ -294,9 +292,7 @@ if (qr_code) paint_image(cr, "pass.png"); - igt_assert(!cairo_status(cr)); - - cairo_destroy(cr); + igt_put_cairo_ctx(drm_fd, fb, cr); } static void sighandler(int signo) diff -Nru intel-gpu-tools-1.21/tests/testdisplay_hotplug.c intel-gpu-tools-1.22/tests/testdisplay_hotplug.c --- intel-gpu-tools-1.21/tests/testdisplay_hotplug.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tests/testdisplay_hotplug.c 2018-03-09 14:22:59.000000000 +0000 @@ -32,7 +32,6 @@ #include "config.h" -#ifdef HAVE_UDEV #include static struct udev_monitor *uevent_monitor; static struct udev *udev; @@ -125,14 +124,3 @@ if (udev) udev_unref(udev); } -#else -gboolean testdisplay_setup_hotplug(void) -{ - igt_warn("no hotplug support on this platform\n"); - return TRUE; -} - -void testdisplay_cleanup_hotplug(void) -{ -} -#endif diff -Nru intel-gpu-tools-1.21/tests/vc4_purgeable_bo.c intel-gpu-tools-1.22/tests/vc4_purgeable_bo.c --- intel-gpu-tools-1.21/tests/vc4_purgeable_bo.c 1970-01-01 00:00:00.000000000 +0000 +++ intel-gpu-tools-1.22/tests/vc4_purgeable_bo.c 2018-03-09 14:22:59.000000000 +0000 @@ -0,0 +1,264 @@ +/* + * Copyright © 2017 Broadcom + * + * 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 "igt.h" +#include "igt_vc4.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "vc4_drm.h" + +struct igt_vc4_bo { + struct igt_list node; + int handle; + void *map; + size_t size; +}; + +static jmp_buf jmp; + +static void __attribute__((noreturn)) sigtrap(int sig) +{ + longjmp(jmp, sig); +} + +static void igt_vc4_alloc_mmap_max_bo(int fd, struct igt_list *list, + size_t size) +{ + struct igt_vc4_bo *bo; + struct drm_vc4_create_bo create = { + .size = size, + }; + + while (true) { + if (igt_ioctl(fd, DRM_IOCTL_VC4_CREATE_BO, &create)) + break; + + bo = malloc(sizeof(*bo)); + igt_assert(bo); + bo->handle = create.handle; + bo->size = create.size; + bo->map = igt_vc4_mmap_bo(fd, bo->handle, bo->size, + PROT_READ | PROT_WRITE); + igt_list_add_tail(&bo->node, list); + } +} + +static void igt_vc4_unmap_free_bo_pool(int fd, struct igt_list *list) +{ + struct igt_vc4_bo *bo; + + while (!igt_list_empty(list)) { + bo = igt_list_first_entry(list, bo, node); + igt_assert(bo); + igt_list_del(&bo->node); + munmap(bo->map, bo->size); + gem_close(fd, bo->handle); + free(bo); + } +} + +static void igt_vc4_trigger_purge(int fd) +{ + struct igt_list list; + + igt_list_init(&list); + + /* Try to allocate as much as we can to trigger a purge. */ + igt_vc4_alloc_mmap_max_bo(fd, &list, 64 * 1024); + igt_assert(!igt_list_empty(&list)); + igt_vc4_unmap_free_bo_pool(fd, &list); +} + +static void igt_vc4_purgeable_subtest_prepare(int fd, struct igt_list *list) +{ + igt_vc4_unmap_free_bo_pool(fd, list); + igt_vc4_alloc_mmap_max_bo(fd, list, 64 * 1024); + igt_assert(!igt_list_empty(list)); +} + +igt_main +{ + struct igt_vc4_bo *bo; + struct igt_list list; + uint32_t *map; + int fd, ret; + + igt_fixture { + uint64_t val = 0; + + fd = drm_open_driver(DRIVER_VC4); + igt_vc4_get_param(fd, DRM_VC4_PARAM_SUPPORTS_MADVISE, &val); + igt_require(val); + igt_list_init(&list); + } + + igt_subtest("mark-willneed") { + igt_vc4_purgeable_subtest_prepare(fd, &list); + igt_list_for_each(bo, &list, node) + igt_assert(igt_vc4_purgeable_bo(fd, bo->handle, + false)); + } + + igt_subtest("mark-purgeable") { + igt_vc4_purgeable_subtest_prepare(fd, &list); + igt_list_for_each(bo, &list, node) + igt_vc4_purgeable_bo(fd, bo->handle, true); + + igt_list_for_each(bo, &list, node) + igt_vc4_purgeable_bo(fd, bo->handle, false); + } + + igt_subtest("mark-purgeable-twice") { + igt_vc4_purgeable_subtest_prepare(fd, &list); + bo = igt_list_first_entry(&list, bo, node); + igt_vc4_purgeable_bo(fd, bo->handle, true); + igt_vc4_purgeable_bo(fd, bo->handle, true); + igt_vc4_purgeable_bo(fd, bo->handle, false); + } + + igt_subtest("mark-unpurgeable-twice") { + igt_vc4_purgeable_subtest_prepare(fd, &list); + bo = igt_list_first_entry(&list, bo, node); + igt_vc4_purgeable_bo(fd, bo->handle, true); + igt_vc4_purgeable_bo(fd, bo->handle, false); + igt_vc4_purgeable_bo(fd, bo->handle, false); + } + + igt_subtest("access-purgeable-bo-mem") { + igt_vc4_purgeable_subtest_prepare(fd, &list); + bo = igt_list_first_entry(&list, bo, node); + map = (uint32_t *)bo->map; + + /* Mark the BO as purgeable, but do not try to allocate a new + * BO. This should leave the BO in a non-purged state unless + * someone else tries to allocated a new BO. + */ + igt_vc4_purgeable_bo(fd, bo->handle, true); + + /* Accessing a purgeable BO should generate a SIGBUS event if + * the BO has been purged by the system in the meantime. + */ + signal(SIGSEGV, sigtrap); + signal(SIGBUS, sigtrap); + ret = setjmp(jmp); + if (!ret) + *map = 0xdeadbeef; + else + igt_assert(ret == SIGBUS); + signal(SIGBUS, SIG_DFL); + signal(SIGSEGV, SIG_DFL); + } + + igt_subtest("access-purged-bo-mem") { + igt_vc4_purgeable_subtest_prepare(fd, &list); + + /* Mark the first BO in our list as purgeable and try to + * allocate a new one. This should trigger a purge and render + * the first BO inaccessible. + */ + bo = igt_list_first_entry(&list, bo, node); + map = (uint32_t *)bo->map; + igt_vc4_purgeable_bo(fd, bo->handle, true); + + /* Trigger a purge. */ + igt_vc4_trigger_purge(fd); + + /* Accessing a purged BO should generate a SIGBUS event. */ + signal(SIGSEGV, sigtrap); + signal(SIGBUS, sigtrap); + ret = setjmp(jmp); + if (!ret) + *map = 0; + igt_assert(ret == SIGBUS); + signal(SIGBUS, SIG_DFL); + signal(SIGSEGV, SIG_DFL); + igt_vc4_purgeable_bo(fd, bo->handle, false); + } + + igt_subtest("mark-unpurgeable-check-retained") { + igt_vc4_purgeable_subtest_prepare(fd, &list); + igt_list_for_each(bo, &list, node) { + map = (uint32_t *)bo->map; + *map = 0xdeadbeef; + igt_vc4_purgeable_bo(fd, bo->handle, true); + } + + igt_list_for_each(bo, &list, node) { + map = (uint32_t *)bo->map; + if (igt_vc4_purgeable_bo(fd, bo->handle, false)) + igt_assert(*map == 0xdeadbeef); + } + } + + igt_subtest("mark-unpurgeable-purged") { + igt_vc4_purgeable_subtest_prepare(fd, &list); + + igt_list_for_each(bo, &list, node) + igt_vc4_purgeable_bo(fd, bo->handle, true); + + /* Trigger a purge. */ + igt_vc4_trigger_purge(fd); + + bo = igt_list_first_entry(&list, bo, node); + map = (uint32_t *)bo->map; + + igt_assert(!igt_vc4_purgeable_bo(fd, bo->handle, false)); + + /* Purged BOs are unusable and any access to their + * mmap-ed region should trigger a SIGBUS. + */ + signal(SIGSEGV, sigtrap); + signal(SIGBUS, sigtrap); + ret = setjmp(jmp); + if (!ret) + *map = 0; + igt_assert(ret == SIGBUS); + signal(SIGBUS, SIG_DFL); + signal(SIGSEGV, SIG_DFL); + } + + igt_subtest("free-purged-bo") { + igt_vc4_purgeable_subtest_prepare(fd, &list); + bo = igt_list_first_entry(&list, bo, node); + igt_vc4_purgeable_bo(fd, bo->handle, true); + + /* Trigger a purge. */ + igt_vc4_trigger_purge(fd); + + igt_list_del(&bo->node); + munmap(bo->map, bo->size); + gem_close(fd, bo->handle); + free(bo); + } + + igt_fixture + close(fd); +} diff -Nru intel-gpu-tools-1.21/tools/aubdump.c intel-gpu-tools-1.22/tools/aubdump.c --- intel-gpu-tools-1.21/tools/aubdump.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tools/aubdump.c 2018-03-09 14:22:59.000000000 +0000 @@ -72,6 +72,14 @@ #define EXECLIST_STATUS_VCSUNIT0 0x12234 #define EXECLIST_STATUS_BCSUNIT 0x22234 +#define EXECLIST_SQ_CONTENTS0_RCSUNIT 0x02510 +#define EXECLIST_SQ_CONTENTS0_VCSUNIT0 0x12510 +#define EXECLIST_SQ_CONTENTS0_BCSUNIT 0x22510 + +#define EXECLIST_CONTROL_RCSUNIT 0x02550 +#define EXECLIST_CONTROL_VCSUNIT0 0x12550 +#define EXECLIST_CONTROL_BCSUNIT 0x22550 + #define MEMORY_MAP_SIZE (64 /* MiB */ * 1024 * 1024) #define PTE_SIZE 4 @@ -584,7 +592,9 @@ uint32_t ring_addr; uint64_t descriptor; uint32_t elsp_reg; + uint32_t elsq_reg; uint32_t status_reg; + uint32_t control_reg; switch (ring_flag) { case I915_EXEC_DEFAULT: @@ -592,19 +602,25 @@ ring_addr = RENDER_RING_ADDR; descriptor = RENDER_CONTEXT_DESCRIPTOR; elsp_reg = EXECLIST_SUBMITPORT_RCSUNIT; + elsq_reg = EXECLIST_SQ_CONTENTS0_RCSUNIT; status_reg = EXECLIST_STATUS_RCSUNIT; + control_reg = EXECLIST_CONTROL_RCSUNIT; break; case I915_EXEC_BSD: ring_addr = VIDEO_RING_ADDR; descriptor = VIDEO_CONTEXT_DESCRIPTOR; elsp_reg = EXECLIST_SUBMITPORT_VCSUNIT0; + elsq_reg = EXECLIST_SQ_CONTENTS0_VCSUNIT0; status_reg = EXECLIST_STATUS_VCSUNIT0; + control_reg = EXECLIST_CONTROL_VCSUNIT0; break; case I915_EXEC_BLT: ring_addr = BLITTER_RING_ADDR; descriptor = BLITTER_CONTEXT_DESCRIPTOR; elsp_reg = EXECLIST_SUBMITPORT_BCSUNIT; + elsq_reg = EXECLIST_SQ_CONTENTS0_BCSUNIT; status_reg = EXECLIST_STATUS_BCSUNIT; + control_reg = EXECLIST_CONTROL_BCSUNIT; break; } @@ -622,18 +638,30 @@ AUB_MEM_TRACE_MEMORY_ADDRESS_SPACE_LOCAL); dword_out(16); /* RING_BUFFER_TAIL */ - register_write_out(elsp_reg, 0); - register_write_out(elsp_reg, 8); - register_write_out(elsp_reg, descriptor >> 32); - register_write_out(elsp_reg, descriptor & 0xFFFFFFFF); + if (gen >= 11) { + register_write_out(elsq_reg, descriptor & 0xFFFFFFFF); + register_write_out(elsq_reg + sizeof(uint32_t), descriptor >> 32); + register_write_out(control_reg, 1); + } else { + register_write_out(elsp_reg, 0); + register_write_out(elsp_reg, 0); + register_write_out(elsp_reg, descriptor >> 32); + register_write_out(elsp_reg, descriptor & 0xFFFFFFFF); + } dword_out(CMD_MEM_TRACE_REGISTER_POLL | (5 + 1 - 1)); dword_out(status_reg); dword_out(AUB_MEM_TRACE_REGISTER_SIZE_DWORD | AUB_MEM_TRACE_REGISTER_SPACE_MMIO); - dword_out(0x00000010); /* mask lo */ - dword_out(0x00000000); /* mask hi */ - dword_out(0x00000000); + if (gen >= 11) { + dword_out(0x00000001); /* mask lo */ + dword_out(0x00000000); /* mask hi */ + dword_out(0x00000001); + } else { + dword_out(0x00000010); /* mask lo */ + dword_out(0x00000000); /* mask hi */ + dword_out(0x00000000); + } } static void @@ -803,13 +831,18 @@ return; } - if (verbose) - printf("BO #%d (%dB) @ 0x%x\n", obj->handle, bo->size, offset); - if (obj->flags & EXEC_OBJECT_PINNED) { bo->offset = obj->offset; + if (verbose) + printf("BO #%d (%dB) pinned @ 0x%lx\n", + obj->handle, bo->size, bo->offset); } else { + if (obj->alignment != 0) + offset = align_u32(offset, obj->alignment); bo->offset = offset; + if (verbose) + printf("BO #%d (%dB) @ 0x%lx\n", obj->handle, + bo->size, bo->offset); offset = align_u32(offset + bo->size + 4095, 4096); } @@ -855,6 +888,22 @@ if (files[i] != NULL) fflush(files[i]); } + + if (device_override && + (execbuffer2->flags & I915_EXEC_FENCE_ARRAY) != 0) { + struct drm_i915_gem_exec_fence *fences = + (void*)(uintptr_t)execbuffer2->cliprects_ptr; + for (uint32_t i = 0; i < execbuffer2->num_cliprects; i++) { + if ((fences[i].flags & I915_EXEC_FENCE_SIGNAL) != 0) { + struct drm_syncobj_array arg = { + .handles = (uintptr_t)&fences[i].handle, + .count_handles = 1, + .pad = 0, + }; + libc_ioctl(fd, DRM_IOCTL_SYNCOBJ_SIGNAL, &arg); + } + } + } } static void diff -Nru intel-gpu-tools-1.21/tools/intel_guc_logger.c intel-gpu-tools-1.22/tools/intel_guc_logger.c --- intel-gpu-tools-1.21/tools/intel_guc_logger.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tools/intel_guc_logger.c 2018-03-09 14:22:59.000000000 +0000 @@ -1,3 +1,26 @@ +/* + * Copyright © 2014-2018 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 #include @@ -51,17 +74,27 @@ pthread_cond_t underflow_cond, overflow_cond; bool stop_logging, discard_oldlogs, capturing_stopped; -static void guc_log_control(bool enable_logging) +static void guc_log_control(bool enable, uint32_t log_level) { int control_fd; char data[19]; uint64_t val; int ret; + igt_assert_lte(log_level, 3); + control_fd = igt_debugfs_open(-1, CONTROL_FILE_NAME, O_WRONLY); igt_assert_f(control_fd >= 0, "couldn't open the guc log control file\n"); - val = enable_logging ? ((verbosity_level << 4) | 0x1) : 0; + /* + * i915 expects GuC log level to be specified as: + * 0: disabled + * 1: enabled (verbosity level 0 = min) + * 2: enabled (verbosity level 1) + * 3: enabled (verbosity level 2) + * 4: enabled (verbosity level 3 = max) + */ + val = enable ? log_level + 1 : 0; ret = snprintf(data, sizeof(data), "0x%" PRIx64, val); igt_assert(ret > 2 && ret < sizeof(data)); @@ -288,7 +321,7 @@ /* Enable the logging, it may not have been enabled from boot and so * the relay file also wouldn't have been created. */ - guc_log_control(true); + guc_log_control(true, verbosity_level); open_relay_file(); open_output_file(); @@ -420,7 +453,7 @@ } while (!stop_logging); /* Pause logging on the GuC side */ - guc_log_control(false); + guc_log_control(false, 0); /* Signal flusher thread to make an exit */ capturing_stopped = 1; diff -Nru intel-gpu-tools-1.21/tools/intel_l3_parity.c intel-gpu-tools-1.22/tools/intel_l3_parity.c --- intel-gpu-tools-1.21/tools/intel_l3_parity.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tools/intel_l3_parity.c 2018-03-09 14:22:59.000000000 +0000 @@ -39,10 +39,8 @@ #include "igt_sysfs.h" #include "drmtest.h" #include "config.h" -#ifdef HAVE_UDEV #include #include -#endif #include "intel_l3_parity.h" static unsigned int devid; @@ -318,10 +316,6 @@ /* Daemon doesn't work like the other commands */ if (action == 'L') { -#ifndef HAVE_UDEV - fprintf(stderr, "Daemon requires udev support. Please reconfigure.\n"); - exit(EXIT_FAILURE); -#else struct l3_parity par; struct l3_location loc; if (daemonize) { @@ -332,7 +326,6 @@ assert(l3_uevent_setup(&par) == 0); assert(l3_listen(&par, daemonize == 1, &loc) == 0); exit(EXIT_SUCCESS); -#endif } if (action == 'l') diff -Nru intel-gpu-tools-1.21/tools/intel_l3_parity.h intel-gpu-tools-1.22/tools/intel_l3_parity.h --- intel-gpu-tools-1.21/tools/intel_l3_parity.h 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tools/intel_l3_parity.h 2018-03-09 14:22:59.000000000 +0000 @@ -18,14 +18,9 @@ uint8_t subbank; }; -#ifdef HAVE_UDEV int l3_uevent_setup(struct l3_parity *par); /* Listens (blocks) for an l3 parity event. Returns the location of the error. */ int l3_listen(struct l3_parity *par, bool daemon, struct l3_location *loc); #define l3_uevent_teardown(par) {} -#else -#define l3_uevent_setup(par, daemon, loc) -1 -#define l3_listen(par) -1 -#endif #endif diff -Nru intel-gpu-tools-1.21/tools/intel_l3_udev_listener.c intel-gpu-tools-1.22/tools/intel_l3_udev_listener.c --- intel-gpu-tools-1.21/tools/intel_l3_udev_listener.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tools/intel_l3_udev_listener.c 2018-03-09 14:22:59.000000000 +0000 @@ -23,7 +23,6 @@ #include "config.h" -#ifdef HAVE_UDEV #include #include #include @@ -123,4 +122,3 @@ return 0; } -#endif diff -Nru intel-gpu-tools-1.21/tools/intel_reg.c intel-gpu-tools-1.22/tools/intel_reg.c --- intel-gpu-tools-1.21/tools/intel_reg.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tools/intel_reg.c 2018-03-09 14:22:59.000000000 +0000 @@ -33,6 +33,7 @@ #include #include "igt.h" +#include "igt_gt.h" #include "intel_io.h" #include "intel_chipset.h" @@ -73,6 +74,10 @@ /* register spec */ char *specfile; + + /* fd for engine access avoiding reopens */ + int fd; + struct reg *regs; ssize_t regcount; @@ -236,13 +241,130 @@ } } +static const struct intel_execution_engine2 *find_engine(const char *name) +{ + const struct intel_execution_engine2 *e; + + if (strlen(name) < 2) + return NULL; + + if (name[0] == '-') + name++; + + for (e = intel_execution_engines2; e->name; e++) { + if (!strcasecmp(e->name, name)) + return e; + } + + return NULL; +} + +static int register_srm(struct config *config, struct reg *reg, + uint32_t *val_in) +{ + const int gen = intel_gen(config->devid); + const bool r64b = gen >= 8; + const uint32_t ctx = 0; + struct drm_i915_gem_exec_object2 obj[2]; + struct drm_i915_gem_relocation_entry reloc[1]; + struct drm_i915_gem_execbuffer2 execbuf; + uint32_t *batch, *r; + const struct intel_execution_engine2 *engine; + bool secure; + int fd, i; + uint32_t val; + + if (config->fd == -1) { + config->fd = __drm_open_driver(DRIVER_INTEL); + if (config->fd == -1) { + fprintf(stderr, "Error opening driver: %s", + strerror(errno)); + exit(EXIT_FAILURE); + } + } + + fd = config->fd; + engine = find_engine(reg->engine); + if (engine == NULL) + exit(EXIT_FAILURE); + + secure = reg->engine[0] != '-'; + + memset(obj, 0, sizeof(obj)); + obj[0].handle = gem_create(fd, 4096); + obj[1].handle = gem_create(fd, 4096); + obj[1].relocs_ptr = to_user_pointer(reloc); + obj[1].relocation_count = 1; + + batch = gem_mmap__cpu(fd, obj[1].handle, 0, 4096, PROT_WRITE); + gem_set_domain(fd, obj[1].handle, + I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU); + + i = 0; + if (val_in) { + batch[i++] = MI_NOOP; + batch[i++] = MI_NOOP; + + batch[i++] = MI_LOAD_REGISTER_IMM; + batch[i++] = reg->addr; + batch[i++] = *val_in; + batch[i++] = MI_NOOP; + } + + batch[i++] = 0x24 << 23 | (1 + r64b); /* SRM */ + batch[i++] = reg->addr; + reloc[0].target_handle = obj[0].handle; + reloc[0].presumed_offset = obj[0].offset; + reloc[0].offset = i * sizeof(uint32_t); + reloc[0].delta = 0; + reloc[0].read_domains = I915_GEM_DOMAIN_RENDER; + reloc[0].write_domain = I915_GEM_DOMAIN_RENDER; + batch[i++] = reloc[0].delta; + if (r64b) + batch[i++] = 0; + + batch[i++] = MI_BATCH_BUFFER_END; + munmap(batch, 4096); + + memset(&execbuf, 0, sizeof(execbuf)); + execbuf.buffers_ptr = to_user_pointer(obj); + execbuf.buffer_count = 2; + execbuf.flags = gem_class_instance_to_eb_flags(fd, + engine->class, + engine->instance); + if (secure) + execbuf.flags |= I915_EXEC_SECURE; + + if (config->verbosity > 0) + printf("%s: using %sprivileged batch\n", + engine->name, + secure ? "" : "non-"); + + execbuf.rsvd1 = ctx; + gem_execbuf(fd, &execbuf); + gem_close(fd, obj[1].handle); + + r = gem_mmap__cpu(fd, obj[0].handle, 0, 4096, PROT_READ); + gem_set_domain(fd, obj[0].handle, I915_GEM_DOMAIN_CPU, 0); + + val = r[0]; + munmap(r, 4096); + + gem_close(fd, obj[0].handle); + + return val; +} + static int read_register(struct config *config, struct reg *reg, uint32_t *valp) { uint32_t val = 0; switch (reg->port_desc.port) { case PORT_MMIO: - val = INREG(reg->mmio_offset + reg->addr); + if (reg->engine) + val = register_srm(config, reg, NULL); + else + val = INREG(reg->mmio_offset + reg->addr); break; case PORT_PORTIO_VGA: iopl(3); @@ -299,7 +421,11 @@ switch (reg->port_desc.port) { case PORT_MMIO: - OUTREG(reg->mmio_offset + reg->addr, val); + if (reg->engine) { + register_srm(config, reg, &val); + } else { + OUTREG(reg->mmio_offset + reg->addr, val); + } break; case PORT_PORTIO_VGA: if (val > 0xff) { @@ -351,7 +477,25 @@ return ret; } -/* s has [(PORTNAME|PORTNUM|MMIO-OFFSET):](REGNAME|REGADDR) */ +static int parse_engine(struct reg *reg, const char *s) +{ + const struct intel_execution_engine2 *e; + + e = find_engine(s); + if (e) { + reg->port_desc.port = PORT_MMIO; + reg->port_desc.name = strdup(s); + reg->port_desc.stride = 4; + reg->engine = strdup(s); + reg->mmio_offset = 0; + } else { + reg->engine = NULL; + } + + return reg->engine == NULL; +} + +/* s has [(PORTNAME|PORTNUM|ENGINE|MMIO-OFFSET):](REGNAME|REGADDR) */ static int parse_reg(struct config *config, struct reg *reg, const char *s) { unsigned long addr; @@ -367,7 +511,9 @@ } else if (p) { char *port_name = strndup(s, p - s); - ret = parse_port_desc(reg, port_name); + ret = parse_engine(reg, port_name); + if (ret) + ret = parse_port_desc(reg, port_name); free(port_name); p++; @@ -616,6 +762,7 @@ static int intel_reg_help(struct config *config, int argc, char *argv[]) { + const struct intel_execution_engine2 *e; int i; printf("Intel graphics register multitool\n\n"); @@ -629,14 +776,18 @@ printf("\n"); printf("REGISTER is defined as:\n"); - printf(" [(PORTNAME|PORTNUM|MMIO-OFFSET):](REGNAME|REGADDR)\n"); + printf(" [(PORTNAME|PORTNUM|ENGINE|MMIO-OFFSET):](REGNAME|REGADDR)\n"); printf("\n"); printf("PORTNAME is one of:\n"); intel_reg_spec_print_ports(); - printf("\n"); + printf("\n\n"); + + printf("ENGINE is one of:\n"); + for (e = intel_execution_engines2; e->name; e++) + printf("%s -%s ", e->name, e->name); + printf("\n\n"); - printf("\n"); printf("OPTIONS common to most COMMANDS:\n"); printf(" --spec=PATH Read register spec from directory or file\n"); printf(" --mmio=FILE Use an MMIO snapshot\n"); @@ -771,6 +922,7 @@ const struct command *command = NULL; struct config config = { .count = 1, + .fd = -1, }; bool help = false; @@ -898,5 +1050,8 @@ free(config.mmiofile); + if (config.fd >= 0) + close(config.fd); + return ret; } diff -Nru intel-gpu-tools-1.21/tools/intel_reg_decode.c intel-gpu-tools-1.22/tools/intel_reg_decode.c --- intel-gpu-tools-1.21/tools/intel_reg_decode.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tools/intel_reg_decode.c 2018-03-09 14:22:59.000000000 +0000 @@ -2746,7 +2746,7 @@ for (j = 0; j < known_registers[i].count; j++) { const struct reg_debug *reg_in = &known_registers[i].regs[j]; - struct reg reg; + struct reg reg = {}; /* XXX: Could be optimized. */ parse_port_desc(®, NULL); diff -Nru intel-gpu-tools-1.21/tools/intel_reg_spec.c intel-gpu-tools-1.22/tools/intel_reg_spec.c --- intel-gpu-tools-1.21/tools/intel_reg_spec.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tools/intel_reg_spec.c 2018-03-09 14:22:59.000000000 +0000 @@ -219,8 +219,6 @@ initialized = true; } - memset(reg, 0, sizeof(*reg)); - ret = regexec(®ex, line, ARRAY_SIZE(match), match, 0); if (ret) ret = -1; @@ -267,7 +265,7 @@ } while (getline(&line, &linesize, file) != -1) { - struct reg reg; + struct reg reg = {}; lineno++; diff -Nru intel-gpu-tools-1.21/tools/intel_reg_spec.h intel-gpu-tools-1.22/tools/intel_reg_spec.h --- intel-gpu-tools-1.21/tools/intel_reg_spec.h 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tools/intel_reg_spec.h 2018-03-09 14:22:59.000000000 +0000 @@ -53,6 +53,7 @@ struct reg { struct port_desc port_desc; + char *engine; uint32_t mmio_offset; uint32_t addr; char *name; diff -Nru intel-gpu-tools-1.21/tools/intel_vbt_decode.c intel-gpu-tools-1.22/tools/intel_vbt_decode.c --- intel-gpu-tools-1.21/tools/intel_vbt_decode.c 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tools/intel_vbt_decode.c 2018-03-09 14:22:59.000000000 +0000 @@ -25,6 +25,7 @@ * */ +#include #include #include #include @@ -309,8 +310,8 @@ { DEVICE_TYPE_COMPOSITE_OUTPUT, "Composite output" }, { DEVICE_TYPE_DUAL_CHANNEL, "Dual channel" }, { 1 << 7, "Content protection" }, - { DEVICE_TYPE_HIGH_SPEED_LINK, "High speel link" }, - { DEVICE_TYPE_LVDS_SINGALING, "LVDS signaling" }, + { DEVICE_TYPE_HIGH_SPEED_LINK, "High speed link" }, + { DEVICE_TYPE_LVDS_SIGNALING, "LVDS signaling" }, { DEVICE_TYPE_TMDS_DVI_SIGNALING, "TMDS/DVI signaling" }, { DEVICE_TYPE_VIDEO_SIGNALING, "Video signaling" }, { DEVICE_TYPE_DISPLAYPORT_OUTPUT, "DisplayPort output" }, @@ -513,6 +514,8 @@ const struct bdb_general_definitions *defs = block->data; int child_dev_num; + child_dev_num = (block->size - sizeof(*defs)) / defs->child_dev_size; + printf("\tCRT DDC GMBUS addr: 0x%02x\n", defs->crt_ddc_gmbus_pin); printf("\tUse ACPI DPMS CRT power states: %s\n", YESNO(defs->dpms_acpi)); @@ -522,8 +525,8 @@ printf("\tBoot display type: 0x%02x%02x\n", defs->boot_display[1], defs->boot_display[0]); printf("\tChild device size: %d\n", defs->child_dev_size); + printf("\tChild device count: %d\n", child_dev_num); - child_dev_num = (block->size - sizeof(*defs)) / defs->child_dev_size; dump_child_devices(context, defs->devices, child_dev_num, defs->child_dev_size); } @@ -534,9 +537,11 @@ const struct bdb_legacy_child_devices *defs = block->data; int child_dev_num; + child_dev_num = (block->size - sizeof(*defs)) / defs->child_dev_size; + printf("\tChild device size: %d\n", defs->child_dev_size); + printf("\tChild device count: %d\n", child_dev_num); - child_dev_num = (block->size - sizeof(*defs)) / defs->child_dev_size; dump_child_devices(context, defs->devices, child_dev_num, defs->child_dev_size); } @@ -1658,6 +1663,33 @@ return true; } +/* print a description of the VBT of the form - */ +static void print_description(struct context *context) +{ + const struct vbt_header *vbt = context->vbt; + const struct bdb_header *bdb = context->bdb; + char *desc = strndup((char *)vbt->signature, sizeof(vbt->signature)); + char *p; + + for (p = desc + strlen(desc) - 1; p >= desc && isspace(*p); p--) + *p = '\0'; + + for (p = desc; *p; p++) { + if (!isalnum(*p)) + *p = '-'; + else + *p = tolower(*p); + } + + p = desc; + if (strncmp(p, "-vbt-", 5) == 0) + p += 5; + + printf("%d-%s\n", bdb->version, p); + + free (desc); +} + static void dump_headers(struct context *context) { const struct vbt_header *vbt = context->vbt; @@ -1720,6 +1752,8 @@ OPT_HEXDUMP, OPT_BLOCK, OPT_USAGE, + OPT_HEADER, + OPT_DESCRIBE, }; static void usage(const char *toolname) @@ -1731,6 +1765,8 @@ " [--all-panels]" " [--hexdump]" " [--block=]" + " [--header]" + " [--describe]" " [--help]\n"); } @@ -1751,6 +1787,7 @@ }; char *endp; int block_number = -1; + bool header_only = false, describe = false; static struct option options[] = { { "file", required_argument, NULL, OPT_FILE }, @@ -1759,6 +1796,8 @@ { "all-panels", no_argument, NULL, OPT_ALL_PANELS }, { "hexdump", no_argument, NULL, OPT_HEXDUMP }, { "block", required_argument, NULL, OPT_BLOCK }, + { "header", no_argument, NULL, OPT_HEADER }, + { "describe", no_argument, NULL, OPT_DESCRIBE }, { "help", no_argument, NULL, OPT_USAGE }, { 0 } }; @@ -1799,6 +1838,12 @@ return EXIT_FAILURE; } break; + case OPT_HEADER: + header_only = true; + break; + case OPT_DESCRIBE: + describe = true; + break; case OPT_END: break; case OPT_USAGE: /* fall-through */ @@ -1902,7 +1947,11 @@ context.panel_type = 0; } - if (block_number != -1) { + if (describe) { + print_description(&context); + } else if (header_only) { + dump_headers(&context); + } else if (block_number != -1) { /* dump specific section only */ if (!dump_section(&context, block_number)) { fprintf(stderr, "Block %d not found\n", block_number); diff -Nru intel-gpu-tools-1.21/tools/intel_vbt_defs.h intel-gpu-tools-1.22/tools/intel_vbt_defs.h --- intel-gpu-tools-1.21/tools/intel_vbt_defs.h 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tools/intel_vbt_defs.h 2018-03-09 14:22:59.000000000 +0000 @@ -227,7 +227,7 @@ #define DEVICE_TYPE_COMPOSITE_OUTPUT (1 << 9) #define DEVICE_TYPE_DUAL_CHANNEL (1 << 8) #define DEVICE_TYPE_HIGH_SPEED_LINK (1 << 6) -#define DEVICE_TYPE_LVDS_SINGALING (1 << 5) +#define DEVICE_TYPE_LVDS_SIGNALING (1 << 5) #define DEVICE_TYPE_TMDS_DVI_SIGNALING (1 << 4) #define DEVICE_TYPE_VIDEO_SIGNALING (1 << 3) #define DEVICE_TYPE_DISPLAYPORT_OUTPUT (1 << 2) @@ -243,7 +243,7 @@ DEVICE_TYPE_MIPI_OUTPUT | \ DEVICE_TYPE_COMPOSITE_OUTPUT | \ DEVICE_TYPE_DUAL_CHANNEL | \ - DEVICE_TYPE_LVDS_SINGALING | \ + DEVICE_TYPE_LVDS_SIGNALING | \ DEVICE_TYPE_TMDS_DVI_SIGNALING | \ DEVICE_TYPE_VIDEO_SIGNALING | \ DEVICE_TYPE_DISPLAYPORT_OUTPUT | \ @@ -253,7 +253,7 @@ (DEVICE_TYPE_INTERNAL_CONNECTOR | \ DEVICE_TYPE_MIPI_OUTPUT | \ DEVICE_TYPE_COMPOSITE_OUTPUT | \ - DEVICE_TYPE_LVDS_SINGALING | \ + DEVICE_TYPE_LVDS_SIGNALING | \ DEVICE_TYPE_TMDS_DVI_SIGNALING | \ DEVICE_TYPE_VIDEO_SIGNALING | \ DEVICE_TYPE_DISPLAYPORT_OUTPUT | \ @@ -304,8 +304,20 @@ #define DVO_PORT_MIPIC 23 /* 171 */ #define DVO_PORT_MIPID 24 /* 171 */ +#define HDMI_MAX_DATA_RATE_PLATFORM 0 /* 204 */ +#define HDMI_MAX_DATA_RATE_297 1 /* 204 */ +#define HDMI_MAX_DATA_RATE_165 2 /* 204 */ + #define LEGACY_CHILD_DEVICE_CONFIG_SIZE 33 +/* DDC Bus DDI Type 155+ */ +enum vbt_gmbus_ddi { + DDC_BUS_DDI_B = 0x1, + DDC_BUS_DDI_C, + DDC_BUS_DDI_D, + DDC_BUS_DDI_F, +}; + /* * The child device config, aka the display device data structure, provides a * description of a port and its configuration on the platform. @@ -334,8 +346,8 @@ u8 i2c_speed; u8 dp_onboard_redriver; /* 158 */ u8 dp_ondock_redriver; /* 158 */ - u8 hdmi_level_shifter_value:4; /* 169 */ - u8 hdmi_max_data_rate:4; /* 204 */ + u8 hdmi_level_shifter_value:5; /* 169 */ + u8 hdmi_max_data_rate:3; /* 204 */ u16 dtd_buf_ptr; /* 161 */ u8 edidless_efp:1; /* 161 */ u8 compression_enable:1; /* 198 */ @@ -400,6 +412,8 @@ u16 dp_gpio_pin_num; /* 195 */ u8 dp_iboost_level:4; /* 196 */ u8 hdmi_iboost_level:4; /* 196 */ + u8 dp_max_link_rate:2; /* 216 CNL+ */ + u8 dp_max_link_rate_reserved:6; /* 216 */ } __packed; struct bdb_general_definitions { diff -Nru intel-gpu-tools-1.21/tools/Makefile.am intel-gpu-tools-1.22/tools/Makefile.am --- intel-gpu-tools-1.21/tools/Makefile.am 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tools/Makefile.am 2018-03-09 14:22:59.000000000 +0000 @@ -7,11 +7,9 @@ intel_error_decode_LDFLAGS = -lz endif -if HAVE_UDEV bin_PROGRAMS += intel_dp_compliance -intel_dp_compliance_CFLAGS = $(AM_CFLAGS) +intel_dp_compliance_CFLAGS = $(AM_CFLAGS) $(GLIB_CFLAGS) intel_dp_compliance_LDADD = $(top_builddir)/lib/libintel_tools.la -endif SUBDIRS = null_state_gen registers diff -Nru intel-gpu-tools-1.21/tools/meson.build intel-gpu-tools-1.22/tools/meson.build --- intel-gpu-tools-1.21/tools/meson.build 2018-01-16 14:04:42.000000000 +0000 +++ intel-gpu-tools-1.22/tools/meson.build 2018-03-09 14:22:59.000000000 +0000 @@ -56,8 +56,6 @@ install : true) endforeach -pkgdatadir = join_paths(get_option('prefix'), get_option('datadir'), 'intel-gpu-tools') - if libudev.found() intel_dp_compliance_src = [ 'intel_dp_compliance.c', @@ -78,14 +76,12 @@ dependencies : tool_deps, install : true, c_args : [ - '-DIGT_DATADIR="@0@"'.format(pkgdatadir), + '-DIGT_DATADIR="@0@"'.format(join_paths(prefix, datadir)), ]) -bindir = join_paths(get_option('prefix'), get_option('bindir')) - install_data('intel_gpu_abrt', install_dir : bindir) -install_subdir('registers', install_dir : pkgdatadir, +install_subdir('registers', install_dir : datadir, exclude_files : [ 'Makefile', 'Makefile.in', 'Makefile.am', ]) @@ -96,10 +92,10 @@ install : true) conf_data = configuration_data() -conf_data.set('prefix', get_option('prefix')) +conf_data.set('prefix', prefix) conf_data.set('exec_prefix', '${prefix}') -conf_data.set('libdir', join_paths('${prefix}', get_option('libdir'))) +conf_data.set('libdir', join_paths('${prefix}', libdir)) configure_file(input : 'intel_aubdump.in', output : 'intel_aubdump', - configuration : conf_data, install_dir : get_option('bindir')) + configuration : conf_data, install_dir : bindir) subdir('null_state_gen')