aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2019-04-10 15:01:20 -0400
committerChris Wilson <chris@chris-wilson.co.uk>2019-04-10 16:18:11 -0400
commit9726920b7ea287673eead69e5276b3abff91fd8c (patch)
tree048fb270a33682849b973cc28a81a069e4b10444
parentfeb8846b3a4f88c8807dbbb8176defd419371887 (diff)
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 <chris@chris-wilson.co.uk> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20190410190120.830-1-chris@chris-wilson.co.uk
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h1
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c9
-rw-r--r--drivers/gpu/drm/i915/intel_context_types.h1
-rw-r--r--drivers/gpu/drm/i915/intel_engine_cs.c24
-rw-r--r--drivers/gpu/drm/i915/intel_lrc.c49
-rw-r--r--drivers/gpu/drm/i915/intel_lrc.h1
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c17
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.h3
8 files changed, 60 insertions, 45 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 63eca3061d10..35d0782c077e 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1995,7 +1995,6 @@ struct drm_i915_private {
1995 1995
1996 /* Abstract the submission mechanism (legacy ringbuffer or execlists) away */ 1996 /* Abstract the submission mechanism (legacy ringbuffer or execlists) away */
1997 struct { 1997 struct {
1998 void (*resume)(struct drm_i915_private *);
1999 void (*cleanup_engine)(struct intel_engine_cs *engine); 1998 void (*cleanup_engine)(struct intel_engine_cs *engine);
2000 1999
2001 struct i915_gt_timelines { 2000 struct i915_gt_timelines {
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index bf3d12f94365..0a818a60ad31 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -4513,7 +4513,7 @@ void i915_gem_resume(struct drm_i915_private *i915)
4513 * guarantee that the context image is complete. So let's just reset 4513 * guarantee that the context image is complete. So let's just reset
4514 * it and start again. 4514 * it and start again.
4515 */ 4515 */
4516 i915->gt.resume(i915); 4516 intel_gt_resume(i915);
4517 4517
4518 if (i915_gem_init_hw(i915)) 4518 if (i915_gem_init_hw(i915))
4519 goto err_wedged; 4519 goto err_wedged;
@@ -4853,13 +4853,10 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
4853 4853
4854 dev_priv->mm.unordered_timeline = dma_fence_context_alloc(1); 4854 dev_priv->mm.unordered_timeline = dma_fence_context_alloc(1);
4855 4855
4856 if (HAS_LOGICAL_RING_CONTEXTS(dev_priv)) { 4856 if (HAS_LOGICAL_RING_CONTEXTS(dev_priv))
4857 dev_priv->gt.resume = intel_lr_context_resume;
4858 dev_priv->gt.cleanup_engine = intel_logical_ring_cleanup; 4857 dev_priv->gt.cleanup_engine = intel_logical_ring_cleanup;
4859 } else { 4858 else
4860 dev_priv->gt.resume = intel_legacy_submission_resume;
4861 dev_priv->gt.cleanup_engine = intel_engine_cleanup; 4859 dev_priv->gt.cleanup_engine = intel_engine_cleanup;
4862 }
4863 4860
4864 i915_timelines_init(dev_priv); 4861 i915_timelines_init(dev_priv);
4865 4862
diff --git a/drivers/gpu/drm/i915/intel_context_types.h b/drivers/gpu/drm/i915/intel_context_types.h
index 624729a35875..68b4ca1611e0 100644
--- a/drivers/gpu/drm/i915/intel_context_types.h
+++ b/drivers/gpu/drm/i915/intel_context_types.h
@@ -24,6 +24,7 @@ struct intel_context_ops {
24 int (*pin)(struct intel_context *ce); 24 int (*pin)(struct intel_context *ce);
25 void (*unpin)(struct intel_context *ce); 25 void (*unpin)(struct intel_context *ce);
26 26
27 void (*reset)(struct intel_context *ce);
27 void (*destroy)(struct kref *kref); 28 void (*destroy)(struct kref *kref);
28}; 29};
29 30
diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c
index d0427c2e3997..f29a667cad52 100644
--- a/drivers/gpu/drm/i915/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/intel_engine_cs.c
@@ -753,6 +753,30 @@ err_unpin:
753 return ret; 753 return ret;
754} 754}
755 755
756void 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
756/** 780/**
757 * intel_engines_cleanup_common - cleans up the engine state created by 781 * intel_engines_cleanup_common - cleans up the engine state created by
758 * the common initiailizers. 782 * the common initiailizers.
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 6931dbb2888c..b54dbf36197e 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -1379,9 +1379,33 @@ static int execlists_context_pin(struct intel_context *ce)
1379 return __execlists_context_pin(ce, ce->engine); 1379 return __execlists_context_pin(ce, ce->engine);
1380} 1380}
1381 1381
1382static 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
1382static const struct intel_context_ops execlists_context_ops = { 1404static const struct intel_context_ops execlists_context_ops = {
1383 .pin = execlists_context_pin, 1405 .pin = execlists_context_pin,
1384 .unpin = execlists_context_unpin, 1406 .unpin = execlists_context_unpin,
1407
1408 .reset = execlists_context_reset,
1385 .destroy = execlists_context_destroy, 1409 .destroy = execlists_context_destroy,
1386}; 1410};
1387 1411
@@ -2895,31 +2919,6 @@ error_deref_obj:
2895 return ret; 2919 return ret;
2896} 2920}
2897 2921
2898void 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
2923void intel_execlists_show_requests(struct intel_engine_cs *engine, 2922void intel_execlists_show_requests(struct intel_engine_cs *engine,
2924 struct drm_printer *m, 2923 struct drm_printer *m,
2925 void (*show_request)(struct drm_printer *m, 2924 void (*show_request)(struct drm_printer *m,
diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h
index 92642ab91472..4d0b7736cb6d 100644
--- a/drivers/gpu/drm/i915/intel_lrc.h
+++ b/drivers/gpu/drm/i915/intel_lrc.h
@@ -102,7 +102,6 @@ struct drm_printer;
102struct drm_i915_private; 102struct drm_i915_private;
103struct i915_gem_context; 103struct i915_gem_context;
104 104
105void intel_lr_context_resume(struct drm_i915_private *dev_priv);
106void intel_execlists_set_default_submission(struct intel_engine_cs *engine); 105void intel_execlists_set_default_submission(struct intel_engine_cs *engine);
107 106
108void intel_execlists_show_requests(struct intel_engine_cs *engine, 107void intel_execlists_show_requests(struct intel_engine_cs *engine,
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 8a19eee9c5d4..af35f99c5940 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -1508,9 +1508,16 @@ err_unpin:
1508 return err; 1508 return err;
1509} 1509}
1510 1510
1511static void ring_context_reset(struct intel_context *ce)
1512{
1513 intel_ring_reset(ce->ring, 0);
1514}
1515
1511static const struct intel_context_ops ring_context_ops = { 1516static const struct intel_context_ops ring_context_ops = {
1512 .pin = ring_context_pin, 1517 .pin = ring_context_pin,
1513 .unpin = ring_context_unpin, 1518 .unpin = ring_context_unpin,
1519
1520 .reset = ring_context_reset,
1514 .destroy = ring_context_destroy, 1521 .destroy = ring_context_destroy,
1515}; 1522};
1516 1523
@@ -1581,16 +1588,6 @@ void intel_engine_cleanup(struct intel_engine_cs *engine)
1581 kfree(engine); 1588 kfree(engine);
1582} 1589}
1583 1590
1584void 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
1594static int load_pd_dir(struct i915_request *rq, 1591static int load_pd_dir(struct i915_request *rq,
1595 const struct i915_hw_ppgtt *ppgtt) 1592 const struct i915_hw_ppgtt *ppgtt)
1596{ 1593{
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index e58d6f04177b..0dea6c7fd438 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -268,8 +268,6 @@ static inline void intel_ring_put(struct intel_ring *ring)
268void intel_engine_stop(struct intel_engine_cs *engine); 268void intel_engine_stop(struct intel_engine_cs *engine);
269void intel_engine_cleanup(struct intel_engine_cs *engine); 269void intel_engine_cleanup(struct intel_engine_cs *engine);
270 270
271void intel_legacy_submission_resume(struct drm_i915_private *dev_priv);
272
273int __must_check intel_ring_cacheline_align(struct i915_request *rq); 271int __must_check intel_ring_cacheline_align(struct i915_request *rq);
274 272
275u32 __must_check *intel_ring_begin(struct i915_request *rq, unsigned int n); 273u32 __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,
463} 461}
464 462
465void intel_engines_sanitize(struct drm_i915_private *i915, bool force); 463void intel_engines_sanitize(struct drm_i915_private *i915, bool force);
464void intel_gt_resume(struct drm_i915_private *i915);
466 465
467bool intel_engine_is_idle(struct intel_engine_cs *engine); 466bool intel_engine_is_idle(struct intel_engine_cs *engine);
468bool intel_engines_are_idle(struct drm_i915_private *dev_priv); 467bool intel_engines_are_idle(struct drm_i915_private *dev_priv);