On Thu, Jan 20, 2011 at 9:51 AM, Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx> wrote: > > So how about just doing this in the loop? It will mean that the > _first_ read uses the fast cached one (the common case, hopefully), > but then if we loop, we'll use the slow exact one. > > (cut-and-paste, so whitespace isn't good): > > diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c > b/drivers/gpu/drm/i915/intel_ringbuffer.c > index 03e3370..11bbfb5 100644 > --- a/drivers/gpu/drm/i915/intel_ringbuffer.c > +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c > @@ -961,6 +961,8 @@ int intel_wait_ring_buffer(struct > intel_ring_buffer *ring, int n) > msleep(1); > if (atomic_read(&dev_priv->mm.wedged)) > return -EAGAIN; > + /* Force a re-read. FIXME: what if read_status_page > says 0 too */ > + ring->actual_head = 0; > } while (!time_after(jiffies, end)); > trace_i915_ring_wait_end (dev); > return -EBUSY; This makes no difference. And the reason is exactly that we get the zero case that I had in the comment. But THIS attached patch actually seems to fix the slow suspend for me. I removed the accesses to "actual_head", because that whole field seems to not be used. So it seems like the intel_read_status_page() thing returns zero forever when suspending. Maybe you can explain why. Linus
drivers/gpu/drm/i915/intel_ringbuffer.c | 5 +++-- drivers/gpu/drm/i915/intel_ringbuffer.h | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 03e3370..f6b9baa 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -928,6 +928,7 @@ static int intel_wrap_ring_buffer(struct intel_ring_buffer *ring) int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n) { + int reread = 0; struct drm_device *dev = ring->dev; struct drm_i915_private *dev_priv = dev->dev_private; unsigned long end; @@ -940,9 +941,8 @@ int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n) * fallback to the slow and accurate path. */ head = intel_read_status_page(ring, 4); - if (head < ring->actual_head) + if (reread) 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) @@ -961,6 +961,7 @@ int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n) msleep(1); if (atomic_read(&dev_priv->mm.wedged)) return -EAGAIN; + reread = 1; } while (!time_after(jiffies, end)); trace_i915_ring_wait_end (dev); return -EBUSY; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index be9087e..5b0abfa 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -47,7 +47,6 @@ struct intel_ring_buffer { struct drm_device *dev; struct drm_i915_gem_object *obj; - u32 actual_head; u32 head; u32 tail; int space;
_______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel