Skip to content

Commit 9726920

Browse files
committed
drm/i915: Only reset the pinned kernel contexts on resume
On resume, we know that the only pinned contexts in danger of seeing corruption are the kernel context, and so we do not need to walk the list of all GEM contexts as we tracked them on each engine. Signed-off-by: Chris Wilson <[email protected]> Reviewed-by: Tvrtko Ursulin <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent feb8846 commit 9726920

File tree

8 files changed

+60
-45
lines changed

8 files changed

+60
-45
lines changed

drivers/gpu/drm/i915/i915_drv.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1995,7 +1995,6 @@ struct drm_i915_private {
19951995

19961996
/* Abstract the submission mechanism (legacy ringbuffer or execlists) away */
19971997
struct {
1998-
void (*resume)(struct drm_i915_private *);
19991998
void (*cleanup_engine)(struct intel_engine_cs *engine);
20001999

20012000
struct i915_gt_timelines {

drivers/gpu/drm/i915/i915_gem.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4513,7 +4513,7 @@ void i915_gem_resume(struct drm_i915_private *i915)
45134513
* guarantee that the context image is complete. So let's just reset
45144514
* it and start again.
45154515
*/
4516-
i915->gt.resume(i915);
4516+
intel_gt_resume(i915);
45174517

45184518
if (i915_gem_init_hw(i915))
45194519
goto err_wedged;
@@ -4853,13 +4853,10 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
48534853

48544854
dev_priv->mm.unordered_timeline = dma_fence_context_alloc(1);
48554855

4856-
if (HAS_LOGICAL_RING_CONTEXTS(dev_priv)) {
4857-
dev_priv->gt.resume = intel_lr_context_resume;
4856+
if (HAS_LOGICAL_RING_CONTEXTS(dev_priv))
48584857
dev_priv->gt.cleanup_engine = intel_logical_ring_cleanup;
4859-
} else {
4860-
dev_priv->gt.resume = intel_legacy_submission_resume;
4858+
else
48614859
dev_priv->gt.cleanup_engine = intel_engine_cleanup;
4862-
}
48634860

48644861
i915_timelines_init(dev_priv);
48654862

drivers/gpu/drm/i915/intel_context_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ struct intel_context_ops {
2424
int (*pin)(struct intel_context *ce);
2525
void (*unpin)(struct intel_context *ce);
2626

27+
void (*reset)(struct intel_context *ce);
2728
void (*destroy)(struct kref *kref);
2829
};
2930

drivers/gpu/drm/i915/intel_engine_cs.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,30 @@ int intel_engine_init_common(struct intel_engine_cs *engine)
753753
return ret;
754754
}
755755

756+
void intel_gt_resume(struct drm_i915_private *i915)
757+
{
758+
struct intel_engine_cs *engine;
759+
enum intel_engine_id id;
760+
761+
/*
762+
* After resume, we may need to poke into the pinned kernel
763+
* contexts to paper over any damage caused by the sudden suspend.
764+
* Only the kernel contexts should remain pinned over suspend,
765+
* allowing us to fixup the user contexts on their first pin.
766+
*/
767+
for_each_engine(engine, i915, id) {
768+
struct intel_context *ce;
769+
770+
ce = engine->kernel_context;
771+
if (ce)
772+
ce->ops->reset(ce);
773+
774+
ce = engine->preempt_context;
775+
if (ce)
776+
ce->ops->reset(ce);
777+
}
778+
}
779+
756780
/**
757781
* intel_engines_cleanup_common - cleans up the engine state created by
758782
* the common initiailizers.

drivers/gpu/drm/i915/intel_lrc.c

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1379,9 +1379,33 @@ static int execlists_context_pin(struct intel_context *ce)
13791379
return __execlists_context_pin(ce, ce->engine);
13801380
}
13811381

1382+
static void execlists_context_reset(struct intel_context *ce)
1383+
{
1384+
/*
1385+
* Because we emit WA_TAIL_DWORDS there may be a disparity
1386+
* between our bookkeeping in ce->ring->head and ce->ring->tail and
1387+
* that stored in context. As we only write new commands from
1388+
* ce->ring->tail onwards, everything before that is junk. If the GPU
1389+
* starts reading from its RING_HEAD from the context, it may try to
1390+
* execute that junk and die.
1391+
*
1392+
* The contexts that are stilled pinned on resume belong to the
1393+
* kernel, and are local to each engine. All other contexts will
1394+
* have their head/tail sanitized upon pinning before use, so they
1395+
* will never see garbage,
1396+
*
1397+
* So to avoid that we reset the context images upon resume. For
1398+
* simplicity, we just zero everything out.
1399+
*/
1400+
intel_ring_reset(ce->ring, 0);
1401+
__execlists_update_reg_state(ce, ce->engine);
1402+
}
1403+
13821404
static const struct intel_context_ops execlists_context_ops = {
13831405
.pin = execlists_context_pin,
13841406
.unpin = execlists_context_unpin,
1407+
1408+
.reset = execlists_context_reset,
13851409
.destroy = execlists_context_destroy,
13861410
};
13871411

@@ -2895,31 +2919,6 @@ static int execlists_context_deferred_alloc(struct intel_context *ce,
28952919
return ret;
28962920
}
28972921

2898-
void intel_lr_context_resume(struct drm_i915_private *i915)
2899-
{
2900-
struct i915_gem_context *ctx;
2901-
struct intel_context *ce;
2902-
2903-
/*
2904-
* Because we emit WA_TAIL_DWORDS there may be a disparity
2905-
* between our bookkeeping in ce->ring->head and ce->ring->tail and
2906-
* that stored in context. As we only write new commands from
2907-
* ce->ring->tail onwards, everything before that is junk. If the GPU
2908-
* starts reading from its RING_HEAD from the context, it may try to
2909-
* execute that junk and die.
2910-
*
2911-
* So to avoid that we reset the context images upon resume. For
2912-
* simplicity, we just zero everything out.
2913-
*/
2914-
list_for_each_entry(ctx, &i915->contexts.list, link) {
2915-
list_for_each_entry(ce, &ctx->active_engines, active_link) {
2916-
GEM_BUG_ON(!ce->ring);
2917-
intel_ring_reset(ce->ring, 0);
2918-
__execlists_update_reg_state(ce, ce->engine);
2919-
}
2920-
}
2921-
}
2922-
29232922
void intel_execlists_show_requests(struct intel_engine_cs *engine,
29242923
struct drm_printer *m,
29252924
void (*show_request)(struct drm_printer *m,

drivers/gpu/drm/i915/intel_lrc.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@ struct drm_printer;
102102
struct drm_i915_private;
103103
struct i915_gem_context;
104104

105-
void intel_lr_context_resume(struct drm_i915_private *dev_priv);
106105
void intel_execlists_set_default_submission(struct intel_engine_cs *engine);
107106

108107
void intel_execlists_show_requests(struct intel_engine_cs *engine,

drivers/gpu/drm/i915/intel_ringbuffer.c

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1508,9 +1508,16 @@ static int ring_context_pin(struct intel_context *ce)
15081508
return err;
15091509
}
15101510

1511+
static void ring_context_reset(struct intel_context *ce)
1512+
{
1513+
intel_ring_reset(ce->ring, 0);
1514+
}
1515+
15111516
static const struct intel_context_ops ring_context_ops = {
15121517
.pin = ring_context_pin,
15131518
.unpin = ring_context_unpin,
1519+
1520+
.reset = ring_context_reset,
15141521
.destroy = ring_context_destroy,
15151522
};
15161523

@@ -1581,16 +1588,6 @@ void intel_engine_cleanup(struct intel_engine_cs *engine)
15811588
kfree(engine);
15821589
}
15831590

1584-
void intel_legacy_submission_resume(struct drm_i915_private *dev_priv)
1585-
{
1586-
struct intel_engine_cs *engine;
1587-
enum intel_engine_id id;
1588-
1589-
/* Restart from the beginning of the rings for convenience */
1590-
for_each_engine(engine, dev_priv, id)
1591-
intel_ring_reset(engine->buffer, 0);
1592-
}
1593-
15941591
static int load_pd_dir(struct i915_request *rq,
15951592
const struct i915_hw_ppgtt *ppgtt)
15961593
{

drivers/gpu/drm/i915/intel_ringbuffer.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,8 +268,6 @@ static inline void intel_ring_put(struct intel_ring *ring)
268268
void intel_engine_stop(struct intel_engine_cs *engine);
269269
void intel_engine_cleanup(struct intel_engine_cs *engine);
270270

271-
void intel_legacy_submission_resume(struct drm_i915_private *dev_priv);
272-
273271
int __must_check intel_ring_cacheline_align(struct i915_request *rq);
274272

275273
u32 __must_check *intel_ring_begin(struct i915_request *rq, unsigned int n);
@@ -463,6 +461,7 @@ static inline void intel_engine_reset(struct intel_engine_cs *engine,
463461
}
464462

465463
void intel_engines_sanitize(struct drm_i915_private *i915, bool force);
464+
void intel_gt_resume(struct drm_i915_private *i915);
466465

467466
bool intel_engine_is_idle(struct intel_engine_cs *engine);
468467
bool intel_engines_are_idle(struct drm_i915_private *dev_priv);

0 commit comments

Comments
 (0)