diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-12-09 15:56:37 +0300 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-12-09 15:53:19 +0300 |
commit | 8c0a6bfef165ccdbf5d73afb9dd660107b0c98d5 (patch) | |
tree | 09455156e4e46ac5137ddab9ec3aed65bc6a8c59 /drivers/gpu/drm/i915/intel_ringbuffer.c | |
parent | 8316f33766a82907c694267ff911e45e256f09f9 (diff) | |
download | linux-8c0a6bfef165ccdbf5d73afb9dd660107b0c98d5.tar.xz |
drm/i915/ringbuffer: Handle wrapping of the autoreported HEAD
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>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_ringbuffer.c | 19 |
1 files changed, 8 insertions, 11 deletions
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 89a65be8a3f3..31cd7e33e820 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -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; |