aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Widawsky <ben@bwidawsk.net>2013-03-04 20:00:29 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-03-05 03:38:22 -0500
commit8c123e549fd1533f371b7877d4c0458ba3a30b22 (patch)
tree12584be660620a36d7161f2c951bea81a3122f5f
parent4f3a8bc7ba6e34403f36e600bc6f54cf0e0041e4 (diff)
drm/i915: Capture current context on error
On error, this represents the state of the currently running context at the time it was loaded. Unfortunately, since we're hung and can't switch out the context this may not tell us too much about the most current state of the context, but does give clues about what has happened since loading. Thanks to recent doc updates, we have a little more confidence regarding what is actually in this memory, and perhaps it will help us gain more insight into certain bugs. AFAICT, the most interesting info is in the first page. To save space, we only capture the first page. In the future, we might want to dump more. Sample of the relevant part of error state: render ring --- HW Context = 0x01b20000 [0000] 00000000 1100105f 00002028 ffff0880 [0010] 0000209c feff4040 000020c0 efdf0080 [0020] 00002178 00000001 0000217c 00145855 [0030] 00002310 00000000 00002314 00000000 v2: Move error collection to the ring error code Change format of dump to not confuse intel_error_decode (Chris) Put the context error object with the others (Chris) Don't search bound_list instead of active_list (chris) v3: extract and flatten context recording (daniel) checkpatch related fixes for the copypasta in debugfs v4: bug in v3 (Daniel) - if ((ring->id == RCS) && error->ccid) + if ((ring->id != RCS) || !error->ccid) References: https://bugs.freedesktop.org/show_bug.cgi?id=55845 Reviewed-by (v2): Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Ben Widawsky <ben@bwidawsk.net> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> [danvet: Bikeshed away the redudant parenthese around ring->id != RCS] Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c17
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h2
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c23
3 files changed, 41 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 7c65ab83914a..c92ae7ff4718 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -772,6 +772,23 @@ static int i915_error_state(struct seq_file *m, void *unused)
772 } 772 }
773 } 773 }
774 } 774 }
775
776 obj = error->ring[i].ctx;
777 if (obj) {
778 seq_printf(m, "%s --- HW Context = 0x%08x\n",
779 dev_priv->ring[i].name,
780 obj->gtt_offset);
781 offset = 0;
782 for (elt = 0; elt < PAGE_SIZE/16; elt += 4) {
783 seq_printf(m, "[%04x] %08x %08x %08x %08x\n",
784 offset,
785 obj->pages[0][elt],
786 obj->pages[0][elt+1],
787 obj->pages[0][elt+2],
788 obj->pages[0][elt+3]);
789 offset += 16;
790 }
791 }
775 } 792 }
776 793
777 if (error->overlay) 794 if (error->overlay)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 669a535e82f3..ca6b215c090c 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -243,7 +243,7 @@ struct drm_i915_error_state {
243 int page_count; 243 int page_count;
244 u32 gtt_offset; 244 u32 gtt_offset;
245 u32 *pages[0]; 245 u32 *pages[0];
246 } *ringbuffer, *batchbuffer; 246 } *ringbuffer, *batchbuffer, *ctx;
247 struct drm_i915_error_request { 247 struct drm_i915_error_request {
248 long jiffies; 248 long jiffies;
249 u32 seqno; 249 u32 seqno;
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 12561f2f7fd7..2139714b2a67 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1242,6 +1242,26 @@ static void i915_record_ring_state(struct drm_device *dev,
1242 error->cpu_ring_tail[ring->id] = ring->tail; 1242 error->cpu_ring_tail[ring->id] = ring->tail;
1243} 1243}
1244 1244
1245
1246static void i915_gem_record_active_context(struct intel_ring_buffer *ring,
1247 struct drm_i915_error_state *error,
1248 struct drm_i915_error_ring *ering)
1249{
1250 struct drm_i915_private *dev_priv = ring->dev->dev_private;
1251 struct drm_i915_gem_object *obj;
1252
1253 /* Currently render ring is the only HW context user */
1254 if (ring->id != RCS || !error->ccid)
1255 return;
1256
1257 list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list) {
1258 if ((error->ccid & PAGE_MASK) == obj->gtt_offset) {
1259 ering->ctx = i915_error_object_create_sized(dev_priv,
1260 obj, 1);
1261 }
1262 }
1263}
1264
1245static void i915_gem_record_rings(struct drm_device *dev, 1265static void i915_gem_record_rings(struct drm_device *dev,
1246 struct drm_i915_error_state *error) 1266 struct drm_i915_error_state *error)
1247{ 1267{
@@ -1259,6 +1279,9 @@ static void i915_gem_record_rings(struct drm_device *dev,
1259 error->ring[i].ringbuffer = 1279 error->ring[i].ringbuffer =
1260 i915_error_object_create(dev_priv, ring->obj); 1280 i915_error_object_create(dev_priv, ring->obj);
1261 1281
1282
1283 i915_gem_record_active_context(ring, error, &error->ring[i]);
1284
1262 count = 0; 1285 count = 0;
1263 list_for_each_entry(request, &ring->request_list, list) 1286 list_for_each_entry(request, &ring->request_list, list)
1264 count++; 1287 count++;