The workarounds are only valid whilst the GPU is active. To be sure we are reading the registers in the right state, issue the reads from the GPU. Signed-off-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> --- tests/gem_workarounds.c | 138 +++++++++++++++++++++++++++--------------------- 1 file changed, 77 insertions(+), 61 deletions(-) diff --git a/tests/gem_workarounds.c b/tests/gem_workarounds.c index d6641bd5..e5db1b39 100644 --- a/tests/gem_workarounds.c +++ b/tests/gem_workarounds.c @@ -44,66 +44,100 @@ struct intel_wa_reg { static struct intel_wa_reg *wa_regs; static int num_wa_regs; -static void wait_gpu(void) -{ - int fd = drm_open_driver(DRIVER_INTEL); - gem_quiescent_gpu(fd); - close(fd); -} - -static void test_hang_gpu(void) -{ - int fd = drm_open_driver(DRIVER_INTEL); - igt_post_hang_ring(fd, igt_hang_ring(fd, I915_EXEC_DEFAULT)); - close(fd); -} - static void test_suspend_resume(void) { igt_info("Suspending the device ...\n"); igt_system_suspend_autoresume(SUSPEND_STATE_MEM, SUSPEND_TEST_NONE); } -static int workaround_fail_count(void) +#define MI_STORE_REGISTER_MEM (0x24 << 23) + +static int workaround_fail_count(int fd) { - int i, fail_count = 0; + const int gen = intel_gen(intel_get_drm_devid(fd)); + struct drm_i915_gem_exec_object2 obj[2]; + struct drm_i915_gem_relocation_entry *reloc; + struct drm_i915_gem_execbuffer2 execbuf; + uint32_t result_sz, batch_sz; + uint32_t *base, *out; + int fail_count = 0; + + reloc = calloc(num_wa_regs, sizeof(*reloc)); + igt_assert(reloc); + + result_sz = 4 * num_wa_regs; + result_sz = (result_sz + 4095) & -4096; + + batch_sz = 16 * num_wa_regs; + batch_sz = (batch_sz + 4 + 4095) & -4096; + + memset(obj, 0, sizeof(obj)); + obj[0].handle = gem_create(fd, result_sz); + gem_set_caching(fd, obj[0].handle, 1); + obj[1].handle = gem_create(fd, batch_sz); + obj[1].relocs_ptr = to_user_pointer(reloc); + obj[1].relocation_count = num_wa_regs; + + out = base = gem_mmap__cpu(fd, obj[1].handle, 0, batch_sz, PROT_WRITE); + for (int i = 0; i < num_wa_regs; i++) { + *out++ = MI_STORE_REGISTER_MEM | ((gen >= 8 ? 4 : 2) - 2); + *out++ = wa_regs[i].addr; + reloc[i].target_handle = obj[0].handle; + reloc[i].offset = (out - base) * sizeof(*out); + reloc[i].delta = i * sizeof(uint32_t); + reloc[i].read_domains = I915_GEM_DOMAIN_INSTRUCTION; + reloc[i].write_domain = I915_GEM_DOMAIN_INSTRUCTION; + *out++ = reloc[i].delta; + if (gen >= 8) + *out++ = 0; + } + *out++ = MI_BATCH_BUFFER_END; + munmap(base, batch_sz); + + memset(&execbuf, 0, sizeof(execbuf)); + execbuf.buffers_ptr = to_user_pointer(obj); + execbuf.buffer_count = 2; + gem_execbuf(fd, &execbuf); - /* There is a small delay after coming ot of rc6 to the correct - render context values will get loaded by hardware (bdw,chv). - This here ensures that we have the correct context loaded before - we start to read values */ - wait_gpu(); + gem_set_domain(fd, obj[0].handle, I915_GEM_DOMAIN_CPU, 0); igt_debug("Address\tval\t\tmask\t\tread\t\tresult\n"); - for (i = 0; i < num_wa_regs; ++i) { - const uint32_t val = intel_register_read(wa_regs[i].addr); - const bool ok = (wa_regs[i].value & wa_regs[i].mask) == - (val & wa_regs[i].mask); + out = gem_mmap__cpu(fd, obj[0].handle, 0, result_sz, PROT_READ); + for (int i = 0; i < num_wa_regs; i++) { + const bool ok = + (wa_regs[i].value & wa_regs[i].mask) == + (out[i] & wa_regs[i].mask); + char buf[80]; - igt_debug("0x%05X\t0x%08X\t0x%08X\t0x%08X\t%s\n", - wa_regs[i].addr, wa_regs[i].value, wa_regs[i].mask, - val, ok ? "OK" : "FAIL"); + snprintf(buf, sizeof(buf), + "0x%05X\t0x%08X\t0x%08X\t0x%08X", + wa_regs[i].addr, wa_regs[i].value, wa_regs[i].mask, + out[i]); if (!ok) { - igt_warn("0x%05X\t0x%08X\t0x%08X\t0x%08X\t%s\n", - wa_regs[i].addr, wa_regs[i].value, - wa_regs[i].mask, - val, ok ? "OK" : "FAIL"); + igt_warn("%s\tFAIL\n", buf); fail_count++; + } else { + igt_debug("%s\tOK\n", buf); } } + munmap(out, result_sz); + + gem_close(fd, obj[1].handle); + gem_close(fd, obj[0].handle); + free(reloc); return fail_count; } -static void check_workarounds(enum operation op) +static void check_workarounds(int fd, enum operation op) { - igt_assert_eq(workaround_fail_count(), 0); + igt_assert_eq(workaround_fail_count(fd), 0); switch (op) { case GPU_RESET: - test_hang_gpu(); + igt_force_gpu_reset(fd); break; case SUSPEND_RESUME: @@ -117,39 +151,28 @@ static void check_workarounds(enum operation op) igt_assert(0); } - igt_assert_eq(workaround_fail_count(), 0); + igt_assert_eq(workaround_fail_count(fd), 0); } igt_main { + int device = -1; + igt_fixture { - int device = drm_open_driver_master(DRIVER_INTEL); - const int gen = intel_gen(intel_get_drm_devid(device)); - struct pci_device *pci_dev; FILE *file; char *line = NULL; size_t line_size; int i, fd; + device = drm_open_driver(DRIVER_INTEL); igt_require_gem(device); - pci_dev = intel_get_pci_device(); - igt_require(pci_dev); - - intel_register_access_init(pci_dev, 0, device); - fd = igt_debugfs_open(device, "i915_wa_registers", O_RDONLY); file = fdopen(fd, "r"); igt_assert(getline(&line, &line_size, file) > 0); igt_debug("i915_wa_registers: %s", line); sscanf(line, "Workarounds applied: %d", &num_wa_regs); - - /* For newer gens, the lri wa list has always something. - * If it doesn't, go and add one. */ - if (gen >= 8) - igt_assert_lt(0, num_wa_regs); - else - igt_assert_lte(0, num_wa_regs); + igt_require(num_wa_regs > 0); wa_regs = malloc(num_wa_regs * sizeof(*wa_regs)); igt_assert(wa_regs); @@ -169,21 +192,14 @@ igt_main free(line); fclose(file); close(fd); - close(device); } igt_subtest("basic-read") - check_workarounds(SIMPLE_READ); + check_workarounds(device, SIMPLE_READ); igt_subtest("reset") - check_workarounds(GPU_RESET); + check_workarounds(device, GPU_RESET); igt_subtest("suspend-resume") - check_workarounds(SUSPEND_RESUME); - - igt_fixture { - free(wa_regs); - intel_register_access_fini(); - } - + check_workarounds(device, SUSPEND_RESUME); } -- 2.14.2 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx