summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorChris Wilson2010-08-07 15:18:47 +0200
committerEric Anholt2010-08-09 20:24:36 +0200
commite78d73b16bcde921c9cf458d2e4de8e4fc2518f3 (patch)
treece189a9f57f1ef6dc9d3368bd20ac6d566605ad7 /drivers
parentdrm/i915: Apply i830 errata for cursor alignment (diff)
downloadkernel-qcow2-linux-e78d73b16bcde921c9cf458d2e4de8e4fc2518f3.tar.gz
kernel-qcow2-linux-e78d73b16bcde921c9cf458d2e4de8e4fc2518f3.tar.xz
kernel-qcow2-linux-e78d73b16bcde921c9cf458d2e4de8e4fc2518f3.zip
drm/i915: Wake-up wait_request() from elapsed hang-check (v2)
If our watchdog fires and we see that the GPU is idle, but that we are still waiting on an interrupt, forcibly wake-up the waiter. i915_do_wait_request() should not be racy, yet there are persistent reports that 945GM hangs whilst the GPU is idle. This implies that the hardware is not quite as coherent as the documentation claims - a write followed by a flush is supposed to be coherent in main memory before the flush is retired and the irq is emitted. This seems to be a sensible and elegant guard to force the wait to timeout. v2: Daniel Vetter pointed out that a warning would be useful to explain why the machine appeared to stall. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 5161cea7a4ef..69a36fc035dc 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1304,6 +1304,16 @@ void i915_hangcheck_elapsed(unsigned long data)
&dev_priv->render_ring),
i915_get_tail_request(dev)->seqno)) {
dev_priv->hangcheck_count = 0;
+
+ /* Issue a wake-up to catch stuck h/w. */
+ if (dev_priv->render_ring.waiting_gem_seqno |
+ dev_priv->bsd_ring.waiting_gem_seqno) {
+ DRM_ERROR("Hangcheck timer elapsed... GPU idle, missed IRQ.\n");
+ if (dev_priv->render_ring.waiting_gem_seqno)
+ DRM_WAKEUP(&dev_priv->render_ring.irq_queue);
+ if (dev_priv->bsd_ring.waiting_gem_seqno)
+ DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue);
+ }
return;
}