[PATCH 6/6] lrm-literestore
Chris Wilson
chris at chris-wilson.co.uk
Sun Feb 9 18:35:01 UTC 2020
---
drivers/gpu/drm/i915/gt/intel_engine.h | 20 ---
drivers/gpu/drm/i915/gt/intel_engine_types.h | 1 -
drivers/gpu/drm/i915/gt/intel_lrc.c | 105 ++++++++++++++--
drivers/gpu/drm/i915/gt/selftest_lrc.c | 122 -------------------
4 files changed, 94 insertions(+), 154 deletions(-)
diff --git a/drivers/gpu/drm/i915/gt/intel_engine.h b/drivers/gpu/drm/i915/gt/intel_engine.h
index b36ec1fddc3d..29c8c03c5caa 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine.h
+++ b/drivers/gpu/drm/i915/gt/intel_engine.h
@@ -305,26 +305,6 @@ intel_engine_find_active_request(struct intel_engine_cs *engine);
u32 intel_engine_context_size(struct intel_gt *gt, u8 class);
-#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
-
-static inline bool inject_preempt_hang(struct intel_engine_execlists *execlists)
-{
- if (!execlists->preempt_hang.inject_hang)
- return false;
-
- complete(&execlists->preempt_hang.completion);
- return true;
-}
-
-#else
-
-static inline bool inject_preempt_hang(struct intel_engine_execlists *execlists)
-{
- return false;
-}
-
-#endif
-
void intel_engine_init_active(struct intel_engine_cs *engine,
unsigned int subclass);
#define ENGINE_PHYSICAL 0
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h
index 8eb7365b4230..24cff658e6e5 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h
@@ -127,7 +127,6 @@ DECLARE_EWMA(_engine_latency, 6, 4)
struct st_preempt_hang {
struct completion completion;
unsigned int count;
- bool inject_hang;
};
/**
diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c
index 4b6a707e7268..6ada30a0062a 100644
--- a/drivers/gpu/drm/i915/gt/intel_lrc.c
+++ b/drivers/gpu/drm/i915/gt/intel_lrc.c
@@ -1797,6 +1797,74 @@ static inline void clear_ports(struct i915_request **ports, int count)
memset_p((void **)ports, NULL, count);
}
+static struct i915_request *
+skip_lite_restore(struct intel_engine_cs *const engine,
+ struct i915_request *first,
+ bool *submit)
+{
+ struct intel_engine_execlists *const execlists = &engine->execlists;
+ struct i915_request *last = first;
+ struct rb_node *rb;
+
+ if (!intel_engine_has_semaphores(engine))
+ return last;
+
+ GEM_BUG_ON(*submit);
+ while ((rb = rb_first_cached(&execlists->queue))) {
+ struct i915_priolist *p = to_priolist(rb);
+ struct i915_request *rq, *rn;
+ int i;
+
+ priolist_for_each_request_consume(rq, rn, p, i) {
+ if (!can_merge_rq(last, rq))
+ goto out;
+
+ if (__i915_request_submit(rq)) {
+ *submit = true;
+ last = rq;
+ }
+ }
+
+ rb_erase_cached(&p->node, &execlists->queue);
+ i915_priolist_free(p);
+ }
+out:
+ if (*submit) {
+ ring_set_paused(engine, 1);
+
+ /*
+ * If we are quick and the current context hasn't yet completed
+ * its request, we can just tell it to extend the RING_TAIL
+ * onto the next without having to submit a new ELSP.
+ */
+ if (!i915_request_completed(first)) {
+ struct i915_request **port;
+
+ ENGINE_TRACE(engine,
+ "eliding lite-restore last=%llx:%lld->%lld, current %d\n",
+ first->fence.context,
+ first->fence.seqno,
+ last->fence.seqno,
+ hwsp_seqno(last));
+ GEM_BUG_ON(first->context != last->context);
+
+ execlists_update_context(last);
+ for (port = (struct i915_request **)execlists->active;
+ *port != first;
+ port++)
+ ;
+ WRITE_ONCE(*port, i915_request_get(last));
+ i915_request_put(first);
+
+ *submit = false;
+ }
+
+ ring_set_paused(engine, 0);
+ }
+
+ return last;
+}
+
static void execlists_dequeue(struct intel_engine_cs *engine)
{
struct intel_engine_execlists * const execlists = &engine->execlists;
@@ -1934,6 +2002,8 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
return;
}
+
+ last = skip_lite_restore(engine, last, &submit);
}
}
@@ -2155,10 +2225,10 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
WRITE_ONCE(execlists->yield, -1);
execlists_submit_ports(engine);
set_preempt_timeout(engine);
- } else {
-skip_submit:
- ring_set_paused(engine, 0);
}
+
+skip_submit:
+ ring_set_paused(engine, 0);
}
static void
@@ -2323,19 +2393,17 @@ static void process_csb(struct intel_engine_cs *engine)
if (promote) {
struct i915_request * const *old = execlists->active;
+ GEM_BUG_ON(!assert_pending_valid(execlists, "promote"));
+
/* Point active to the new ELSP; prevent overwriting */
WRITE_ONCE(execlists->active, execlists->pending);
- if (!inject_preempt_hang(execlists))
- ring_set_paused(engine, 0);
-
/* cancel old inflight, prepare for switch */
trace_ports(execlists, "preempted", old);
while (*old)
execlists_schedule_out(*old++);
/* switch pending to inflight */
- GEM_BUG_ON(!assert_pending_valid(execlists, "promote"));
WRITE_ONCE(execlists->active,
memcpy(execlists->inflight,
execlists->pending,
@@ -4122,15 +4190,28 @@ static u32 *emit_preempt_busywait(struct i915_request *request, u32 *cs)
return cs;
}
+static u32 *emit_lrm_tail(struct i915_request *request, u32 *cs)
+{
+ *cs++ = MI_LOAD_REGISTER_MEM_GEN8 | MI_USE_GGTT;
+ *cs++ = i915_mmio_reg_offset(RING_TAIL(request->engine->mmio_base));
+ *cs++ = i915_ggtt_offset(request->context->state) +
+ LRC_STATE_PN * PAGE_SIZE +
+ CTX_RING_TAIL * sizeof(u32);
+ *cs++ = 0;
+
+ return cs;
+}
+
static __always_inline u32*
-gen8_emit_fini_breadcrumb_footer(struct i915_request *request,
- u32 *cs)
+gen8_emit_fini_breadcrumb_footer(struct i915_request *request, u32 *cs)
{
*cs++ = MI_USER_INTERRUPT;
*cs++ = MI_ARB_ON_OFF | MI_ARB_ENABLE;
- if (intel_engine_has_semaphores(request->engine))
+ if (intel_engine_has_semaphores(request->engine)) {
cs = emit_preempt_busywait(request, cs);
+ cs = emit_lrm_tail(request, cs);
+ }
request->tail = intel_ring_offset(request, cs);
assert_ring_tail_valid(request->ring, request->tail);
@@ -4222,8 +4303,10 @@ gen12_emit_fini_breadcrumb_footer(struct i915_request *request, u32 *cs)
*cs++ = MI_USER_INTERRUPT;
*cs++ = MI_ARB_ON_OFF | MI_ARB_ENABLE;
- if (intel_engine_has_semaphores(request->engine))
+ if (intel_engine_has_semaphores(request->engine)) {
cs = gen12_emit_preempt_busywait(request, cs);
+ cs = emit_lrm_tail(request, cs);
+ }
request->tail = intel_ring_offset(request, cs);
assert_ring_tail_valid(request->ring, request->tail);
diff --git a/drivers/gpu/drm/i915/gt/selftest_lrc.c b/drivers/gpu/drm/i915/gt/selftest_lrc.c
index 09657bb16523..75d2e81433e0 100644
--- a/drivers/gpu/drm/i915/gt/selftest_lrc.c
+++ b/drivers/gpu/drm/i915/gt/selftest_lrc.c
@@ -2636,127 +2636,6 @@ static int live_preempt_gang(void *arg)
return 0;
}
-static int live_preempt_hang(void *arg)
-{
- struct intel_gt *gt = arg;
- struct i915_gem_context *ctx_hi, *ctx_lo;
- struct igt_spinner spin_hi, spin_lo;
- struct intel_engine_cs *engine;
- enum intel_engine_id id;
- int err = -ENOMEM;
-
- if (!HAS_LOGICAL_RING_PREEMPTION(gt->i915))
- return 0;
-
- if (!intel_has_reset_engine(gt))
- return 0;
-
- if (igt_spinner_init(&spin_hi, gt))
- return -ENOMEM;
-
- if (igt_spinner_init(&spin_lo, gt))
- goto err_spin_hi;
-
- ctx_hi = kernel_context(gt->i915);
- if (!ctx_hi)
- goto err_spin_lo;
- ctx_hi->sched.priority =
- I915_USER_PRIORITY(I915_CONTEXT_MAX_USER_PRIORITY);
-
- ctx_lo = kernel_context(gt->i915);
- if (!ctx_lo)
- goto err_ctx_hi;
- ctx_lo->sched.priority =
- I915_USER_PRIORITY(I915_CONTEXT_MIN_USER_PRIORITY);
-
- for_each_engine(engine, gt, id) {
- unsigned long heartbeat;
- struct i915_request *rq;
-
- if (!intel_engine_has_preemption(engine))
- continue;
-
- engine_heartbeat_disable(engine, &heartbeat);
-
- rq = spinner_create_request(&spin_lo, ctx_lo, engine,
- MI_ARB_CHECK);
- if (IS_ERR(rq)) {
- err = PTR_ERR(rq);
- engine_heartbeat_enable(engine, heartbeat);
- goto err_ctx_lo;
- }
-
- i915_request_add(rq);
- if (!igt_wait_for_spinner(&spin_lo, rq)) {
- GEM_TRACE("lo spinner failed to start\n");
- GEM_TRACE_DUMP();
- intel_gt_set_wedged(gt);
- err = -EIO;
- engine_heartbeat_enable(engine, heartbeat);
- goto err_ctx_lo;
- }
-
- rq = spinner_create_request(&spin_hi, ctx_hi, engine,
- MI_ARB_CHECK);
- if (IS_ERR(rq)) {
- igt_spinner_end(&spin_lo);
- engine_heartbeat_enable(engine, heartbeat);
- err = PTR_ERR(rq);
- goto err_ctx_lo;
- }
-
- init_completion(&engine->execlists.preempt_hang.completion);
- engine->execlists.preempt_hang.inject_hang = true;
-
- i915_request_add(rq);
-
- if (!wait_for_completion_timeout(&engine->execlists.preempt_hang.completion,
- HZ / 10)) {
- pr_err("Preemption did not occur within timeout!");
- GEM_TRACE_DUMP();
- intel_gt_set_wedged(gt);
- engine_heartbeat_enable(engine, heartbeat);
- err = -EIO;
- goto err_ctx_lo;
- }
-
- set_bit(I915_RESET_ENGINE + id, >->reset.flags);
- intel_engine_reset(engine, NULL);
- clear_bit(I915_RESET_ENGINE + id, >->reset.flags);
-
- engine->execlists.preempt_hang.inject_hang = false;
-
- if (!igt_wait_for_spinner(&spin_hi, rq)) {
- GEM_TRACE("hi spinner failed to start\n");
- GEM_TRACE_DUMP();
- intel_gt_set_wedged(gt);
- engine_heartbeat_enable(engine, heartbeat);
- err = -EIO;
- goto err_ctx_lo;
- }
-
- igt_spinner_end(&spin_hi);
- igt_spinner_end(&spin_lo);
- engine_heartbeat_enable(engine, heartbeat);
-
- if (igt_flush_test(gt->i915)) {
- err = -EIO;
- goto err_ctx_lo;
- }
- }
-
- err = 0;
-err_ctx_lo:
- kernel_context_close(ctx_lo);
-err_ctx_hi:
- kernel_context_close(ctx_hi);
-err_spin_lo:
- igt_spinner_fini(&spin_lo);
-err_spin_hi:
- igt_spinner_fini(&spin_hi);
- return err;
-}
-
static int live_preempt_timeout(void *arg)
{
struct intel_gt *gt = arg;
@@ -3962,7 +3841,6 @@ int intel_execlists_live_selftests(struct drm_i915_private *i915)
SUBTEST(live_suppress_wait_preempt),
SUBTEST(live_chain_preempt),
SUBTEST(live_preempt_gang),
- SUBTEST(live_preempt_hang),
SUBTEST(live_preempt_timeout),
SUBTEST(live_preempt_smoke),
SUBTEST(live_virtual_engine),
--
2.25.0
More information about the Intel-gfx-trybot
mailing list