drm/i915/ringbuffer: Handle wrapping of the autoreported HEAD
authorChris Wilson <chris@chris-wilson.co.uk>
Thu, 9 Dec 2010 12:56:37 +0000 (12:56 +0000)
committerChris Wilson <chris@chris-wilson.co.uk>
Thu, 9 Dec 2010 12:53:19 +0000 (12:53 +0000)
If the tail advances beyond the autoreport HEAD value, then we need to
fallback to an uncached read of the HEAD register in order to ascertain
the correct amount of remaining space in the ringbuffer.

Reported-by: Fang, Xun <xunx.fang@intel.com>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=32259
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_ringbuffer.h

index 89a65be8a3f364359edaf6add71b6259affa3cbd..31cd7e33e8208b8112ed7cb2b278e8cc8b84fc61 100644 (file)
@@ -696,20 +696,17 @@ int intel_wait_ring_buffer(struct drm_device *dev,
        drm_i915_private_t *dev_priv = dev->dev_private;
        u32 head;
 
-       head = intel_read_status_page(ring, 4);
-       if (head) {
-               ring->head = head & HEAD_ADDR;
-               ring->space = ring->head - (ring->tail + 8);
-               if (ring->space < 0)
-                       ring->space += ring->size;
-               if (ring->space >= n)
-                       return 0;
-       }
-
        trace_i915_ring_wait_begin (dev);
        end = jiffies + 3 * HZ;
        do {
-               ring->head = I915_READ_HEAD(ring) & HEAD_ADDR;
+               /* If the reported head position has wrapped or hasn't advanced,
+                * fallback to the slow and accurate path.
+                */
+               head = intel_read_status_page(ring, 4);
+               if (head < ring->actual_head)
+                       head = I915_READ_HEAD(ring);
+               ring->actual_head = head;
+               ring->head = head & HEAD_ADDR;
                ring->space = ring->head - (ring->tail + 8);
                if (ring->space < 0)
                        ring->space += ring->size;
index 3126c2681983e21ba729d9ca599d104f4f1323de..d2cd0f1efeedfdec3102f0436dc70d0d47a2d52d 100644 (file)
@@ -30,8 +30,9 @@ struct  intel_ring_buffer {
        struct          drm_device *dev;
        struct          drm_gem_object *gem_object;
 
-       unsigned int    head;
-       unsigned int    tail;
+       u32             actual_head;
+       u32             head;
+       u32             tail;
        int             space;
        struct intel_hw_status_page status_page;