From: John.C.Harrison@Intel.com
To: Intel-GFX@Lists.FreeDesktop.Org
Subject: [RFC 12/37] drm/i915/guc: implement submission via REQUEST_PREEMPTION action
Date: Mon, 23 Nov 2015 11:41:47 +0000 [thread overview]
Message-ID: <1448278932-31551-13-git-send-email-John.C.Harrison@Intel.com> (raw)
In-Reply-To: <1448278932-31551-1-git-send-email-John.C.Harrison@Intel.com>
From: Dave Gordon <david.s.gordon@intel.com>
If a batch is submitted via the preemptive (KMD_HIGH-priority) client
then instead of ringing the doorbell we dispatch it using the GuC
"REQUEST_PREEMPTION" action. Also, we specify "clear work queue" and
"clear submit queue" in that request, so the scheduler can reconsider
what is to be done next after preemption.
Note that the preemption request requires a reference to the GuC per-
context shared data, which in early versions of the GuC firmware was at
the end of the context object but nowadays is at the start.
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
---
drivers/gpu/drm/i915/i915_guc_submission.c | 64 ++++++++++++++++++++++++++++--
drivers/gpu/drm/i915/intel_guc_fwif.h | 7 ++++
drivers/gpu/drm/i915/intel_lrc.c | 26 +++++++-----
3 files changed, 84 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
index d8fd644..4035ac6 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -94,7 +94,8 @@ static int host2guc_action(struct intel_guc *guc, u32 *data, u32 len)
for (i = 0; i < len; i++)
I915_WRITE(SOFT_SCRATCH(i), data[i]);
- POSTING_READ(SOFT_SCRATCH(i - 1));
+ I915_WRITE(SOFT_SCRATCH(15), 0);
+ POSTING_READ(SOFT_SCRATCH(0));
I915_WRITE(HOST2GUC_INTERRUPT, HOST2GUC_TRIGGER);
@@ -126,6 +127,55 @@ static int host2guc_action(struct intel_guc *guc, u32 *data, u32 len)
}
/*
+ * Tell the GuC to submit a request pre-emptively
+ */
+static int
+host2guc_preempt(struct i915_guc_client *client,
+ struct intel_context *ctx,
+ struct intel_engine_cs *ring)
+{
+ struct drm_i915_private *dev_priv = ring->dev->dev_private;
+ struct intel_guc *guc = &dev_priv->guc;
+ uint32_t engine_id = ring->id;
+ struct drm_i915_gem_object *ctx_obj = ctx->engine[engine_id].state;
+ struct intel_ringbuffer *ringbuf = ctx->engine[engine_id].ringbuf;
+ struct guc_process_desc *desc;
+ void *base;
+ u32 data[7];
+ int ret;
+
+ if (WARN_ON(!ctx_obj || !ringbuf))
+ return -EINVAL;
+
+ WARN_ON(!i915_gem_obj_is_pinned(ctx_obj));
+ WARN_ON(!i915_gem_obj_is_pinned(ringbuf->obj));
+
+ WARN_ON(guc->preempt_client != client);
+
+ base = kmap_atomic(i915_gem_object_get_page(client->client_obj, 0));
+ desc = base + client->proc_desc_offset;
+
+ /* Update the tail so it is visible to GuC */
+ desc->tail = client->wq_tail;
+ kunmap_atomic(base);
+
+ data[0] = HOST2GUC_ACTION_REQUEST_PREEMPTION;
+ data[1] = guc->preempt_client->ctx_index; // preemptive client
+ data[2] = /* PREEMPT_ENGINE_OPTIONS */
+ HOST2GUC_PREEMPT_OPTION_IMMEDIATE | // submit before return
+ HOST2GUC_PREEMPT_OPTION_DROP_WORK_Q | // drop wq for client data[5]
+ HOST2GUC_PREEMPT_OPTION_DROP_SUBMIT_Q; // drop submitted (engine, priority)
+ data[3] = engine_id; // target engine
+ data[4] = guc->execbuf_client->priority; // victim priority
+ data[5] = guc->execbuf_client->ctx_index; // victim ctx/wq
+ data[6] = i915_gem_obj_ggtt_offset(ctx_obj) + LRC_GUCSHR_PN*PAGE_SIZE;
+
+ ret = host2guc_action(guc, data, 7);
+ WARN_ON(ret);
+ return ret;
+}
+
+/*
* Tell the GuC to allocate or deallocate a specific doorbell
*/
@@ -585,8 +635,9 @@ static void lr_context_update(struct drm_i915_gem_request *rq)
int i915_guc_submit(struct i915_guc_client *client,
struct drm_i915_gem_request *rq)
{
- struct intel_guc *guc = client->guc;
+ bool preemptive = client->priority <= GUC_CTX_PRIORITY_HIGH;
enum intel_ring_id ring_id = rq->ring->id;
+ struct intel_guc *guc = client->guc;
unsigned long flags;
int q_ret, b_ret;
@@ -600,8 +651,12 @@ int i915_guc_submit(struct i915_guc_client *client,
spin_lock_irqsave(&client->wq_lock, flags);
q_ret = guc_add_workqueue_item(client, rq);
- if (q_ret == 0)
- b_ret = guc_ring_doorbell(client);
+ if (q_ret == 0) {
+ if (preemptive)
+ b_ret = host2guc_preempt(client, rq->ctx, rq->ring);
+ else
+ b_ret = guc_ring_doorbell(client);
+ }
client->submissions[ring_id] += 1;
if (q_ret) {
@@ -612,6 +667,7 @@ int i915_guc_submit(struct i915_guc_client *client,
client->retcode = q_ret = b_ret;
} else {
client->retcode = 0;
+ rq->elsp_submitted += 1;
}
spin_unlock_irqrestore(&client->wq_lock, flags);
diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h
index 40b2ea5..48da20d 100644
--- a/drivers/gpu/drm/i915/intel_guc_fwif.h
+++ b/drivers/gpu/drm/i915/intel_guc_fwif.h
@@ -302,6 +302,7 @@ struct guc_context_desc {
/* This Action will be programmed in C180 - SOFT_SCRATCH_O_REG */
enum host2guc_action {
HOST2GUC_ACTION_DEFAULT = 0x0,
+ HOST2GUC_ACTION_REQUEST_PREEMPTION = 0x2,
HOST2GUC_ACTION_SAMPLE_FORCEWAKE = 0x6,
HOST2GUC_ACTION_ALLOCATE_DOORBELL = 0x10,
HOST2GUC_ACTION_DEALLOCATE_DOORBELL = 0x20,
@@ -311,6 +312,12 @@ enum host2guc_action {
HOST2GUC_ACTION_LIMIT
};
+enum action_preempt_options {
+ HOST2GUC_PREEMPT_OPTION_IMMEDIATE = 0x1,
+ HOST2GUC_PREEMPT_OPTION_DROP_WORK_Q = 0x4,
+ HOST2GUC_PREEMPT_OPTION_DROP_SUBMIT_Q = 0x8,
+};
+
/*
* The GuC sends its response to a command by overwriting the
* command in SS0. The response is distinguishable from a command
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 296d900..e99ae53 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -746,6 +746,9 @@ intel_logical_ring_advance_and_submit(struct drm_i915_gem_request *request)
{
struct intel_engine_cs *ring = request->ring;
struct drm_i915_private *dev_priv = request->i915;
+ struct i915_guc_client *client = dev_priv->guc.execbuf_client;
+ const static bool fake = false; /* true => only pretend to preempt */
+ bool preemptive = false; /* for now */
intel_logical_ring_advance(request->ringbuf);
@@ -754,8 +757,11 @@ intel_logical_ring_advance_and_submit(struct drm_i915_gem_request *request)
if (intel_ring_stopped(ring))
return;
- if (dev_priv->guc.execbuf_client)
- i915_guc_submit(dev_priv->guc.execbuf_client, request);
+ if (preemptive && dev_priv->guc.preempt_client && !fake)
+ client = dev_priv->guc.preempt_client;
+
+ if (client)
+ i915_guc_submit(client, request);
else
execlists_context_queue(request);
}
@@ -1894,6 +1900,7 @@ static int gen8_emit_request(struct drm_i915_gem_request *request)
{
struct intel_ringbuffer *ringbuf = request->ringbuf;
struct intel_engine_cs *ring = ringbuf->ring;
+ u64 addr;
u32 cmd;
int ret;
@@ -1906,14 +1913,15 @@ static int gen8_emit_request(struct drm_i915_gem_request *request)
if (ret)
return ret;
- cmd = MI_STORE_DWORD_IMM_GEN4;
- cmd |= MI_GLOBAL_GTT;
-
+ cmd = MI_STORE_DWORD_IMM_GEN4 | MI_GLOBAL_GTT;
intel_logical_ring_emit(ringbuf, cmd);
- intel_logical_ring_emit(ringbuf,
- (ring->status_page.gfx_addr +
- (I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT)));
- intel_logical_ring_emit(ringbuf, 0);
+
+ addr = I915_GEM_HWS_INDEX;
+ addr <<= MI_STORE_DWORD_INDEX_SHIFT;
+ addr += ring->status_page.gfx_addr;
+ intel_logical_ring_emit(ringbuf, lower_32_bits(addr));
+ intel_logical_ring_emit(ringbuf, upper_32_bits(addr));
+
intel_logical_ring_emit(ringbuf, i915_gem_request_get_seqno(request));
intel_logical_ring_emit(ringbuf, MI_USER_INTERRUPT);
intel_logical_ring_emit(ringbuf, MI_NOOP);
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
next prev parent reply other threads:[~2015-11-23 11:42 UTC|newest]
Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-11-23 11:41 [RFC 00/37] Preemption support for GPU scheduler John.C.Harrison
2015-11-23 11:41 ` [RFC 01/37] drm/i915: update ring space correctly John.C.Harrison
2015-11-23 11:41 ` [RFC 02/37] drm/i915: recalculate ring space after reset John.C.Harrison
2015-11-23 11:41 ` [RFC 03/37] drm/i915: hangcheck=idle should wake_up_all every time, not just once John.C.Harrison
2015-11-23 11:41 ` [RFC 04/37] drm/i915/error: capture execlist state on error John.C.Harrison
2015-11-23 11:41 ` [RFC 05/37] drm/i915/error: capture ringbuffer pointed to by START John.C.Harrison
2015-11-23 11:41 ` [RFC 06/37] drm/i915/error: report ctx id & desc for each request in the queue John.C.Harrison
2015-11-23 11:41 ` [RFC 07/37] drm/i915/error: improve CSB reporting John.C.Harrison
2015-11-23 11:41 ` [RFC 08/37] drm/i915/error: report size in pages for each object dumped John.C.Harrison
2015-11-23 11:41 ` [RFC 09/37] drm/i915/error: track, capture & print ringbuffer submission activity John.C.Harrison
2015-11-23 11:41 ` [RFC 10/37] drm/i915/guc: Tidy up GuC proc/ctx descriptor setup John.C.Harrison
2015-11-23 11:41 ` [RFC 11/37] drm/i915/guc: Add a second client, to be used for preemption John.C.Harrison
2015-11-23 11:41 ` John.C.Harrison [this message]
2015-11-23 11:41 ` [RFC 13/37] drm/i915/guc: Improve action error reporting, add preemption debug John.C.Harrison
2015-11-23 11:41 ` [RFC 14/37] drm/i915/guc: Expose GuC-maintained statistics John.C.Harrison
2015-11-23 11:41 ` [RFC 15/37] drm/i915: add i915_wait_request() call after i915_add_request_no_flush() John.C.Harrison
2015-11-23 11:41 ` [RFC 16/37] drm/i915/guc: Expose (intel)_lr_context_size() John.C.Harrison
2015-11-23 11:41 ` [RFC 17/37] drm/i915/guc: Add support for GuC ADS (Addition Data Structure) John.C.Harrison
2015-11-23 11:41 ` [RFC 18/37] drm/i915/guc: Fill in (part of?) the ADS whitelist John.C.Harrison
2015-11-23 11:41 ` [RFC 19/37] drm/i915/error: capture errored context based on request context-id John.C.Harrison
2015-11-23 11:41 ` [RFC 20/37] drm/i915/error: enhanced error capture of requests John.C.Harrison
2015-11-23 11:41 ` [RFC 21/37] drm/i915/error: add GuC state error capture & decode John.C.Harrison
2015-11-23 11:41 ` [RFC 22/37] drm/i915: track relative-constants-mode per-context not per-device John.C.Harrison
2015-11-23 11:41 ` [RFC 23/37] drm/i915: set request 'head' on allocation not in add_request() John.C.Harrison
2015-11-23 11:41 ` [RFC 24/37] drm/i915/sched: set request 'head' on at start of ring submission John.C.Harrison
2015-12-11 14:46 ` [RFC 24/38] " John.C.Harrison
2015-11-23 11:42 ` [RFC 25/37] drm/i915/sched: include scheduler state in error capture John.C.Harrison
2015-11-23 11:42 ` [RFC 26/37] drm/i915/preempt: preemption-related definitions and statistics John.C.Harrison
2015-11-23 11:42 ` [RFC 27/37] drm/i915/preempt: scheduler logic for queueing preemptive requests John.C.Harrison
2015-11-23 11:42 ` [RFC 28/37] drm/i915/preempt: scheduler logic for selecting " John.C.Harrison
2015-11-23 11:42 ` [RFC 29/37] drm/i915/preempt: scheduler logic for preventing recursive preemption John.C.Harrison
2015-11-23 11:42 ` [RFC 30/37] drm/i915/preempt: don't allow nonbatch ctx init when the scheduler is busy John.C.Harrison
2015-11-23 11:42 ` [RFC 31/37] drm/i915/preempt: scheduler logic for landing preemptive requests John.C.Harrison
2015-12-11 14:48 ` [RFC 31/38] " John.C.Harrison
2015-11-23 11:42 ` [RFC 32/37] drm/i915/preempt: add hook to catch 'unexpected' ring submissions John.C.Harrison
2015-12-11 14:49 ` [RFC 32/38] " John.C.Harrison
2015-11-23 11:42 ` [RFC 33/37] drm/i915/preempt: Refactor intel_lr_context_reset() John.C.Harrison
2015-11-23 11:42 ` [RFC 34/37] drm/i915/preempt: scheduler logic for postprocessing preemptive requests John.C.Harrison
2015-11-23 11:42 ` [RFC 35/37] drm/i915/preempt: update (LRC) ringbuffer-filling code to create " John.C.Harrison
2015-12-11 14:49 ` [RFC 36/38] " John.C.Harrison
2015-11-23 11:42 ` [RFC 36/37] drm/i915/preempt: update scheduler parameters to enable preemption John.C.Harrison
2015-11-23 11:42 ` [RFC 37/37] drm/i915: Added preemption info to various trace points John.C.Harrison
2015-12-11 14:50 ` [RFC 38/38] " John.C.Harrison
2015-12-11 14:50 ` [RFC 35/38] drm/i915/preempt: Implement mid-batch preemption support John.C.Harrison
2015-12-11 14:50 ` [RFC 00/38] Preemption support for GPU scheduler John.C.Harrison
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1448278932-31551-13-git-send-email-John.C.Harrison@Intel.com \
--to=john.c.harrison@intel.com \
--cc=Intel-GFX@Lists.FreeDesktop.Org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).