drm/i915: Filter out spurious execlists context-switch interrupts
Back in commita4b2b01523
("drm/i915: Don't mark an execlists context-switch when idle") we noticed the presence of late context-switch interrupts. We were able to filter those out by looking at whether the ELSP remained active, but in commitbeecec9017
("drm/i915/execlists: Preemption!") that became problematic as we now anticipate receiving a context-switch event for preemption while ELSP may be empty. To restore the spurious interrupt suppression, add a counter for the expected number of pending context-switches and skip if we do not need to handle this interrupt to make forward progress. v2: Don't forget to switch on for preempt. v3: Reduce the counter to a on/off boolean tracker. Declare the HW as active when we first submit, and idle after the final completion event (with which we confirm the HW says it is idle), and track each source of activity separately. With a finite number of sources, it should aide us in debugging which gets stuck. Fixes:beecec9017
("drm/i915/execlists: Preemption!") Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Michal Winiarski <michal.winiarski@intel.com> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Cc: Arkadiusz Hiler <arkadiusz.hiler@intel.com> Cc: Mika Kuoppala <mika.kuoppala@intel.com> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20171023213237.26536-3-chris@chris-wilson.co.uk Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com> (cherry picked from commit4a118ecbe9
) Signed-off-by: Jani Nikula <jani.nikula@intel.com>
This commit is contained in:

committed by
Jani Nikula

vanhempi
8a6fb5b582
commit
5d26669237
@@ -575,7 +575,8 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
|
||||
* the state of the GPU is known (idle).
|
||||
*/
|
||||
inject_preempt_context(engine);
|
||||
execlists->preempt = true;
|
||||
execlists_set_active(execlists,
|
||||
EXECLISTS_ACTIVE_PREEMPT);
|
||||
goto unlock;
|
||||
} else {
|
||||
/*
|
||||
@@ -683,8 +684,10 @@ done:
|
||||
unlock:
|
||||
spin_unlock_irq(&engine->timeline->lock);
|
||||
|
||||
if (submit)
|
||||
if (submit) {
|
||||
execlists_set_active(execlists, EXECLISTS_ACTIVE_USER);
|
||||
execlists_submit_ports(engine);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -696,6 +699,7 @@ execlist_cancel_port_requests(struct intel_engine_execlists *execlists)
|
||||
while (num_ports-- && port_isset(port)) {
|
||||
struct drm_i915_gem_request *rq = port_request(port);
|
||||
|
||||
GEM_BUG_ON(!execlists->active);
|
||||
execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_PREEMPTED);
|
||||
i915_gem_request_put(rq);
|
||||
|
||||
@@ -861,15 +865,21 @@ static void intel_lrc_irq_handler(unsigned long data)
|
||||
unwind_incomplete_requests(engine);
|
||||
spin_unlock_irq(&engine->timeline->lock);
|
||||
|
||||
GEM_BUG_ON(!execlists->preempt);
|
||||
execlists->preempt = false;
|
||||
GEM_BUG_ON(!execlists_is_active(execlists,
|
||||
EXECLISTS_ACTIVE_PREEMPT));
|
||||
execlists_clear_active(execlists,
|
||||
EXECLISTS_ACTIVE_PREEMPT);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (status & GEN8_CTX_STATUS_PREEMPTED &&
|
||||
execlists->preempt)
|
||||
execlists_is_active(execlists,
|
||||
EXECLISTS_ACTIVE_PREEMPT))
|
||||
continue;
|
||||
|
||||
GEM_BUG_ON(!execlists_is_active(execlists,
|
||||
EXECLISTS_ACTIVE_USER));
|
||||
|
||||
/* Check the context/desc id for this event matches */
|
||||
GEM_DEBUG_BUG_ON(buf[2 * head + 1] != port->context_id);
|
||||
|
||||
@@ -892,6 +902,9 @@ static void intel_lrc_irq_handler(unsigned long data)
|
||||
/* After the final element, the hw should be idle */
|
||||
GEM_BUG_ON(port_count(port) == 0 &&
|
||||
!(status & GEN8_CTX_STATUS_ACTIVE_IDLE));
|
||||
if (port_count(port) == 0)
|
||||
execlists_clear_active(execlists,
|
||||
EXECLISTS_ACTIVE_USER);
|
||||
}
|
||||
|
||||
if (head != execlists->csb_head) {
|
||||
@@ -901,7 +914,7 @@ static void intel_lrc_irq_handler(unsigned long data)
|
||||
}
|
||||
}
|
||||
|
||||
if (!execlists->preempt)
|
||||
if (!execlists_is_active(execlists, EXECLISTS_ACTIVE_PREEMPT))
|
||||
execlists_dequeue(engine);
|
||||
|
||||
intel_uncore_forcewake_put(dev_priv, execlists->fw_domains);
|
||||
@@ -1460,7 +1473,7 @@ static int gen8_init_common_ring(struct intel_engine_cs *engine)
|
||||
GT_CONTEXT_SWITCH_INTERRUPT << engine->irq_shift);
|
||||
clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted);
|
||||
execlists->csb_head = -1;
|
||||
execlists->preempt = false;
|
||||
execlists->active = 0;
|
||||
|
||||
/* After a GPU reset, we may have requests to replay */
|
||||
if (!i915_modparams.enable_guc_submission && execlists->first)
|
||||
|
Viittaa uudesa ongelmassa
Block a user