Skip to content

Commit 15de9cb

Browse files
icklejnikula
authored andcommitted
drm/i915/gt: Avoid resetting ring->head outside of its timeline mutex
We manipulate ring->head while active in i915_request_retire underneath the timeline manipulation. We cannot rely on a stable ring->head outside of the timeline->mutex, in particular while setting up the context for resume and reset. Closes: https://gitlab.freedesktop.org/drm/intel/issues/1126 Fixes: 0881954 ("drm/i915: Introduce intel_context.pin_mutex for pin management") Fixes: e5dadff ("drm/i915: Protect request retirement with timeline->mutex") References: f3c0efc ("drm/i915/execlists: Leave resetting ring to intel_ring") Signed-off-by: Chris Wilson <[email protected]> Cc: Matthew Auld <[email protected]> Cc: Tvrtko Ursulin <[email protected]> Cc: Mika Kuoppala <[email protected]> Reviewed-by: Andi Shyti <[email protected]> Reviewed-by: Mika Kuoppala <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected] (cherry picked from commit 4282735) Signed-off-by: Jani Nikula <[email protected]>
1 parent b1339ec commit 15de9cb

File tree

3 files changed

+21
-23
lines changed

3 files changed

+21
-23
lines changed

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

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,8 @@ static void execlists_init_reg_state(u32 *reg_state,
237237
bool close);
238238
static void
239239
__execlists_update_reg_state(const struct intel_context *ce,
240-
const struct intel_engine_cs *engine);
240+
const struct intel_engine_cs *engine,
241+
u32 head);
241242

