summaryrefslogtreecommitdiff
path: root/shared-core/i915_dma.c
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2008-05-22 10:48:32 -0700
committerEric Anholt <eric@anholt.net>2008-05-22 22:00:21 -0700
commita51c3a76ff415104426493a97ac686ccfe3f3926 (patch)
treec350968912458fa312c784dcd5b26c1532f38c43 /shared-core/i915_dma.c
parentda3f099a7c4a18468ff84819ed39e42bec641e11 (diff)
[intel] Add debug code to verify the cached ring tail pointer.
Recording the tail pointer in a local variable improves performance, but if someone messes up and fails to reload at the right time, the driver will write commands to the wrong part of the ring and scramble execution badly. This change (available by setting I915_RING_VALIDATE to 1) checks to make sure the cached tail pointer matches the hardware tail pointer at each ring buffer addition, calling BUG_ON when that's not true.
Diffstat (limited to 'shared-core/i915_dma.c')
-rw-r--r--shared-core/i915_dma.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c
index fa73cd29..1fc617d1 100644
--- a/shared-core/i915_dma.c
+++ b/shared-core/i915_dma.c
@@ -69,6 +69,30 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
return -EBUSY;
}
+#if I915_RING_VALIDATE
+/**
+ * Validate the cached ring tail value
+ *
+ * If the X server writes to the ring and DRM doesn't
+ * reload the head and tail pointers, it will end up writing
+ * data to the wrong place in the ring, causing havoc.
+ */
+void i915_ring_validate(struct drm_device *dev, const char *func, int line)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
+ u32 tail = I915_READ(LP_RING+RING_TAIL) & HEAD_ADDR;
+ u32 head = I915_READ(LP_RING+RING_HEAD) & HEAD_ADDR;
+
+ if (tail != ring->tail) {
+ DRM_ERROR("%s:%d head sw %x, hw %x. tail sw %x hw %x\n",
+ func, line,
+ ring->head, head, ring->tail, tail);
+ BUG_ON(1);
+ }
+}
+#endif
+
void i915_kernel_lost_context(struct drm_device * dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;