[Intel-gfx] [PATCH] i915: dump error state when error interrupt is raised

Jesse Barnes jbarnes at virtuousgeek.org
Sat Apr 18 00:10:59 CEST 2009


This is long overdue.  I'm still in the process of testing it though,
and it probably needs work on pre-965.  Would be good to get it working
for 945 and 8xx though, since we seem to have a lot of problems with
those chips these days, and it would be good to get data on the hangs
people see there.

The patch is simple, it just enables the error interrupt and unmasks
all error types, then dumps info from the interrupt handler if an error
is detected.

My s-o-b is here in the unlikely event that the patch is ok on 8xx and
9xx.

Signed-off-by: Jesse Barnes <jbarnes at virtuousgeek.org>

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index ee7ce7b..ee07af1 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -41,8 +41,9 @@
  * we leave them always unmasked in IMR and then control enabling them through
  * PIPESTAT alone.
  */
-#define I915_INTERRUPT_ENABLE_FIX (I915_ASLE_INTERRUPT | \
-				   I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |  \
+#define I915_INTERRUPT_ENABLE_FIX (I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT |\
+				   I915_ASLE_INTERRUPT |		\
+				   I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \
 				   I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
 
 /** Interrupts that we mask and unmask at runtime. */
@@ -267,6 +268,23 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 			I915_READ(PORT_HOTPLUG_STAT);
 		}
 
+		if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) {
+			u32 eir = I915_READ(EIR);
+			DRM_ERROR("render error detected, EIR: 0x%08x\n", eir);
+			I915_WRITE(EIR, eir);
+			if (eir & I915_ERROR_PAGE_TABLE) {
+				DRM_ERROR("page table error, 0x%08x\n",
+					  I915_READ(PGTBL_ER));
+			}
+			if (eir & I915_ERROR_MEMORY_REFRESH) {
+				DRM_ERROR("memory refresh error\n");
+			}
+			if (eir & I915_ERROR_INSTRUCTION) {
+				DRM_ERROR("instruction error: 0x%08x\n",
+					  I915_READ(IPEIR));
+			}
+		}
+
 		I915_WRITE(IIR, iir);
 		new_iir = I915_READ(IIR); /* Flush posted writes */
 
@@ -569,6 +587,7 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR;
+	u32 error_mask;
 
 	dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
 
@@ -602,6 +621,13 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
 		i915_enable_irq(dev_priv, I915_DISPLAY_PORT_INTERRUPT);
 	}
 
+	/* Enable some error detection */
+	error_mask = ~(I915_ERROR_PAGE_TABLE | I915_ERROR_MEMORY_REFRESH |
+		       I915_ERROR_INSTRUCTION);
+	I915_WRITE(EMR, error_mask);
+	enable_mask |= I915_DISPLAY_PORT_INTERRUPT;
+	i915_enable_irq(dev_priv, I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT);
+
 	/* Disable pipe interrupt enables, clear pending pipe status */
 	I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff);
 	I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff);
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 5211947..bf768b2 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -205,6 +205,7 @@
 /*
  * Instruction and interrupt control regs
  */
+#define PGTBL_ER	0x02024
 #define PRB0_TAIL	0x02030
 #define PRB0_HEAD	0x02034
 #define PRB0_START	0x02038
@@ -257,6 +258,9 @@
 #define EIR		0x020b0
 #define EMR		0x020b4
 #define ESR		0x020b8
+#define   I915_ERROR_PAGE_TABLE				(1<<4)
+#define   I915_ERROR_MEMORY_REFRESH			(1<<1)
+#define   I915_ERROR_INSTRUCTION			(1<<0)
 #define INSTPM	        0x020c0
 #define ACTHD	        0x020c8
 #define FW_BLC		0x020d8



More information about the Intel-gfx mailing list