[Intel-gfx] [PATCH 07/33] drm/i915: Move active request tracking to a vfunc
Move active request tracking to a backend vfunc rather than assuming all backends want to do this in the manner. In the of case execlists / ring submission the tracking is on the physical engine while with GuC submission it is on the context. Signed-off-by: Matthew Brost Reviewed-by: John Harrison --- drivers/gpu/drm/i915/gt/intel_context.c | 3 ++ drivers/gpu/drm/i915/gt/intel_context_types.h | 7 drivers/gpu/drm/i915/gt/intel_engine_types.h | 6 +++ .../drm/i915/gt/intel_execlists_submission.c | 40 ++ .../gpu/drm/i915/gt/intel_ring_submission.c | 22 ++ drivers/gpu/drm/i915/gt/mock_engine.c | 30 ++ .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 33 +++ drivers/gpu/drm/i915/i915_request.c | 41 ++- drivers/gpu/drm/i915/i915_request.h | 2 + 9 files changed, 147 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c index baa05fddd690..0bf4a13e9759 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.c +++ b/drivers/gpu/drm/i915/gt/intel_context.c @@ -393,6 +393,9 @@ intel_context_init(struct intel_context *ce, struct intel_engine_cs *engine) spin_lock_init(>guc_state.lock); INIT_LIST_HEAD(>guc_state.fences); + spin_lock_init(>guc_active.lock); + INIT_LIST_HEAD(>guc_active.requests); + ce->guc_id = GUC_INVALID_LRC_ID; INIT_LIST_HEAD(>guc_id_link); diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h b/drivers/gpu/drm/i915/gt/intel_context_types.h index 542c98418771..035108c10b2c 100644 --- a/drivers/gpu/drm/i915/gt/intel_context_types.h +++ b/drivers/gpu/drm/i915/gt/intel_context_types.h @@ -162,6 +162,13 @@ struct intel_context { struct list_head fences; } guc_state; + struct { + /** lock: protects everything in guc_active */ + spinlock_t lock; + /** requests: active requests on this context */ + struct list_head requests; + } guc_active; + /* GuC scheduling state flags that do not require a lock. */ atomic_t guc_sched_state_no_lock; diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h index e55776e27a2a..1c7e2724cdae 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_types.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h @@ -414,6 +414,12 @@ struct intel_engine_cs { void(*release)(struct intel_engine_cs *engine); + /* +* Add / remove request from engine active tracking +*/ + void(*add_active_request)(struct i915_request *rq); + void(*remove_active_request)(struct i915_request *rq); + struct intel_engine_execlists execlists; /* diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c index 6e4959ee5065..b4a876736074 100644 --- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c @@ -3157,6 +3157,42 @@ static void execlists_park(struct intel_engine_cs *engine) cancel_timer(>execlists.preempt); } +static void add_to_engine(struct i915_request *rq) +{ + lockdep_assert_held(>engine->sched_engine->lock); + list_move_tail(>sched.link, >engine->sched_engine->requests); +} + +static void remove_from_engine(struct i915_request *rq) +{ + struct intel_engine_cs *engine, *locked; + + /* +* Virtual engines complicate acquiring the engine timeline lock, +* as their rq->engine pointer is not stable until under that +* engine lock. The simple ploy we use is to take the lock then +* check that the rq still belongs to the newly locked engine. +*/ + locked = READ_ONCE(rq->engine); + spin_lock_irq(>sched_engine->lock); + while (unlikely(locked != (engine = READ_ONCE(rq->engine { + spin_unlock(>sched_engine->lock); + spin_lock(>sched_engine->lock); + locked = engine; + } + list_del_init(>sched.link); + + clear_bit(I915_FENCE_FLAG_PQUEUE, >fence.flags); + clear_bit(I915_FENCE_FLAG_HOLD, >fence.flags); + + /* Prevent further __await_execution() registering a cb, then flush */ + set_bit(I915_FENCE_FLAG_ACTIVE, >fence.flags); + + spin_unlock_irq(>sched_engine->lock); + + i915_request_notify_execute_cb_imm(rq); +} + static bool can_preempt(struct intel_engine_cs *engine) { if (GRAPHICS_VER(engine->i915) > 8) @@ -3251,6 +3287,8 @@ logical_ring_default_vfuncs(struct intel_engine_cs *engine) engine->cops = _context_ops; engine->request_alloc = execlists_request_alloc; + engine->add_active_request = add_to_engine; + engine->remove_active_request = remove_from_engine;
[Intel-gfx] [PATCH 07/33] drm/i915: Move active request tracking to a vfunc
Move active request tracking to a backend vfunc rather than assuming all backends want to do this in the manner. In the of case execlists / ring submission the tracking is on the physical engine while with GuC submission it is on the context. Signed-off-by: Matthew Brost Reviewed-by: John Harrison --- drivers/gpu/drm/i915/gt/intel_context.c | 3 ++ drivers/gpu/drm/i915/gt/intel_context_types.h | 7 drivers/gpu/drm/i915/gt/intel_engine_types.h | 6 +++ .../drm/i915/gt/intel_execlists_submission.c | 40 ++ .../gpu/drm/i915/gt/intel_ring_submission.c | 22 ++ drivers/gpu/drm/i915/gt/mock_engine.c | 30 ++ .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 33 +++ drivers/gpu/drm/i915/i915_request.c | 41 ++- drivers/gpu/drm/i915/i915_request.h | 2 + 9 files changed, 147 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c index baa05fddd690..0bf4a13e9759 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.c +++ b/drivers/gpu/drm/i915/gt/intel_context.c @@ -393,6 +393,9 @@ intel_context_init(struct intel_context *ce, struct intel_engine_cs *engine) spin_lock_init(>guc_state.lock); INIT_LIST_HEAD(>guc_state.fences); + spin_lock_init(>guc_active.lock); + INIT_LIST_HEAD(>guc_active.requests); + ce->guc_id = GUC_INVALID_LRC_ID; INIT_LIST_HEAD(>guc_id_link); diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h b/drivers/gpu/drm/i915/gt/intel_context_types.h index 542c98418771..035108c10b2c 100644 --- a/drivers/gpu/drm/i915/gt/intel_context_types.h +++ b/drivers/gpu/drm/i915/gt/intel_context_types.h @@ -162,6 +162,13 @@ struct intel_context { struct list_head fences; } guc_state; + struct { + /** lock: protects everything in guc_active */ + spinlock_t lock; + /** requests: active requests on this context */ + struct list_head requests; + } guc_active; + /* GuC scheduling state flags that do not require a lock. */ atomic_t guc_sched_state_no_lock; diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h index 03a81e8d87f4..950fc73ed6af 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_types.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h @@ -420,6 +420,12 @@ struct intel_engine_cs { void(*release)(struct intel_engine_cs *engine); + /* +* Add / remove request from engine active tracking +*/ + void(*add_active_request)(struct i915_request *rq); + void(*remove_active_request)(struct i915_request *rq); + struct intel_engine_execlists execlists; /* diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c index 605dd7cb2901..60427b106bad 100644 --- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c @@ -3157,6 +3157,42 @@ static void execlists_park(struct intel_engine_cs *engine) cancel_timer(>execlists.preempt); } +static void add_to_engine(struct i915_request *rq) +{ + lockdep_assert_held(>engine->sched_engine->lock); + list_move_tail(>sched.link, >engine->sched_engine->requests); +} + +static void remove_from_engine(struct i915_request *rq) +{ + struct intel_engine_cs *engine, *locked; + + /* +* Virtual engines complicate acquiring the engine timeline lock, +* as their rq->engine pointer is not stable until under that +* engine lock. The simple ploy we use is to take the lock then +* check that the rq still belongs to the newly locked engine. +*/ + locked = READ_ONCE(rq->engine); + spin_lock_irq(>sched_engine->lock); + while (unlikely(locked != (engine = READ_ONCE(rq->engine { + spin_unlock(>sched_engine->lock); + spin_lock(>sched_engine->lock); + locked = engine; + } + list_del_init(>sched.link); + + clear_bit(I915_FENCE_FLAG_PQUEUE, >fence.flags); + clear_bit(I915_FENCE_FLAG_HOLD, >fence.flags); + + /* Prevent further __await_execution() registering a cb, then flush */ + set_bit(I915_FENCE_FLAG_ACTIVE, >fence.flags); + + spin_unlock_irq(>sched_engine->lock); + + i915_request_notify_execute_cb_imm(rq); +} + static bool can_preempt(struct intel_engine_cs *engine) { if (GRAPHICS_VER(engine->i915) > 8) @@ -3251,6 +3287,8 @@ logical_ring_default_vfuncs(struct intel_engine_cs *engine) engine->cops = _context_ops; engine->request_alloc = execlists_request_alloc; + engine->add_active_request = add_to_engine; + engine->remove_active_request = remove_from_engine;