Skip to content

Commit 76cb9d3

Browse files
icklejlahtine-intel
authored andcommitted
drm/i915/execlists: Use a locked clear_bit() for synchronisation with interrupt
We were relying on the uncached reads when processing the CSB to provide ourselves with the serialisation with the interrupt handler (so we could detect new interrupts in the middle of processing the old one). However, in commit 767a983 ("drm/i915/execlists: Read the context-status HEAD from the HWSP") those uncached reads were eliminated (on one path at least) and along with them our serialisation. The result is that we would very rarely miss notification of a new interrupt and leave a context-switch unprocessed, hanging the GPU. Fixes: 767a983 ("drm/i915/execlists: Read the context-status HEAD from the HWSP") Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Michel Thierry <michel.thierry@intel.com> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Cc: Mika Kuoppala <mika.kuoppala@intel.com> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com> Reviewed-by: Michel Thierry <michel.thierry@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20180321091027.21034-1-chris@chris-wilson.co.uk (cherry picked from commit 9153e6b) Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
1 parent 8f30c40 commit 76cb9d3

File tree

1 file changed

+8
-13
lines changed

1 file changed

+8
-13
lines changed

drivers/gpu/drm/i915/intel_lrc.c

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -831,7 +831,8 @@ static void execlists_submission_tasklet(unsigned long data)
831831
struct drm_i915_private *dev_priv = engine->i915;
832832
bool fw = false;
833833

834-
/* We can skip acquiring intel_runtime_pm_get() here as it was taken
834+
/*
835+
* We can skip acquiring intel_runtime_pm_get() here as it was taken
835836
* on our behalf by the request (see i915_gem_mark_busy()) and it will
836837
* not be relinquished until the device is idle (see
837838
* i915_gem_idle_work_handler()). As a precaution, we make sure
@@ -840,7 +841,8 @@ static void execlists_submission_tasklet(unsigned long data)
840841
*/
841842
GEM_BUG_ON(!dev_priv->gt.awake);
842843

843-
/* Prefer doing test_and_clear_bit() as a two stage operation to avoid
844+
/*
845+
* Prefer doing test_and_clear_bit() as a two stage operation to avoid
844846
* imposing the cost of a locked atomic transaction when submitting a
845847
* new request (outside of the context-switch interrupt).
846848
*/
@@ -856,17 +858,10 @@ static void execlists_submission_tasklet(unsigned long data)
856858
execlists->csb_head = -1; /* force mmio read of CSB ptrs */
857859
}
858860

859-
/* The write will be ordered by the uncached read (itself
860-
* a memory barrier), so we do not need another in the form
861-
* of a locked instruction. The race between the interrupt
862-
* handler and the split test/clear is harmless as we order
863-
* our clear before the CSB read. If the interrupt arrived
864-
* first between the test and the clear, we read the updated
865-
* CSB and clear the bit. If the interrupt arrives as we read
866-
* the CSB or later (i.e. after we had cleared the bit) the bit
867-
* is set and we do a new loop.
868-
*/
869-
__clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted);
861+
/* Clear before reading to catch new interrupts */
862+
clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted);
863+
smp_mb__after_atomic();
864+
870865
if (unlikely(execlists->csb_head == -1)) { /* following a reset */
871866
if (!fw) {
872867
intel_uncore_forcewake_get(dev_priv,

0 commit comments

Comments
 (0)