[RFC 25/44] drm/i915: Added hook to catch 'unexpected' ring submissions

John.C.Harrison
2014-06-26T17:25:41Z

The scheduler needs to know what each seqno that pops out of the ring is
referring to. This change adds a hook into the the 'submit some random work that
got forgotten about' clean up code to inform the scheduler that a new seqno has
been sent to the ring for some non-batch buffer operation.
---
drivers/gpu/drm/i915/i915_gem.c | 20 +++++++++++++++++++-
drivers/gpu/drm/i915/i915_scheduler.c | 7 +++++++
drivers/gpu/drm/i915/i915_scheduler.h | 1 +
3 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 57b24f0..7727f0f 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2347,6 +2347,25 @@ int __i915_add_request(struct intel_engine_cs *ring,
if (WARN_ON(request == NULL))
return -ENOMEM;

+ request->seqno = intel_ring_get_seqno(ring);
+
+#ifdef CONFIG_DRM_I915_SCHEDULER
+ /* The scheduler needs to know about all seqno values that can pop out
+ * of the ring. Otherwise, things can get confused when batch buffers
+ * are re-ordered. Specifically, the scheduler has to work out which
+ * buffers have completed by matching the last completed seqno with its
+ * internal list of all seqnos ordered by when they were sent to the
+ * ring. If an unknown seqno appears, the scheduler is unable to process
+ * any batch buffers that might have completed just before the unknown
+ * one.
+ * NB: The scheduler must be told before the request is actually sent
+ * to the ring as it needs to know about it before the interrupt occurs.
+ */
+ ret = i915_scheduler_fly_seqno(ring, request->seqno);
+ if (ret)
+ return ret;
+#endif
+
/* Record the position of the start of the request so that
* should we detect the updated seqno part-way through the
* GPU processing the request, we never over-estimate the
@@ -2358,7 +2377,6 @@ int __i915_add_request(struct intel_engine_cs *ring,
if (ret)
return ret;

- request->seqno = intel_ring_get_seqno(ring);
request->ring = ring;
request->head = request_start;
request->tail = request_ring_position;
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c
index 1e4d7c313..b5d391c 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -92,6 +92,13 @@ int i915_scheduler_queue_execbuffer(struct i915_scheduler_queue_entry *qe)
return ret;
}

+int i915_scheduler_fly_seqno(struct intel_engine_cs *ring, uint32_t seqno)
+{
+ /* Do stuff... */
+
+ return 0;
+}
+
int i915_scheduler_handle_IRQ(struct intel_engine_cs *ring)
{
struct drm_i915_private *dev_priv = ring->dev->dev_private;
diff --git a/drivers/gpu/drm/i915/i915_scheduler.h b/drivers/gpu/drm/i915/i915_scheduler.h
index dd7d699..57e001a 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.h
+++ b/drivers/gpu/drm/i915/i915_scheduler.h
@@ -72,6 +72,7 @@ struct i915_scheduler {
uint32_t index;
};

+int i915_scheduler_fly_seqno(struct intel_engine_cs *ring, uint32_t seqno);
int i915_scheduler_remove(struct intel_engine_cs *ring);
bool i915_scheduler_is_seqno_in_flight(struct intel_engine_cs *ring,
uint32_t seqno, bool *completed);
--
1.7.9.5