aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-06-06 07:16:24 -0400
committerEric Anholt <eric@anholt.net>2010-08-01 22:03:46 -0400
commitcbb465e72ae2cf37d252284c28a0d89ddfaaa240 (patch)
tree4ea7d5ba990ca20ebb768b2993ca70e37c56b157
parent0b3400040d189b129e9770b7ea2e38729e3d75c4 (diff)
drm/i915: Include instdone[1] in hangcheck
References: Bug 26691 - Spurious hangcheck whilst executing a long shader over a large vertex buffer https://bugs.freedesktop.org/show_bug.cgi?id=26691 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Eric Anholt <eric@anholt.net>
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h2
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c38
2 files changed, 25 insertions, 15 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 21a4af999191..70e252768ab3 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -286,6 +286,8 @@ typedef struct drm_i915_private {
286 struct timer_list hangcheck_timer; 286 struct timer_list hangcheck_timer;
287 int hangcheck_count; 287 int hangcheck_count;
288 uint32_t last_acthd; 288 uint32_t last_acthd;
289 uint32_t last_instdone;
290 uint32_t last_instdone1;
289 291
290 struct drm_mm vram; 292 struct drm_mm vram;
291 293
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index fb6b46285471..85785a8844ed 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1229,16 +1229,21 @@ void i915_hangcheck_elapsed(unsigned long data)
1229{ 1229{
1230 struct drm_device *dev = (struct drm_device *)data; 1230 struct drm_device *dev = (struct drm_device *)data;
1231 drm_i915_private_t *dev_priv = dev->dev_private; 1231 drm_i915_private_t *dev_priv = dev->dev_private;
1232 uint32_t acthd; 1232 uint32_t acthd, instdone, instdone1;
1233 1233
1234 /* No reset support on this chip yet. */ 1234 /* No reset support on this chip yet. */
1235 if (IS_GEN6(dev)) 1235 if (IS_GEN6(dev))
1236 return; 1236 return;
1237 1237
1238 if (!IS_I965G(dev)) 1238 if (!IS_I965G(dev)) {
1239 acthd = I915_READ(ACTHD); 1239 acthd = I915_READ(ACTHD);
1240 else 1240 instdone = I915_READ(INSTDONE);
1241 instdone1 = 0;
1242 } else {
1241 acthd = I915_READ(ACTHD_I965); 1243 acthd = I915_READ(ACTHD_I965);
1244 instdone = I915_READ(INSTDONE_I965);
1245 instdone1 = I915_READ(INSTDONE1);
1246 }
1242 1247
1243 /* If all work is done then ACTHD clearly hasn't advanced. */ 1248 /* If all work is done then ACTHD clearly hasn't advanced. */
1244 if (list_empty(&dev_priv->render_ring.request_list) || 1249 if (list_empty(&dev_priv->render_ring.request_list) ||
@@ -1249,21 +1254,24 @@ void i915_hangcheck_elapsed(unsigned long data)
1249 return; 1254 return;
1250 } 1255 }
1251 1256
1252 if (dev_priv->last_acthd == acthd && dev_priv->hangcheck_count > 0) { 1257 if (dev_priv->last_acthd == acthd &&
1253 DRM_ERROR("Hangcheck timer elapsed... GPU hung\n"); 1258 dev_priv->last_instdone == instdone &&
1254 i915_handle_error(dev, true); 1259 dev_priv->last_instdone1 == instdone1) {
1255 return; 1260 if (dev_priv->hangcheck_count++ > 1) {
1256 } 1261 DRM_ERROR("Hangcheck timer elapsed... GPU hung\n");
1262 i915_handle_error(dev, true);
1263 return;
1264 }
1265 } else {
1266 dev_priv->hangcheck_count = 0;
1267
1268 dev_priv->last_acthd = acthd;
1269 dev_priv->last_instdone = instdone;
1270 dev_priv->last_instdone1 = instdone1;
1271 }
1257 1272
1258 /* Reset timer case chip hangs without another request being added */ 1273 /* Reset timer case chip hangs without another request being added */
1259 mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); 1274 mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
1260
1261 if (acthd != dev_priv->last_acthd)
1262 dev_priv->hangcheck_count = 0;
1263 else
1264 dev_priv->hangcheck_count++;
1265
1266 dev_priv->last_acthd = acthd;
1267} 1275}
1268 1276
1269/* drm_dma.h hooks 1277/* drm_dma.h hooks