OSDN Git Service

drm/i915: Capture interesting display registers on error
authorChris Wilson <chris@chris-wilson.co.uk>
Sun, 21 Nov 2010 13:12:35 +0000 (13:12 +0000)
committerChris Wilson <chris@chris-wilson.co.uk>
Mon, 22 Nov 2010 08:08:19 +0000 (08:08 +0000)
When trying to diagnose mysterious errors on resume, capture the
display register contents as well.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_display.c

index 24a88ac..421b841 100644 (file)
@@ -729,6 +729,9 @@ static int i915_error_state(struct seq_file *m, void *unused)
        if (error->overlay)
                intel_overlay_print_error_state(m, error->overlay);
 
+       if (error->display)
+               intel_display_print_error_state(m, dev, error->display);
+
 out:
        spin_unlock_irqrestore(&dev_priv->error_lock, flags);
 
index 826c723..4c20ad9 100644 (file)
@@ -140,6 +140,8 @@ struct sdvo_device_mapping {
        u8 ddc_pin;
 };
 
+struct intel_display_error_state;
+
 struct drm_i915_error_state {
        u32 eir;
        u32 pgtbl_er;
@@ -187,6 +189,7 @@ struct drm_i915_error_state {
        } *active_bo, *pinned_bo;
        u32 active_bo_count, pinned_bo_count;
        struct intel_overlay_error_state *overlay;
+       struct intel_display_error_state *display;
 };
 
 struct drm_i915_display_funcs {
@@ -1223,6 +1226,11 @@ extern int intel_trans_dp_port_sel (struct drm_crtc *crtc);
 #ifdef CONFIG_DEBUG_FS
 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);
+
+extern struct intel_display_error_state *intel_display_capture_error_state(struct drm_device *dev);
+extern void intel_display_print_error_state(struct seq_file *m,
+                                           struct drm_device *dev,
+                                           struct intel_display_error_state *error);
 #endif
 
 /**
index bbcd5da..0b6052a 100644 (file)
@@ -766,6 +766,7 @@ static void i915_capture_error_state(struct drm_device *dev)
        do_gettimeofday(&error->time);
 
        error->overlay = intel_overlay_capture_error_state(dev);
+       error->display = intel_display_capture_error_state(dev);
 
        spin_lock_irqsave(&dev_priv->error_lock, flags);
        if (dev_priv->first_error == NULL) {
index 886c0e0..ec2a8b0 100644 (file)
 #define VTOTAL(pipe) _PIPE(pipe, VTOTAL_A, VTOTAL_B)
 #define VBLANK(pipe) _PIPE(pipe, VBLANK_A, VBLANK_B)
 #define VSYNC(pipe) _PIPE(pipe, VSYNC_A, VSYNC_B)
-#define PIPESRC(pipe) _PIPE(pipe, PIPEASRC, PIPEBSRC)
 #define BCLRPAT(pipe) _PIPE(pipe, BCLRPAT_A, BCLRPAT_B)
 
 /* VGA port control */
 #define   PIPE_6BPC                            (2 << 5)
 #define   PIPE_12BPC                           (3 << 5)
 
+#define PIPESRC(pipe) _PIPE(pipe, PIPEASRC, PIPEBSRC)
 #define PIPECONF(pipe) _PIPE(pipe, PIPEACONF, PIPEBCONF)
 #define PIPEDSL(pipe)  _PIPE(pipe, PIPEADSL, PIPEBDSL)
 
 #define CURBBASE               0x700c4
 #define CURBPOS                        0x700c8
 
+#define CURCNTR(pipe) _PIPE(pipe, CURACNTR, CURBCNTR)
+#define CURBASE(pipe) _PIPE(pipe, CURABASE, CURBBASE)
+#define CURPOS(pipe) _PIPE(pipe, CURAPOS, CURBPOS)
+
 /* Display A control */
 #define DSPACNTR                0x70180
 #define   DISPLAY_PLANE_ENABLE                 (1<<31)
index 3fa5aaa..d4bc443 100644 (file)
@@ -6269,3 +6269,113 @@ int intel_modeset_vga_set_state(struct drm_device *dev, bool state)
        pci_write_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, gmch_ctrl);
        return 0;
 }
