[PATCH 22/22] retire-req
Chris Wilson
chris at chris-wilson.co.uk
Wed May 23 21:37:39 UTC 2018
---
drivers/gpu/drm/i915/i915_request.c | 56 ++----------------
drivers/gpu/drm/i915/intel_engine_cs.c | 65 +++++++++++++++++++++
drivers/gpu/drm/i915/intel_guc_submission.c | 4 +-
drivers/gpu/drm/i915/intel_lrc.c | 10 +---
drivers/gpu/drm/i915/intel_ringbuffer.h | 2 +
5 files changed, 73 insertions(+), 64 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c
index 818ea3574759..a166e6a8d44b 100644
--- a/drivers/gpu/drm/i915/i915_request.c
+++ b/drivers/gpu/drm/i915/i915_request.c
@@ -344,50 +344,6 @@ static void free_capture_list(struct i915_request *request)
}
}
-static void __retire_engine_request(struct intel_engine_cs *engine,
- struct i915_request *rq)
-{
- GEM_TRACE("%s(%s) fence %llx:%d, global=%d, current %d\n",
- __func__, engine->name,
- rq->fence.context, rq->fence.seqno,
- rq->global_seqno,
- intel_engine_get_seqno(engine));
-
- GEM_BUG_ON(!i915_request_completed(rq));
-
- local_irq_disable();
-
- spin_lock(&engine->timeline.lock);
- GEM_BUG_ON(!list_is_first(&rq->link, &engine->timeline.requests));
- list_del_init(&rq->link);
- spin_unlock(&engine->timeline.lock);
-
- spin_lock(&rq->lock);
- if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &rq->fence.flags))
- dma_fence_signal_locked(&rq->fence);
- if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &rq->fence.flags))
- intel_engine_cancel_signaling(rq);
- if (rq->waitboost) {
- GEM_BUG_ON(!atomic_read(&rq->i915->gt_pm.rps.num_waiters));
- atomic_dec(&rq->i915->gt_pm.rps.num_waiters);
- }
- spin_unlock(&rq->lock);
-
- local_irq_enable();
-
- /*
- * The backing object for the context is done after switching to the
- * *next* context. Therefore we cannot retire the previous context until
- * the next context has already started running. However, since we
- * cannot take the required locks at i915_request_submit() we
- * defer the unpinning of the active context to now, retirement of
- * the subsequent request.
- */
- if (engine->last_retired_context)
- intel_context_unpin(engine->last_retired_context);
- engine->last_retired_context = rq->hw_context;
-}
-
static void __retire_engine_upto(struct intel_engine_cs *engine,
struct i915_request *rq)
{
@@ -399,10 +355,7 @@ static void __retire_engine_upto(struct intel_engine_cs *engine,
do {
tmp = list_first_entry(&engine->timeline.requests,
typeof(*tmp), link);
-
- GEM_BUG_ON(tmp->engine != engine);
- __retire_engine_request(engine, tmp);
- } while (tmp != rq);
+ } while (intel_engine_retire_request(engine, tmp) && tmp != rq);
}
static void i915_request_retire(struct i915_request *request)
@@ -421,6 +374,8 @@ static void i915_request_retire(struct i915_request *request)
trace_i915_request_retire(request);
+ __retire_engine_upto(request->engine, request);
+
advance_ring(request);
free_capture_list(request);
@@ -459,8 +414,6 @@ static void i915_request_retire(struct i915_request *request)
atomic_dec_if_positive(&request->gem_context->ban_score);
intel_context_unpin(request->hw_context);
- __retire_engine_upto(request->engine, request);
-
unreserve_gt(request->i915);
i915_sched_node_fini(request->i915, &request->sched);
@@ -637,7 +590,6 @@ submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state)
break;
case FENCE_FREE:
- i915_request_put(request);
break;
}
@@ -767,7 +719,7 @@ i915_request_alloc(struct intel_engine_cs *engine, struct i915_gem_context *ctx)
rq->timeline->fence_context,
timeline_get_seqno(rq->timeline));
- /* We bump the ref for the fence chain */
+ /* We bump the ref for the fence chain and hold for submit backend. */
i915_sw_fence_init(&i915_request_get(rq)->submit, submit_notify);
init_waitqueue_head(&rq->execute);
diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c
index 72e4cfd00230..2f7523cc058e 100644
--- a/drivers/gpu/drm/i915/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/intel_engine_cs.c
@@ -1041,6 +1041,68 @@ void intel_engines_reset_default_submission(struct drm_i915_private *i915)
engine->set_default_submission(engine);
}
+bool intel_engine_retire_request(struct intel_engine_cs *engine,
+ struct i915_request *rq)
+{
+ GEM_TRACE("%s(%s) fence %llx:%d, global=%d, current %d\n",
+ __func__, engine->name,
+ rq->fence.context, rq->fence.seqno,
+ rq->global_seqno,
+ intel_engine_get_seqno(engine));
+
+ GEM_BUG_ON(!i915_request_completed(rq));
+ GEM_BUG_ON(rq->engine != engine);
+
+ /* Don't drop the final ref until after the backend has finished */
+ if (port_request(engine->execlists.port) == rq)
+ return false;
+
+ local_irq_disable();
+
+ spin_lock(&engine->timeline.lock);
+ GEM_BUG_ON(!list_is_first(&rq->link, &engine->timeline.requests));
+ list_del_init(&rq->link);
+ spin_unlock(&engine->timeline.lock);
+
+ spin_lock(&rq->lock);
+ if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &rq->fence.flags))
+ dma_fence_signal_locked(&rq->fence);
+ if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &rq->fence.flags))
+ intel_engine_cancel_signaling(rq);
+ if (rq->waitboost) {
+ GEM_BUG_ON(!atomic_read(&rq->i915->gt_pm.rps.num_waiters));
+ atomic_dec(&rq->i915->gt_pm.rps.num_waiters);
+ }
+ spin_unlock(&rq->lock);
+
+ local_irq_enable();
+
+ /*
+ * The backing object for the context is done after switching to the
+ * *next* context. Therefore we cannot retire the previous context until
+ * the next context has already started running. However, since we
+ * cannot take the required locks at i915_request_submit() we
+ * defer the unpinning of the active context to now, retirement of
+ * the subsequent request.
+ */
+ if (engine->last_retired_context)
+ intel_context_unpin(engine->last_retired_context);
+ engine->last_retired_context = rq->hw_context;
+
+ i915_request_put(rq);
+ return true;
+}
+
+static void engine_retire_requests(struct intel_engine_cs *engine)
+{
+ struct i915_request *rq, *next;
+
+ list_for_each_entry_safe(rq, next, &engine->timeline.requests, link) {
+ if (WARN_ON(!intel_engine_retire_request(engine, rq)))
+ break;
+ }
+}
+
/**
* intel_engines_park: called when the GT is transitioning from busy->idle
* @i915: the i915 device
@@ -1071,6 +1133,7 @@ void intel_engines_park(struct drm_i915_private *i915)
"%s is not idle before parking\n",
engine->name);
intel_engine_dump(engine, &p, NULL);
+ engine->cancel_requests(engine);
}
/* Must be reset upon idling, or we may miss the busy wakeup. */
@@ -1079,6 +1142,8 @@ void intel_engines_park(struct drm_i915_private *i915)
if (engine->park)
engine->park(engine);
+ engine_retire_requests(engine);
+
if (engine->pinned_default_state) {
i915_gem_object_unpin_map(engine->default_state);
engine->pinned_default_state = NULL;
diff --git a/drivers/gpu/drm/i915/intel_guc_submission.c b/drivers/gpu/drm/i915/intel_guc_submission.c
index 133367a17863..6f6223644140 100644
--- a/drivers/gpu/drm/i915/intel_guc_submission.c
+++ b/drivers/gpu/drm/i915/intel_guc_submission.c
@@ -669,8 +669,7 @@ static void guc_submit(struct intel_engine_cs *engine)
static void port_assign(struct execlist_port *port, struct i915_request *rq)
{
GEM_BUG_ON(port_isset(port));
-
- port_set(port, i915_request_get(rq));
+ port_set(port, rq);
}
static inline int rq_prio(const struct i915_request *rq)
@@ -793,7 +792,6 @@ static void guc_submission_tasklet(unsigned long data)
rq = port_request(port);
while (rq && i915_request_completed(rq)) {
trace_i915_request_out(rq);
- i915_request_put(rq);
port = execlists_port_complete(execlists, port);
if (port_isset(port)) {
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index c88ea807945a..a0b139debe1f 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -513,11 +513,7 @@ static bool can_merge_ctx(const struct intel_context *prev,
static void port_assign(struct execlist_port *port, struct i915_request *rq)
{
GEM_BUG_ON(rq == port_request(port));
-
- if (port_isset(port))
- i915_request_put(port_request(port));
-
- port_set(port, port_pack(i915_request_get(rq), port_count(port)));
+ port_set(port, port_pack(rq, port_count(port)));
}
static void inject_preempt_context(struct intel_engine_cs *engine)
@@ -793,8 +789,6 @@ execlists_cancel_port_requests(struct intel_engine_execlists * const execlists)
INTEL_CONTEXT_SCHEDULE_OUT :
INTEL_CONTEXT_SCHEDULE_PREEMPTED);
- i915_request_put(rq);
-
memset(port, 0, sizeof(*port));
port++;
}
@@ -1061,8 +1055,6 @@ static void process_csb(struct intel_engine_cs *engine)
execlists_context_schedule_out(rq,
INTEL_CONTEXT_SCHEDULE_OUT);
- i915_request_put(rq);
-
GEM_TRACE("%s completed ctx=%d\n",
engine->name, port->context_id);
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 636a1b1ac0dc..1d4847c11d71 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -888,6 +888,8 @@ int intel_init_bsd_ring_buffer(struct intel_engine_cs *engine);
int intel_init_blt_ring_buffer(struct intel_engine_cs *engine);
int intel_init_vebox_ring_buffer(struct intel_engine_cs *engine);
+bool intel_engine_retire_request(struct intel_engine_cs *engine,
+ struct i915_request *rq);
int intel_engine_stop_cs(struct intel_engine_cs *engine);
u64 intel_engine_get_active_head(const struct intel_engine_cs *engine);
--
2.17.0
More information about the Intel-gfx-trybot
mailing list