Commit 097354eb authored by Daniel Vetter's avatar Daniel Vetter Committed by Keith Packard

drm/i915: check ACTHD of all rings

Otherwise hangcheck spuriously fires when running blitter/bsd-only
workloads.

Contrary to a similar patch by Ben Widawsky this does not check
INSTDONE of the other rings. Chris Wilson implied that in a failure to
detect a hang, most likely because INSTDONE was fluctuating. Thus only
check ACTHD, which as far as I know is rather reliable. Also, blitter
and bsd rings can't launch complex tasks from a single instruction
(like 3D_PRIM on the render with complex or even infinite shaders).

This fixes spurious gpu hang detection when running
tests/gem_hangcheck_forcewake on snb/ivb.
Signed-Off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Reviewed-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: default avatarKeith Packard <keithp@keithp.com>
parent 832afda6
...@@ -337,6 +337,8 @@ typedef struct drm_i915_private { ...@@ -337,6 +337,8 @@ typedef struct drm_i915_private {
struct timer_list hangcheck_timer; struct timer_list hangcheck_timer;
int hangcheck_count; int hangcheck_count;
uint32_t last_acthd; uint32_t last_acthd;
uint32_t last_acthd_bsd;
uint32_t last_acthd_blt;
uint32_t last_instdone; uint32_t last_instdone;
uint32_t last_instdone1; uint32_t last_instdone1;
......
...@@ -1669,7 +1669,7 @@ void i915_hangcheck_elapsed(unsigned long data) ...@@ -1669,7 +1669,7 @@ void i915_hangcheck_elapsed(unsigned long data)
{ {
struct drm_device *dev = (struct drm_device *)data; struct drm_device *dev = (struct drm_device *)data;
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
uint32_t acthd, instdone, instdone1; uint32_t acthd, instdone, instdone1, acthd_bsd, acthd_blt;
bool err = false; bool err = false;
if (!i915_enable_hangcheck) if (!i915_enable_hangcheck)
...@@ -1686,16 +1686,21 @@ void i915_hangcheck_elapsed(unsigned long data) ...@@ -1686,16 +1686,21 @@ void i915_hangcheck_elapsed(unsigned long data)
} }
if (INTEL_INFO(dev)->gen < 4) { if (INTEL_INFO(dev)->gen < 4) {
acthd = I915_READ(ACTHD);
instdone = I915_READ(INSTDONE); instdone = I915_READ(INSTDONE);
instdone1 = 0; instdone1 = 0;
} else { } else {
acthd = I915_READ(ACTHD_I965);
instdone = I915_READ(INSTDONE_I965); instdone = I915_READ(INSTDONE_I965);
instdone1 = I915_READ(INSTDONE1); instdone1 = I915_READ(INSTDONE1);
} }
acthd = intel_ring_get_active_head(&dev_priv->ring[RCS]);
acthd_bsd = HAS_BSD(dev) ?
intel_ring_get_active_head(&dev_priv->ring[VCS]) : 0;
acthd_blt = HAS_BLT(dev) ?
intel_ring_get_active_head(&dev_priv->ring[BCS]) : 0;
if (dev_priv->last_acthd == acthd && if (dev_priv->last_acthd == acthd &&
dev_priv->last_acthd_bsd == acthd_bsd &&
dev_priv->last_acthd_blt == acthd_blt &&
dev_priv->last_instdone == instdone && dev_priv->last_instdone == instdone &&
dev_priv->last_instdone1 == instdone1) { dev_priv->last_instdone1 == instdone1) {
if (dev_priv->hangcheck_count++ > 1) { if (dev_priv->hangcheck_count++ > 1) {
...@@ -1727,6 +1732,8 @@ void i915_hangcheck_elapsed(unsigned long data) ...@@ -1727,6 +1732,8 @@ void i915_hangcheck_elapsed(unsigned long data)
dev_priv->hangcheck_count = 0; dev_priv->hangcheck_count = 0;
dev_priv->last_acthd = acthd; dev_priv->last_acthd = acthd;
dev_priv->last_acthd_bsd = acthd_bsd;
dev_priv->last_acthd_blt = acthd_blt;
dev_priv->last_instdone = instdone; dev_priv->last_instdone = instdone;
dev_priv->last_instdone1 = instdone1; dev_priv->last_instdone1 = instdone1;
} }
......
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