@@ -426,7 +426,8 @@ static struct intel_engine_cs *active_engine(struct intel_context *ce)
return engine;
}
-static void kill_engines(struct i915_gem_engines *engines, bool ban)
+static void
+kill_engines(struct i915_gem_engines *engines, bool ban, bool persistent)
{
struct i915_gem_engines_iter it;
struct intel_context *ce;
@@ -443,6 +444,9 @@ static void kill_engines(struct i915_gem_engines *engines, bool ban)
if (ban && intel_context_set_banned(ce))
continue;
+ else if (!persistent &&
+ intel_context_set_closed_non_persistent(ce))
+ continue;
/*
* Check the current active state of this context; if we
@@ -454,7 +458,7 @@ static void kill_engines(struct i915_gem_engines *engines, bool ban)
engine = active_engine(ce);
/* First attempt to gracefully cancel the context */
- if (engine && !__cancel_engine(engine) && ban)
+ if (engine && !__cancel_engine(engine) && (ban || !persistent))
/*
* If we are unable to send a preemptive pulse to bump
* the context from the GPU, we have to resort to a full
@@ -466,8 +470,6 @@ static void kill_engines(struct i915_gem_engines *engines, bool ban)
static void kill_context(struct i915_gem_context *ctx)
{
- bool ban = (!i915_gem_context_is_persistent(ctx) ||
- !ctx->i915->params.enable_hangcheck);
struct i915_gem_engines *pos, *next;
spin_lock_irq(&ctx->stale.lock);
@@ -480,7 +482,8 @@ static void kill_context(struct i915_gem_context *ctx)
spin_unlock_irq(&ctx->stale.lock);
- kill_engines(pos, ban);
+ kill_engines(pos, !ctx->i915->params.enable_hangcheck,
+ i915_gem_context_is_persistent(ctx));
spin_lock_irq(&ctx->stale.lock);
GEM_BUG_ON(i915_sw_fence_signaled(&pos->fence));
@@ -526,7 +529,8 @@ static void engines_idle_release(struct i915_gem_context *ctx,
kill:
if (list_empty(&engines->link)) /* raced, already closed */
- kill_engines(engines, true);
+ kill_engines(engines, true,
+ i915_gem_context_is_persistent(ctx));
i915_sw_fence_commit(&engines->fence);
}
@@ -374,6 +374,8 @@ intel_context_init(struct intel_context *ce, struct intel_engine_cs *engine)
ce->sseu = engine->sseu;
ce->ring = __intel_context_ring_size(SZ_4K);
+ __set_bit(CONTEXT_SCHEDULABLE, &ce->flags);
+
ewma_runtime_init(&ce->runtime.avg);
ce->vm = i915_vm_get(engine->gt->vm);
@@ -217,9 +217,29 @@ static inline bool intel_context_is_banned(const struct intel_context *ce)
static inline bool intel_context_set_banned(struct intel_context *ce)
{
+ clear_bit(CONTEXT_SCHEDULABLE, &ce->flags);
return test_and_set_bit(CONTEXT_BANNED, &ce->flags);
}
+static inline bool
+intel_context_is_closed_non_persistent(const struct intel_context *ce)
+{
+ return test_bit(CONTEXT_NON_PERSISTENT, &ce->flags);
+}
+
+static inline bool
+intel_context_set_closed_non_persistent(struct intel_context *ce)
+{
+ GEM_BUG_ON(!intel_context_is_closed(ce));
+ clear_bit(CONTEXT_SCHEDULABLE, &ce->flags);
+ return test_and_set_bit(CONTEXT_NON_PERSISTENT, &ce->flags);
+}
+
+static inline bool intel_context_is_schedulable(const struct intel_context *ce)
+{
+ return test_bit(CONTEXT_SCHEDULABLE, &ce->flags);
+}
+
static inline bool
intel_context_force_single_submission(const struct intel_context *ce)
{
@@ -95,6 +95,8 @@ struct intel_context {
#define CONTEXT_BANNED 6
#define CONTEXT_FORCE_SINGLE_SUBMISSION 7
#define CONTEXT_NOPREEMPT 8
+#define CONTEXT_SCHEDULABLE 9 /* Unless banned or non-persistent closed. */
+#define CONTEXT_NON_PERSISTENT 10 /* Only if also closed. */
struct {
u64 timeout_us;
@@ -478,7 +478,7 @@ __execlists_schedule_in(struct i915_request *rq)
!intel_engine_has_heartbeat(engine)))
intel_context_set_banned(ce);
- if (unlikely(intel_context_is_banned(ce) || bad_request(rq)))
+ if (unlikely(!intel_context_is_schedulable(ce) || bad_request(rq)))
reset_active(rq, engine);
if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
@@ -1204,12 +1204,19 @@ static void record_preemption(struct intel_engine_execlists *execlists)
static unsigned long active_preempt_timeout(struct intel_engine_cs *engine,
const struct i915_request *rq)
{
+ struct intel_context *ce;
+
if (!rq)
return 0;
+ ce = rq->context;
+
/* Force a fast reset for terminated contexts (ignoring sysfs!) */
- if (unlikely(intel_context_is_banned(rq->context) || bad_request(rq)))
+ if (unlikely(intel_context_is_banned(ce) || bad_request(rq)))
return 1;
+ /* Longer grace for closed non-persistent contexts to avoid resets. */
+ else if (unlikely(intel_context_is_closed_non_persistent(ce)))
+ return 15;
return READ_ONCE(engine->props.preempt_timeout_ms);
}
@@ -660,7 +660,7 @@ bool __i915_request_submit(struct i915_request *request)
goto active;
}
- if (unlikely(intel_context_is_banned(request->context)))
+ if (unlikely(!intel_context_is_schedulable(request->context)))
i915_request_set_error_once(request, -EIO);
if (unlikely(fatal_error(request->fence.error)))