diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-08-04 15:26:07 -0400 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2010-08-09 14:24:31 -0400 |
commit | 6ef3d4278034982c13df87c4a51e0445f762d316 (patch) | |
tree | bb67e30d7898a1024d68b5bce4e526b40a2807fd | |
parent | dbd7ac9661ba321fe9c1f1b7cb5f4471a6e59570 (diff) |
drm/i915: Capture the overlay status upon a GPU hang.
v2: Add the interrupt status and address.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Eric Anholt <eric@anholt.net>
-rw-r--r-- | drivers/gpu/drm/i915/i915_debugfs.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_overlay.c | 96 |
4 files changed, 110 insertions, 2 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 9214119c0154..92d5605a34d1 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c | |||
@@ -467,6 +467,9 @@ static int i915_error_state(struct seq_file *m, void *unused) | |||
467 | } | 467 | } |
468 | } | 468 | } |
469 | 469 | ||
470 | if (error->overlay) | ||
471 | intel_overlay_print_error_state(m, error->overlay); | ||
472 | |||
470 | out: | 473 | out: |
471 | spin_unlock_irqrestore(&dev_priv->error_lock, flags); | 474 | spin_unlock_irqrestore(&dev_priv->error_lock, flags); |
472 | 475 | ||
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 5cd593f826ef..151056501a5f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -113,6 +113,9 @@ struct intel_opregion { | |||
113 | int enabled; | 113 | int enabled; |
114 | }; | 114 | }; |
115 | 115 | ||
116 | struct intel_overlay; | ||
117 | struct intel_overlay_error_state; | ||
118 | |||
116 | struct drm_i915_master_private { | 119 | struct drm_i915_master_private { |
117 | drm_local_map_t *sarea; | 120 | drm_local_map_t *sarea; |
118 | struct _drm_i915_sarea *sarea_priv; | 121 | struct _drm_i915_sarea *sarea_priv; |
@@ -166,6 +169,7 @@ struct drm_i915_error_state { | |||
166 | u32 purgeable:1; | 169 | u32 purgeable:1; |
167 | } *active_bo; | 170 | } *active_bo; |
168 | u32 active_bo_count; | 171 | u32 active_bo_count; |
172 | struct intel_overlay_error_state *overlay; | ||
169 | }; | 173 | }; |
170 | 174 | ||
171 | struct drm_i915_display_funcs { | 175 | struct drm_i915_display_funcs { |
@@ -186,8 +190,6 @@ struct drm_i915_display_funcs { | |||
186 | /* clock gating init */ | 190 | /* clock gating init */ |
187 | }; | 191 | }; |
188 | 192 | ||
189 | struct intel_overlay; | ||
190 | |||
191 | struct intel_device_info { | 193 | struct intel_device_info { |
192 | u8 is_mobile : 1; | 194 | u8 is_mobile : 1; |
193 | u8 is_i8xx : 1; | 195 | u8 is_i8xx : 1; |
@@ -1069,6 +1071,10 @@ extern bool ironlake_set_drps(struct drm_device *dev, u8 val); | |||
1069 | extern void intel_detect_pch (struct drm_device *dev); | 1071 | extern void intel_detect_pch (struct drm_device *dev); |
1070 | extern int intel_trans_dp_port_sel (struct drm_crtc *crtc); | 1072 | extern int intel_trans_dp_port_sel (struct drm_crtc *crtc); |
1071 | 1073 | ||
1074 | /* overlay */ | ||
1075 | extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev); | ||
1076 | extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_overlay_error_state *error); | ||
1077 | |||
1072 | /** | 1078 | /** |
1073 | * Lock test for when it's just for synchronization of ring access. | 1079 | * Lock test for when it's just for synchronization of ring access. |
1074 | * | 1080 | * |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 85785a8844ed..854ab1e92fd9 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -489,6 +489,7 @@ i915_error_state_free(struct drm_device *dev, | |||
489 | i915_error_object_free(error->batchbuffer[1]); | 489 | i915_error_object_free(error->batchbuffer[1]); |
490 | i915_error_object_free(error->ringbuffer); | 490 | i915_error_object_free(error->ringbuffer); |
491 | kfree(error->active_bo); | 491 | kfree(error->active_bo); |
492 | kfree(error->overlay); | ||
492 | kfree(error); | 493 | kfree(error); |
493 | } | 494 | } |
494 | 495 | ||
@@ -667,6 +668,8 @@ static void i915_capture_error_state(struct drm_device *dev) | |||
667 | 668 | ||
668 | do_gettimeofday(&error->time); | 669 | do_gettimeofday(&error->time); |
669 | 670 | ||
671 | error->overlay = intel_overlay_capture_error_state(dev); | ||
672 | |||
670 | spin_lock_irqsave(&dev_priv->error_lock, flags); | 673 | spin_lock_irqsave(&dev_priv->error_lock, flags); |
671 | if (dev_priv->first_error == NULL) { | 674 | if (dev_priv->first_error == NULL) { |
672 | dev_priv->first_error = error; | 675 | dev_priv->first_error = error; |
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index d39aea24eabe..9ae61aa05a1f 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c | |||
@@ -1416,3 +1416,99 @@ void intel_cleanup_overlay(struct drm_device *dev) | |||
1416 | kfree(dev_priv->overlay); | 1416 | kfree(dev_priv->overlay); |
1417 | } | 1417 | } |
1418 | } | 1418 | } |
1419 | |||
1420 | struct intel_overlay_error_state { | ||
1421 | struct overlay_registers regs; | ||
1422 | unsigned long base; | ||
1423 | u32 dovsta; | ||
1424 | u32 isr; | ||
1425 | }; | ||
1426 | |||
1427 | struct intel_overlay_error_state * | ||
1428 | intel_overlay_capture_error_state(struct drm_device *dev) | ||
1429 | { | ||
1430 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
1431 | struct intel_overlay *overlay = dev_priv->overlay; | ||
1432 | struct intel_overlay_error_state *error; | ||
1433 | struct overlay_registers __iomem *regs; | ||
1434 | |||
1435 | if (!overlay || !overlay->active) | ||
1436 | return NULL; | ||
1437 | |||
1438 | error = kmalloc(sizeof(*error), GFP_ATOMIC); | ||
1439 | if (error == NULL) | ||
1440 | return NULL; | ||
1441 | |||
1442 | error->dovsta = I915_READ(DOVSTA); | ||
1443 | error->isr = I915_READ(ISR); | ||
1444 | if (OVERLAY_NONPHYSICAL(overlay->dev)) | ||
1445 | error->base = (long) overlay->reg_bo->gtt_offset; | ||
1446 | else | ||
1447 | error->base = (long) overlay->reg_bo->phys_obj->handle->vaddr; | ||
1448 | |||
1449 | regs = intel_overlay_map_regs_atomic(overlay); | ||
1450 | if (!regs) | ||
1451 | goto err; | ||
1452 | |||
1453 | memcpy_fromio(&error->regs, regs, sizeof(struct overlay_registers)); | ||
1454 | intel_overlay_unmap_regs_atomic(overlay); | ||
1455 | |||
1456 | return error; | ||
1457 | |||
1458 | err: | ||
1459 | kfree(error); | ||
1460 | return NULL; | ||
1461 | } | ||
1462 | |||
1463 | void | ||
1464 | intel_overlay_print_error_state(struct seq_file *m, struct intel_overlay_error_state *error) | ||
1465 | { | ||
1466 | seq_printf(m, "Overlay, status: 0x%08x, interrupt: 0x%08x\n", | ||
1467 | error->dovsta, error->isr); | ||
1468 | seq_printf(m, " Register file at 0x%08lx:\n", | ||
1469 | error->base); | ||
1470 | |||
1471 | #define P(x) seq_printf(m, " " #x ": 0x%08x\n", error->regs.x) | ||
1472 | P(OBUF_0Y); | ||
1473 | P(OBUF_1Y); | ||
1474 | P(OBUF_0U); | ||
1475 | P(OBUF_0V); | ||
1476 | P(OBUF_1U); | ||
1477 | P(OBUF_1V); | ||
1478 | P(OSTRIDE); | ||
1479 | P(YRGB_VPH); | ||
1480 | P(UV_VPH); | ||
1481 | P(HORZ_PH); | ||
1482 | P(INIT_PHS); | ||
1483 | P(DWINPOS); | ||
1484 | P(DWINSZ); | ||
1485 | P(SWIDTH); | ||
1486 | P(SWIDTHSW); | ||
1487 | P(SHEIGHT); | ||
1488 | P(YRGBSCALE); | ||
1489 | P(UVSCALE); | ||
1490 | P(OCLRC0); | ||
1491 | P(OCLRC1); | ||
1492 | P(DCLRKV); | ||
1493 | P(DCLRKM); | ||
1494 | P(SCLRKVH); | ||
1495 | P(SCLRKVL); | ||
1496 | P(SCLRKEN); | ||
1497 | P(OCONFIG); | ||
1498 | P(OCMD); | ||
1499 | P(OSTART_0Y); | ||
1500 | P(OSTART_1Y); | ||
1501 | P(OSTART_0U); | ||
1502 | P(OSTART_0V); | ||
1503 | P(OSTART_1U); | ||
1504 | P(OSTART_1V); | ||
1505 | P(OTILEOFF_0Y); | ||
1506 | P(OTILEOFF_1Y); | ||
1507 | P(OTILEOFF_0U); | ||
1508 | P(OTILEOFF_0V); | ||
1509 | P(OTILEOFF_1U); | ||
1510 | P(OTILEOFF_1V); | ||
1511 | P(FASTHSCALE); | ||
1512 | P(UVSCALEV); | ||
1513 | #undef P | ||
1514 | } | ||