diff mbox

drm/i915: Check that the plane points to the pipe's framebuffer before enabling

Message ID 1303032761-2991-1-git-send-email-chris@chris-wilson.co.uk (mailing list archive)
State New, archived
Headers show

Commit Message

Chris Wilson April 17, 2011, 9:32 a.m. UTC
Knut Petersen reported a GPU hang when he left x11perf running
overnight. The error state quite clearly indicates that plane A was
enabled without being fully setup:

PGTBL_ER: 0x00000010
    Display A: Invalid GTT PTE
Plane [0]:
  CNTR: c1000000
  STRIDE: 00000c80
  SIZE: 03ff04ff
  POS: 00000000
  ADDR: 00000000

[That GTT offset on his system being pinned for the ringbuffer.]

This is a simple debugging patch to assert that this cannot be so!

References: https://bugs.freedesktop.org/show_bug.cgi?id=36246
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
---

v2: Remember that gen4 splits the base + offset between different regs...

---
 drivers/gpu/drm/i915/intel_display.c |   29 +++++++++++++++++++++++++++++
 1 files changed, 29 insertions(+), 0 deletions(-)

Comments

Jesse Barnes April 18, 2011, 3:54 p.m. UTC | #1
On Sun, 17 Apr 2011 10:32:41 +0100
Chris Wilson <chris@chris-wilson.co.uk> wrote:

> Knut Petersen reported a GPU hang when he left x11perf running
> overnight. The error state quite clearly indicates that plane A was
> enabled without being fully setup:
> 
> PGTBL_ER: 0x00000010
>     Display A: Invalid GTT PTE
> Plane [0]:
>   CNTR: c1000000
>   STRIDE: 00000c80
>   SIZE: 03ff04ff
>   POS: 00000000
>   ADDR: 00000000
> 
> [That GTT offset on his system being pinned for the ringbuffer.]
> 
> This is a simple debugging patch to assert that this cannot be so!
> 

I like it (though now the comment talks about DSPADDR and leaves
DSPSURF out in the cold).

Sounds like our dpms code may be causing trouble for this x11perf run
perhaps?  What else would cause us to change base addrs during a bench
run like that?
Chris Wilson April 19, 2011, 5:55 a.m. UTC | #2
On Mon, 18 Apr 2011 08:54:44 -0700, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> I like it (though now the comment talks about DSPADDR and leaves
> DSPSURF out in the cold).

D'oh. That'll teach me to try and write a comment to explain a function
first!

> Sounds like our dpms code may be causing trouble for this x11perf run
> perhaps?  What else would cause us to change base addrs during a bench
> run like that?

Right. The early observation is that we don't assign a framebuffer to
the CRTC borrowed for VGA/TV load detection. And I can postulate that we
contrived to access a PTE during a hotplug poll whilst rewriting the GTT
(or something similar to the object following the ringbuffer).

I think we can just attach the fbcon for the purposes of load detection.
-Chris
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 7734d1e..ab80046 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1274,6 +1274,34 @@  static void intel_disable_pipe(struct drm_i915_private *dev_priv,
 	intel_wait_for_pipe_off(dev_priv->dev, pipe);
 }
 
+/* Check that the DSPADDR points to the right framebufffer for the pipe. */
+static void assert_fb_bound_to_plane(struct drm_i915_private *dev_priv,
+				     enum pipe pipe, enum plane plane)
+{
+	struct drm_crtc *crtc;
+	struct intel_framebuffer *intel_fb;
+	u32 val, base, size;
+
+	crtc = intel_get_crtc_for_pipe(dev_priv->dev, pipe);
+	if (WARN(crtc->fb == NULL,
+		 "no framebuffer attached to pipe %c\n",
+		 pipe_name(pipe)))
+		return;
+
+	intel_fb = to_intel_framebuffer(crtc->fb);
+	base = intel_fb->obj->gtt_offset;
+	size = intel_fb->obj->base.size;
+
+	if (dev_priv->info->gen >= 4)
+		val = I915_READ(DSPSURF(plane));
+	else
+		val = I915_READ(DSPADDR(plane));
+	WARN(val < base || val >= base + size,
+	     "mismatching framebuffer for plane %c attached to pipe %c, expected %x-%x found %x\n",
+	     plane_name(plane), pipe_name(pipe),
+	     base, base + size, val);
+}
+
 /**
  * intel_enable_plane - enable a display plane on a given pipe
  * @dev_priv: i915 private structure
@@ -1290,6 +1318,7 @@  static void intel_enable_plane(struct drm_i915_private *dev_priv,
 
 	/* If the pipe isn't enabled, we can't pump pixels and may hang */
 	assert_pipe_enabled(dev_priv, pipe);
+	assert_fb_bound_to_plane(dev_priv, pipe, plane);
 
 	reg = DSPCNTR(plane);
 	val = I915_READ(reg);