drm/i915: Declare the driver wedged if hangcheck makes no progress

Hangcheck is our back up in case the GPU or the driver gets stuck. It
detects when the GPU is not making any progress and issues a GPU reset.
However, if the driver is failing to make any progress, we can get
ourselves into a situation where we continually try resetting the GPU to
no avail. Employ a second timeout such that if we continue to see the
same seqno (the stalled engine has made no progress at all) over the
course of several hangchecks, declare the driver wedged and attempt to
start afresh.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180602104853.17140-1-chris@chris-wilson.co.uk
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
This commit is contained in:
Chris Wilson 2018-06-02 11:48:53 +01:00
parent 5db1d4ea91
commit 1fd00c0fae
4 changed files with 23 additions and 4 deletions

View File

@ -1359,11 +1359,12 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused)
seq_printf(m, "\tseqno = %x [current %x, last %x]\n", seq_printf(m, "\tseqno = %x [current %x, last %x]\n",
engine->hangcheck.seqno, seqno[id], engine->hangcheck.seqno, seqno[id],
intel_engine_last_submit(engine)); intel_engine_last_submit(engine));
seq_printf(m, "\twaiters? %s, fake irq active? %s, stalled? %s\n", seq_printf(m, "\twaiters? %s, fake irq active? %s, stalled? %s, wedged? %s\n",
yesno(intel_engine_has_waiter(engine)), yesno(intel_engine_has_waiter(engine)),
yesno(test_bit(engine->id, yesno(test_bit(engine->id,
&dev_priv->gpu_error.missed_irq_rings)), &dev_priv->gpu_error.missed_irq_rings)),
yesno(engine->hangcheck.stalled)); yesno(engine->hangcheck.stalled),
yesno(engine->hangcheck.wedged));
spin_lock_irq(&b->rb_lock); spin_lock_irq(&b->rb_lock);
for (rb = rb_first(&b->waiters); rb; rb = rb_next(rb)) { for (rb = rb_first(&b->waiters); rb; rb = rb_next(rb)) {

View File

@ -1006,6 +1006,8 @@ struct i915_gem_mm {
#define I915_ENGINE_DEAD_TIMEOUT (4 * HZ) /* Seqno, head and subunits dead */ #define I915_ENGINE_DEAD_TIMEOUT (4 * HZ) /* Seqno, head and subunits dead */
#define I915_SEQNO_DEAD_TIMEOUT (12 * HZ) /* Seqno dead with active head */ #define I915_SEQNO_DEAD_TIMEOUT (12 * HZ) /* Seqno dead with active head */
#define I915_ENGINE_WEDGED_TIMEOUT (60 * HZ) /* Reset but no recovery? */
enum modeset_restore { enum modeset_restore {
MODESET_ON_LID_OPEN, MODESET_ON_LID_OPEN,
MODESET_DONE, MODESET_DONE,

View File

@ -294,6 +294,7 @@ static void hangcheck_store_sample(struct intel_engine_cs *engine,
engine->hangcheck.seqno = hc->seqno; engine->hangcheck.seqno = hc->seqno;
engine->hangcheck.action = hc->action; engine->hangcheck.action = hc->action;
engine->hangcheck.stalled = hc->stalled; engine->hangcheck.stalled = hc->stalled;
engine->hangcheck.wedged = hc->wedged;
} }
static enum intel_engine_hangcheck_action static enum intel_engine_hangcheck_action
@ -368,6 +369,9 @@ static void hangcheck_accumulate_sample(struct intel_engine_cs *engine,
hc->stalled = time_after(jiffies, hc->stalled = time_after(jiffies,
engine->hangcheck.action_timestamp + timeout); engine->hangcheck.action_timestamp + timeout);
hc->wedged = time_after(jiffies,
engine->hangcheck.action_timestamp +
I915_ENGINE_WEDGED_TIMEOUT);
} }
static void hangcheck_declare_hang(struct drm_i915_private *i915, static void hangcheck_declare_hang(struct drm_i915_private *i915,
@ -409,7 +413,7 @@ static void i915_hangcheck_elapsed(struct work_struct *work)
gpu_error.hangcheck_work.work); gpu_error.hangcheck_work.work);
struct intel_engine_cs *engine; struct intel_engine_cs *engine;
enum intel_engine_id id; enum intel_engine_id id;
unsigned int hung = 0, stuck = 0; unsigned int hung = 0, stuck = 0, wedged = 0;
if (!i915_modparams.enable_hangcheck) if (!i915_modparams.enable_hangcheck)
return; return;
@ -440,6 +444,17 @@ static void i915_hangcheck_elapsed(struct work_struct *work)
if (hc.action != ENGINE_DEAD) if (hc.action != ENGINE_DEAD)
stuck |= intel_engine_flag(engine); stuck |= intel_engine_flag(engine);
} }
if (engine->hangcheck.wedged)
wedged |= intel_engine_flag(engine);
}
if (wedged) {
dev_err(dev_priv->drm.dev,
"GPU recovery timed out,"
" cancelling all in-flight rendering.\n");
GEM_TRACE_DUMP();
i915_gem_set_wedged(dev_priv);
} }
if (hung) if (hung)

View File

@ -122,7 +122,8 @@ struct intel_engine_hangcheck {
int deadlock; int deadlock;
struct intel_instdone instdone; struct intel_instdone instdone;
struct i915_request *active_request; struct i915_request *active_request;
bool stalled; bool stalled:1;
bool wedged:1;
}; };
struct intel_ring { struct intel_ring {