242243
static void mark_eio(struct i915_request *rq)
243244
{
@@ -1186,12 +1187,11 @@ static void reset_active(struct i915_request *rq,
11861187
head = rq->tail;
11871188
else
11881189
head = active_request(ce->timeline, rq)->head;
1189-
ce->ring->head = intel_ring_wrap(ce->ring, head);
1190-
intel_ring_update_space(ce->ring);
1190+
head = intel_ring_wrap(ce->ring, head);
11911191

11921192
/* Scrub the context image to prevent replaying the previous batch */
11931193
restore_default_state(ce, engine);
1194-
__execlists_update_reg_state(ce, engine);
1194+
__execlists_update_reg_state(ce, engine, head);
11951195

11961196
/* We've switched away, so this should be a no-op, but intent matters */
11971197
ce->lrc_desc |= CTX_DESC_FORCE_RESTORE;
@@ -2863,16 +2863,17 @@ static void execlists_context_unpin(struct intel_context *ce)
28632863

28642864
static void
28652865
__execlists_update_reg_state(const struct intel_context *ce,
2866-
const struct intel_engine_cs *engine)
2866+
const struct intel_engine_cs *engine,
2867+
u32 head)
28672868
{
28682869
struct intel_ring *ring = ce->ring;
28692870
u32 *regs = ce->lrc_reg_state;
28702871

2871-
GEM_BUG_ON(!intel_ring_offset_valid(ring, ring->head));
2872+
GEM_BUG_ON(!intel_ring_offset_valid(ring, head));
28722873
GEM_BUG_ON(!intel_ring_offset_valid(ring, ring->tail));
28732874

28742875
regs[CTX_RING_START] = i915_ggtt_offset(ring->vma);
2875-
regs[CTX_RING_HEAD] = ring->head;
2876+
regs[CTX_RING_HEAD] = head;
28762877
regs[CTX_RING_TAIL] = ring->tail;
28772878

28782879
/* RPCS */
@@ -2901,7 +2902,7 @@ __execlists_context_pin(struct intel_context *ce,
29012902

29022903
ce->lrc_desc = lrc_descriptor(ce, engine) | CTX_DESC_FORCE_RESTORE;
29032904
ce->lrc_reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE;
2904-
__execlists_update_reg_state(ce, engine);
2905+
__execlists_update_reg_state(ce, engine, ce->ring->tail);
29052906

29062907
return 0;
29072908
}
@@ -2942,7 +2943,7 @@ static void execlists_context_reset(struct intel_context *ce)
29422943
/* Scrub away the garbage */
29432944
execlists_init_reg_state(ce->lrc_reg_state,
29442945
ce, ce->engine, ce->ring, true);
2945-
__execlists_update_reg_state(ce, ce->engine);
2946+
__execlists_update_reg_state(ce, ce->engine, ce->ring->tail);
29462947

29472948
ce->lrc_desc |= CTX_DESC_FORCE_RESTORE;
29482949
}
@@ -3497,6 +3498,7 @@ static void __execlists_reset(struct intel_engine_cs *engine, bool stalled)
34973498
struct intel_engine_execlists * const execlists = &engine->execlists;
34983499
struct intel_context *ce;
34993500
struct i915_request *rq;
3501+
u32 head;
35003502

35013503
mb(); /* paranoia: read the CSB pointers from after the reset */
35023504
clflush(execlists->csb_write);
@@ -3524,15 +3526,15 @@ static void __execlists_reset(struct intel_engine_cs *engine, bool stalled)
35243526

35253527
if (i915_request_completed(rq)) {
35263528
/* Idle context; tidy up the ring so we can restart afresh */
3527-
ce->ring->head = intel_ring_wrap(ce->ring, rq->tail);
3529+
head = intel_ring_wrap(ce->ring, rq->tail);
35283530
goto out_replay;
35293531
}
35303532

35313533
/* Context has requests still in-flight; it should not be idle! */
35323534
GEM_BUG_ON(i915_active_is_idle(&ce->active));
35333535
rq = active_request(ce->timeline, rq);
3534-
ce->ring->head = intel_ring_wrap(ce->ring, rq->head);
3535-
GEM_BUG_ON(ce->ring->head == ce->ring->tail);
3536+
head = intel_ring_wrap(ce->ring, rq->head);
3537+
GEM_BUG_ON(head == ce->ring->tail);
35363538

35373539
/*
35383540
* If this request hasn't started yet, e.g. it is waiting on a
@@ -3577,10 +3579,9 @@ static void __execlists_reset(struct intel_engine_cs *engine, bool stalled)
35773579

35783580
out_replay:
35793581
ENGINE_TRACE(engine, "replay {head:%04x, tail:%04x}\n",
3580-
ce->ring->head, ce->ring->tail);
3581-
intel_ring_update_space(ce->ring);
3582+
head, ce->ring->tail);
35823583
__execlists_reset_reg_state(ce, engine);
3583-
__execlists_update_reg_state(ce, engine);
3584+
__execlists_update_reg_state(ce, engine, head);
35843585
ce->lrc_desc |= CTX_DESC_FORCE_RESTORE; /* paranoid: GPU was reset! */
35853586

35863587
unwind:
@@ -5223,10 +5224,7 @@ void intel_lr_context_reset(struct intel_engine_cs *engine,
52235224
restore_default_state(ce, engine);
52245225

52255226
/* Rerun the request; its payload has been neutered (if guilty). */
5226-
ce->ring->head = head;
5227-
intel_ring_update_space(ce->ring);
5228-
5229-
__execlists_update_reg_state(ce, engine);
5227+
__execlists_update_reg_state(ce, engine, head);
52305228
}
52315229

52325230
bool

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ struct intel_ring {
3939
*/
4040
atomic_t pin_count;
4141

42-
u32 head;
43-
u32 tail;
44-
u32 emit;
42+
u32 head; /* updated during retire, loosely tracks RING_HEAD */
43+
u32 tail; /* updated on submission, used for RING_TAIL */
44+
u32 emit; /* updated during request construction */
4545

4646
u32 space;
4747
u32 size;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ static int live_unlite_restore(struct intel_gt *gt, int prio)
186186
}
187187
GEM_BUG_ON(!ce[1]->ring->size);
188188
intel_ring_reset(ce[1]->ring, ce[1]->ring->size / 2);
189-
__execlists_update_reg_state(ce[1], engine);
189+
__execlists_update_reg_state(ce[1], engine, ce[1]->ring->head);
190190

191191
rq[0] = igt_spinner_create_request(&spin, ce[0], MI_ARB_CHECK);
192192
if (IS_ERR(rq[0])) {

0 commit comments

Comments
 (0)