From af833ea2683b093966f966c30bc025cde36f89d2 Mon Sep 17 00:00:00 2001 From: Dave Gordon Date: Mon, 26 Oct 2015 18:37:36 +0000 Subject: drm/i915/preempt: scheduler logic for queueing preemptive requests This is the very first stage of the scheduler's preemption logic, where it determines whether a request should be marked as potentially preemptive, at the point where it is added to the scheduler's queue. Subsequent logic will determine how to handle the request on the basis of the flags set here. Actually-preemptive requests are disabled via a module parameter at this early stage, as the rest of the logic to process them isn't in place yet. For: VIZ-2021 Signed-off-by: Dave Gordon --- drivers/gpu/drm/i915/i915_debugfs.c | 6 ++++++ drivers/gpu/drm/i915/i915_params.c | 4 ++++ drivers/gpu/drm/i915/i915_params.h | 1 + drivers/gpu/drm/i915/i915_scheduler.c | 38 ++++++++++++++++++++++++++++++++--- 4 files changed, 46 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index c55b5ec8c16b..0ed102d87d5a 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -3666,6 +3666,12 @@ const char *i915_scheduler_queue_status_str( case I915_SQS_FLYING: return "Flying"; + case I915_SQS_OVERTAKING: + return "Overtaking"; + + case I915_SQS_PREEMPTED: + return "Preempted"; + case I915_SQS_COMPLETE: return "Complete"; diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index f10482d06864..7d93b5b9d12c 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -59,6 +59,7 @@ struct i915_params i915 __read_mostly = { .enable_dp_mst = true, .inject_load_failure = 0, .enable_scheduler = 1, + .enable_preemption = 0, }; module_param_named(modeset, i915.modeset, int, 0400); @@ -214,3 +215,6 @@ MODULE_PARM_DESC(inject_load_failure, module_param_named_unsafe(enable_scheduler, i915.enable_scheduler, int, 0600); MODULE_PARM_DESC(enable_scheduler, "Enable scheduler (0 = disable, 1 = enable [default])"); + +module_param_named_unsafe(enable_preemption, i915.enable_preemption, int, 0600); +MODULE_PARM_DESC(enable_preemption, "Enable pre-emption within scheduler (0 = disable [default], 1 = enable)"); diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index 44b08b3d5b90..6031b69493ad 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h @@ -51,6 +51,7 @@ struct i915_params { int edp_vswing; unsigned int inject_load_failure; int enable_scheduler; + int enable_preemption; /* leave bools at the end to not create holes */ bool enable_hangcheck; bool fastboot; diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c index c74606520ebc..b2e1c386fb12 100644 --- a/drivers/gpu/drm/i915/i915_scheduler.c +++ b/drivers/gpu/drm/i915/i915_scheduler.c @@ -51,10 +51,13 @@ bool i915_scheduler_is_enabled(struct drm_device *dev) const char *i915_qe_state_str(struct i915_scheduler_queue_entry *node) { + uint32_t sched_flags = node->params.request->scheduler_flags; static char str[50]; char *ptr = str; *(ptr++) = node->bumped ? 'B' : '-', + *(ptr++) = (sched_flags & I915_REQ_SF_PREEMPT) ? 'P' : '-'; + *(ptr++) = (sched_flags & I915_REQ_SF_WAS_PREEMPT) ? 'p' : '-'; *(ptr++) = i915_gem_request_completed(node->params.request) ? 'C' : '-'; *ptr = 0; @@ -77,6 +80,12 @@ char i915_scheduler_queue_status_chr(enum i915_scheduler_queue_status status) case I915_SQS_FLYING: return 'F'; + case I915_SQS_OVERTAKING: + return 'O'; + + case I915_SQS_PREEMPTED: + return 'P'; + case I915_SQS_COMPLETE: return 'C'; @@ -241,6 +250,7 @@ static void i915_scheduler_node_fly(struct i915_scheduler_queue_entry *node) struct drm_i915_private *dev_priv = to_i915(node->params.dev); struct i915_scheduler *scheduler = dev_priv->scheduler; struct intel_engine_cs *engine = node->params.engine; + struct drm_i915_gem_request *req = node->params.request; assert_scheduler_lock_held(scheduler); @@ -253,7 +263,10 @@ static void i915_scheduler_node_fly(struct i915_scheduler_queue_entry *node) */ list_add(&node->link, &scheduler->node_queue[engine->id]); - node->status = I915_SQS_FLYING; + if (req->scheduler_flags & I915_REQ_SF_PREEMPT) + node->status = I915_SQS_OVERTAKING; + else + node->status = I915_SQS_FLYING; scheduler->counts[engine->id].flying++; trace_i915_scheduler_fly(engine, node); @@ -858,7 +871,7 @@ int i915_scheduler_queue_execbuffer(struct i915_scheduler_queue_entry *qe) struct i915_scheduler *scheduler = dev_priv->scheduler; struct intel_engine_cs *engine = qe->params.engine; struct i915_scheduler_queue_entry *node; - bool not_flying; + bool not_flying, want_preempt; int i, e; int incomplete; @@ -939,6 +952,25 @@ int i915_scheduler_queue_execbuffer(struct i915_scheduler_queue_entry *qe) not_flying = i915_scheduler_count_flying(scheduler, engine) < scheduler->min_flying; + want_preempt = node->priority >= scheduler->priority_level_preempt; + + if (!i915.enable_preemption) + want_preempt = false; + + /* Pre-emption is not yet implemented in non-execlist mode */ + if (!i915.enable_execlists) + want_preempt = false; + + /* Pre-emption is not yet implemented in non-GUC mode */ + if (!i915.enable_guc_submission) + want_preempt = false; + + if (want_preempt) { + node->params.request->scheduler_flags |= + I915_REQ_SF_WAS_PREEMPT | I915_REQ_SF_PREEMPT; + scheduler->stats[engine->id].preempts_queued++; + } + scheduler->counts[engine->id].queued++; scheduler->stats[engine->id].queued++; @@ -947,7 +979,7 @@ int i915_scheduler_queue_execbuffer(struct i915_scheduler_queue_entry *qe) spin_unlock_irq(&scheduler->lock); - if (not_flying) + if (not_flying || want_preempt) i915_scheduler_submit(engine); return 0; -- cgit v1.2.3