summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c14
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine_types.h1
2 files changed, 13 insertions, 2 deletions
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c b/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c
index 8db7e93abde5..1c6c6692dd17 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c
@@ -65,6 +65,7 @@ static void heartbeat(struct work_struct *wrk)
container_of(wrk, typeof(*engine), heartbeat.work.work);
struct intel_context *ce = engine->kernel_context;
struct i915_request *rq;
+ unsigned long serial;
/* Just in case everything has gone horribly wrong, give it a kick */
intel_engine_flush_submission(engine);
@@ -122,10 +123,19 @@ static void heartbeat(struct work_struct *wrk)
goto out;
}
- if (engine->wakeref_serial == engine->serial)
+ serial = READ_ONCE(engine->serial);
+ if (engine->wakeref_serial == serial)
goto out;
- mutex_lock(&ce->timeline->mutex);
+ if (!mutex_trylock(&ce->timeline->mutex)) {
+ /* Unable to lock the kernel timeline, is the engine stuck? */
+ if (xchg(&engine->heartbeat.blocked, serial) == serial)
+ intel_gt_handle_error(engine->gt, engine->mask,
+ I915_ERROR_CAPTURE,
+ "no heartbeat on %s",
+ engine->name);
+ goto out;
+ }
intel_context_enter(ce);
rq = __i915_request_create(ce, GFP_NOWAIT | __GFP_NOWARN);
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h
index 073c3769e8cc..490af81bd6f3 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h
@@ -348,6 +348,7 @@ struct intel_engine_cs {
struct {
struct delayed_work work;
struct i915_request *systole;
+ unsigned long blocked;
} heartbeat;
unsigned long serial;