Commit 198d2533 authored by Chris Wilson's avatar Chris Wilson

drm/i915/execlists: Ignore lost completion events

Icelake hit an issue where it missed reporting a completion event and
instead jumped straight to a idle->active event (skipping over the
active->idle and not even hitting the lite-restore preemption).

661497511us : process_csb: rcs0 cs-irq head=11, tail=0
661497512us : process_csb: rcs0 csb[0]: status=0x10008002:0x00000020 [lite-restore]
661497512us : trace_ports: rcs0: preempted { 28cc8:11052, 0:0 }
661497513us : trace_ports: rcs0: promote { 28cc8:11054, 0:0 }
661497514us : __i915_request_submit: rcs0 fence 28cc8:11056, current 11052
661497514us : __execlists_submission_tasklet: rcs0: queue_priority_hint:-2147483648, submit:yes
661497515us : trace_ports: rcs0: submit { 28cc8:11056, 0:0 }
661497530us : process_csb: rcs0 cs-irq head=0, tail=1
661497530us : process_csb: rcs0 csb[1]: status=0x10008002:0x00000020 [lite-restore]
661497531us : trace_ports: rcs0: preempted { 28cc8:11054!, 0:0 }
661497535us : trace_ports: rcs0: promote { 28cc8:11056, 0:0 }
661497540us : __i915_request_submit: rcs0 fence 28cc8:11058, current 11054
661497544us : __execlists_submission_tasklet: rcs0: queue_priority_hint:-2147483648, submit:yes
661497545us : trace_ports: rcs0: submit { 28cc8:11058, 0:0 }
661497553us : process_csb: rcs0 cs-irq head=1, tail=2
661497553us : process_csb: rcs0 csb[2]: status=0x10000001:0x00000000 [idle->active]
661497574us : process_csb: process_csb:1538 GEM_BUG_ON(*execlists->active)
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Reviewed-by: default avatarMika Kuoppala <mika.kuoppala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190907084334.28952-1-chris@chris-wilson.co.uk
parent 4d154d33
...@@ -692,6 +692,9 @@ trace_ports(const struct intel_engine_execlists *execlists, ...@@ -692,6 +692,9 @@ trace_ports(const struct intel_engine_execlists *execlists,
const struct intel_engine_cs *engine = const struct intel_engine_cs *engine =
container_of(execlists, typeof(*engine), execlists); container_of(execlists, typeof(*engine), execlists);
if (!ports[0])
return;
GEM_TRACE("%s: %s { %llx:%lld%s, %llx:%lld }\n", GEM_TRACE("%s: %s { %llx:%lld%s, %llx:%lld }\n",
engine->name, msg, engine->name, msg,
ports[0]->fence.context, ports[0]->fence.context,
...@@ -1380,13 +1383,6 @@ reset_in_progress(const struct intel_engine_execlists *execlists) ...@@ -1380,13 +1383,6 @@ reset_in_progress(const struct intel_engine_execlists *execlists)
return unlikely(!__tasklet_is_enabled(&execlists->tasklet)); return unlikely(!__tasklet_is_enabled(&execlists->tasklet));
} }
enum csb_step {
CSB_NOP,
CSB_PROMOTE,
CSB_PREEMPT,
CSB_COMPLETE,
};
/* /*
* Starting with Gen12, the status has a new format: * Starting with Gen12, the status has a new format:
* *
...@@ -1413,7 +1409,7 @@ enum csb_step { ...@@ -1413,7 +1409,7 @@ enum csb_step {
* bits 47-57: sw context id of the lrc the GT switched away from * bits 47-57: sw context id of the lrc the GT switched away from
* bits 58-63: sw counter of the lrc the GT switched away from * bits 58-63: sw counter of the lrc the GT switched away from
*/ */
static inline enum csb_step static inline bool
gen12_csb_parse(const struct intel_engine_execlists *execlists, const u32 *csb) gen12_csb_parse(const struct intel_engine_execlists *execlists, const u32 *csb)
{ {
u32 lower_dw = csb[0]; u32 lower_dw = csb[0];
...@@ -1423,7 +1419,7 @@ gen12_csb_parse(const struct intel_engine_execlists *execlists, const u32 *csb) ...@@ -1423,7 +1419,7 @@ gen12_csb_parse(const struct intel_engine_execlists *execlists, const u32 *csb)
bool new_queue = lower_dw & GEN12_CTX_STATUS_SWITCHED_TO_NEW_QUEUE; bool new_queue = lower_dw & GEN12_CTX_STATUS_SWITCHED_TO_NEW_QUEUE;
if (!ctx_away_valid && ctx_to_valid) if (!ctx_away_valid && ctx_to_valid)
return CSB_PROMOTE; return true;
/* /*
* The context switch detail is not guaranteed to be 5 when a preemption * The context switch detail is not guaranteed to be 5 when a preemption
...@@ -1433,7 +1429,7 @@ gen12_csb_parse(const struct intel_engine_execlists *execlists, const u32 *csb) ...@@ -1433,7 +1429,7 @@ gen12_csb_parse(const struct intel_engine_execlists *execlists, const u32 *csb)
* would require some extra handling, but we don't support that. * would require some extra handling, but we don't support that.
*/ */
if (new_queue && ctx_away_valid) if (new_queue && ctx_away_valid)
return CSB_PREEMPT; return true;
/* /*
* switch detail = 5 is covered by the case above and we do not expect a * switch detail = 5 is covered by the case above and we do not expect a
...@@ -1442,29 +1438,13 @@ gen12_csb_parse(const struct intel_engine_execlists *execlists, const u32 *csb) ...@@ -1442,29 +1438,13 @@ gen12_csb_parse(const struct intel_engine_execlists *execlists, const u32 *csb)
*/ */
GEM_BUG_ON(GEN12_CTX_SWITCH_DETAIL(upper_dw)); GEM_BUG_ON(GEN12_CTX_SWITCH_DETAIL(upper_dw));
if (*execlists->active) { return false;
GEM_BUG_ON(!ctx_away_valid);
return CSB_COMPLETE;
}
return CSB_NOP;
} }
static inline enum csb_step static inline bool
gen8_csb_parse(const struct intel_engine_execlists *execlists, const u32 *csb) gen8_csb_parse(const struct intel_engine_execlists *execlists, const u32 *csb)
{ {
unsigned int status = *csb; return *csb & (GEN8_CTX_STATUS_IDLE_ACTIVE | GEN8_CTX_STATUS_PREEMPTED);
if (status & GEN8_CTX_STATUS_IDLE_ACTIVE)
return CSB_PROMOTE;
if (status & GEN8_CTX_STATUS_PREEMPTED)
return CSB_PREEMPT;
if (*execlists->active)
return CSB_COMPLETE;
return CSB_NOP;
} }
static void process_csb(struct intel_engine_cs *engine) static void process_csb(struct intel_engine_cs *engine)
...@@ -1503,7 +1483,7 @@ static void process_csb(struct intel_engine_cs *engine) ...@@ -1503,7 +1483,7 @@ static void process_csb(struct intel_engine_cs *engine)
rmb(); rmb();
do { do {
enum csb_step csb_step; bool promote;
if (++head == num_entries) if (++head == num_entries)
head = 0; head = 0;
...@@ -1531,20 +1511,16 @@ static void process_csb(struct intel_engine_cs *engine) ...@@ -1531,20 +1511,16 @@ static void process_csb(struct intel_engine_cs *engine)
buf[2 * head + 0], buf[2 * head + 1]); buf[2 * head + 0], buf[2 * head + 1]);
if (INTEL_GEN(engine->i915) >= 12) if (INTEL_GEN(engine->i915) >= 12)
csb_step = gen12_csb_parse(execlists, buf + 2 * head); promote = gen12_csb_parse(execlists, buf + 2 * head);
else else
csb_step = gen8_csb_parse(execlists, buf + 2 * head); promote = gen8_csb_parse(execlists, buf + 2 * head);
if (promote) {
switch (csb_step) { /* cancel old inflight, prepare for switch */
case CSB_PREEMPT: /* cancel old inflight, prepare for switch */
trace_ports(execlists, "preempted", execlists->active); trace_ports(execlists, "preempted", execlists->active);
while (*execlists->active) while (*execlists->active)
execlists_schedule_out(*execlists->active++); execlists_schedule_out(*execlists->active++);
/* fallthrough */ /* switch pending to inflight */
case CSB_PROMOTE: /* switch pending to inflight */
GEM_BUG_ON(*execlists->active);
GEM_BUG_ON(!assert_pending_valid(execlists, "promote")); GEM_BUG_ON(!assert_pending_valid(execlists, "promote"));
execlists->active = execlists->active =
memcpy(execlists->inflight, memcpy(execlists->inflight,
...@@ -1559,9 +1535,10 @@ static void process_csb(struct intel_engine_cs *engine) ...@@ -1559,9 +1535,10 @@ static void process_csb(struct intel_engine_cs *engine)
ring_set_paused(engine, 0); ring_set_paused(engine, 0);
WRITE_ONCE(execlists->pending[0], NULL); WRITE_ONCE(execlists->pending[0], NULL);
break; } else {
GEM_BUG_ON(!*execlists->active);
case CSB_COMPLETE: /* port0 completed, advanced to port1 */ /* port0 completed, advanced to port1 */
trace_ports(execlists, "completed", execlists->active); trace_ports(execlists, "completed", execlists->active);
/* /*
...@@ -1576,10 +1553,6 @@ static void process_csb(struct intel_engine_cs *engine) ...@@ -1576,10 +1553,6 @@ static void process_csb(struct intel_engine_cs *engine)
GEM_BUG_ON(execlists->active - execlists->inflight > GEM_BUG_ON(execlists->active - execlists->inflight >
execlists_num_ports(execlists)); execlists_num_ports(execlists));
break;
case CSB_NOP:
break;
} }
} while (head != tail); } while (head != tail);
......
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