aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_gem.c
diff options
context:
space:
mode:
authorMika Kuoppala <mika.kuoppala@linux.intel.com>2014-01-30 12:04:43 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-02-04 05:57:24 -0500
commitb6b0fac04de9ae9b1559eddf8e9490f3c9a01885 (patch)
tree9f912bd88ae30b6407400f7d5c8a4882ee0a82a6 /drivers/gpu/drm/i915/i915_gem.c
parent94825369fe046696c7b472e14f4f76a63956b2d3 (diff)
drm/i915: Use hangcheck score to find guilty context
With full ppgtt using acthd is not enough to find guilty batch buffer. We get multiple false positives as acthd is per vm. Instead of scanning which vm was running on a ring, to find corressponding context, use a different, simpler, strategy of finding batches that caused gpu hang: If hangcheck has declared ring to be hung, find first non complete request on that ring and claim it was guilty. v2: Rebase Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=73652 Suggested-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Mika Kuoppala <mika.kuoppala@intel.com> Reviewed-by: Ben Widawsky <ben@bwidawsk.net> (v1) Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem.c')
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c42
1 files changed, 29 insertions, 13 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 08331e105f89..37c2ea45f6db 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2332,9 +2332,10 @@ static bool i915_context_is_banned(struct drm_device *dev,
2332 2332
2333static void i915_set_reset_status(struct intel_ring_buffer *ring, 2333static void i915_set_reset_status(struct intel_ring_buffer *ring,
2334 struct drm_i915_gem_request *request, 2334 struct drm_i915_gem_request *request,
2335 u32 acthd) 2335 const bool guilty)
2336{ 2336{
2337 bool inside, guilty; 2337 const u32 acthd = intel_ring_get_active_head(ring);
2338 bool inside;
2338 unsigned long offset = 0; 2339 unsigned long offset = 0;
2339 struct i915_hw_context *ctx = request->ctx; 2340 struct i915_hw_context *ctx = request->ctx;
2340 struct i915_ctx_hang_stats *hs; 2341 struct i915_ctx_hang_stats *hs;
@@ -2342,14 +2343,11 @@ static void i915_set_reset_status(struct intel_ring_buffer *ring,
2342 if (WARN_ON(!ctx)) 2343 if (WARN_ON(!ctx))
2343 return; 2344 return;
2344 2345
2345 /* Innocent until proven guilty */
2346 guilty = false;
2347
2348 if (request->batch_obj) 2346 if (request->batch_obj)
2349 offset = i915_gem_obj_offset(request->batch_obj, 2347 offset = i915_gem_obj_offset(request->batch_obj,
2350 request_to_vm(request)); 2348 request_to_vm(request));
2351 2349
2352 if (ring->hangcheck.action != HANGCHECK_WAIT && 2350 if (guilty &&
2353 i915_request_guilty(request, acthd, &inside)) { 2351 i915_request_guilty(request, acthd, &inside)) {
2354 DRM_DEBUG("%s hung %s bo (0x%lx ctx %d) at 0x%x\n", 2352 DRM_DEBUG("%s hung %s bo (0x%lx ctx %d) at 0x%x\n",
2355 ring->name, 2353 ring->name,
@@ -2357,8 +2355,6 @@ static void i915_set_reset_status(struct intel_ring_buffer *ring,
2357 offset, 2355 offset,
2358 ctx->id, 2356 ctx->id,
2359 acthd); 2357 acthd);
2360
2361 guilty = true;
2362 } 2358 }
2363 2359
2364 WARN_ON(!ctx->last_ring); 2360 WARN_ON(!ctx->last_ring);
@@ -2385,19 +2381,39 @@ static void i915_gem_free_request(struct drm_i915_gem_request *request)
2385 kfree(request); 2381 kfree(request);
2386} 2382}
2387 2383
2388static void i915_gem_reset_ring_status(struct drm_i915_private *dev_priv, 2384static struct drm_i915_gem_request *
2389 struct intel_ring_buffer *ring) 2385i915_gem_find_first_non_complete(struct intel_ring_buffer *ring)
2390{ 2386{
2391 u32 completed_seqno = ring->get_seqno(ring, false);
2392 u32 acthd = intel_ring_get_active_head(ring);
2393 struct drm_i915_gem_request *request; 2387 struct drm_i915_gem_request *request;
2388 const u32 completed_seqno = ring->get_seqno(ring, false);
2394 2389
2395 list_for_each_entry(request, &ring->request_list, list) { 2390 list_for_each_entry(request, &ring->request_list, list) {
2396 if (i915_seqno_passed(completed_seqno, request->seqno)) 2391 if (i915_seqno_passed(completed_seqno, request->seqno))
2397 continue; 2392 continue;
2398 2393
2399 i915_set_reset_status(ring, request, acthd); 2394 return request;
2400 } 2395 }
2396
2397 return NULL;
2398}
2399
2400static void i915_gem_reset_ring_status(struct drm_i915_private *dev_priv,
2401 struct intel_ring_buffer *ring)
2402{
2403 struct drm_i915_gem_request *request;
2404 bool ring_hung;
2405
2406 request = i915_gem_find_first_non_complete(ring);
2407
2408 if (request == NULL)
2409 return;
2410
2411 ring_hung = ring->hangcheck.score >= HANGCHECK_SCORE_RING_HUNG;
2412
2413 i915_set_reset_status(ring, request, ring_hung);
2414
2415 list_for_each_entry_continue(request, &ring->request_list, list)
2416 i915_set_reset_status(ring, request, false);
2401} 2417}
2402 2418
2403static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv, 2419static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv,