mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git
synced 2026-04-18 03:23:53 -04:00
drm/i915/selftests: Add a cancel request selftest that triggers a reset
Add a cancel request selftest that results in an engine reset to cancel the request as it is non-preemptable. Also insert a NOP request after the cancelled request and confirm that it completes successfully. v2: (Tvrtko) - Skip test if preemption timeout compiled out - Skip test if engine reset isn't supported - Update debug prints to be more descriptive v3: - Add comment explaining test v4: (John Harrison) - Fix typos in comment explaining test - goto out_rq is NOP creation fails Signed-off-by: Matthew Brost <matthew.brost@intel.com> Reviewed-by: John Harrison <John.C.Harrison@Intel.com> Signed-off-by: John Harrison <John.C.Harrison@Intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20220113181351.21296-2-matthew.brost@intel.com
This commit is contained in:
committed by
John Harrison
parent
b5cfe6f7a6
commit
4e68354667
@@ -782,6 +782,115 @@ out_spin:
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test to prove a non-preemptable request can be cancelled and a subsequent
|
||||
* request on the same context can successfully complete after cancellation.
|
||||
*
|
||||
* Testing methodology is to create a non-preemptible request and submit it,
|
||||
* wait for spinner to start, create a NOP request and submit it, cancel the
|
||||
* spinner, wait for spinner to complete and verify it failed with an error,
|
||||
* finally wait for NOP request to complete verify it succeeded without an
|
||||
* error. Preemption timeout also reduced / restored so test runs in a timely
|
||||
* maner.
|
||||
*/
|
||||
static int __cancel_reset(struct drm_i915_private *i915,
|
||||
struct intel_engine_cs *engine)
|
||||
{
|
||||
struct intel_context *ce;
|
||||
struct igt_spinner spin;
|
||||
struct i915_request *rq, *nop;
|
||||
unsigned long preempt_timeout_ms;
|
||||
int err = 0;
|
||||
|
||||
if (!CONFIG_DRM_I915_PREEMPT_TIMEOUT ||
|
||||
!intel_has_reset_engine(engine->gt))
|
||||
return 0;
|
||||
|
||||
preempt_timeout_ms = engine->props.preempt_timeout_ms;
|
||||
engine->props.preempt_timeout_ms = 100;
|
||||
|
||||
if (igt_spinner_init(&spin, engine->gt))
|
||||
goto out_restore;
|
||||
|
||||
ce = intel_context_create(engine);
|
||||
if (IS_ERR(ce)) {
|
||||
err = PTR_ERR(ce);
|
||||
goto out_spin;
|
||||
}
|
||||
|
||||
rq = igt_spinner_create_request(&spin, ce, MI_NOOP);
|
||||
if (IS_ERR(rq)) {
|
||||
err = PTR_ERR(rq);
|
||||
goto out_ce;
|
||||
}
|
||||
|
||||
pr_debug("%s: Cancelling active non-preemptable request\n",
|
||||
engine->name);
|
||||
i915_request_get(rq);
|
||||
i915_request_add(rq);
|
||||
if (!igt_wait_for_spinner(&spin, rq)) {
|
||||
struct drm_printer p = drm_info_printer(engine->i915->drm.dev);
|
||||
|
||||
pr_err("Failed to start spinner on %s\n", engine->name);
|
||||
intel_engine_dump(engine, &p, "%s\n", engine->name);
|
||||
err = -ETIME;
|
||||
goto out_rq;
|
||||
}
|
||||
|
||||
nop = intel_context_create_request(ce);
|
||||
if (IS_ERR(nop))
|
||||
goto out_rq;
|
||||
i915_request_get(nop);
|
||||
i915_request_add(nop);
|
||||
|
||||
i915_request_cancel(rq, -EINTR);
|
||||
|
||||
if (i915_request_wait(rq, 0, HZ) < 0) {
|
||||
struct drm_printer p = drm_info_printer(engine->i915->drm.dev);
|
||||
|
||||
pr_err("%s: Failed to cancel hung request\n", engine->name);
|
||||
intel_engine_dump(engine, &p, "%s\n", engine->name);
|
||||
err = -ETIME;
|
||||
goto out_nop;
|
||||
}
|
||||
|
||||
if (rq->fence.error != -EINTR) {
|
||||
pr_err("%s: fence not cancelled (%u)\n",
|
||||
engine->name, rq->fence.error);
|
||||
err = -EINVAL;
|
||||
goto out_nop;
|
||||
}
|
||||
|
||||
if (i915_request_wait(nop, 0, HZ) < 0) {
|
||||
struct drm_printer p = drm_info_printer(engine->i915->drm.dev);
|
||||
|
||||
pr_err("%s: Failed to complete nop request\n", engine->name);
|
||||
intel_engine_dump(engine, &p, "%s\n", engine->name);
|
||||
err = -ETIME;
|
||||
goto out_nop;
|
||||
}
|
||||
|
||||
if (nop->fence.error != 0) {
|
||||
pr_err("%s: Nop request errored (%u)\n",
|
||||
engine->name, nop->fence.error);
|
||||
err = -EINVAL;
|
||||
}
|
||||
|
||||
out_nop:
|
||||
i915_request_put(nop);
|
||||
out_rq:
|
||||
i915_request_put(rq);
|
||||
out_ce:
|
||||
intel_context_put(ce);
|
||||
out_spin:
|
||||
igt_spinner_fini(&spin);
|
||||
out_restore:
|
||||
engine->props.preempt_timeout_ms = preempt_timeout_ms;
|
||||
if (err)
|
||||
pr_err("%s: %s error %d\n", __func__, engine->name, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int live_cancel_request(void *arg)
|
||||
{
|
||||
struct drm_i915_private *i915 = arg;
|
||||
@@ -814,6 +923,14 @@ static int live_cancel_request(void *arg)
|
||||
return err;
|
||||
if (err2)
|
||||
return err2;
|
||||
|
||||
/* Expects reset so call outside of igt_live_test_* */
|
||||
err = __cancel_reset(i915, engine);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (igt_flush_test(i915))
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user