diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-12-09 07:56:37 -0500 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-12-09 07:53:19 -0500 |
commit | 8c0a6bfef165ccdbf5d73afb9dd660107b0c98d5 (patch) | |
tree | 09455156e4e46ac5137ddab9ec3aed65bc6a8c59 | |
parent | 8316f33766a82907c694267ff911e45e256f09f9 (diff) |
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>
-rw-r--r-- | drivers/gpu/drm/i915/intel_ringbuffer.c | 19 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_ringbuffer.h | 5 |
2 files changed, 11 insertions, 13 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, | |||
696 | drm_i915_private_t *dev_priv = dev->dev_private; | 696 | drm_i915_private_t *dev_priv = dev->dev_private; |
697 | u32 head; | 697 | u32 head; |
698 | 698 | ||
699 | head = intel_read_status_page(ring, 4); | ||
700 | if (head) { | ||
701 | ring->head = head & HEAD_ADDR; | ||
702 | ring->space = ring->head - (ring->tail + 8); | ||
703 | if (ring->space < 0) | ||
704 | ring->space += ring->size; | ||
705 | if (ring->space >= n) | ||
706 | return 0; | ||
707 | } | ||
708 | |||
709 | trace_i915_ring_wait_begin (dev); | 699 | trace_i915_ring_wait_begin (dev); |
710 | end = jiffies + 3 * HZ; | 700 | end = jiffies + 3 * HZ; |
711 | do { | 701 | do { |
712 | ring->head = I915_READ_HEAD(ring) & HEAD_ADDR; | 702 | /* If the reported head position has wrapped or hasn't advanced, |
703 | * fallback to the slow and accurate path. | ||
704 | */ | ||
705 | head = intel_read_status_page(ring, 4); | ||
706 | if (head < ring->actual_head) | ||
707 | head = I915_READ_HEAD(ring); | ||
708 | ring->actual_head = head; | ||
709 | ring->head = head & HEAD_ADDR; | ||
713 | ring->space = ring->head - (ring->tail + 8); | 710 | ring->space = ring->head - (ring->tail + 8); |
714 | if (ring->space < 0) | 711 | if (ring->space < 0) |
715 | ring->space += ring->size; | 712 | ring->space += ring->size; |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 3126c2681983..d2cd0f1efeed 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h | |||
@@ -30,8 +30,9 @@ struct intel_ring_buffer { | |||
30 | struct drm_device *dev; | 30 | struct drm_device *dev; |
31 | struct drm_gem_object *gem_object; | 31 | struct drm_gem_object *gem_object; |
32 | 32 | ||
33 | unsigned int head; | 33 | u32 actual_head; |
34 | unsigned int tail; | 34 | u32 head; |
35 | u32 tail; | ||
35 | int space; | 36 | int space; |
36 | struct intel_hw_status_page status_page; | 37 | struct intel_hw_status_page status_page; |
37 | 38 | ||