[PATCH 73/78] dfs-defer
Chris Wilson
chris at chris-wilson.co.uk
Sun Aug 9 12:51:30 UTC 2020
---
drivers/gpu/drm/i915/i915_scheduler.c | 53 +++++++++++++++++++--------
1 file changed, 38 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c
index ec73d88e7c5d..f98bfef054c2 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -466,8 +466,9 @@ void i915_request_set_priority(struct i915_request *rq, int prio)
void __intel_engine_defer_request(struct intel_engine_cs *engine,
struct i915_request *rq)
{
- struct list_head *pl;
- LIST_HEAD(list);
+ struct list_head *pos = &rq->sched.waiters_list;
+ struct i915_request *rn;
+ LIST_HEAD(dfs);
lockdep_assert_held(&engine->active.lock);
GEM_BUG_ON(!test_bit(I915_FENCE_FLAG_PQUEUE, &rq->fence.flags));
@@ -477,14 +478,11 @@ void __intel_engine_defer_request(struct intel_engine_cs *engine,
* to those that are waiting upon it. So we traverse its chain of
* waiters and move any that are earlier than the request to after it.
*/
- pl = i915_sched_lookup_priolist(engine, rq_prio(rq));
+ rq->sched.dfs.next = NULL;
do {
- struct i915_dependency *p;
-
- GEM_BUG_ON(i915_request_is_active(rq));
- list_move_tail(&rq->sched.link, pl);
-
- for_each_waiter(p, rq) {
+ list_for_each_continue(pos, &rq->sched.waiters_list) {
+ struct i915_dependency *p =
+ list_entry(pos, typeof(*p), wait_link);
struct i915_request *w =
container_of(p->waiter, typeof(*w), sched);
@@ -500,19 +498,44 @@ void __intel_engine_defer_request(struct intel_engine_cs *engine,
i915_request_started(w) &&
!i915_request_completed(rq));
- GEM_BUG_ON(i915_request_is_active(w));
- if (!i915_request_is_ready(w))
+ if (!i915_request_in_priority_queue(w))
continue;
+ /*
+ * We also need to reorder within the same priority.
+ *
+ * This is unlike priority-inheritance, where if the
+ * signaler already has a higher priority [earlier
+ * deadline] than us, we can ignore as it will be
+ * scheduled first. If a waiter already has the
+ * same priority, we still have to push it to the end
+ * of the list. This unfortunately means we cannot
+ * use the rq_deadline() itself as a 'visited' bit.
+ */
if (rq_prio(w) < rq_prio(rq))
continue;
- GEM_BUG_ON(rq_prio(w) > rq_prio(rq));
- list_move_tail(&w->sched.link, &list);
+ GEM_BUG_ON(rq_prio(w) != rq_prio(rq));
+
+ /* Remember our position along this branch */
+ rq = stack_push(w, rq, pos);
+ pos = &rq->sched.waiters_list;
}
- rq = list_first_entry_or_null(&list, typeof(*rq), sched.link);
- } while (rq);
+ /* Note list is reversed for waiters wrt signal hierarchy */
+ GEM_BUG_ON(rq->engine != engine);
+ GEM_BUG_ON(!i915_request_in_priority_queue(rq));
+ list_move(&rq->sched.link, &dfs);
+
+ /* Track our visit, and prevent duplicate processing */
+ clear_bit(I915_FENCE_FLAG_PQUEUE, &rq->fence.flags);
+ } while ((rq = stack_pop(rq, &pos)));
+
+ pos = i915_sched_lookup_priolist(engine, rq_prio(rq));
+ list_for_each_entry_safe(rq, rn, &dfs, sched.link) {
+ set_bit(I915_FENCE_FLAG_PQUEUE, &rq->fence.flags);
+ list_add_tail(&rq->sched.link, pos);
+ }
}
static void queue_request(struct intel_engine_cs *engine,
--
2.20.1
More information about the Intel-gfx-trybot
mailing list