drm/i915/guc: Fix request re-submission after reset
authorTvrtko Ursulin <tvrtko.ursulin@intel.com>
Thu, 9 Mar 2017 13:20:04 +0000 (13:20 +0000)
committerTvrtko Ursulin <tvrtko.ursulin@intel.com>
Fri, 10 Mar 2017 07:47:12 +0000 (07:47 +0000)
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 <tvrtko.ursulin@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Cc: Oscar Mateo <oscar.mateo@intel.com>
Cc: Sagar Arun Kamble <sagar.a.kamble@intel.com>
Cc: Arkadiusz Hiler <arkadiusz.hiler@intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/20170309132005.1317-1-tvrtko.ursulin@linux.intel.com
drivers/gpu/drm/i915/i915_guc_submission.c
drivers/gpu/drm/i915/intel_guc_loader.c

index beb38e30d0e9e1638677dc693df7c1757c0b7f24..41f2dd87b41340ab6519c2f72edc16af528eb865 100644 (file)
@@ -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);
index 64cdef479d1dfefcc563aae56bb731460b42b713..2e24712cf3ee70cd9d7c54a463deb361fb0f9b78 100644 (file)
@@ -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",