[PATCH 7/7] inactive
Chris Wilson
chris at chris-wilson.co.uk
Thu Jun 18 09:15:29 UTC 2020
---
drivers/gpu/drm/i915/gt/intel_engine_cs.c | 2 -
drivers/gpu/drm/i915/gt/intel_engine_types.h | 13 ----
drivers/gpu/drm/i915/gt/intel_lrc.c | 79 +++++++++++++-------
3 files changed, 50 insertions(+), 44 deletions(-)
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
index b7116854831a..60881c8b5b7c 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
@@ -515,8 +515,6 @@ void intel_engine_init_execlists(struct intel_engine_cs *engine)
memset(execlists->pending, 0, sizeof(execlists->pending));
execlists->active =
memset(execlists->inflight, 0, sizeof(execlists->inflight));
- execlists->inactive =
- memset(execlists->post, 0, sizeof(execlists->post));
execlists->queue_priority_hint = INT_MIN;
execlists->queue = RB_ROOT_CACHED;
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h
index 31cf60cef5a8..073c3769e8cc 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h
@@ -208,10 +208,6 @@ struct intel_engine_execlists {
* @active: the currently known context executing on HW
*/
struct i915_request * const *active;
- /**
- * @inactive: the current vacancy of completed CS
- */
- struct i915_request **inactive;
/**
* @inflight: the set of contexts submitted and acknowleged by HW
*
@@ -229,15 +225,6 @@ struct intel_engine_execlists {
* preemption or idle-to-active event.
*/
struct i915_request *pending[EXECLIST_MAX_PORTS + 1];
- /**
- * @post: the set of completed context switches
- *
- * Since we may want to stagger the processing of the CS switches
- * with the next submission, so that the context are notionally
- * kept in flight across the dequeue, we defer scheduling out of
- * the completed context switches.
- */
- struct i915_request *post[2 * EXECLIST_MAX_PORTS + 1];
/**
* @port_mask: number of execlist ports - 1
diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c
index 0144b1c77490..15e073a0ff7c 100644
--- a/drivers/gpu/drm/i915/gt/intel_lrc.c
+++ b/drivers/gpu/drm/i915/gt/intel_lrc.c
@@ -2453,22 +2453,25 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
}
}
-static void
-cancel_port_requests(struct intel_engine_execlists * const execlists)
+static struct i915_request **
+cancel_port_requests(struct intel_engine_execlists * const execlists,
+ struct i915_request **inactive)
{
struct i915_request * const *port;
for (port = execlists->pending; *port; port++)
- *execlists->inactive++ = *port;
+ *inactive++ = *port;
clear_ports(execlists->pending, ARRAY_SIZE(execlists->pending));
/* Mark the end of active before we overwrite *active */
for (port = xchg(&execlists->active, execlists->pending); *port; port++)
- *execlists->inactive++ = *port;
+ *inactive++ = *port;
clear_ports(execlists->inflight, ARRAY_SIZE(execlists->inflight));
smp_wmb(); /* complete the seqlock for execlists_active() */
WRITE_ONCE(execlists->active, execlists->inflight);
+
+ return inactive;
}
static inline void
@@ -2540,7 +2543,8 @@ gen8_csb_parse(const struct intel_engine_execlists *execlists, const u32 *csb)
return *csb & (GEN8_CTX_STATUS_IDLE_ACTIVE | GEN8_CTX_STATUS_PREEMPTED);
}
-static void process_csb(struct intel_engine_cs *engine)
+static struct i915_request **
+process_csb(struct intel_engine_cs *engine, struct i915_request **inactive)
{
struct intel_engine_execlists * const execlists = &engine->execlists;
const u32 * const buf = execlists->csb_status;
@@ -2569,7 +2573,7 @@ static void process_csb(struct intel_engine_cs *engine)
head = execlists->csb_head;
tail = READ_ONCE(*execlists->csb_write);
if (unlikely(head == tail))
- return;
+ return inactive;
/*
* Hopefully paired with a wmb() in HW!
@@ -2625,7 +2629,7 @@ static void process_csb(struct intel_engine_cs *engine)
/* cancel old inflight, prepare for switch */
trace_ports(execlists, "preempted", old);
while (*old)
- *execlists->inactive++ = *old++;
+ *inactive++ = *old++;
/* switch pending to inflight */
GEM_BUG_ON(!assert_pending_valid(execlists, "promote"));
@@ -2682,7 +2686,7 @@ static void process_csb(struct intel_engine_cs *engine)
regs[CTX_RING_TAIL]);
}
- *execlists->inactive++ = *execlists->active++;
+ *inactive++ = *execlists->active++;
GEM_BUG_ON(execlists->active - execlists->inflight >
execlists_num_ports(execlists));
@@ -2704,20 +2708,16 @@ static void process_csb(struct intel_engine_cs *engine)
* invalidation before.
*/
invalidate_csb_entries(&buf[0], &buf[num_entries - 1]);
+
+ return inactive;
}
-static void post_process_csb(struct intel_engine_cs *engine)
+static void post_process_csb(struct intel_engine_cs *engine,
+ struct i915_request **port,
+ struct i915_request **last)
{
- struct intel_engine_execlists * const el = &engine->execlists;
- struct i915_request **port;
-
- if (!el->post[0])
- return;
-
- GEM_BUG_ON(el->post[2 * EXECLIST_MAX_PORTS]);
- for (port = el->post; *port; port++)
- execlists_schedule_out(*port);
- el->inactive = clear_ports(el->post, port - el->post);
+ while (port != last)
+ execlists_schedule_out(*port++);
}
static void __execlists_hold(struct i915_request *rq)
@@ -3119,8 +3119,11 @@ static bool preempt_timeout(const struct intel_engine_cs *const engine)
static void execlists_submission_tasklet(unsigned long data)
{
struct intel_engine_cs * const engine = (struct intel_engine_cs *)data;
+ struct i915_request *post[2 * EXECLIST_MAX_PORTS];
+ struct i915_request **inactive;
- process_csb(engine);
+ inactive = process_csb(engine, post);
+ GEM_BUG_ON(inactive - post > ARRAY_SIZE(post));
if (unlikely(READ_ONCE(engine->execlists.error_interrupt))) {
engine->execlists.error_interrupt = 0;
@@ -3134,7 +3137,7 @@ static void execlists_submission_tasklet(unsigned long data)
if (!engine->execlists.pending[0])
execlists_dequeue(engine);
- post_process_csb(engine);
+ post_process_csb(engine, post, inactive);
}
static void __execlists_kick(struct intel_engine_execlists *execlists)
@@ -4143,22 +4146,29 @@ static void __execlists_reset_reg_state(const struct intel_context *ce,
__reset_stop_ring(regs, engine);
}
-static void __execlists_reset(struct intel_engine_cs *engine, bool stalled)
+static struct i915_request **reset_csb(struct intel_engine_cs *engine,
+ struct i915_request **inactive)
{
struct intel_engine_execlists * const execlists = &engine->execlists;
- struct intel_context *ce;
- struct i915_request *rq;
- u32 head;
mb(); /* paranoia: read the CSB pointers from after the reset */
clflush(execlists->csb_write);
mb();
- process_csb(engine); /* drain preemption events */
+ inactive = process_csb(engine, inactive); /* drain preemption events */
/* Following the reset, we need to reload the CSB read/write pointers */
reset_csb_pointers(engine);
+ return inactive;
+}
+
+static void __execlists_reset(struct intel_engine_cs *engine, bool stalled)
+{
+ struct intel_context *ce;
+ struct i915_request *rq;
+ u32 head;
+
/*
* Save the currently executing context, even if we completed
* its request, it was still running at the time of the
@@ -4232,21 +4242,25 @@ static void __execlists_reset(struct intel_engine_cs *engine, bool stalled)
unwind:
/* Push back any incomplete requests for replay after the reset. */
- cancel_port_requests(execlists);
__unwind_incomplete_requests(engine);
}
static void execlists_reset_rewind(struct intel_engine_cs *engine, bool stalled)
{
+ struct i915_request *post[2 * EXECLIST_MAX_PORTS];
+ struct i915_request **inactive;
unsigned long flags;
ENGINE_TRACE(engine, "\n");
- spin_lock_irqsave(&engine->active.lock, flags);
+ inactive = reset_csb(engine, post);
+ spin_lock_irqsave(&engine->active.lock, flags);
__execlists_reset(engine, stalled);
-
spin_unlock_irqrestore(&engine->active.lock, flags);
+
+ inactive = cancel_port_requests(&engine->execlists, inactive);
+ post_process_csb(engine, post, inactive);
}
static void nop_submission_tasklet(unsigned long data)
@@ -4260,12 +4274,16 @@ static void nop_submission_tasklet(unsigned long data)
static void execlists_reset_cancel(struct intel_engine_cs *engine)
{
struct intel_engine_execlists * const execlists = &engine->execlists;
+ struct i915_request *post[2 * EXECLIST_MAX_PORTS];
+ struct i915_request **inactive;
struct i915_request *rq, *rn;
struct rb_node *rb;
unsigned long flags;
ENGINE_TRACE(engine, "\n");
+ inactive = reset_csb(engine, post);
+
/*
* Before we call engine->cancel_requests(), we should have exclusive
* access to the submission state. This is arranged for us by the
@@ -4337,6 +4355,9 @@ static void execlists_reset_cancel(struct intel_engine_cs *engine)
execlists->tasklet.func = nop_submission_tasklet;
spin_unlock_irqrestore(&engine->active.lock, flags);
+
+ inactive = cancel_port_requests(execlists, inactive);
+ post_process_csb(engine, post, inactive);
}
static void execlists_reset_finish(struct intel_engine_cs *engine)
--
2.20.1
More information about the Intel-gfx-trybot
mailing list