[PATCH 33/33] preempt-timeout
Chris Wilson
chris at chris-wilson.co.uk
Sun May 19 13:46:42 UTC 2019
---
drivers/gpu/drm/i915/Kconfig.profile | 4 +++
drivers/gpu/drm/i915/gt/intel_lrc.c | 50 ++++++++++++++++++++++++++--
2 files changed, 51 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/i915/Kconfig.profile b/drivers/gpu/drm/i915/Kconfig.profile
index 0e5db98da8f3..807df2c25ed5 100644
--- a/drivers/gpu/drm/i915/Kconfig.profile
+++ b/drivers/gpu/drm/i915/Kconfig.profile
@@ -11,3 +11,7 @@ config DRM_I915_SPIN_REQUEST
May be 0 to disable the initial spin. In practice, we estimate
the cost of enabling the interrupt (if currently disabled) to be
a few microseconds.
+
+config DRM_I915_PREEMPT_TIMEOUT
+ int
+ default 10 # microseconds
diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c
index 109b32c6aead..b6d54a3a2897 100644
--- a/drivers/gpu/drm/i915/gt/intel_lrc.c
+++ b/drivers/gpu/drm/i915/gt/intel_lrc.c
@@ -1218,6 +1218,11 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
*port = execlists_schedule_in(last, port - execlists->pending);
memset(port + 1, 0, (last_port - port) * sizeof(*port));
execlists_submit_ports(engine);
+
+ if (CONFIG_DRM_I915_PREEMPT_TIMEOUT) {
+ mod_timer(&execlists->timer,
+ jiffies + msecs_to_jiffies_timeout(CONFIG_DRM_I915_PREEMPT_TIMEOUT));
+ }
}
}
@@ -1373,13 +1378,49 @@ static void process_csb(struct intel_engine_cs *engine)
invalidate_csb_entries(&buf[0], &buf[num_entries - 1]);
}
-static void __execlists_submission_tasklet(struct intel_engine_cs *const engine)
+static bool __execlists_submission_tasklet(struct intel_engine_cs *const engine)
{
lockdep_assert_held(&engine->active.lock);
process_csb(engine);
- if (!engine->execlists.pending[0])
+ if (!engine->execlists.pending[0]) {
execlists_dequeue(engine);
+ return true;
+ }
+
+ return false;
+}
+
+static void preempt_reset(struct intel_engine_cs *engine)
+{
+ const unsigned int bit = I915_RESET_ENGINE + engine->id;
+ unsigned long *lock = &engine->i915->gpu_error.flags;
+ unsigned long flags;
+
+ if (test_and_set_bit(bit, lock))
+ return;
+
+ tasklet_disable_nosync(&engine->execlists.tasklet);
+ spin_unlock(&engine->active.lock);
+
+ i915_reset_engine(engine, "preemption timed out");
+
+ spin_lock_irqsave(&engine->active.lock, flags);
+ tasklet_enable(&engine->execlists.tasklet);
+
+ clear_bit(bit, lock);
+ wake_up_bit(lock, bit);
+}
+
+static bool preempt_timeout(struct intel_engine_cs *const engine)
+{
+ if (!CONFIG_DRM_I915_PREEMPT_TIMEOUT)
+ return false;
+
+ if (!intel_engine_has_preemption(engine))
+ return false;
+
+ return !timer_pending(&engine->execlists.timer);
}
/*
@@ -1392,7 +1433,10 @@ static void execlists_submission_tasklet(unsigned long data)
unsigned long flags;
spin_lock_irqsave(&engine->active.lock, flags);
- __execlists_submission_tasklet(engine);
+
+ if (!__execlists_submission_tasklet(engine) && preempt_timeout(engine))
+ preempt_reset(engine);
+
spin_unlock_irqrestore(&engine->active.lock, flags);
}
--
2.20.1
More information about the Intel-gfx-trybot
mailing list