This reverts686c7c35ab
("drm/i915/gem: Asynchronous cmdparser"). The justification for this commit in the git history was a vague comment about getting it out from under the struct_mutex. While this may improve perf for some workloads on Gen7 platforms where we rely on the command parser for features such as indirect rendering, no numbers were provided to prove such an improvement. It claims to closed two gitlab/bugzilla issues but with no explanation whatsoever as to why or what bug it's fixing. Meanwhile, by moving command parsing off to an async callback, it leaves us with a problem of what to do on error. When things were synchronous, EXECBUFFER2 would fail with an error code if parsing failed. When moving it to async, we needed another way to handle that error and the solution employed was to set an error on the dma_fence and then trust that said error gets propagated to the client eventually. Moving back to synchronous will help us untangle the fence error propagation mess. This also reverts most of0edbb9ba1b
("drm/i915: Move cmd parser pinning to execbuffer") which is a refactor of some of our allocation paths for asynchronous parsing. Now that everything is synchronous, we don't need it. v2 (Daniel Vetter): - Add stabel Cc and Fixes tag Signed-off-by: Jason Ekstrand <jason@jlekstrand.net> Cc: <stable@vger.kernel.org> # v5.6+ Fixes:9e31c1fe45
("drm/i915: Propagate errors on awaiting already signaled fences") Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Jon Bloomfield <jon.bloomfield@intel.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20210714193419.1459723-2-jason@jlekstrand.net (cherry picked from commit93b7133041
) Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
191 lines
4.0 KiB
C
191 lines
4.0 KiB
C
// SPDX-License-Identifier: MIT
|
|
/*
|
|
* Copyright © 2020 Intel Corporation
|
|
*/
|
|
|
|
#include "i915_selftest.h"
|
|
|
|
#include "gt/intel_engine_pm.h"
|
|
#include "selftests/igt_flush_test.h"
|
|
|
|
static u64 read_reloc(const u32 *map, int x, const u64 mask)
|
|
{
|
|
u64 reloc;
|
|
|
|
memcpy(&reloc, &map[x], sizeof(reloc));
|
|
return reloc & mask;
|
|
}
|
|
|
|
static int __igt_gpu_reloc(struct i915_execbuffer *eb,
|
|
struct drm_i915_gem_object *obj)
|
|
{
|
|
const unsigned int offsets[] = { 8, 3, 0 };
|
|
const u64 mask =
|
|
GENMASK_ULL(eb->reloc_cache.use_64bit_reloc ? 63 : 31, 0);
|
|
const u32 *map = page_mask_bits(obj->mm.mapping);
|
|
struct i915_request *rq;
|
|
struct i915_vma *vma;
|
|
int err;
|
|
int i;
|
|
|
|
vma = i915_vma_instance(obj, eb->context->vm, NULL);
|
|
if (IS_ERR(vma))
|
|
return PTR_ERR(vma);
|
|
|
|
err = i915_gem_object_lock(obj, &eb->ww);
|
|
if (err)
|
|
return err;
|
|
|
|
err = i915_vma_pin_ww(vma, &eb->ww, 0, 0, PIN_USER | PIN_HIGH);
|
|
if (err)
|
|
return err;
|
|
|
|
/* 8-Byte aligned */
|
|
err = __reloc_entry_gpu(eb, vma, offsets[0] * sizeof(u32), 0);
|
|
if (err <= 0)
|
|
goto reloc_err;
|
|
|
|
/* !8-Byte aligned */
|
|
err = __reloc_entry_gpu(eb, vma, offsets[1] * sizeof(u32), 1);
|
|
if (err <= 0)
|
|
goto reloc_err;
|
|
|
|
/* Skip to the end of the cmd page */
|
|
i = PAGE_SIZE / sizeof(u32) - 1;
|
|
i -= eb->reloc_cache.rq_size;
|
|
memset32(eb->reloc_cache.rq_cmd + eb->reloc_cache.rq_size,
|
|
MI_NOOP, i);
|
|
eb->reloc_cache.rq_size += i;
|
|
|
|
/* Force next batch */
|
|
err = __reloc_entry_gpu(eb, vma, offsets[2] * sizeof(u32), 2);
|
|
if (err <= 0)
|
|
goto reloc_err;
|
|
|
|
GEM_BUG_ON(!eb->reloc_cache.rq);
|
|
rq = i915_request_get(eb->reloc_cache.rq);
|
|
reloc_gpu_flush(eb, &eb->reloc_cache);
|
|
GEM_BUG_ON(eb->reloc_cache.rq);
|
|
|
|
err = i915_gem_object_wait(obj, I915_WAIT_INTERRUPTIBLE, HZ / 2);
|
|
if (err) {
|
|
intel_gt_set_wedged(eb->engine->gt);
|
|
goto put_rq;
|
|
}
|
|
|
|
if (!i915_request_completed(rq)) {
|
|
pr_err("%s: did not wait for relocations!\n", eb->engine->name);
|
|
err = -EINVAL;
|
|
goto put_rq;
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_SIZE(offsets); i++) {
|
|
u64 reloc = read_reloc(map, offsets[i], mask);
|
|
|
|
if (reloc != i) {
|
|
pr_err("%s[%d]: map[%d] %llx != %x\n",
|
|
eb->engine->name, i, offsets[i], reloc, i);
|
|
err = -EINVAL;
|
|
}
|
|
}
|
|
if (err)
|
|
igt_hexdump(map, 4096);
|
|
|
|
put_rq:
|
|
i915_request_put(rq);
|
|
unpin_vma:
|
|
i915_vma_unpin(vma);
|
|
return err;
|
|
|
|
reloc_err:
|
|
if (!err)
|
|
err = -EIO;
|
|
goto unpin_vma;
|
|
}
|
|
|
|
static int igt_gpu_reloc(void *arg)
|
|
{
|
|
struct i915_execbuffer eb;
|
|
struct drm_i915_gem_object *scratch;
|
|
int err = 0;
|
|
u32 *map;
|
|
|
|
eb.i915 = arg;
|
|
|
|
scratch = i915_gem_object_create_internal(eb.i915, 4096);
|
|
if (IS_ERR(scratch))
|
|
return PTR_ERR(scratch);
|
|
|
|
map = i915_gem_object_pin_map_unlocked(scratch, I915_MAP_WC);
|
|
if (IS_ERR(map)) {
|
|
err = PTR_ERR(map);
|
|
goto err_scratch;
|
|
}
|
|
|
|
intel_gt_pm_get(&eb.i915->gt);
|
|
|
|
for_each_uabi_engine(eb.engine, eb.i915) {
|
|
if (intel_engine_requires_cmd_parser(eb.engine) ||
|
|
intel_engine_using_cmd_parser(eb.engine))
|
|
continue;
|
|
|
|
reloc_cache_init(&eb.reloc_cache, eb.i915);
|
|
memset(map, POISON_INUSE, 4096);
|
|
|
|
intel_engine_pm_get(eb.engine);
|
|
eb.context = intel_context_create(eb.engine);
|
|
if (IS_ERR(eb.context)) {
|
|
err = PTR_ERR(eb.context);
|
|
goto err_pm;
|
|
}
|
|
eb.reloc_pool = NULL;
|
|
eb.reloc_context = NULL;
|
|
|
|
i915_gem_ww_ctx_init(&eb.ww, false);
|
|
retry:
|
|
err = intel_context_pin_ww(eb.context, &eb.ww);
|
|
if (!err) {
|
|
err = __igt_gpu_reloc(&eb, scratch);
|
|
|
|
intel_context_unpin(eb.context);
|
|
}
|
|
if (err == -EDEADLK) {
|
|
err = i915_gem_ww_ctx_backoff(&eb.ww);
|
|
if (!err)
|
|
goto retry;
|
|
}
|
|
i915_gem_ww_ctx_fini(&eb.ww);
|
|
|
|
if (eb.reloc_pool)
|
|
intel_gt_buffer_pool_put(eb.reloc_pool);
|
|
if (eb.reloc_context)
|
|
intel_context_put(eb.reloc_context);
|
|
|
|
intel_context_put(eb.context);
|
|
err_pm:
|
|
intel_engine_pm_put(eb.engine);
|
|
if (err)
|
|
break;
|
|
}
|
|
|
|
if (igt_flush_test(eb.i915))
|
|
err = -EIO;
|
|
|
|
intel_gt_pm_put(&eb.i915->gt);
|
|
err_scratch:
|
|
i915_gem_object_put(scratch);
|
|
return err;
|
|
}
|
|
|
|
int i915_gem_execbuffer_live_selftests(struct drm_i915_private *i915)
|
|
{
|
|
static const struct i915_subtest tests[] = {
|
|
SUBTEST(igt_gpu_reloc),
|
|
};
|
|
|
|
if (intel_gt_is_wedged(&i915->gt))
|
|
return 0;
|
|
|
|
return i915_live_subtests(tests, i915);
|
|
}
|