diff options
| author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-11-21 08:12:35 -0500 |
|---|---|---|
| committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-11-22 03:08:19 -0500 |
| commit | c4a1d9e4dc5d5313cfec2cc0c9d630efe8a6f287 (patch) | |
| tree | 6b8c839478c8cf8a8fb1a6b02f32a03878247a94 | |
| parent | c724e8a9407683a8a2ee8eb00b972badf237bbe1 (diff) | |
drm/i915: Capture interesting display registers on error
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>
| -rw-r--r-- | drivers/gpu/drm/i915/i915_debugfs.c | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 8 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 6 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 110 |
5 files changed, 127 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 24a88ac63212..421b8414b577 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c | |||
| @@ -729,6 +729,9 @@ static int i915_error_state(struct seq_file *m, void *unused) | |||
| 729 | if (error->overlay) | 729 | if (error->overlay) |
| 730 | intel_overlay_print_error_state(m, error->overlay); | 730 | intel_overlay_print_error_state(m, error->overlay); |
| 731 | 731 | ||
| 732 | if (error->display) | ||
| 733 | intel_display_print_error_state(m, dev, error->display); | ||
| 734 | |||
| 732 | out: | 735 | out: |
| 733 | spin_unlock_irqrestore(&dev_priv->error_lock, flags); | 736 | spin_unlock_irqrestore(&dev_priv->error_lock, flags); |
| 734 | 737 | ||
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 826c7237409b..4c20ad92c0f3 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
| @@ -140,6 +140,8 @@ struct sdvo_device_mapping { | |||
| 140 | u8 ddc_pin; | 140 | u8 ddc_pin; |
| 141 | }; | 141 | }; |
| 142 | 142 | ||
| 143 | struct intel_display_error_state; | ||
| 144 | |||
| 143 | struct drm_i915_error_state { | 145 | struct drm_i915_error_state { |
| 144 | u32 eir; | 146 | u32 eir; |
| 145 | u32 pgtbl_er; | 147 | u32 pgtbl_er; |
| @@ -187,6 +189,7 @@ struct drm_i915_error_state { | |||
| 187 | } *active_bo, *pinned_bo; | 189 | } *active_bo, *pinned_bo; |
| 188 | u32 active_bo_count, pinned_bo_count; | 190 | u32 active_bo_count, pinned_bo_count; |
| 189 | struct intel_overlay_error_state *overlay; | 191 | struct intel_overlay_error_state *overlay; |
| 192 | struct intel_display_error_state *display; | ||
| 190 | }; | 193 | }; |
| 191 | 194 | ||
| 192 | struct drm_i915_display_funcs { | 195 | struct drm_i915_display_funcs { |
| @@ -1223,6 +1226,11 @@ extern int intel_trans_dp_port_sel (struct drm_crtc *crtc); | |||
| 1223 | #ifdef CONFIG_DEBUG_FS | 1226 | #ifdef CONFIG_DEBUG_FS |
| 1224 | extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev); | 1227 | extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev); |
| 1225 | extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_overlay_error_state *error); | 1228 | extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_overlay_error_state *error); |
| 1229 | |||
| 1230 | extern struct intel_display_error_state *intel_display_capture_error_state(struct drm_device *dev); | ||
| 1231 | extern void intel_display_print_error_state(struct seq_file *m, | ||
| 1232 | struct drm_device *dev, | ||
| 1233 | struct intel_display_error_state *error); | ||
| 1226 | #endif | 1234 | #endif |
| 1227 | 1235 | ||
| 1228 | /** | 1236 | /** |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index bbcd5da89ba5..0b6052abedd1 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
| @@ -766,6 +766,7 @@ static void i915_capture_error_state(struct drm_device *dev) | |||
| 766 | do_gettimeofday(&error->time); | 766 | do_gettimeofday(&error->time); |
| 767 | 767 | ||
| 768 | error->overlay = intel_overlay_capture_error_state(dev); | 768 | error->overlay = intel_overlay_capture_error_state(dev); |
| 769 | error->display = intel_display_capture_error_state(dev); | ||
| 769 | 770 | ||
| 770 | spin_lock_irqsave(&dev_priv->error_lock, flags); | 771 | spin_lock_irqsave(&dev_priv->error_lock, flags); |
| 771 | if (dev_priv->first_error == NULL) { | 772 | if (dev_priv->first_error == NULL) { |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 886c0e072490..ec2a8b07ba5b 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
| @@ -1193,7 +1193,6 @@ | |||
| 1193 | #define VTOTAL(pipe) _PIPE(pipe, VTOTAL_A, VTOTAL_B) | 1193 | #define VTOTAL(pipe) _PIPE(pipe, VTOTAL_A, VTOTAL_B) |
| 1194 | #define VBLANK(pipe) _PIPE(pipe, VBLANK_A, VBLANK_B) | 1194 | #define VBLANK(pipe) _PIPE(pipe, VBLANK_A, VBLANK_B) |
| 1195 | #define VSYNC(pipe) _PIPE(pipe, VSYNC_A, VSYNC_B) | 1195 | #define VSYNC(pipe) _PIPE(pipe, VSYNC_A, VSYNC_B) |
| 1196 | #define PIPESRC(pipe) _PIPE(pipe, PIPEASRC, PIPEBSRC) | ||
| 1197 | #define BCLRPAT(pipe) _PIPE(pipe, BCLRPAT_A, BCLRPAT_B) | 1196 | #define BCLRPAT(pipe) _PIPE(pipe, BCLRPAT_A, BCLRPAT_B) |
| 1198 | 1197 | ||
| 1199 | /* VGA port control */ | 1198 | /* VGA port control */ |
| @@ -2207,6 +2206,7 @@ | |||
| 2207 | #define PIPE_6BPC (2 << 5) | 2206 | #define PIPE_6BPC (2 << 5) |
| 2208 | #define PIPE_12BPC (3 << 5) | 2207 | #define PIPE_12BPC (3 << 5) |
| 2209 | 2208 | ||
| 2209 | #define PIPESRC(pipe) _PIPE(pipe, PIPEASRC, PIPEBSRC) | ||
| 2210 | #define PIPECONF(pipe) _PIPE(pipe, PIPEACONF, PIPEBCONF) | 2210 | #define PIPECONF(pipe) _PIPE(pipe, PIPEACONF, PIPEBCONF) |
| 2211 | #define PIPEDSL(pipe) _PIPE(pipe, PIPEADSL, PIPEBDSL) | 2211 | #define PIPEDSL(pipe) _PIPE(pipe, PIPEADSL, PIPEBDSL) |
| 2212 | 2212 | ||
| @@ -2376,6 +2376,10 @@ | |||
| 2376 | #define CURBBASE 0x700c4 | 2376 | #define CURBBASE 0x700c4 |
| 2377 | #define CURBPOS 0x700c8 | 2377 | #define CURBPOS 0x700c8 |
| 2378 | 2378 | ||
| 2379 | #define CURCNTR(pipe) _PIPE(pipe, CURACNTR, CURBCNTR) | ||
| 2380 | #define CURBASE(pipe) _PIPE(pipe, CURABASE, CURBBASE) | ||
| 2381 | #define CURPOS(pipe) _PIPE(pipe, CURAPOS, CURBPOS) | ||
| 2382 | |||
| 2379 | /* Display A control */ | 2383 | /* Display A control */ |
| 2380 | #define DSPACNTR 0x70180 | 2384 | #define DSPACNTR 0x70180 |
| 2381 | #define DISPLAY_PLANE_ENABLE (1<<31) | 2385 | #define DISPLAY_PLANE_ENABLE (1<<31) |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3fa5aaa941d2..d4bc443f43fc 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
| @@ -6269,3 +6269,113 @@ int intel_modeset_vga_set_state(struct drm_device *dev, bool state) | |||
| 6269 | pci_write_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, gmch_ctrl); | 6269 | pci_write_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, gmch_ctrl); |
| 6270 | return 0; | 6270 | return 0; |
| 6271 | } | 6271 | } |
| 6272 | |||
| 6273 | #ifdef CONFIG_DEBUG_FS | ||
| 6274 | #include <linux/seq_file.h> | ||
| 6275 | |||
| 6276 | struct intel_display_error_state { | ||
| 6277 | struct intel_cursor_error_state { | ||
| 6278 | u32 control; | ||
| 6279 | u32 position; | ||
| 6280 | u32 base; | ||
| 6281 | u32 size; | ||
| 6282 | } cursor[2]; | ||
| 6283 | |||
| 6284 | struct intel_pipe_error_state { | ||
| 6285 | u32 conf; | ||
| 6286 | u32 source; | ||
| 6287 | |||
| 6288 | u32 htotal; | ||
| 6289 | u32 hblank; | ||
| 6290 | u32 hsync; | ||
| 6291 | u32 vtotal; | ||
| 6292 | u32 vblank; | ||
| 6293 | u32 vsync; | ||
| 6294 | } pipe[2]; | ||
| 6295 | |||
| 6296 | struct intel_plane_error_state { | ||
| 6297 | u32 control; | ||
| 6298 | u32 stride; | ||
| 6299 | u32 size; | ||
| 6300 | u32 pos; | ||
| 6301 | u32 addr; | ||
| 6302 | u32 surface; | ||
| 6303 | u32 tile_offset; | ||
| 6304 | } plane[2]; | ||
| 6305 | }; | ||
| 6306 | |||
| 6307 | struct intel_display_error_state * | ||
| 6308 | intel_display_capture_error_state(struct drm_device *dev) | ||
| 6309 | { | ||
| 6310 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
| 6311 | struct intel_display_error_state *error; | ||
| 6312 | int i; | ||
| 6313 | |||
| 6314 | error = kmalloc(sizeof(*error), GFP_ATOMIC); | ||
| 6315 | if (error == NULL) | ||
| 6316 | return NULL; | ||
| 6317 | |||
| 6318 | for (i = 0; i < 2; i++) { | ||
| 6319 | error->cursor[i].control = I915_READ(CURCNTR(i)); | ||
| 6320 | error->cursor[i].position = I915_READ(CURPOS(i)); | ||
| 6321 | error->cursor[i].base = I915_READ(CURBASE(i)); | ||
| 6322 | |||
| 6323 | error->plane[i].control = I915_READ(DSPCNTR(i)); | ||
| 6324 | error->plane[i].stride = I915_READ(DSPSTRIDE(i)); | ||
| 6325 | error->plane[i].size = I915_READ(DSPSIZE(i)); | ||
| 6326 | error->plane[i].pos= I915_READ(DSPPOS(i)); | ||
| 6327 | error->plane[i].addr = I915_READ(DSPADDR(i)); | ||
| 6328 | if (INTEL_INFO(dev)->gen >= 4) { | ||
| 6329 | error->plane[i].surface = I915_READ(DSPSURF(i)); | ||
| 6330 | error->plane[i].tile_offset = I915_READ(DSPTILEOFF(i)); | ||
| 6331 | } | ||
| 6332 | |||
| 6333 | error->pipe[i].conf = I915_READ(PIPECONF(i)); | ||
| 6334 | error->pipe[i].source = I915_READ(PIPESRC(i)); | ||
| 6335 | error->pipe[i].htotal = I915_READ(HTOTAL(i)); | ||
| 6336 | error->pipe[i].hblank = I915_READ(HBLANK(i)); | ||
| 6337 | error->pipe[i].hsync = I915_READ(HSYNC(i)); | ||
| 6338 | error->pipe[i].vtotal = I915_READ(VTOTAL(i)); | ||
| 6339 | error->pipe[i].vblank = I915_READ(VBLANK(i)); | ||
| 6340 | error->pipe[i].vsync = I915_READ(VSYNC(i)); | ||
| 6341 | } | ||
| 6342 | |||
| 6343 | return error; | ||
| 6344 | } | ||
| 6345 | |||
| 6346 | void | ||
| 6347 | intel_display_print_error_state(struct seq_file *m, | ||
| 6348 | struct drm_device *dev, | ||
| 6349 | struct intel_display_error_state *error) | ||
| 6350 | { | ||
| 6351 | int i; | ||
| 6352 | |||
| 6353 | for (i = 0; i < 2; i++) { | ||
| 6354 | seq_printf(m, "Pipe [%d]:\n", i); | ||
| 6355 | seq_printf(m, " CONF: %08x\n", error->pipe[i].conf); | ||
| 6356 | seq_printf(m, " SRC: %08x\n", error->pipe[i].source); | ||
| 6357 | seq_printf(m, " HTOTAL: %08x\n", error->pipe[i].htotal); | ||
| 6358 | seq_printf(m, " HBLANK: %08x\n", error->pipe[i].hblank); | ||
| 6359 | seq_printf(m, " HSYNC: %08x\n", error->pipe[i].hsync); | ||
| 6360 | seq_printf(m, " VTOTAL: %08x\n", error->pipe[i].vtotal); | ||
| 6361 | seq_printf(m, " VBLANK: %08x\n", error->pipe[i].vblank); | ||
| 6362 | seq_printf(m, " VSYNC: %08x\n", error->pipe[i].vsync); | ||
| 6363 | |||
| 6364 | seq_printf(m, "Plane [%d]:\n", i); | ||
| 6365 | seq_printf(m, " CNTR: %08x\n", error->plane[i].control); | ||
| 6366 | seq_printf(m, " STRIDE: %08x\n", error->plane[i].stride); | ||
| 6367 | seq_printf(m, " SIZE: %08x\n", error->plane[i].size); | ||
| 6368 | seq_printf(m, " POS: %08x\n", error->plane[i].pos); | ||
| 6369 | seq_printf(m, " ADDR: %08x\n", error->plane[i].addr); | ||
| 6370 | if (INTEL_INFO(dev)->gen >= 4) { | ||
| 6371 | seq_printf(m, " SURF: %08x\n", error->plane[i].surface); | ||
| 6372 | seq_printf(m, " TILEOFF: %08x\n", error->plane[i].tile_offset); | ||
| 6373 | } | ||
| 6374 | |||
| 6375 | seq_printf(m, "Cursor [%d]:\n", i); | ||
| 6376 | seq_printf(m, " CNTR: %08x\n", error->cursor[i].control); | ||
| 6377 | seq_printf(m, " POS: %08x\n", error->cursor[i].position); | ||
| 6378 | seq_printf(m, " BASE: %08x\n", error->cursor[i].base); | ||
| 6379 | } | ||
| 6380 | } | ||
| 6381 | #endif | ||
