[Intel-gfx] [PATCH v3 22/28] drm/i915: Cache request completion status

John.C.Harrison at Intel.com John.C.Harrison at Intel.com
Mon Nov 24 19:49:44 CET 2014


From: John Harrison <John.C.Harrison at Intel.com>

Continuing the removal of seqno based operations - updated the request
completion query to not simply chain on to i915_seqno_passed(). Instead, it now
returns a pre-cached completion flag in the fast case. In the slow case it reads
the hardware seqno and, only if it has moved on since the last scan, looks
through the outstanding request list to see which requests can be marked as
completed.

Later in the patch series, this will be optimised further by only doing the
completion scan when an interrupt is raised to say that a request has actually
completed on the hardware. Thus the call to test the completion status of an
arbitrary request simply becomes 'return req->completed'.

For: VIZ-4377
Signed-off-by: John Harrison <John.C.Harrison at Intel.com>
Reviewed-by: Thomas Daniel <Thomas.Daniel at intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h         |   32 +++++++++++++++----------------
 drivers/gpu/drm/i915/i915_gem.c         |   24 +++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_lrc.c        |    1 +
 drivers/gpu/drm/i915/intel_ringbuffer.c |    2 ++
 drivers/gpu/drm/i915/intel_ringbuffer.h |    3 +++
 5 files changed, 45 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 36a4413..d30823e 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1996,6 +1996,9 @@ void i915_gem_track_fb(struct drm_i915_gem_object *old,
 struct drm_i915_gem_request {
 	struct kref ref;
 
+	/** Is this request known to be complete? */
+	bool complete;
+
 	/** On Which ring this request was generated */
 	struct intel_engine_cs *ring;
 
@@ -2030,6 +2033,8 @@ struct drm_i915_gem_request {
 };
 
 void i915_gem_request_free(struct kref *req_ref);
+void i915_gem_complete_requests_ring(struct intel_engine_cs *ring,
+				     bool lazy_coherency);
 
 static inline uint32_t
 i915_gem_request_get_seqno(struct drm_i915_gem_request *req)
@@ -2070,11 +2075,16 @@ static inline void i915_gem_request_assign(struct drm_i915_gem_request **pdst,
 	*pdst = src;
 }
 
-/*
- * XXX: i915_gem_request_completed should be here but currently needs the
- * definition of i915_seqno_passed() which is below. It will be moved in
- * a later patch when the call to i915_seqno_passed() is obsoleted...
- */
+static inline bool i915_gem_request_completed(struct drm_i915_gem_request *req,
+					      bool lazy_coherency)
+{
+	if (req->complete)
+		return true;
+
+	i915_gem_complete_requests_ring(req->ring, lazy_coherency);
+
+	return req->complete;
+}
 
 struct drm_i915_file_private {
 	struct drm_i915_private *dev_priv;
@@ -3134,18 +3144,6 @@ wait_remaining_ms_from_jiffies(unsigned long timestamp_jiffies, int to_wait_ms)
 	}
 }
 
-static inline bool i915_gem_request_completed(struct drm_i915_gem_request *req,
-					      bool lazy_coherency)
-{
-	u32 seqno;
-
-	BUG_ON(req == NULL);
-
-	seqno = req->ring->get_seqno(req->ring, lazy_coherency);
-
-	return i915_seqno_passed(seqno, req->seqno);
-}
-
 static inline void i915_trace_irq_get(struct intel_engine_cs *ring,
 				      struct drm_i915_gem_request *req)
 {
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 68c23dd..ce316fa 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2736,6 +2736,30 @@ void i915_gem_request_unreference_irq(struct drm_i915_gem_request *req)
 	spin_unlock_irqrestore(&ring->reqlist_lock, flags);
 }
 
+void i915_gem_complete_requests_ring(struct intel_engine_cs *ring,
+				     bool lazy_coherency)
+{
+	struct drm_i915_gem_request *req;
+	u32 seqno;
+
+	seqno = ring->get_seqno(ring, lazy_coherency);
+	if (!seqno)
+		return;
+
+	if (seqno == ring->last_read_seqno)
+		return;
+
+	list_for_each_entry(req, &ring->request_list, list) {
+		if (req->complete)
+			continue;
+
+		if (i915_seqno_passed(seqno, req->seqno))
+			req->complete = true;
+	}
+
+	ring->last_read_seqno = seqno;
+}
+
 /**
  * This function clears the request list as sequence numbers are passed.
  */
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 0acb448..6711020 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -899,6 +899,7 @@ static int logical_ring_alloc_request(struct intel_engine_cs *ring,
 
 	kref_init(&request->ref);
 	request->ring = ring;
+	request->complete = false;
 
 	ret = i915_gem_get_seqno(ring->dev, &request->seqno);
 	if (ret) {
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 5a1e6fe..92c72b3 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -2047,6 +2047,7 @@ intel_ring_alloc_request(struct intel_engine_cs *ring)
 
 	kref_init(&request->ref);
 	request->ring = ring;
+	request->complete = false;
 
 	ret = i915_gem_get_seqno(ring->dev, &request->seqno);
 	if (ret) {
@@ -2139,6 +2140,7 @@ void intel_ring_init_seqno(struct intel_engine_cs *ring, u32 seqno)
 			I915_WRITE(RING_SYNC_2(ring->mmio_base), 0);
 	}
 
+	ring->last_read_seqno = 0;
 	ring->set_seqno(ring, seqno);
 	ring->hangcheck.seqno = seqno;
 }
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index c8b84de..1c035c8 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -273,6 +273,9 @@ struct  intel_engine_cs {
 	bool gpu_caches_dirty;
 	bool fbc_dirty;
 
+	/* For optimising request completion events */
+	u32 last_read_seqno;
+
 	wait_queue_head_t irq_queue;
 
 	struct intel_context *default_context;
-- 
1.7.9.5




More information about the Intel-gfx mailing list