+
+#ifdef CONFIG_DEBUG_FS
+#include <linux/seq_file.h>
+
+struct intel_display_error_state {
+       struct intel_cursor_error_state {
+               u32 control;
+               u32 position;
+               u32 base;
+               u32 size;
+       } cursor[2];
+
+       struct intel_pipe_error_state {
+               u32 conf;
+               u32 source;
+
+               u32 htotal;
+               u32 hblank;
+               u32 hsync;
+               u32 vtotal;
+               u32 vblank;
+               u32 vsync;
+       } pipe[2];
+
+       struct intel_plane_error_state {
+               u32 control;
+               u32 stride;
+               u32 size;
+               u32 pos;
+               u32 addr;
+               u32 surface;
+               u32 tile_offset;
+       } plane[2];
+};
+
+struct intel_display_error_state *
+intel_display_capture_error_state(struct drm_device *dev)
+{
+        drm_i915_private_t *dev_priv = dev->dev_private;
+       struct intel_display_error_state *error;
+       int i;
+
+       error = kmalloc(sizeof(*error), GFP_ATOMIC);
+       if (error == NULL)
+               return NULL;
+
+       for (i = 0; i < 2; i++) {
+               error->cursor[i].control = I915_READ(CURCNTR(i));
+               error->cursor[i].position = I915_READ(CURPOS(i));
+               error->cursor[i].base = I915_READ(CURBASE(i));
+
+               error->plane[i].control = I915_READ(DSPCNTR(i));
+               error->plane[i].stride = I915_READ(DSPSTRIDE(i));
+               error->plane[i].size = I915_READ(DSPSIZE(i));
+               error->plane[i].pos= I915_READ(DSPPOS(i));
+               error->plane[i].addr = I915_READ(DSPADDR(i));
+               if (INTEL_INFO(dev)->gen >= 4) {
+                       error->plane[i].surface = I915_READ(DSPSURF(i));
+                       error->plane[i].tile_offset = I915_READ(DSPTILEOFF(i));
+               }
+
+               error->pipe[i].conf = I915_READ(PIPECONF(i));
+               error->pipe[i].source = I915_READ(PIPESRC(i));
+               error->pipe[i].htotal = I915_READ(HTOTAL(i));
+               error->pipe[i].hblank = I915_READ(HBLANK(i));
+               error->pipe[i].hsync = I915_READ(HSYNC(i));
+               error->pipe[i].vtotal = I915_READ(VTOTAL(i));
+               error->pipe[i].vblank = I915_READ(VBLANK(i));
+               error->pipe[i].vsync = I915_READ(VSYNC(i));
+       }
+
+       return error;
+}
+
+void
+intel_display_print_error_state(struct seq_file *m,
+                               struct drm_device *dev,
+                               struct intel_display_error_state *error)
+{
+       int i;
+
+       for (i = 0; i < 2; i++) {
+               seq_printf(m, "Pipe [%d]:\n", i);
+               seq_printf(m, "  CONF: %08x\n", error->pipe[i].conf);
+               seq_printf(m, "  SRC: %08x\n", error->pipe[i].source);
+               seq_printf(m, "  HTOTAL: %08x\n", error->pipe[i].htotal);
+               seq_printf(m, "  HBLANK: %08x\n", error->pipe[i].hblank);
+               seq_printf(m, "  HSYNC: %08x\n", error->pipe[i].hsync);
+               seq_printf(m, "  VTOTAL: %08x\n", error->pipe[i].vtotal);
+               seq_printf(m, "  VBLANK: %08x\n", error->pipe[i].vblank);
+               seq_printf(m, "  VSYNC: %08x\n", error->pipe[i].vsync);
+
+               seq_printf(m, "Plane [%d]:\n", i);
+               seq_printf(m, "  CNTR: %08x\n", error->plane[i].control);
+               seq_printf(m, "  STRIDE: %08x\n", error->plane[i].stride);
+               seq_printf(m, "  SIZE: %08x\n", error->plane[i].size);
+               seq_printf(m, "  POS: %08x\n", error->plane[i].pos);
+               seq_printf(m, "  ADDR: %08x\n", error->plane[i].addr);
+               if (INTEL_INFO(dev)->gen >= 4) {
+                       seq_printf(m, "  SURF: %08x\n", error->plane[i].surface);
+                       seq_printf(m, "  TILEOFF: %08x\n", error->plane[i].tile_offset);
+               }
+
+               seq_printf(m, "Cursor [%d]:\n", i);
+               seq_printf(m, "  CNTR: %08x\n", error->cursor[i].control);
+               seq_printf(m, "  POS: %08x\n", error->cursor[i].position);
+               seq_printf(m, "  BASE: %08x\n", error->cursor[i].base);
+       }
+}
+#endif