Even though we wait until the HW has sent us its first CS interrupt
before believing that it is powered on, a read from the powercontext
saved CSB registers may still return garbage. So we must wait a little
bit for the right result. This, of course, assumes that we always see an
invalid result when the powercontext is not loaded, otherwise we will
attempt to read stale data.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
drivers/gpu/drm/i915/intel_lrc.c | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index e114776b8836..8b03595c8c01 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -806,7 +806,8 @@ static void execlists_submission_tasklet(unsigned long data)
execlists->csb_head = -1; /* force mmio read of CSB ptrs */
}
- /* The write will be ordered by the uncached read (itself
+ /*
+ * The write will be ordered by the uncached read (itself
* a memory barrier), so we do not need another in the form
* of a locked instruction. The race between the interrupt
* handler and the split test/clear is harmless as we order
@@ -818,8 +819,20 @@ static void execlists_submission_tasklet(unsigned long data)
*/
__clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted);
if (unlikely(execlists->csb_head == -1)) { /* following a reset */
- head = readl(dev_priv->regs + i915_mmio_reg_offset(RING_CONTEXT_STATUS_PTR(engine)));
- tail = GEN8_CSB_WRITE_PTR(head);
+ do {
+ head = readl(dev_priv->regs +
+ i915_mmio_reg_offset(RING_CONTEXT_STATUS_PTR(engine)));
+ tail = GEN8_CSB_WRITE_PTR(head);
+ /*
+ * We have to wait until the powercontext has
+ * been loaded by the GPU before it starts
+ * reporting correctly. As we sometimes see
+ * an CS interrupt before we are able to
+ * read from the powercontext saved
+ * register, we repeat the read. Baffling and
+ * quite scary.
+ */
+ } while (unlikely(tail >= GEN8_CSB_ENTRIES));
head = GEN8_CSB_READ_PTR(head);
execlists->csb_head = head;
} else {
--
2.15.1