Re: more intel drm issues (was Re: [git pull] drm intel only fixes)

From: Linus Torvalds
Date: Thu Jan 20 2011 - 15:45:28 EST


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;