aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2018-03-21 05:10:27 -0400
committerJoonas Lahtinen <joonas.lahtinen@linux.intel.com>2018-03-27 04:20:00 -0400
commit76cb9d314a5385020c3adabf563df8efe71c6325 (patch)
tree7ad192169bcc3cb2a2c48b057bdb584a8c217d67
parent8f30c4085b72485c05e85d56e9a84098da2ba5b7 (diff)
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 767a983ab255 ("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: 767a983ab255 ("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 9153e6b7c85edbc89e874e5c83f86217c53dcfaf) Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
-rw-r--r--drivers/gpu/drm/i915/intel_lrc.c21
1 files changed, 8 insertions, 13 deletions
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 3a69b367e565..697af5add78b 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -831,7 +831,8 @@ static void execlists_submission_tasklet(unsigned long data)
831 struct drm_i915_private *dev_priv = engine->i915; 831 struct drm_i915_private *dev_priv = engine->i915;
832 bool fw = false; 832 bool fw = false;
833 833
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
835 * on our behalf by the request (see i915_gem_mark_busy()) and it will 836 * on our behalf by the request (see i915_gem_mark_busy()) and it will
836 * not be relinquished until the device is idle (see 837 * not be relinquished until the device is idle (see
837 * i915_gem_idle_work_handler()). As a precaution, we make sure 838 * i915_gem_idle_work_handler()). As a precaution, we make sure
@@ -840,7 +841,8 @@ static void execlists_submission_tasklet(unsigned long data)
840 */ 841 */
841 GEM_BUG_ON(!dev_priv->gt.awake); 842 GEM_BUG_ON(!dev_priv->gt.awake);
842 843
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
844 * imposing the cost of a locked atomic transaction when submitting a 846 * imposing the cost of a locked atomic transaction when submitting a
845 * new request (outside of the context-switch interrupt). 847 * new request (outside of the context-switch interrupt).
846 */ 848 */
@@ -856,17 +858,10 @@ static void execlists_submission_tasklet(unsigned long data)
856 execlists->csb_head = -1; /* force mmio read of CSB ptrs */ 858 execlists->csb_head = -1; /* force mmio read of CSB ptrs */
857 } 859 }
858 860
859 /* The write will be ordered by the uncached read (itself 861 /* Clear before reading to catch new interrupts */
860 * a memory barrier), so we do not need another in the form 862 clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted);
861 * of a locked instruction. The race between the interrupt 863 smp_mb__after_atomic();
862 * handler and the split test/clear is harmless as we order 864
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);
870 if (unlikely(execlists->csb_head == -1)) { /* following a reset */ 865 if (unlikely(execlists->csb_head == -1)) { /* following a reset */
871 if (!fw) { 866 if (!fw) {
872 intel_uncore_forcewake_get(dev_priv, 867 intel_uncore_forcewake_get(dev_priv,