Commit f9e9e9de authored by Chris Wilson's avatar Chris Wilson

drm/i915: Prioritise non-busywait semaphore workloads

We don't want to busywait on the GPU if we have other work to do. If we
give non-busywaiting workloads higher (initial) priority than workloads
that require a busywait, we will prioritise work that is ready to run
immediately. We then also have to be careful that we don't give earlier
semaphores an accidental boost because later work doesn't wait on other
rings, hence we keep a history of semaphore usage of the dependency chain.

v2: Stop rolling the bits into a chain and just use a flag in case this
request or any of our dependencies use a semaphore. The rolling around
was contagious as Tvrtko was heard to fall off his chair.

Testcase: igt/gem_exec_schedule/semaphore
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Reviewed-by: default avatarTvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190301170901.8340-4-chris@chris-wilson.co.uk
parent e8861964
...@@ -813,6 +813,7 @@ emit_semaphore_wait(struct i915_request *to, ...@@ -813,6 +813,7 @@ emit_semaphore_wait(struct i915_request *to,
*cs++ = 0; *cs++ = 0;
intel_ring_advance(to, cs); intel_ring_advance(to, cs);
to->sched.flags |= I915_SCHED_HAS_SEMAPHORE;
return 0; return 0;
} }
...@@ -1083,6 +1084,21 @@ void i915_request_add(struct i915_request *request) ...@@ -1083,6 +1084,21 @@ void i915_request_add(struct i915_request *request)
if (engine->schedule) { if (engine->schedule) {
struct i915_sched_attr attr = request->gem_context->sched; struct i915_sched_attr attr = request->gem_context->sched;
/*
* Boost actual workloads past semaphores!
*
* With semaphores we spin on one engine waiting for another,
* simply to reduce the latency of starting our work when
* the signaler completes. However, if there is any other
* work that we could be doing on this engine instead, that
* is better utilisation and will reduce the overall duration
* of the current work. To avoid PI boosting a semaphore
* far in the distance past over useful work, we keep a history
* of any semaphore use along our dependency chain.
*/
if (!(request->sched.flags & I915_SCHED_HAS_SEMAPHORE))
attr.priority |= I915_PRIORITY_NOSEMAPHORE;
/* /*
* Boost priorities to new clients (new request flows). * Boost priorities to new clients (new request flows).
* *
......
...@@ -39,6 +39,7 @@ void i915_sched_node_init(struct i915_sched_node *node) ...@@ -39,6 +39,7 @@ void i915_sched_node_init(struct i915_sched_node *node)
INIT_LIST_HEAD(&node->waiters_list); INIT_LIST_HEAD(&node->waiters_list);
INIT_LIST_HEAD(&node->link); INIT_LIST_HEAD(&node->link);
node->attr.priority = I915_PRIORITY_INVALID; node->attr.priority = I915_PRIORITY_INVALID;
node->flags = 0;
} }
static struct i915_dependency * static struct i915_dependency *
...@@ -69,6 +70,11 @@ bool __i915_sched_node_add_dependency(struct i915_sched_node *node, ...@@ -69,6 +70,11 @@ bool __i915_sched_node_add_dependency(struct i915_sched_node *node,
dep->signaler = signal; dep->signaler = signal;
dep->flags = flags; dep->flags = flags;
/* Keep track of whether anyone on this chain has a semaphore */
if (signal->flags & I915_SCHED_HAS_SEMAPHORE &&
!node_started(signal))
node->flags |= I915_SCHED_HAS_SEMAPHORE;
ret = true; ret = true;
} }
......
...@@ -24,7 +24,7 @@ enum { ...@@ -24,7 +24,7 @@ enum {
I915_PRIORITY_INVALID = INT_MIN I915_PRIORITY_INVALID = INT_MIN
}; };
#define I915_USER_PRIORITY_SHIFT 2 #define I915_USER_PRIORITY_SHIFT 3
#define I915_USER_PRIORITY(x) ((x) << I915_USER_PRIORITY_SHIFT) #define I915_USER_PRIORITY(x) ((x) << I915_USER_PRIORITY_SHIFT)
#define I915_PRIORITY_COUNT BIT(I915_USER_PRIORITY_SHIFT) #define I915_PRIORITY_COUNT BIT(I915_USER_PRIORITY_SHIFT)
...@@ -32,6 +32,7 @@ enum { ...@@ -32,6 +32,7 @@ enum {
#define I915_PRIORITY_WAIT ((u8)BIT(0)) #define I915_PRIORITY_WAIT ((u8)BIT(0))
#define I915_PRIORITY_NEWCLIENT ((u8)BIT(1)) #define I915_PRIORITY_NEWCLIENT ((u8)BIT(1))
#define I915_PRIORITY_NOSEMAPHORE ((u8)BIT(2))
#define __NO_PREEMPTION (I915_PRIORITY_WAIT) #define __NO_PREEMPTION (I915_PRIORITY_WAIT)
...@@ -74,6 +75,8 @@ struct i915_sched_node { ...@@ -74,6 +75,8 @@ struct i915_sched_node {
struct list_head waiters_list; /* those after us, they depend upon us */ struct list_head waiters_list; /* those after us, they depend upon us */
struct list_head link; struct list_head link;
struct i915_sched_attr attr; struct i915_sched_attr attr;
unsigned int flags;
#define I915_SCHED_HAS_SEMAPHORE BIT(0)
}; };
struct i915_dependency { struct i915_dependency {
......
...@@ -164,7 +164,7 @@ ...@@ -164,7 +164,7 @@
#define WA_TAIL_DWORDS 2 #define WA_TAIL_DWORDS 2
#define WA_TAIL_BYTES (sizeof(u32) * WA_TAIL_DWORDS) #define WA_TAIL_BYTES (sizeof(u32) * WA_TAIL_DWORDS)
#define ACTIVE_PRIORITY (I915_PRIORITY_NEWCLIENT) #define ACTIVE_PRIORITY (I915_PRIORITY_NEWCLIENT | I915_PRIORITY_NOSEMAPHORE)
static int execlists_context_deferred_alloc(struct i915_gem_context *ctx, static int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
struct intel_engine_cs *engine, struct intel_engine_cs *engine,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment