Commit 6ef3d427 authored by Chris Wilson's avatar Chris Wilson Committed by Eric Anholt

drm/i915: Capture the overlay status upon a GPU hang.

v2: Add the interrupt status and address.
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: default avatarEric Anholt <eric@anholt.net>
parent dbd7ac96
...@@ -467,6 +467,9 @@ static int i915_error_state(struct seq_file *m, void *unused) ...@@ -467,6 +467,9 @@ static int i915_error_state(struct seq_file *m, void *unused)
} }
} }
if (error->overlay)
intel_overlay_print_error_state(m, error->overlay);
out: out:
spin_unlock_irqrestore(&dev_priv->error_lock, flags); spin_unlock_irqrestore(&dev_priv->error_lock, flags);
......
...@@ -113,6 +113,9 @@ struct intel_opregion { ...@@ -113,6 +113,9 @@ struct intel_opregion {
int enabled; int enabled;
}; };
struct intel_overlay;
struct intel_overlay_error_state;
struct drm_i915_master_private { struct drm_i915_master_private {
drm_local_map_t *sarea; drm_local_map_t *sarea;
struct _drm_i915_sarea *sarea_priv; struct _drm_i915_sarea *sarea_priv;
...@@ -166,6 +169,7 @@ struct drm_i915_error_state { ...@@ -166,6 +169,7 @@ struct drm_i915_error_state {
u32 purgeable:1; u32 purgeable:1;
} *active_bo; } *active_bo;
u32 active_bo_count; u32 active_bo_count;
struct intel_overlay_error_state *overlay;
}; };
struct drm_i915_display_funcs { struct drm_i915_display_funcs {
...@@ -186,8 +190,6 @@ struct drm_i915_display_funcs { ...@@ -186,8 +190,6 @@ struct drm_i915_display_funcs {
/* clock gating init */ /* clock gating init */
}; };
struct intel_overlay;
struct intel_device_info { struct intel_device_info {
u8 is_mobile : 1; u8 is_mobile : 1;
u8 is_i8xx : 1; u8 is_i8xx : 1;
...@@ -1069,6 +1071,10 @@ extern bool ironlake_set_drps(struct drm_device *dev, u8 val); ...@@ -1069,6 +1071,10 @@ extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
extern void intel_detect_pch (struct drm_device *dev); extern void intel_detect_pch (struct drm_device *dev);
extern int intel_trans_dp_port_sel (struct drm_crtc *crtc); 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. * Lock test for when it's just for synchronization of ring access.
* *
......
...@@ -489,6 +489,7 @@ i915_error_state_free(struct drm_device *dev, ...@@ -489,6 +489,7 @@ i915_error_state_free(struct drm_device *dev,
i915_error_object_free(error->batchbuffer[1]); i915_error_object_free(error->batchbuffer[1]);
i915_error_object_free(error->ringbuffer); i915_error_object_free(error->ringbuffer);
kfree(error->active_bo); kfree(error->active_bo);
kfree(error->overlay);
kfree(error); kfree(error);
} }
...@@ -667,6 +668,8 @@ static void i915_capture_error_state(struct drm_device *dev) ...@@ -667,6 +668,8 @@ static void i915_capture_error_state(struct drm_device *dev)
do_gettimeofday(&error->time); do_gettimeofday(&error->time);
error->overlay = intel_overlay_capture_error_state(dev);
spin_lock_irqsave(&dev_priv->error_lock, flags); spin_lock_irqsave(&dev_priv->error_lock, flags);
if (dev_priv->first_error == NULL) { if (dev_priv->first_error == NULL) {
dev_priv->first_error = error; dev_priv->first_error = error;
......
...@@ -1416,3 +1416,99 @@ void intel_cleanup_overlay(struct drm_device *dev) ...@@ -1416,3 +1416,99 @@ void intel_cleanup_overlay(struct drm_device *dev)
kfree(dev_priv->overlay); kfree(dev_priv->overlay);
} }
} }
struct intel_overlay_error_state {
struct overlay_registers regs;
unsigned long base;
u32 dovsta;
u32 isr;
};
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 *overlay = dev_priv->overlay;
struct intel_overlay_error_state *error;
struct overlay_registers __iomem *regs;
if (!overlay || !overlay->active)
return NULL;
error = kmalloc(sizeof(*error), GFP_ATOMIC);
if (error == NULL)
return NULL;
error->dovsta = I915_READ(DOVSTA);
error->isr = I915_READ(ISR);
if (OVERLAY_NONPHYSICAL(overlay->dev))
error->base = (long) overlay->reg_bo->gtt_offset;
else
error->base = (long) overlay->reg_bo->phys_obj->handle->vaddr;
regs = intel_overlay_map_regs_atomic(overlay);
if (!regs)
goto err;
memcpy_fromio(&error->regs, regs, sizeof(struct overlay_registers));
intel_overlay_unmap_regs_atomic(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, interrupt: 0x%08x\n",
error->dovsta, error->isr);
seq_printf(m, " Register file at 0x%08lx:\n",
error->base);
#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);
P(OSTART_1Y);
P(OSTART_0U);
P(OSTART_0V);
P(OSTART_1U);
P(OSTART_1V);
P(OTILEOFF_0Y);
P(OTILEOFF_1Y);
P(OTILEOFF_0U);
P(OTILEOFF_0V);
P(OTILEOFF_1U);
P(OTILEOFF_1V);
P(FASTHSCALE);
P(UVSCALEV);
#undef P
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment