Skip to content

Commit b1339ec

Browse files
icklejnikula
authored andcommitted
drm/i915/execlists: Always force a context reload when rewinding RING_TAIL
If we rewind the RING_TAIL on a context, due to a preemption event, we must force the context restore for the RING_TAIL update to be properly handled. Rather than note which preemption events may cause us to rewind the tail, compare the new request's tail with the previously submitted RING_TAIL, as it turns out that timeslicing was causing unexpected rewinds. <idle>-0 0d.s2 1280851190us : __execlists_submission_tasklet: 0000:00:02.0 rcs0: expired last=130:4698, prio=3, hint=3 <idle>-0 0d.s2 1280851192us : __i915_request_unsubmit: 0000:00:02.0 rcs0: fence 66:119966, current 119964 <idle>-0 0d.s2 1280851195us : __i915_request_unsubmit: 0000:00:02.0 rcs0: fence 130:4698, current 4695 <idle>-0 0d.s2 1280851198us : __i915_request_unsubmit: 0000:00:02.0 rcs0: fence 130:4696, current 4695 ^---- Note we unwind 2 requests from the same context <idle>-0 0d.s2 1280851208us : __i915_request_submit: 0000:00:02.0 rcs0: fence 130:4696, current 4695 <idle>-0 0d.s2 1280851213us : __i915_request_submit: 0000:00:02.0 rcs0: fence 134:1508, current 1506 ^---- But to apply the new timeslice, we have to replay the first request before the new client can start -- the unexpected RING_TAIL rewind <idle>-0 0d.s2 1280851219us : trace_ports: 0000:00:02.0 rcs0: submit { 130:4696*, 134:1508 } synmark2-5425 2..s. 1280851239us : process_csb: 0000:00:02.0 rcs0: cs-irq head=5, tail=0 synmark2-5425 2..s. 1280851240us : process_csb: 0000:00:02.0 rcs0: csb[0]: status=0x00008002:0x00000000 ^---- Preemption event for the ELSP update; note the lite-restore synmark2-5425 2..s. 1280851243us : trace_ports: 0000:00:02.0 rcs0: preempted { 130:4698, 66:119966 } synmark2-5425 2..s. 1280851246us : trace_ports: 0000:00:02.0 rcs0: promote { 130:4696*, 134:1508 } synmark2-5425 2.... 1280851462us : __i915_request_commit: 0000:00:02.0 rcs0: fence 130:4700, current 4695 synmark2-5425 2.... 1280852111us : __i915_request_commit: 0000:00:02.0 rcs0: fence 130:4702, current 4695 synmark2-5425 2.Ns1 1280852296us : process_csb: 0000:00:02.0 rcs0: cs-irq head=0, tail=2 synmark2-5425 2.Ns1 1280852297us : process_csb: 0000:00:02.0 rcs0: csb[1]: status=0x00000814:0x00000000 synmark2-5425 2.Ns1 1280852299us : trace_ports: 0000:00:02.0 rcs0: completed { 130:4696!, 134:1508 } synmark2-5425 2.Ns1 1280852301us : process_csb: 0000:00:02.0 rcs0: csb[2]: status=0x00000818:0x00000040 synmark2-5425 2.Ns1 1280852302us : trace_ports: 0000:00:02.0 rcs0: completed { 134:1508, 0:0 } synmark2-5425 2.Ns1 1280852313us : process_csb: process_csb:2336 GEM_BUG_ON(!i915_request_completed(*execlists->active) && !reset_in_progress(execlists)) Fixes: 8ee36e0 ("drm/i915/execlists: Minimalistic timeslicing") Referenecs: 82c69bf ("drm/i915/gt: Detect if we miss WaIdleLiteRestore") Signed-off-by: Chris Wilson <[email protected]> Cc: Mika Kuoppala <[email protected]> Reviewed-by: Mika Kuoppala <[email protected]> Cc: <[email protected]> # v5.4+ Link: https://patchwork.freedesktop.org/patch/msgid/[email protected] (cherry picked from commit 5ba32c7) Signed-off-by: Jani Nikula <[email protected]>
1 parent aa31461 commit b1339ec

File tree

4 files changed

+18
-10
lines changed

4 files changed

+18
-10
lines changed

drivers/gpu/drm/i915/gt/intel_lrc.c

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1321,7 +1321,7 @@ static u64 execlists_update_context(struct i915_request *rq)
13211321
{
13221322
struct intel_context *ce = rq->context;
13231323
u64 desc = ce->lrc_desc;
1324-
u32 tail;
1324+
u32 tail, prev;
13251325

13261326
/*
13271327
* WaIdleLiteRestore:bdw,skl
@@ -1334,9 +1334,15 @@ static u64 execlists_update_context(struct i915_request *rq)
13341334
* subsequent resubmissions (for lite restore). Should that fail us,
13351335
* and we try and submit the same tail again, force the context
13361336
* reload.
1337+
*
1338+
* If we need to return to a preempted context, we need to skip the
1339+
* lite-restore and force it to reload the RING_TAIL. Otherwise, the
1340+
* HW has a tendency to ignore us rewinding the TAIL to the end of
1341+
* an earlier request.
13371342
*/
13381343
tail = intel_ring_set_tail(rq->ring, rq->tail);
1339-
if (unlikely(ce->lrc_reg_state[CTX_RING_TAIL] == tail))
1344+
prev = ce->lrc_reg_state[CTX_RING_TAIL];
1345+
if (unlikely(intel_ring_direction(rq->ring, tail, prev) <= 0))
13401346
desc |= CTX_DESC_FORCE_RESTORE;
13411347
ce->lrc_reg_state[CTX_RING_TAIL] = tail;
13421348
rq->tail = rq->wa_tail;
@@ -1839,14 +1845,6 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
18391845
*/
18401846
__unwind_incomplete_requests(engine);
18411847

1842-
/*
1843-
* If we need to return to the preempted context, we
1844-
* need to skip the lite-restore and force it to
1845-
* reload the RING_TAIL. Otherwise, the HW has a
1846-
* tendency to ignore us rewinding the TAIL to the
1847-
* end of an earlier request.
1848-
*/
1849-
last->context->lrc_desc |= CTX_DESC_FORCE_RESTORE;
18501848
last = NULL;
18511849
} else if (need_timeslice(engine, last) &&
18521850
timer_expired(&engine->execlists.timer)) {

drivers/gpu/drm/i915/gt/intel_ring.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ intel_engine_create_ring(struct intel_engine_cs *engine, int size)
145145

146146
kref_init(&ring->ref);
147147
ring->size = size;
148+
ring->wrap = BITS_PER_TYPE(ring->size) - ilog2(size);
148149

149150
/*
150151
* Workaround an erratum on the i830 which causes a hang if

drivers/gpu/drm/i915/gt/intel_ring.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,14 @@ static inline u32 intel_ring_wrap(const struct intel_ring *ring, u32 pos)
5656
return pos & (ring->size - 1);
5757
}
5858

59+
static inline int intel_ring_direction(const struct intel_ring *ring,
60+
u32 next, u32 prev)
61+
{
62+
typecheck(typeof(ring->size), next);
63+
typecheck(typeof(ring->size), prev);
64+
return (next - prev) << ring->wrap;
65+
}
66+
5967
static inline bool
6068
intel_ring_offset_valid(const struct intel_ring *ring,
6169
unsigned int pos)

drivers/gpu/drm/i915/gt/intel_ring_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ struct intel_ring {
4545

4646
u32 space;
4747
u32 size;
48+
u32 wrap;
4849
u32 effective_size;
4950
};
5051

0 commit comments

Comments
 (0)