[PATCH v2 22/28] drm/i915: Cache request completion status

John.C.Harrison
2014-11-14T12:19:45Z

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@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 918d61b..8531e0f 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1990,6 +1990,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;

@@ -2024,6 +2027,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)
@@ -2064,11 +2069,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;
@@ -3138,18 +3148,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 1d07a14..b6c75b0 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2726,6 +2726,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 a583cf3..960cb9f 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -806,6 +806,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 f29c31e..5cbc5c2 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -2043,6 +2043,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) {
@@ -2135,6 +2136,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 15ec7c4..4957c35 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -272,6 +272,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;