From cbf4b77af11ba93ea2ed7effa37da2a39e970851 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 9 Mar 2017 13:20:04 +0000 Subject: drm/i915/guc: Fix request re-submission after reset In order to ensure no missed interrupts we must first re-direct the interrupts to GuC, and only then re-submit the requests to be replayed after a GPU reset. Otherwise context switch can fire before GuC has been set up to receive it triggering more hangs. v2: Rebase. Signed-off-by: Tvrtko Ursulin Cc: Chris Wilson Cc: Michal Wajdeczko Cc: Mika Kuoppala Cc: Oscar Mateo Cc: Sagar Arun Kamble Cc: Arkadiusz Hiler Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/20170309132005.1317-1-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_guc_submission.c | 32 ++++++++++++++++++++++++++---- drivers/gpu/drm/i915/intel_guc_loader.c | 21 -------------------- 2 files changed, 28 insertions(+), 25 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index beb38e30d0e9..41f2dd87b413 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -936,6 +936,26 @@ static void guc_reset_wq(struct i915_guc_client *client) client->wq_tail = 0; } +static void guc_interrupts_capture(struct drm_i915_private *dev_priv) +{ + struct intel_engine_cs *engine; + enum intel_engine_id id; + int irqs; + + /* tell all command streamers to forward interrupts (but not vblank) to GuC */ + irqs = _MASKED_BIT_ENABLE(GFX_INTERRUPT_STEERING); + for_each_engine(engine, dev_priv, id) + I915_WRITE(RING_MODE_GEN7(engine), irqs); + + /* route USER_INTERRUPT to Host, all others are sent to GuC. */ + irqs = GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT | + GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT; + /* These three registers have the same bit definitions */ + I915_WRITE(GUC_BCS_RCS_IER, ~irqs); + I915_WRITE(GUC_VCS2_VCS1_IER, ~irqs); + I915_WRITE(GUC_WD_VECS_IER, ~irqs); +} + int i915_guc_submission_enable(struct drm_i915_private *dev_priv) { struct intel_guc *guc = &dev_priv->guc; @@ -953,13 +973,17 @@ int i915_guc_submission_enable(struct drm_i915_private *dev_priv) /* Take over from manual control of ELSP (execlists) */ for_each_engine(engine, dev_priv, id) { - const int wqi_size = sizeof(struct guc_wq_item); - struct drm_i915_gem_request *rq; - engine->submit_request = i915_guc_submit; engine->schedule = NULL; + } + + guc_interrupts_capture(dev_priv); + + /* Replay the current set of previously submitted requests */ + for_each_engine(engine, dev_priv, id) { + const int wqi_size = sizeof(struct guc_wq_item); + struct drm_i915_gem_request *rq; - /* Replay the current set of previously submitted requests */ spin_lock_irq(&engine->timeline->lock); list_for_each_entry(rq, &engine->timeline->requests, link) { guc_client_update_wq_rsvd(client, wqi_size); diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index 64cdef479d1d..2e24712cf3ee 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -109,26 +109,6 @@ static void guc_interrupts_release(struct drm_i915_private *dev_priv) I915_WRITE(GUC_WD_VECS_IER, 0); } -static void guc_interrupts_capture(struct drm_i915_private *dev_priv) -{ - struct intel_engine_cs *engine; - enum intel_engine_id id; - int irqs; - - /* tell all command streamers to forward interrupts (but not vblank) to GuC */ - irqs = _MASKED_BIT_ENABLE(GFX_INTERRUPT_STEERING); - for_each_engine(engine, dev_priv, id) - I915_WRITE(RING_MODE_GEN7(engine), irqs); - - /* route USER_INTERRUPT to Host, all others are sent to GuC. */ - irqs = GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT | - GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT; - /* These three registers have the same bit definitions */ - I915_WRITE(GUC_BCS_RCS_IER, ~irqs); - I915_WRITE(GUC_VCS2_VCS1_IER, ~irqs); - I915_WRITE(GUC_WD_VECS_IER, ~irqs); -} - static u32 get_gttype(struct drm_i915_private *dev_priv) { /* XXX: GT type based on PCI device ID? field seems unused by fw */ @@ -503,7 +483,6 @@ int intel_guc_setup(struct drm_i915_private *dev_priv) err = i915_guc_submission_enable(dev_priv); if (err) goto fail; - guc_interrupts_capture(dev_priv); } DRM_INFO("GuC %s (firmware %s [version %u.%u])\n", -- cgit v1.2.3-55-g7522