Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk
---
drivers/gpu/drm/i915/i915_debugfs.c |3 +
drivers/gpu/drm/i915/i915_drv.h | 10 +++-
drivers/gpu/drm/i915/i915_irq.c |3 +
drivers/gpu/drm/i915/intel_overlay.c | 85 ++
4 files changed, 99 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c
b/drivers/gpu/drm/i915/i915_debugfs.c
index 08f279b..8e09931 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -488,6 +488,9 @@ static int i915_error_state(struct seq_file *m, void
*unused)
}
}
+ if (error-overlay)
+ intel_overlay_print_error_state(m, error-overlay);
+
out:
spin_unlock_irqrestore(dev_priv-error_lock, flags);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 392dcb8..1787e06 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -113,6 +113,9 @@ struct intel_opregion {
int enabled;
};
+struct intel_overlay;
+struct intel_overlay_error_state;
+
struct drm_i915_master_private {
drm_local_map_t *sarea;
struct _drm_i915_sarea *sarea_priv;
@@ -166,6 +169,7 @@ struct drm_i915_error_state {
u32 purgeable:1;
} *active_bo;
u32 active_bo_count;
+ struct intel_overlay_error_state *overlay;
};
struct drm_i915_display_funcs {
@@ -186,8 +190,6 @@ struct drm_i915_display_funcs {
/* clock gating init */
};
-struct intel_overlay;
-
struct intel_device_info {
u8 is_mobile : 1;
u8 is_i8xx : 1;
@@ -1076,6 +1078,10 @@ extern bool ironlake_set_drps(struct drm_device *dev, u8
val);
extern void intel_detect_pch (struct drm_device *dev);
extern int intel_trans_dp_port_sel (struct drm_crtc *crtc);
+/* overlay */
+extern struct intel_overlay_error_state
*intel_overlay_capture_error_state(struct drm_device *dev);
+extern void intel_overlay_print_error_state(struct seq_file *m, struct
intel_overlay_error_state *error);
+
/**
* Lock test for when it's just for synchronization of ring access.
*
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 8aed608..5161cea 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -500,6 +500,7 @@ i915_error_state_free(struct drm_device *dev,
i915_error_object_free(error-batchbuffer[1]);
i915_error_object_free(error-ringbuffer);
kfree(error-active_bo);
+ kfree(error-overlay);
kfree(error);
}
@@ -717,6 +718,8 @@ static void i915_capture_error_state(struct drm_device *dev)
do_gettimeofday(error-time);
+ error-overlay = intel_overlay_capture_error_state(dev);
+
spin_lock_irqsave(dev_priv-error_lock, flags);
if (dev_priv-first_error == NULL) {
dev_priv-first_error = error;
diff --git a/drivers/gpu/drm/i915/intel_overlay.c
b/drivers/gpu/drm/i915/intel_overlay.c
index d39aea2..f11ea5c 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -1416,3 +1416,88 @@ void intel_cleanup_overlay(struct drm_device *dev)
kfree(dev_priv-overlay);
}
}
+
+struct intel_overlay_error_state {
+ struct overlay_registers regs;
+ u32 status;
+};
+
+struct intel_overlay_error_state *
+intel_overlay_capture_error_state(struct drm_device *dev)
+{
+drm_i915_private_t *dev_priv = dev-dev_private;
+ struct intel_overlay_error_state *error;
+ struct overlay_registers __iomem *regs;
+
+ if (!dev_priv-overlay || !dev_priv-overlay-active)
+ return NULL;
+
+ error = kmalloc(sizeof(*error), GFP_ATOMIC);
+ if (error == NULL)
+ return NULL;
+
+ error-status = I915_READ(DOVSTA);
+
+ regs = intel_overlay_map_regs_atomic(dev_priv-overlay);
+ if (!regs)
+ goto err;
+
+ memcpy_fromio(error-regs, regs, sizeof(struct overlay_registers));
+ intel_overlay_unmap_regs_atomic(dev_priv-overlay);
+
+ return error;
+
+err:
+ kfree(error);
+ return NULL;
+}
+
+void
+intel_overlay_print_error_state(struct seq_file *m, struct
intel_overlay_error_state *error)
+{
+ seq_printf(m, Overlay, status: 0x%08x\n, error-status);
+
+#define P(x) seq_printf(m,#x : 0x%08x\n, error-regs.x)
+ P(OBUF_0Y);
+ P(OBUF_1Y);
+ P(OBUF_0U);
+ P(OBUF_0V);
+ P(OBUF_1U);
+ P(OBUF_1V);
+ P(OSTRIDE);
+ P(YRGB_VPH);
+ P(UV_VPH);
+ P(HORZ_PH);
+ P(INIT_PHS);
+ P(DWINPOS);
+ P(DWINSZ);
+ P(SWIDTH);
+ P(SWIDTHSW);
+ P(SHEIGHT);
+ P(YRGBSCALE);
+ P(UVSCALE);
+ P(OCLRC0);
+ P(OCLRC1);
+ P(DCLRKV);
+ P(DCLRKM);
+ P(SCLRKVH);
+ P(SCLRKVL);
+ P(SCLRKEN);
+ P(OCONFIG);
+ P(OCMD);
+ P(OSTART_0Y);
+