Quoting Tvrtko Ursulin (2020-05-18 14:01:27) > > On 18/05/2020 13:33, Chris Wilson wrote: > > +static struct virtual_engine * > > +first_virtual_engine(struct intel_engine_cs *engine) > > +{ > > + struct intel_engine_execlists *el = &engine->execlists; > > + struct rb_node *rb = rb_first_cached(&el->virtual); > > + > > + while (rb) { > > + struct virtual_engine *ve = > > + rb_entry(rb, typeof(*ve), nodes[engine->id].rb); > > + struct i915_request *rq = READ_ONCE(ve->request); > > + > > + if (!rq) { /* lazily cleanup after another engine handled rq */ > > + rb_erase_cached(rb, &el->virtual); > > + RB_CLEAR_NODE(rb); > > + rb = rb_first_cached(&el->virtual); > > + continue; > > + } > > + > > + if (!virtual_matches(ve, rq, engine)) { > > + rb = rb_next(rb); > > + continue; > > + } > > + > > + return ve; > > + } > > + > > + return NULL; > > +} > > - while (rb) { /* XXX virtual is always taking precedence */ > > - struct virtual_engine *ve = > > - rb_entry(rb, typeof(*ve), nodes[engine->id].rb); > > + while (ve) { /* XXX virtual is always taking precedence */ > > struct i915_request *rq; > > > > spin_lock(&ve->base.active.lock); > > > > rq = ve->request; > > - if (unlikely(!rq)) { /* lost the race to a sibling */ > > - spin_unlock(&ve->base.active.lock); > > - rb_erase_cached(rb, &execlists->virtual); > > - RB_CLEAR_NODE(rb); > > - rb = rb_first_cached(&execlists->virtual); > > - continue; > > - } > > + if (unlikely(!rq)) /* lost the race to a sibling */ > > + goto unlock; > > Doesn't this now rely on a later patch to clear the node? This is cleared by first_virtual_engine > > > > GEM_BUG_ON(rq != ve->request); > > GEM_BUG_ON(rq->engine != &ve->base); > > GEM_BUG_ON(rq->context != &ve->context); > > > > - if (rq_prio(rq) >= queue_prio(execlists)) { > > - if (!virtual_matches(ve, rq, engine)) { > > - spin_unlock(&ve->base.active.lock); > > - rb = rb_next(rb); > > - continue; > > - } > > + if (rq_prio(rq) < queue_prio(execlists)) { > > + spin_unlock(&ve->base.active.lock); > > + break; > > + } > > > > - if (last && !can_merge_rq(last, rq)) { > > - spin_unlock(&ve->base.active.lock); > > - start_timeslice(engine, rq_prio(rq)); > > - return; /* leave this for another sibling */ > > - } > > + GEM_BUG_ON(!virtual_matches(ve, rq, engine)); > > This as well. As first_virtual_engine skips non-matching nodes, it should only unmatch during the unlocked phase since the lookup if it is claimed by another engine. Then ve->request would be set to NULL and we the above check fails. So I think this patch stands by itself. -Chris _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx