To check that static workarounds are set and stay after init, hang and suspend/restore. Checks are currently provided for ivb and bdw only. Signed-off-by: Mika Kuoppala <mika.kuoppala@xxxxxxxxx> --- lib/intel_chipset.h | 4 + lib/intel_workaround.h | 142 +++++++++++++++++++++++++++ tests/Makefile.sources | 1 + tests/drv_workarounds.c | 244 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 391 insertions(+) create mode 100644 lib/intel_workaround.h create mode 100644 tests/drv_workarounds.c diff --git a/lib/intel_chipset.h b/lib/intel_chipset.h index 404c632..5a03f2b 100644 --- a/lib/intel_chipset.h +++ b/lib/intel_chipset.h @@ -263,6 +263,10 @@ void intel_check_pch(void); (devid) == PCI_CHIP_IVYBRIDGE_S || \ (devid) == PCI_CHIP_IVYBRIDGE_S_GT2) +#define IS_IVB_GT1(devid) ((devid) == PCI_CHIP_IVYBRIDGE_GT1 || \ + (devid) == PCI_CHIP_IVYBRIDGE_M_GT1 || \ + (devid) == PCI_CHIP_IVYBRIDGE_S) + #define IS_VALLEYVIEW(devid) ((devid) == PCI_CHIP_VALLEYVIEW_PO || \ (devid) == PCI_CHIP_VALLEYVIEW_1 || \ (devid) == PCI_CHIP_VALLEYVIEW_2 || \ diff --git a/lib/intel_workaround.h b/lib/intel_workaround.h new file mode 100644 index 0000000..87e3a44 --- /dev/null +++ b/lib/intel_workaround.h @@ -0,0 +1,142 @@ +/* + * Copyright © 2013,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: + * Mika Kuoppala <mika.kuoppala@xxxxxxxxx> + * + */ + +#ifndef INTEL_WORKAROUNDS +#define INTEL_WORKAROUNDS + +#include "intel_chipset.h" +#include "intel_io.h" +#include "igt_core.h" + +static int __wa_devid = 0; + +struct wa { + const char * const name; + int (*f)(const int devid); +}; + +static void wa_init(const int devid) +{ + __wa_devid = devid; + intel_register_access_init(intel_get_pci_device(), 0); +} + +static void wa_fini(void) +{ + __wa_devid = 0; + intel_register_access_fini(); +} + +static int wa_check(const struct wa *wa) +{ + igt_assert(__wa_devid); + igt_assert(wa->name); + igt_assert(wa->f); + return wa->f(__wa_devid); +} + +#define WA(_name) /* _name */ static int _name##_fun(const int devid); \ + static const struct wa _name = \ + { #_name, _name##_fun }; \ + static int _name##_fun(const int devid) + +#define wa_assert_m(reg, val, mask) { \ + unsigned int x; \ + igt_assert(mask); \ + x = intel_register_read(reg); \ + if (((x) & (mask)) != (val)) { \ + igt_warn("a:0x%08x r:0x%08x m:0%08x v:0%08x\n", reg, x, mask, val); \ + return 1; \ + } \ + } + +#define wa_assert(reg, val) wa_assert_m(reg, val, 0xffffffff) +#define wa_assert_bit_set(reg, bit) wa_assert_m(reg, (1 << bit), (1 << bit)) +#define wa_assert_bit_clr(reg, bit) wa_assert_m(reg, 0, (1 << bit)) + +#define WA_MASK(_name, reg, val, mask) \ + WA(_name) { \ + wa_assert_m(reg, val, mask); \ + return 0; \ + } + +#define WA_BIT_SET(_name, reg, bit) WA_MASK(_name, reg, (1 << bit), (1 << bit)) +#define WA_BIT_CLR(_name, reg, bit) WA_MASK(_name, reg, 0, (1 << bit)) + + +/* *** ivb workarounds ***************************************/ +WA(WaDisablePSDDualDispatchEnable) { + if (IS_IVB_GT1(devid)) + wa_assert_bit_set(0xe100, 3); + + return 0; +} + +WA_BIT_SET(WaFbcAsynchFlipDisableFbcQueue, 0x42000, 22); +WA_BIT_SET(WaDisableEarlyCull, 0x2090, 10); +WA_MASK(WaDisableBackToBackFlipFix, 0x4200c, 1 << 2 | 1 << 5, 1 << 2 | 1 << 5); +WA_BIT_SET(WaDisableRHWOptimizationForRenderHang, 0x7010, 10); + +WA(WaApplyL3ControlAndL3ChickenMode) { + wa_assert_m(0xb01c, 0x3C47FF8C, 0xFFFFFFFF); + wa_assert_m(0xb030, 0x20000000, 0xFFFFFFFF); + + wa_assert_bit_set(0xe4f4, 0); + if (!IS_IVB_GT1(devid)) + wa_assert_bit_set(0xf4f4, 0); + + return 0; +} + +WA_BIT_CLR(WaForceL3Serialization, 0xb034, 27); +WA_BIT_SET(WaDisableRCZUnitClockGating_ivb, 0x9404, 13); +WA_BIT_SET(WaCatErrorRejectionIssue, 0x9030, 11); +WA_BIT_SET(WaDisable4x2SubspanOptimization, 0x7004, 6); +WA_MASK(WaVSThreadDispatchOverride, 0x20a0, 0, (1 << 4) | (1 << 12) | (1 << 16)); +/*************************************************************/ + +/* *** bdw workarounds ***************************************/ +WA_BIT_SET(WaDisablePartialInstShootdown, 0xe4f0, 8); +WA_BIT_SET(WaDisableThreadStallDopClockGating, 0xe4f0, 5); +WA_BIT_SET(WaDisableDopClockGating, 0xe4f4, 0); +WA_BIT_SET(WaSwitchSolVfFArbitrationPriority, 0x4090, 6); +WA_BIT_SET(WaPsrDPAMaskVBlankInSRD, 0x42080, 15); + +WA(WaPsrDPRSUnmaskVBlankInSRD) { + wa_assert_bit_set(0x420b0, 0); + wa_assert_bit_set(0x420b4, 0); + wa_assert_bit_set(0x420b8, 0); + return 0; +} + +WA_BIT_CLR(WaVSRefCountFullforceMissDisable, 0x20a0, 15); +WA_BIT_CLR(WaDSRefCountFullforceMissDisable, 0x20a0, 19); +WA_BIT_SET(WaDisableSDEUnitClockGating, 0x9430, 14); +WA_BIT_SET(Wa4x4STCOptimizationDisable, 0x7004, 6); +/*************************************************************/ + +#endif diff --git a/tests/Makefile.sources b/tests/Makefile.sources index 0eb9369..e87f81d 100644 --- a/tests/Makefile.sources +++ b/tests/Makefile.sources @@ -18,6 +18,7 @@ TESTS_progs_M = \ core_get_client_auth \ drv_suspend \ drv_hangman \ + drv_workarounds \ gem_bad_reloc \ gem_basic \ gem_caching \ diff --git a/tests/drv_workarounds.c b/tests/drv_workarounds.c new file mode 100644 index 0000000..9afce23 --- /dev/null +++ b/tests/drv_workarounds.c @@ -0,0 +1,244 @@ +/* + * 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: + * Mika Kuoppala <mika.kuoppala@xxxxxxxxx> + * + */ + +#include <string.h> +#include "drm.h" +#include "ioctl_wrappers.h" +#include "drmtest.h" +#include "intel_io.h" +#include "igt_debugfs.h" +#include "igt_aux.h" +#include "intel_workaround.h" + +static const struct wa *ivb_workarounds[] = { + &WaDisableEarlyCull, + &WaDisableBackToBackFlipFix, + &WaDisablePSDDualDispatchEnable, + &WaDisableRHWOptimizationForRenderHang, + &WaApplyL3ControlAndL3ChickenMode, + &WaForceL3Serialization, + &WaDisableRCZUnitClockGating_ivb, + &WaCatErrorRejectionIssue, + &WaVSRefCountFullforceMissDisable, + &WaDisable4x2SubspanOptimization, + &WaVSThreadDispatchOverride, + NULL, +}; + +static const struct wa *bdw_workarounds[] = { + &WaDisablePartialInstShootdown, + &WaDisableThreadStallDopClockGating, + &WaDisableDopClockGating, + &WaSwitchSolVfFArbitrationPriority, + &WaPsrDPAMaskVBlankInSRD, + &WaPsrDPRSUnmaskVBlankInSRD, + &WaVSRefCountFullforceMissDisable, + &WaDSRefCountFullforceMissDisable, + &WaDisableSDEUnitClockGating, + &Wa4x4STCOptimizationDisable, + NULL, +}; + +static void strip_arch(const char* testname, const char *arch, char *tmp, int l) +{ + char *p; + int bytes; + + p = strstr(testname, arch); + if (p) + bytes = p - testname - 1; + else + bytes = strlen(testname); + + if (bytes < 0) + bytes = 0; + + if (bytes >= (l-1)) + bytes = l-1; + + strncpy(tmp, testname, bytes); + tmp[bytes] = '\0'; +} + +static int devid; + +static int check_workarounds(const struct wa **workarounds, const char *arch) +{ + const struct wa **p; + char tmpname[256]; + int fail_count = 0, wa_count = 0; + int ret; + p = workarounds; + + wa_init(devid); + + while(*p) { + wa_count++; + ret = wa_check(*p); + strip_arch((*p)->name, arch, tmpname, sizeof(tmpname)); + printf("%-8s %s:%s\n", ret ? "FAIL" : "OK", tmpname, arch); + if (ret) + fail_count++; + p++; + } + + if (fail_count) { + printf("%d workarounds tested, %d passed, %d failed\n", + wa_count, wa_count - fail_count, fail_count); + } + + wa_fini(); + + return fail_count; +} + +#define do_check(was, arch) igt_assert(check_workarounds(was, arch) == 0) + +typedef enum { SIMPLE, HANG, SUSPEND } test_type; + +static int exec(int fd, uint32_t handle) +{ + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_exec_object2 gem_exec[1]; + int ret = 0; + + gem_exec[0].handle = handle; + gem_exec[0].relocation_count = 0; + gem_exec[0].relocs_ptr = 0; + gem_exec[0].alignment = 0; + gem_exec[0].offset = 0; + gem_exec[0].flags = 0; + gem_exec[0].rsvd1 = 0; + gem_exec[0].rsvd2 = 0; + + execbuf.buffers_ptr = (uintptr_t)gem_exec; + execbuf.buffer_count = 1; + execbuf.batch_start_offset = 0; + execbuf.batch_len = 8; + execbuf.cliprects_ptr = 0; + execbuf.num_cliprects = 0; + execbuf.DR1 = 0; + execbuf.DR4 = 0; + execbuf.flags = I915_EXEC_RENDER; + i915_execbuffer2_set_context_id(execbuf, 0); + execbuf.rsvd2 = 0; + + ret = drmIoctl(fd, + DRM_IOCTL_I915_GEM_EXECBUFFER2, + &execbuf); + + gem_sync(fd, handle); + + return ret; +} + +static void exec_nop(void) +{ + uint32_t batch[2] = {MI_BATCH_BUFFER_END}; + uint32_t handle; + int fd; + + fd = drm_open_any(); + + handle = gem_create(fd, 4096); + gem_write(fd, handle, 0, batch, sizeof(batch)); + + igt_assert(exec(fd, handle) == 0); +} + +static void do_hang(void) +{ + int timeout = 300; + + igt_set_stop_rings(STOP_RING_DEFAULTS); + exec_nop(); + while (timeout-- && igt_get_stop_rings()) + usleep(1000 * 100); +} + +static void do_test(const struct wa **workarounds, const char *arch, test_type tt) +{ + do_check(workarounds, arch); + + switch (tt) { + case SIMPLE: + return; + + case HANG: + do_hang(); + break; + + case SUSPEND: + igt_system_suspend_autoresume(); + break; + } + + do_check(workarounds, arch); +} + +static void wa_check_ivb_t(test_type t) +{ + igt_require(intel_gen(devid) == 7); + do_test(&ivb_workarounds[0], "ivb", t); +} + +static void wa_check_bdw_t(test_type t) +{ + igt_require(IS_BROADWELL(devid)); + do_test(&bdw_workarounds[0], "bdw", t); +} + +static struct subtypes { + test_type type; + const char *name; +} stypes[] = { + { SIMPLE, "simple" }, + { HANG, "hang" }, + { SUSPEND, "suspend" }, +}; + +#define WA_TESTS(x) { for (int i = 0; i < sizeof(stypes)/sizeof(struct subtypes); i++) { \ + igt_subtest_f("wa-%s-%s", #x, stypes[i].name) \ + wa_check_ ## x ## _t(stypes[i].type); \ + } \ + } + +igt_main +{ + igt_fixture { + int fd; + + fd = drm_open_any(); + devid = intel_get_drm_devid(fd); + close(fd); + + igt_skip_on(!IS_INTEL(devid)); + } + + WA_TESTS(ivb); + WA_TESTS(bdw); +} -- 1.7.9.5 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx