public inbox for intel-gfx@lists.freedesktop.org
 help / color / mirror / Atom feed
From: "Michał Winiarski" <michal.winiarski@intel.com>
To: intel-gfx@lists.freedesktop.org
Subject: [RFC 04/11] drm/i915/preempt: Implement null preemption method
Date: Thu, 23 Feb 2017 20:08:26 +0100	[thread overview]
Message-ID: <20170223190833.2888-5-michal.winiarski@intel.com> (raw)
In-Reply-To: <20170223190833.2888-1-michal.winiarski@intel.com>

We're only requesting preemption for requests that have high enough
priority (above threshold). Currently we're also ignoring requests that
have dependencies on different engines.

Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
---
 drivers/gpu/drm/i915/i915_guc_submission.c |  3 ++
 drivers/gpu/drm/i915/intel_lrc.c           | 81 +++++++++++++++++++++++++++++-
 2 files changed, 83 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
index feccd65..6d9431d 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -491,6 +491,9 @@ static int guc_ring_doorbell(struct i915_guc_client *client)
 
 static int i915_guc_preempt_noop(struct intel_engine_cs *engine)
 {
+	engine->preempt_requested = false;
+	intel_write_status_page(engine, I915_GEM_HWS_PREEMPT_INDEX, 0);
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index d4cfaa1..869b96e 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -674,16 +674,93 @@ pt_lock_engine(struct i915_priotree *pt, struct intel_engine_cs *locked)
 	return engine;
 }
 
