[Intel-gfx] [PATCH v7] drm/i915/execlists: Direct submission of new requests (avoid tasklet/ksoftirqd)
Chris Wilson
chris at chris-wilson.co.uk
Thu Jun 28 13:28:31 UTC 2018
Quoting Tvrtko Ursulin (2018-06-28 14:21:06)
>
> On 28/06/2018 14:11, Chris Wilson wrote:
> > +/*
> > + * Check the unread Context Status Buffers and manage the submission of new
> > + * contexts to the ELSP accordingly.
> > + */
> > +static void execlists_submission_tasklet(unsigned long data)
> > +{
> > + struct intel_engine_cs * const engine = (struct intel_engine_cs *)data;
> > + unsigned long flags;
> > +
> > + GEM_TRACE("%s awake?=%d, active=%x\n",
> > + engine->name,
> > + engine->i915->gt.awake,
> > + engine->execlists.active);
> > +
> > + spin_lock_irqsave(&engine->timeline.lock, flags);
> > +
> > + if (engine->i915->gt.awake) /* we may be delayed until after we idle! */
>
> No races between the check and tasklet call? In other words the code
> path which you were describing that can race is taking the timeline lock?
intel_engine_is_idle() is unserialised.
> > + __execlists_submission_tasklet(engine);
> > +
> > + spin_unlock_irqrestore(&engine->timeline.lock, flags);
> > +}
> > +
> > static void queue_request(struct intel_engine_cs *engine,
> > struct i915_sched_node *node,
> > int prio)
> > @@ -1144,16 +1155,30 @@ static void queue_request(struct intel_engine_cs *engine,
> > &lookup_priolist(engine, prio)->requests);
> > }
> >
> > -static void __submit_queue(struct intel_engine_cs *engine, int prio)
> > +static void __update_queue(struct intel_engine_cs *engine, int prio)
> > {
> > engine->execlists.queue_priority = prio;
> > - tasklet_hi_schedule(&engine->execlists.tasklet);
> > +}
> > +
> > +static void __submit_queue_imm(struct intel_engine_cs *engine)
> > +{
> > + struct intel_engine_execlists * const execlists = &engine->execlists;
> > +
> > + if (reset_in_progress(execlists))
> > + return; /* defer until we restart the engine following reset */
>
> We have a tasklet kick somewhere in that path?
In execlists_reset_finish()
> > + if (execlists->tasklet.func == execlists_submission_tasklet)
> > + __execlists_submission_tasklet(engine);
> > + else
> > + tasklet_hi_schedule(&execlists->tasklet);
> > }
> >
> > static void submit_queue(struct intel_engine_cs *engine, int prio)
> > {
> > - if (prio > engine->execlists.queue_priority)
> > - __submit_queue(engine, prio);
> > + if (prio > engine->execlists.queue_priority) {
> > + __update_queue(engine, prio);
> > + __submit_queue_imm(engine);
> > + }
> > }
> >
> > static void execlists_submit_request(struct i915_request *request)
> > @@ -1165,11 +1190,12 @@ static void execlists_submit_request(struct i915_request *request)
> > spin_lock_irqsave(&engine->timeline.lock, flags);
> >
> > queue_request(engine, &request->sched, rq_prio(request));
> > - submit_queue(engine, rq_prio(request));
> >
> > GEM_BUG_ON(!engine->execlists.first);
> > GEM_BUG_ON(list_empty(&request->sched.link));
> >
> > + submit_queue(engine, rq_prio(request));
> > +
> > spin_unlock_irqrestore(&engine->timeline.lock, flags);
> > }
> >
> > @@ -1296,8 +1322,11 @@ static void execlists_schedule(struct i915_request *request,
> > }
> >
> > if (prio > engine->execlists.queue_priority &&
> > - i915_sw_fence_done(&sched_to_request(node)->submit))
> > - __submit_queue(engine, prio);
> > + i915_sw_fence_done(&sched_to_request(node)->submit)) {
> > + /* defer submission until after all of our updates */
> > + __update_queue(engine, prio);
> > + tasklet_hi_schedule(&engine->execlists.tasklet);
>
> _imm suffix on __submit_queue_imm sounds unused if there is no plain
> __submit_queue, which could have been used here. But meh.
I thought of trying to emphasis the immediate nature of this path. It's
not a huge deal, but I didn't particularly like calling it
direct_submit_queue() (or just direct_submit(), too many submits!)
__ prefix to indicate that it's an inner function to submit_queue,
_imm suffix to indicate what's special.
-Chris
More information about the Intel-gfx
mailing list