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 <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
This commit is contained in:
parent
7342a72cc4
commit
cbf4b77af1
|
@ -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;
|
||||
|
@ -952,14 +972,18 @@ int i915_guc_submission_enable(struct drm_i915_private *dev_priv)
|
|||
guc_init_doorbell_hw(guc);
|
||||
|
||||
/* Take over from manual control of ELSP (execlists) */
|
||||
for_each_engine(engine, dev_priv, id) {
|
||||
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;
|
||||
|
||||
engine->submit_request = i915_guc_submit;
|
||||
engine->schedule = NULL;
|
||||
|
||||
/* 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);
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in New Issue