[Intel-gfx] [PATCH] drm/i915: Stop engines around GPU reset preparations
Chris Wilson
chris at chris-wilson.co.uk
Sat Mar 3 09:08:41 UTC 2018
As we make preparations to reset the GPU state, we assume that the GPU
is hung and will not advance. Make this assumption more explicit by
setting the STOP_RING bit on the engines as part of our early reset
preparations.
v2: Move intel_gpu_reset_(prepare|finish) to
i915_gem_reset_engine_(prepare|finish) respectively. When the CS hits
the STOP_RING it emit an arbitration event, causing a context switch
between execlists and associated interrupts. Before we can allow that to
happen, we have to disable the execlists interrupt processing so that we
do not try and handle the partial completion (i.e. seeing the completed
even before the request has been signaled).
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala at linux.intel.com>
Cc: Michel Thierry <michel.thierry at intel.com>
Reviewed-by: Mika Kuoppala <mika.kuoppala at linux.intel.com> #v1
Link: https://patchwork.freedesktop.org/patch/msgid/20180302113324.23189-1-chris@chris-wilson.co.uk
---
drivers/gpu/drm/i915/i915_drv.h | 11 +++++++++--
drivers/gpu/drm/i915/i915_gem.c | 4 ++++
drivers/gpu/drm/i915/intel_uncore.c | 36 +++++++++++++++++++++++++++++++++++-
3 files changed, 48 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 10c9e5e619ab..0cb141f768ed 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2957,8 +2957,15 @@ extern const struct dev_pm_ops i915_pm_ops;
extern int i915_driver_load(struct pci_dev *pdev,
const struct pci_device_id *ent);
extern void i915_driver_unload(struct drm_device *dev);
-extern int intel_gpu_reset(struct drm_i915_private *dev_priv, u32 engine_mask);
-extern bool intel_has_gpu_reset(struct drm_i915_private *dev_priv);
+
+bool intel_has_gpu_reset(struct drm_i915_private *dev_priv);
+
+void intel_gpu_reset_prepare(struct drm_i915_private *dev_priv,
+ unsigned int engine_mask);
+int intel_gpu_reset(struct drm_i915_private *dev_priv,
+ unsigned int engine_mask);
+void intel_gpu_reset_finish(struct drm_i915_private *dev_priv,
+ unsigned int engine_mask);
#define I915_RESET_QUIET BIT(0)
extern void i915_reset(struct drm_i915_private *i915, unsigned int flags);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index a5bd07338b46..3f063967a6e0 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2953,6 +2953,8 @@ i915_gem_reset_prepare_engine(struct intel_engine_cs *engine)
if (engine->i915->guc.preempt_wq)
flush_workqueue(engine->i915->guc.preempt_wq);
+ intel_gpu_reset_prepare(engine->i915, BIT(engine->id));
+
if (engine->irq_seqno_barrier)
engine->irq_seqno_barrier(engine);
@@ -3154,6 +3156,8 @@ void i915_gem_reset(struct drm_i915_private *dev_priv)
void i915_gem_reset_finish_engine(struct intel_engine_cs *engine)
{
+ intel_gpu_reset_finish(engine->i915, BIT(engine->id));
+
tasklet_enable(&engine->execlists.tasklet);
kthread_unpark(engine->breadcrumbs.signaler);
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index 5ae9a62712ca..e193af2feefb 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -1899,7 +1899,31 @@ static reset_func intel_get_gpu_reset(struct drm_i915_private *dev_priv)
return NULL;
}
-int intel_gpu_reset(struct drm_i915_private *dev_priv, unsigned engine_mask)
+static void i915_engines_set_mode(struct drm_i915_private *dev_priv,
+ unsigned int engine_mask,
+ u32 mode)
+{
+ struct intel_engine_cs *engine;
+ enum intel_engine_id id;
+
+ if (INTEL_GEN(dev_priv) < 3)
+ return;
+
+ for_each_engine_masked(engine, dev_priv, engine_mask, id)
+ I915_WRITE_FW(RING_MI_MODE(engine->mmio_base), mode);
+}
+
+void intel_gpu_reset_prepare(struct drm_i915_private *dev_priv,
+ unsigned int engine_mask)
+{
+ intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
+
+ i915_engines_set_mode(dev_priv, engine_mask,
+ _MASKED_BIT_ENABLE(STOP_RING));
+}
+
+int intel_gpu_reset(struct drm_i915_private *dev_priv,
+ unsigned int engine_mask)
{
reset_func reset = intel_get_gpu_reset(dev_priv);
int retry;
@@ -1939,6 +1963,16 @@ int intel_gpu_reset(struct drm_i915_private *dev_priv, unsigned engine_mask)
return ret;
}
+void intel_gpu_reset_finish(struct drm_i915_private *dev_priv,
+ unsigned int engine_mask)
+{
+ /* Clear the STOP_RING bit as the reset may not have occurred */
+ i915_engines_set_mode(dev_priv, engine_mask,
+ _MASKED_BIT_DISABLE(STOP_RING));
+
+ intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
+}
+
bool intel_has_gpu_reset(struct drm_i915_private *dev_priv)
{
return intel_get_gpu_reset(dev_priv) != NULL;
--
2.16.2
More information about the Intel-gfx
mailing list