[Intel-gfx] [PATCH] force-preempt-reset
Chris Wilson
chris at chris-wilson.co.uk
Fri Mar 16 23:04:23 UTC 2018
A more concrete idea of what I think the serialisation should be between
reset timer and tasklet.
---
drivers/gpu/drm/i915/intel_lrc.c | 43 +++++++++++++++++++++++++++++++++
drivers/gpu/drm/i915/intel_ringbuffer.h | 4 +++
2 files changed, 47 insertions(+)
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 2c2eb6d3868a..b6fd4323663d 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -531,6 +531,39 @@ static void inject_preempt_context(struct intel_engine_cs *engine)
execlists_clear_active(execlists, EXECLISTS_ACTIVE_HWACK);
execlists_set_active(execlists, EXECLISTS_ACTIVE_PREEMPT);
+
+ /* Set a timer to force preemption vs hostile userspace */
+ if (execlists->preempt_timeout_ns)
+ hrtimer_start(&execlists->preempt_timer,
+ ktime_set(0, execlists->preempt_timeout_ns),
+ HRTIMER_MODE_REL);
+}
+
+static enum hrtimer_restart preempt_timeout(struct hrtimer *hrtimer)
+{
+ struct intel_engine_cs *engine =
+ container_of(hrtimer, typeof(*engine), execlists.preempt_timer);
+
+ if (execlists_is_active(&engine->execlists, EXECLISTS_ACTIVE_PREEMPT))
+ queue_work(system_highpri_wq, &engine->execlists.preempt_reset);
+
+ return HRTIMER_NORESTART;
+}
+
+static void preempt_reset(struct work_struct *work)
+{
+ struct intel_engine_cs *engine =
+ container_of(work, typeof(*engine), execlists.preempt_reset);
+
+ tasklet_disable(&engine->execlists.tasklet);
+
+ engine->execlists.tasklet.func(engine->execlists.tasklet.data);
+
+ if (execlists_is_active(&engine->execlists, EXECLISTS_ACTIVE_PREEMPT))
+ i915_handle_error(engine->i915, BIT(engine->id), 0,
+ "preemption timed out on %s", engine->name);
+
+ tasklet_enable(&engine->execlists.tasklet);
}
static void complete_preempt_context(struct intel_engine_execlists *execlists)
@@ -539,6 +572,11 @@ static void complete_preempt_context(struct intel_engine_execlists *execlists)
execlists_unwind_incomplete_requests(execlists);
GEM_BUG_ON(!execlists_is_active(execlists, EXECLISTS_ACTIVE_PREEMPT));
+
+ /* If the timer already fired, complete the reset */
+ if (hrtimer_try_to_cancel(&execlists->preempt_timer) < 0)
+ return;
+
execlists_clear_active(execlists, EXECLISTS_ACTIVE_PREEMPT);
}
@@ -2182,6 +2220,11 @@ logical_ring_setup(struct intel_engine_cs *engine)
tasklet_init(&engine->execlists.tasklet,
execlists_submission_tasklet, (unsigned long)engine);
+ INIT_WORK(&engine->execlists.preempt_reset, preempt_reset);
+ hrtimer_init(&engine->execlists.preempt_timer,
+ CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ engine->execlists.preempt_timer.function = preempt_timeout;
+
logical_ring_default_vfuncs(engine);
logical_ring_default_irqs(engine);
}
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 495b21fc33db..74fcff8a2a6e 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -307,6 +307,10 @@ struct intel_engine_execlists {
* @preempt_complete_status: expected CSB upon completing preemption
*/
u32 preempt_complete_status;
+
+ struct hrtimer preempt_timer;
+ struct work_struct preempt_reset;
+ unsigned long preempt_timeout_ns;
};
#define INTEL_ENGINE_CS_MAX_NAME 8
--
2.16.2
More information about the Intel-gfx
mailing list