+#define EXECLISTS_PREEMPT_THRESHOLD 512
+
+static void __execlists_try_preempt(struct intel_engine_cs *engine,
+				  int prio)
+{
+	struct drm_i915_gem_request *rq;
+	int highest_prio = INT_MIN;
+	int ret;
+
+	spin_lock_irq(&engine->timeline->lock);
+
+	/* Engine is idle */
+	if (execlists_elsp_idle(engine))
+		goto out_unlock;
+
+	if (engine->preempt_requested)
+		goto out_unlock;
+
+	list_for_each_entry_reverse(rq, &engine->timeline->requests, link) {
+		if (!i915_gem_request_completed(rq)) {
+			highest_prio = (rq->priotree.priority > highest_prio) ?
+				 rq->priotree.priority : highest_prio;
+		} else
+			break;
+	}
+
+	/* Bail out if our priority is lower than any of the inflight requests
+	 * (also if there are none requests) */
+	if (highest_prio == INT_MIN || prio <= highest_prio)
+		goto out_unlock;
+
+	engine->preempt_requested = true;
+
+	spin_unlock_irq(&engine->timeline->lock);
+
+	ret = engine->preempt(engine);
+	if (ret) {
+		spin_lock_irq(&engine->timeline->lock);
+		engine->preempt_requested = false;
+		spin_unlock_irq(&engine->timeline->lock);
+	}
+
+	return;
+
+out_unlock:
+	spin_unlock_irq(&engine->timeline->lock);
+}
+
+static void execlists_try_preempt(struct intel_engine_cs *engine,
+				     int prio,
+				     unsigned long *engines_bumped)
+{
+	int num_engines_bumped = bitmap_weight(engines_bumped,
+					       I915_NUM_ENGINES);
+
+	/* Preemption is disabled */
+	if (!engine->preempt)
+		return;
+
+	/* We're not a high priority request */
+	if (prio < EXECLISTS_PREEMPT_THRESHOLD)
+		return;
+
+	/* We have dependencies on many engines */
+	if (num_engines_bumped > 1)
+		return;
+
+	/* We have dependency on a single engine - but it's not our engine */
+	if (num_engines_bumped == 1 && !test_bit(engine->id, engines_bumped))
+		return;
+
+	__execlists_try_preempt(engine, prio);
+}
+
 static void execlists_schedule(struct drm_i915_gem_request *request, int prio)
 {
 	struct intel_engine_cs *engine = NULL;
 	struct i915_dependency *dep, *p;
 	struct i915_dependency stack;
 	LIST_HEAD(dfs);
+	DECLARE_BITMAP(engine_bumped, I915_NUM_ENGINES);
 
 	if (prio <= READ_ONCE(request->priotree.priority))
 		return;
 
+	bitmap_zero(engine_bumped, I915_NUM_ENGINES);
+
 	/* Need BKL in order to use the temporary link inside i915_dependency */
 	lockdep_assert_held(&request->i915->drm.struct_mutex);
 
@@ -719,6 +796,7 @@ static void execlists_schedule(struct drm_i915_gem_request *request, int prio)
 			continue;
 
 		engine = pt_lock_engine(pt, engine);
+		__set_bit(engine->id, engine_bumped);
 
 		/* If it is not already in the rbtree, we can update the
 		 * priority inplace and skip over it (and its dependencies)
@@ -737,6 +815,7 @@ static void execlists_schedule(struct drm_i915_gem_request *request, int prio)
 		INIT_LIST_HEAD(&dep->dfs_link);
 
 		engine = pt_lock_engine(pt, engine);
+		__set_bit(engine->id, engine_bumped);
 
 		if (prio <= pt->priority)
 			continue;
@@ -752,7 +831,7 @@ static void execlists_schedule(struct drm_i915_gem_request *request, int prio)
 	if (engine)
 		spin_unlock_irq(&engine->timeline->lock);
 
-	/* XXX Do we need to preempt to make room for us and our deps? */
+	execlists_try_preempt(engine, prio, engine_bumped);
 }
 
 static int execlists_context_pin(struct intel_engine_cs *engine,
-- 
2.9.3

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

  parent reply	other threads:[~2017-02-23 19:09 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-02-23 19:08 [RFC] GuC based preemption Michał Winiarski
2017-02-23 19:08 ` [RFC 01/11] drm/i915/scheduler: Remember request priority throughout its lifetime Michał Winiarski
2017-02-23 21:29   ` Chris Wilson
2017-02-23 19:08 ` [RFC 02/11] drm/i915/preempt: Add module parameter for preemption Michał Winiarski
2017-02-23 19:08 ` [RFC 03/11] drm/i915/preempt: Add information needed to track engine preempt state Michał Winiarski
2017-02-23 19:08 ` Michał Winiarski [this message]
2017-02-23 21:37   ` [RFC 04/11] drm/i915/preempt: Implement null preemption method Chris Wilson
2017-02-23 19:14 ` [RFC 05/11] drm/i915/preempt: Handle preemption event in guc tasklet Michał Winiarski
2017-03-01 12:57   ` Chris Wilson
2017-03-06 10:53     ` Chris Wilson
2017-02-23 19:14 ` [RFC 06/11] drm/i915/guc: Remove extra arguments from guc_client_alloc Michał Winiarski
2017-02-23 16:38   ` Oscar Mateo
2017-02-24  1:39     ` Daniele Ceraolo Spurio
2017-02-23 19:14 ` [RFC 07/11] drm/i915/guc: Add a second client, to be used for preemption Michał Winiarski
2017-02-23 19:14 ` [RFC 08/11] drm/i915/guc: Add preemption action to GuC firmware interface Michał Winiarski
2017-02-23 19:14 ` [RFC 09/11] HACK drm/i915/preempt: Actually send the preemption request Michał Winiarski
2017-02-23 19:14 ` [RFC 10/11] drm/i915/preempt: Emit MI_ARB_CHECK before the start of user batch Michał Winiarski
2017-03-01 12:53   ` Chris Wilson
2017-02-23 19:14 ` [RFC 11/11] drm/i915/preempt: Show engine preempt state in engine_info debugfs Michał Winiarski

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=20170223190833.2888-5-michal.winiarski@intel.com \
    --to=michal.winiarski@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