diff options
author | Dave Gordon <david.s.gordon@intel.com> | 2015-10-26 18:47:47 +0000 |
---|---|---|
committer | John Harrison <John.C.Harrison@Intel.com> | 2016-06-28 17:19:22 +0100 |
commit | 88268ceaff26678db46c0bcca8d77ceccfd61095 (patch) | |
tree | 6a14a99aad946ae4fb463dfd444eef07a4691a1c | |
parent | af833ea2683b093966f966c30bc025cde36f89d2 (diff) |
drm/i915/preempt: scheduler logic for selecting preemptive requests
This patch adds the scheduler logic for managing potentially preemptive
requests, including validating dependencies and working out when a
request can be downgraded to non-preemptive (e.g. when there's nothing
ahead for it to preempt).
Actually-preemptive requests are still disabled via a module parameter
at this early stage, as the rest of the logic to deal with the
consequences of preemption isn't in place yet.
For: VIZ-2021
Signed-off-by: Dave Gordon <david.s.gordon@intel.com>
-rw-r--r-- | drivers/gpu/drm/i915/i915_scheduler.c | 62 |
1 files changed, 60 insertions, 2 deletions
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c index b2e1c386fb12..1d24be142575 100644 --- a/drivers/gpu/drm/i915/i915_scheduler.c +++ b/drivers/gpu/drm/i915/i915_scheduler.c @@ -366,6 +366,9 @@ static inline bool i915_scheduler_is_dependency_valid( if (I915_SQS_IS_FLYING(dep)) { if (node->params.engine != dep->params.engine) return true; + + if (node->params.request->scheduler_flags & I915_REQ_SF_PREEMPT) + return true; } return false; @@ -463,10 +466,12 @@ static int i915_scheduler_pop_from_queue_locked(struct intel_engine_cs *engine, struct i915_scheduler_queue_entry *best_wait = NULL; struct i915_scheduler_queue_entry *best = NULL; struct i915_scheduler_queue_entry *node; + struct drm_i915_gem_request *req; int ret; int i; bool signalled = true, any_queued = false; bool has_local, has_remote, only_remote = false; + bool local_preempt_only; assert_scheduler_lock_held(scheduler); @@ -488,18 +493,44 @@ static int i915_scheduler_pop_from_queue_locked(struct intel_engine_cs *engine, scheduler->stats[node->params.engine->id].fence_ignore++; } + /* + * Attempt to re-enable pre-emption if a node wants to pre-empt + * but previously got downgraded. + */ + req = node->params.request; + if (req->scheduler_flags & I915_REQ_SF_WAS_PREEMPT) + req->scheduler_flags |= I915_REQ_SF_PREEMPT; + has_local = false; has_remote = false; + local_preempt_only = (req->scheduler_flags & I915_REQ_SF_PREEMPT) != 0; for (i = 0; i < node->num_deps; i++) { if (!i915_scheduler_is_dependency_valid(node, i)) continue; - if (node->dep_list[i]->params.engine == node->params.engine) + if (node->dep_list[i]->params.engine == node->params.engine) { has_local = true; - else + + if (local_preempt_only) { + req->scheduler_flags &= ~I915_REQ_SF_PREEMPT; + if (i915_scheduler_is_dependency_valid(node, i)) + local_preempt_only = false; + req->scheduler_flags |= I915_REQ_SF_PREEMPT; + } + } else has_remote = true; } + if (has_local && local_preempt_only) { + /* + * If a preemptive node's local dependencies are all + * flying, then they can be ignored by un-preempting + * the node. + */ + req->scheduler_flags &= ~I915_REQ_SF_PREEMPT; + has_local = false; + } + if (has_remote && !has_local) only_remote = true; @@ -598,6 +629,7 @@ static int i915_scheduler_submit(struct intel_engine_cs *engine) struct drm_i915_private *dev_priv = to_i915(engine->dev); struct i915_scheduler *scheduler = dev_priv->scheduler; struct i915_scheduler_queue_entry *node; + struct drm_i915_gem_request *req; int ret, count = 0, flying; WARN_ON(!mutex_is_locked(&engine->dev->struct_mutex)); @@ -617,6 +649,32 @@ static int i915_scheduler_submit(struct intel_engine_cs *engine) WARN_ON(node->status != I915_SQS_POPPED); count++; + req = node->params.request; + if (req->scheduler_flags & I915_REQ_SF_PREEMPT) { + struct i915_scheduler_queue_entry *fly; + bool got_flying = false; + + for_each_scheduler_node(fly, engine->id) { + if (!I915_SQS_IS_FLYING(fly)) + continue; + + got_flying = true; + if (fly->priority >= node->priority) { + /* + * Already working on something at least + * as important, so don't interrupt it. + */ + req->scheduler_flags &= ~I915_REQ_SF_PREEMPT; + break; + } + } + + if (!got_flying) { + /* Nothing to preempt so don't bother. */ + req->scheduler_flags &= ~I915_REQ_SF_PREEMPT; + } + } + /* * The call to pop above will have removed the node from the * list. So add it back in and mark it as in flight. |