drm/i915: enable error detection & state collection

This patch enables error detection by enabling several types of error
interrupts.  When an error interrupt is received, the interrupt
handler captures the error state; hopefully resulting in an accurate
set of error data (error type, active head pointer, etc.).  The new
record is then available from sysfs.  The current code will also dump
the error state to the system log.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
diff --git a/drivers/gpu/drm/i915/i915_gem_debugfs.c b/drivers/gpu/drm/i915/i915_gem_debugfs.c
index 28146e4..cacae94 100644
--- a/drivers/gpu/drm/i915/i915_gem_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_gem_debugfs.c
@@ -323,6 +323,39 @@
 	return 0;
 }
 
+static int i915_error_state(struct seq_file *m, void *unused)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_i915_error_state *error;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev_priv->error_lock, flags);
+	if (!dev_priv->first_error) {
+		seq_printf(m, "no error state collected\n");
+		goto out;
+	}
+
+	error = dev_priv->first_error;
+
+	seq_printf(m, "EIR: 0x%08x\n", error->eir);
+	seq_printf(m, "  PGTBL_ER: 0x%08x\n", error->pgtbl_er);
+	seq_printf(m, "  INSTPM: 0x%08x\n", error->instpm);
+	seq_printf(m, "  IPEIR: 0x%08x\n", error->ipeir);
+	seq_printf(m, "  IPEHR: 0x%08x\n", error->ipehr);
+	seq_printf(m, "  INSTDONE: 0x%08x\n", error->instdone);
+	seq_printf(m, "  ACTHD: 0x%08x\n", error->acthd);
+	if (IS_I965G(dev)) {
+		seq_printf(m, "  INSTPS: 0x%08x\n", error->instps);
+		seq_printf(m, "  INSTDONE1: 0x%08x\n", error->instdone1);
+	}
+
+out:
+	spin_unlock_irqrestore(&dev_priv->error_lock, flags);
+
+	return 0;
+}
 
 static struct drm_info_list i915_gem_debugfs_list[] = {
 	{"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST},
@@ -336,6 +369,7 @@
 	{"i915_ringbuffer_data", i915_ringbuffer_data, 0},
 	{"i915_ringbuffer_info", i915_ringbuffer_info, 0},
 	{"i915_batchbuffers", i915_batchbuffer_info, 0},
+	{"i915_error_state", i915_error_state, 0},
 };
 #define I915_GEM_DEBUGFS_ENTRIES ARRAY_SIZE(i915_gem_debugfs_list)