Commit 5ec17c76 authored by Chris Wilson's avatar Chris Wilson

drm/i915/gt: Another tweak for flushing the tasklets

tasklet_kill() ensures that we _yield_ the processor until a remote
tasklet is completed. However, this leads to a starvation condition as
being at the bottom of the scheduler's runqueue means that anything else
is able to run, including all hogs keeping the tasklet occupied.
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarMika Kuoppala <mika.kuoppala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20201220134858.10510-1-chris@chris-wilson.co.uk
parent 9bb36cf6
...@@ -232,7 +232,12 @@ static inline void __intel_engine_reset(struct intel_engine_cs *engine, ...@@ -232,7 +232,12 @@ static inline void __intel_engine_reset(struct intel_engine_cs *engine,
bool intel_engines_are_idle(struct intel_gt *gt); bool intel_engines_are_idle(struct intel_gt *gt);
bool intel_engine_is_idle(struct intel_engine_cs *engine); bool intel_engine_is_idle(struct intel_engine_cs *engine);
void intel_engine_flush_submission(struct intel_engine_cs *engine);
void __intel_engine_flush_submission(struct intel_engine_cs *engine, bool sync);
static inline void intel_engine_flush_submission(struct intel_engine_cs *engine)
{
__intel_engine_flush_submission(engine, true);
}
void intel_engines_reset_default_submission(struct intel_gt *gt); void intel_engines_reset_default_submission(struct intel_gt *gt);
......
...@@ -1190,17 +1190,13 @@ static bool ring_is_idle(struct intel_engine_cs *engine) ...@@ -1190,17 +1190,13 @@ static bool ring_is_idle(struct intel_engine_cs *engine)
return idle; return idle;
} }
void intel_engine_flush_submission(struct intel_engine_cs *engine) void __intel_engine_flush_submission(struct intel_engine_cs *engine, bool sync)
{ {
struct tasklet_struct *t = &engine->execlists.tasklet; struct tasklet_struct *t = &engine->execlists.tasklet;
if (!t->func) if (!t->func)
return; return;
/* Synchronise and wait for the tasklet on another CPU */
tasklet_kill(t);
/* Having cancelled the tasklet, ensure that is run */
local_bh_disable(); local_bh_disable();
if (tasklet_trylock(t)) { if (tasklet_trylock(t)) {
/* Must wait for any GPU reset in progress. */ /* Must wait for any GPU reset in progress. */
...@@ -1209,6 +1205,10 @@ void intel_engine_flush_submission(struct intel_engine_cs *engine) ...@@ -1209,6 +1205,10 @@ void intel_engine_flush_submission(struct intel_engine_cs *engine)
tasklet_unlock(t); tasklet_unlock(t);
} }
local_bh_enable(); local_bh_enable();
/* Synchronise and wait for the tasklet on another CPU */
if (sync)
tasklet_unlock_wait(t);
} }
/** /**
......
...@@ -1825,7 +1825,7 @@ long i915_request_wait(struct i915_request *rq, ...@@ -1825,7 +1825,7 @@ long i915_request_wait(struct i915_request *rq,
* for unhappy HW. * for unhappy HW.
*/ */
if (i915_request_is_ready(rq)) if (i915_request_is_ready(rq))
intel_engine_flush_submission(rq->engine); __intel_engine_flush_submission(rq->engine, false);
for (;;) { for (;;) {
set_current_state(state); set_current_state(state);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment