Commit 1bc6a601 authored by Chris Wilson's avatar Chris Wilson Committed by Rodrigo Vivi

drm/i915/execlists: Track inflight CCID

The presumption is that by using a circular counter that is twice as
large as the maximum ELSP submission, we would never reuse the same CCID
for two inflight contexts.

However, if we continually preempt an active context such that it always
remains inflight, it can be resubmitted with an arbitrary number of
paired contexts. As each of its paired contexts will use a new CCID,
eventually it will wrap and submit two ELSP with the same CCID.

Rather than use a simple circular counter, switch over to a small bitmap
of inflight ids so we can avoid reusing one that is still potentially
active.

Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/1796
Fixes: 2935ed53 ("drm/i915: Remove logical HW ID")
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Cc: <stable@vger.kernel.org> # v5.5+
Reviewed-by: default avatarMika Kuoppala <mika.kuoppala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200428184751.11257-2-chris@chris-wilson.co.uk
(cherry picked from commit 5c4a53e3)
(cherry picked from commit 134711240307d5586ae8e828d2699db70a8b74f2)
Signed-off-by: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
parent 53b2622e
...@@ -309,8 +309,7 @@ struct intel_engine_cs { ...@@ -309,8 +309,7 @@ struct intel_engine_cs {
u32 context_size; u32 context_size;
u32 mmio_base; u32 mmio_base;
unsigned int context_tag; unsigned long context_tag;
#define NUM_CONTEXT_TAG roundup_pow_of_two(2 * EXECLIST_MAX_PORTS)
struct rb_node uabi_node; struct rb_node uabi_node;
......
...@@ -1239,13 +1239,17 @@ __execlists_schedule_in(struct i915_request *rq) ...@@ -1239,13 +1239,17 @@ __execlists_schedule_in(struct i915_request *rq)
if (ce->tag) { if (ce->tag) {
/* Use a fixed tag for OA and friends */ /* Use a fixed tag for OA and friends */
GEM_BUG_ON(ce->tag <= BITS_PER_LONG);
ce->lrc.ccid = ce->tag; ce->lrc.ccid = ce->tag;
} else { } else {
/* We don't need a strict matching tag, just different values */ /* We don't need a strict matching tag, just different values */
ce->lrc.ccid = unsigned int tag = ffs(engine->context_tag);
(++engine->context_tag % NUM_CONTEXT_TAG) <<
(GEN11_SW_CTX_ID_SHIFT - 32); GEM_BUG_ON(tag == 0 || tag >= BITS_PER_LONG);
BUILD_BUG_ON(NUM_CONTEXT_TAG > GEN12_MAX_CONTEXT_HW_ID); clear_bit(tag - 1, &engine->context_tag);
ce->lrc.ccid = tag << (GEN11_SW_CTX_ID_SHIFT - 32);
BUILD_BUG_ON(BITS_PER_LONG > GEN12_MAX_CONTEXT_HW_ID);
} }
ce->lrc.ccid |= engine->execlists.ccid; ce->lrc.ccid |= engine->execlists.ccid;
...@@ -1289,7 +1293,8 @@ static void kick_siblings(struct i915_request *rq, struct intel_context *ce) ...@@ -1289,7 +1293,8 @@ static void kick_siblings(struct i915_request *rq, struct intel_context *ce)
static inline void static inline void
__execlists_schedule_out(struct i915_request *rq, __execlists_schedule_out(struct i915_request *rq,
struct intel_engine_cs * const engine) struct intel_engine_cs * const engine,
unsigned int ccid)
{ {
struct intel_context * const ce = rq->context; struct intel_context * const ce = rq->context;
...@@ -1307,6 +1312,14 @@ __execlists_schedule_out(struct i915_request *rq, ...@@ -1307,6 +1312,14 @@ __execlists_schedule_out(struct i915_request *rq,
i915_request_completed(rq)) i915_request_completed(rq))
intel_engine_add_retire(engine, ce->timeline); intel_engine_add_retire(engine, ce->timeline);
ccid >>= GEN11_SW_CTX_ID_SHIFT - 32;
ccid &= GEN12_MAX_CONTEXT_HW_ID;
if (ccid < BITS_PER_LONG) {
GEM_BUG_ON(ccid == 0);
GEM_BUG_ON(test_bit(ccid - 1, &engine->context_tag));
set_bit(ccid - 1, &engine->context_tag);
}
intel_context_update_runtime(ce); intel_context_update_runtime(ce);
intel_engine_context_out(engine); intel_engine_context_out(engine);
execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_OUT); execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_OUT);
...@@ -1332,15 +1345,17 @@ execlists_schedule_out(struct i915_request *rq) ...@@ -1332,15 +1345,17 @@ execlists_schedule_out(struct i915_request *rq)
{ {
struct intel_context * const ce = rq->context; struct intel_context * const ce = rq->context;
struct intel_engine_cs *cur, *old; struct intel_engine_cs *cur, *old;
u32 ccid;
trace_i915_request_out(rq); trace_i915_request_out(rq);
ccid = rq->context->lrc.ccid;
old = READ_ONCE(ce->inflight); old = READ_ONCE(ce->inflight);
do do
cur = ptr_unmask_bits(old, 2) ? ptr_dec(old) : NULL; cur = ptr_unmask_bits(old, 2) ? ptr_dec(old) : NULL;
while (!try_cmpxchg(&ce->inflight, &old, cur)); while (!try_cmpxchg(&ce->inflight, &old, cur));
if (!cur) if (!cur)
__execlists_schedule_out(rq, old); __execlists_schedule_out(rq, old, ccid);
i915_request_put(rq); i915_request_put(rq);
} }
...@@ -3556,7 +3571,7 @@ static void enable_execlists(struct intel_engine_cs *engine) ...@@ -3556,7 +3571,7 @@ static void enable_execlists(struct intel_engine_cs *engine)
enable_error_interrupt(engine); enable_error_interrupt(engine);
engine->context_tag = 0; engine->context_tag = GENMASK(BITS_PER_LONG - 2, 0);
} }
static bool unexpected_starting_state(struct intel_engine_cs *engine) static bool unexpected_starting_state(struct intel_engine_cs *engine)
......
...@@ -1327,11 +1327,10 @@ static int oa_get_render_ctx_id(struct i915_perf_stream *stream) ...@@ -1327,11 +1327,10 @@ static int oa_get_render_ctx_id(struct i915_perf_stream *stream)
((1U << GEN11_SW_CTX_ID_WIDTH) - 1) << (GEN11_SW_CTX_ID_SHIFT - 32); ((1U << GEN11_SW_CTX_ID_WIDTH) - 1) << (GEN11_SW_CTX_ID_SHIFT - 32);
/* /*
* Pick an unused context id * Pick an unused context id
* 0 - (NUM_CONTEXT_TAG - 1) are used by other contexts * 0 - BITS_PER_LONG are used by other contexts
* GEN12_MAX_CONTEXT_HW_ID (0x7ff) is used by idle context * GEN12_MAX_CONTEXT_HW_ID (0x7ff) is used by idle context
*/ */
stream->specific_ctx_id = (GEN12_MAX_CONTEXT_HW_ID - 1) << (GEN11_SW_CTX_ID_SHIFT - 32); stream->specific_ctx_id = (GEN12_MAX_CONTEXT_HW_ID - 1) << (GEN11_SW_CTX_ID_SHIFT - 32);
BUILD_BUG_ON((GEN12_MAX_CONTEXT_HW_ID - 1) < NUM_CONTEXT_TAG);
break; break;
} }
......
...@@ -173,7 +173,7 @@ static int igt_vma_create(void *arg) ...@@ -173,7 +173,7 @@ static int igt_vma_create(void *arg)
} }
nc = 0; nc = 0;
for_each_prime_number(num_ctx, 2 * NUM_CONTEXT_TAG) { for_each_prime_number(num_ctx, 2 * BITS_PER_LONG) {
for (; nc < num_ctx; nc++) { for (; nc < num_ctx; nc++) {
ctx = mock_context(i915, "mock"); ctx = mock_context(i915, "mock");
if (!ctx) if (!ctx)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment