diff options
author | Mika Kuoppala <mika.kuoppala@linux.intel.com> | 2013-05-24 10:16:07 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2013-05-31 14:53:54 -0400 |
commit | 92cab7345131db7af18f630a799ce6b2e8e624c5 (patch) | |
tree | d61c1ac94941db3bdcbbae8753a2864557ed0b67 | |
parent | 79ee20dc85072b0edfb5e461799d192a9cc9d422 (diff) |
drm/i915: track ring progression using seqnos
Instead of relying in acthd, track ring seqno progression
to detect if ring has hung.
v2: put hangcheck stuff inside struct (Chris Wilson)
v3: initialize hangcheck.seqno (Ben Widawsky)
Signed-off-by: Mika Kuoppala <mika.kuoppala@intel.com>
Reviewed-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 30 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_ringbuffer.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_ringbuffer.h | 6 |
4 files changed, 20 insertions, 19 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e09c54c73a22..e417049ea581 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -842,8 +842,6 @@ struct i915_gpu_error { | |||
842 | #define DRM_I915_HANGCHECK_JIFFIES msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD) | 842 | #define DRM_I915_HANGCHECK_JIFFIES msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD) |
843 | struct timer_list hangcheck_timer; | 843 | struct timer_list hangcheck_timer; |
844 | int hangcheck_count; | 844 | int hangcheck_count; |
845 | uint32_t last_acthd[I915_NUM_RINGS]; | ||
846 | uint32_t prev_instdone[I915_NUM_INSTDONE_REG]; | ||
847 | 845 | ||
848 | /* For reset and error_state handling. */ | 846 | /* For reset and error_state handling. */ |
849 | spinlock_t lock; | 847 | spinlock_t lock; |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 0e5c9b0cc5a6..004ad3455992 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -2384,22 +2384,19 @@ void i915_hangcheck_elapsed(unsigned long data) | |||
2384 | { | 2384 | { |
2385 | struct drm_device *dev = (struct drm_device *)data; | 2385 | struct drm_device *dev = (struct drm_device *)data; |
2386 | drm_i915_private_t *dev_priv = dev->dev_private; | 2386 | drm_i915_private_t *dev_priv = dev->dev_private; |
2387 | uint32_t acthd[I915_NUM_RINGS], instdone[I915_NUM_INSTDONE_REG]; | ||
2388 | struct intel_ring_buffer *ring; | 2387 | struct intel_ring_buffer *ring; |
2389 | bool err = false, idle; | 2388 | bool err = false, idle; |
2390 | int i; | 2389 | int i; |
2390 | u32 seqno[I915_NUM_RINGS]; | ||
2391 | bool work_done; | ||
2391 | 2392 | ||
2392 | if (!i915_enable_hangcheck) | 2393 | if (!i915_enable_hangcheck) |
2393 | return; | 2394 | return; |
2394 | 2395 | ||
2395 | memset(acthd, 0, sizeof(acthd)); | ||
2396 | idle = true; | 2396 | idle = true; |
2397 | for_each_ring(ring, dev_priv, i) { | 2397 | for_each_ring(ring, dev_priv, i) { |
2398 | u32 seqno; | 2398 | seqno[i] = ring->get_seqno(ring, false); |
2399 | 2399 | idle &= i915_hangcheck_ring_idle(ring, seqno[i], &err); | |
2400 | seqno = ring->get_seqno(ring, false); | ||
2401 | idle &= i915_hangcheck_ring_idle(ring, seqno, &err); | ||
2402 | acthd[i] = intel_ring_get_active_head(ring); | ||
2403 | } | 2400 | } |
2404 | 2401 | ||
2405 | /* If all work is done then ACTHD clearly hasn't advanced. */ | 2402 | /* If all work is done then ACTHD clearly hasn't advanced. */ |
@@ -2415,20 +2412,19 @@ void i915_hangcheck_elapsed(unsigned long data) | |||
2415 | return; | 2412 | return; |
2416 | } | 2413 | } |
2417 | 2414 | ||
2418 | i915_get_extra_instdone(dev, instdone); | 2415 | work_done = false; |
2419 | if (memcmp(dev_priv->gpu_error.last_acthd, acthd, | 2416 | for_each_ring(ring, dev_priv, i) { |
2420 | sizeof(acthd)) == 0 && | 2417 | if (ring->hangcheck.seqno != seqno[i]) { |
2421 | memcmp(dev_priv->gpu_error.prev_instdone, instdone, | 2418 | work_done = true; |
2422 | sizeof(instdone)) == 0) { | 2419 | ring->hangcheck.seqno = seqno[i]; |
2420 | } | ||
2421 | } | ||
2422 | |||
2423 | if (!work_done) { | ||
2423 | if (i915_hangcheck_hung(dev)) | 2424 | if (i915_hangcheck_hung(dev)) |
2424 | return; | 2425 | return; |
2425 | } else { | 2426 | } else { |
2426 | dev_priv->gpu_error.hangcheck_count = 0; | 2427 | dev_priv->gpu_error.hangcheck_count = 0; |
2427 | |||
2428 | memcpy(dev_priv->gpu_error.last_acthd, acthd, | ||
2429 | sizeof(acthd)); | ||
2430 | memcpy(dev_priv->gpu_error.prev_instdone, instdone, | ||
2431 | sizeof(instdone)); | ||
2432 | } | 2428 | } |
2433 | 2429 | ||
2434 | repeat: | 2430 | repeat: |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 3d2c236e15ab..5698faeee6f6 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c | |||
@@ -1502,6 +1502,7 @@ void intel_ring_init_seqno(struct intel_ring_buffer *ring, u32 seqno) | |||
1502 | } | 1502 | } |
1503 | 1503 | ||
1504 | ring->set_seqno(ring, seqno); | 1504 | ring->set_seqno(ring, seqno); |
1505 | ring->hangcheck.seqno = seqno; | ||
1505 | } | 1506 | } |
1506 | 1507 | ||
1507 | void intel_ring_advance(struct intel_ring_buffer *ring) | 1508 | void intel_ring_advance(struct intel_ring_buffer *ring) |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index dac1614a1bca..ef374a892105 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h | |||
@@ -37,6 +37,10 @@ struct intel_hw_status_page { | |||
37 | #define I915_READ_SYNC_0(ring) I915_READ(RING_SYNC_0((ring)->mmio_base)) | 37 | #define I915_READ_SYNC_0(ring) I915_READ(RING_SYNC_0((ring)->mmio_base)) |
38 | #define I915_READ_SYNC_1(ring) I915_READ(RING_SYNC_1((ring)->mmio_base)) | 38 | #define I915_READ_SYNC_1(ring) I915_READ(RING_SYNC_1((ring)->mmio_base)) |
39 | 39 | ||
40 | struct intel_ring_hangcheck { | ||
41 | u32 seqno; | ||
42 | }; | ||
43 | |||
40 | struct intel_ring_buffer { | 44 | struct intel_ring_buffer { |
41 | const char *name; | 45 | const char *name; |
42 | enum intel_ring_id { | 46 | enum intel_ring_id { |
@@ -137,6 +141,8 @@ struct intel_ring_buffer { | |||
137 | struct i915_hw_context *default_context; | 141 | struct i915_hw_context *default_context; |
138 | struct i915_hw_context *last_context; | 142 | struct i915_hw_context *last_context; |
139 | 143 | ||
144 | struct intel_ring_hangcheck hangcheck; | ||
145 | |||
140 | void *private; | 146 | void *private; |
141 | }; | 147 | }; |
142 | 148 | ||