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>
This commit is contained in:
Chris Wilson 2010-12-09 12:56:37 +00:00
Родитель 8316f33766
Коммит 8c0a6bfef1
2 изменённых файлов: 11 добавлений и 13 удалений

Просмотреть файл

@ -696,20 +696,17 @@ int intel_wait_ring_buffer(struct drm_device *dev,
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
u32 head; 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); trace_i915_ring_wait_begin (dev);
end = jiffies + 3 * HZ; end = jiffies + 3 * HZ;
do { 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); ring->space = ring->head - (ring->tail + 8);
if (ring->space < 0) if (ring->space < 0)
ring->space += ring->size; ring->space += ring->size;

Просмотреть файл

@ -30,8 +30,9 @@ struct intel_ring_buffer {
struct drm_device *dev; struct drm_device *dev;
struct drm_gem_object *gem_object; struct drm_gem_object *gem_object;
unsigned int head; u32 actual_head;
unsigned int tail; u32 head;
u32 tail;
int space; int space;
struct intel_hw_status_page status_page; struct intel_hw_status_page status_page;