drm/i915: Capture pinned buffers on error
authorChris Wilson <chris@chris-wilson.co.uk>
Mon, 22 Nov 2010 08:07:02 +0000 (08:07 +0000)
committerChris Wilson <chris@chris-wilson.co.uk>
Mon, 22 Nov 2010 08:07:02 +0000 (08:07 +0000)
The pinned buffers are useful for diagnosing errors in setting up state
for the chipset, which may not necessarily be 'active' at the time of
the error, e.g. the cursor buffer object.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_irq.c

index 4c8fae9baaadd631ad2c44520d28f43b889377f3..24a88ac632123003870003ee5f0c25ffdfb6e029 100644 (file)
@@ -609,6 +609,36 @@ static const char *purgeable_flag(int purgeable)
        return purgeable ? " purgeable" : "";
 }
 
+static void print_error_buffers(struct seq_file *m,
+                               const char *name,
+                               struct drm_i915_error_buffer *err,
+                               int count)
+{
+       seq_printf(m, "%s [%d]:\n", name, count);
+
+       while (count--) {
+               seq_printf(m, "  %08x %8zd %04x %04x %08x%s%s%s%s%s",
+                          err->gtt_offset,
+                          err->size,
+                          err->read_domains,
+                          err->write_domain,
+                          err->seqno,
+                          pin_flag(err->pinned),
+                          tiling_flag(err->tiling),
+                          dirty_flag(err->dirty),
+                          purgeable_flag(err->purgeable),
+                          ring_str(err->ring));
+
+               if (err->name)
+                       seq_printf(m, " (name: %d)", err->name);
+               if (err->fence_reg != I915_FENCE_REG_NONE)
+                       seq_printf(m, " (fence: %d)", err->fence_reg);
+
+               seq_printf(m, "\n");
+               err++;
+       }
+}
+
 static int i915_error_state(struct seq_file *m, void *unused)
 {
        struct drm_info_node *node = (struct drm_info_node *) m->private;
@@ -658,30 +688,15 @@ static int i915_error_state(struct seq_file *m, void *unused)
        seq_printf(m, "  INSTPM: 0x%08x\n", error->instpm);
        seq_printf(m, "  seqno: 0x%08x\n", error->seqno);
 
-       if (error->active_bo_count) {
-               seq_printf(m, "Buffers [%d]:\n", error->active_bo_count);
-
-               for (i = 0; i < error->active_bo_count; i++) {
-                       seq_printf(m, "  %08x %8zd %08x %08x %08x%s%s%s%s %s",
-                                  error->active_bo[i].gtt_offset,
-                                  error->active_bo[i].size,
-                                  error->active_bo[i].read_domains,
-                                  error->active_bo[i].write_domain,
-                                  error->active_bo[i].seqno,
-                                  pin_flag(error->active_bo[i].pinned),
-                                  tiling_flag(error->active_bo[i].tiling),
-                                  dirty_flag(error->active_bo[i].dirty),
-                                  purgeable_flag(error->active_bo[i].purgeable),
-                                  ring_str(error->active_bo[i].ring));
-
-                       if (error->active_bo[i].name)
-                               seq_printf(m, " (name: %d)", error->active_bo[i].name);
-                       if (error->active_bo[i].fence_reg != I915_FENCE_REG_NONE)
-                               seq_printf(m, " (fence: %d)", error->active_bo[i].fence_reg);
-
-                       seq_printf(m, "\n");
-               }
-       }
+       if (error->active_bo)
+               print_error_buffers(m, "Active",
+                                   error->active_bo,
+                                   error->active_bo_count);
+
+       if (error->pinned_bo)
+               print_error_buffers(m, "Pinned",
+                                   error->pinned_bo,
+                                   error->pinned_bo_count);
 
        for (i = 0; i < ARRAY_SIZE(error->batchbuffer); i++) {
                if (error->batchbuffer[i]) {
index 73a41f7ab8c68fac6ab388f5f4a9173720ce0aca..826c7237409b516713b30433f95a256e90b8eec3 100644 (file)
@@ -184,8 +184,8 @@ struct drm_i915_error_state {
                u32 dirty:1;
                u32 purgeable:1;
                u32 ring:4;
-       } *active_bo;
-       u32 active_bo_count;
+       } *active_bo, *pinned_bo;
+       u32 active_bo_count, pinned_bo_count;
        struct intel_overlay_error_state *overlay;
 };
 
index ef3503733ebb5492c9b9625441f9e597f58de6bc..bbcd5da89ba5e7165a50347561626a33f277d125 100644 (file)
@@ -552,6 +552,40 @@ i915_ringbuffer_last_batch(struct drm_device *dev,
        return bbaddr;
 }
 
+static u32 capture_bo_list(struct drm_i915_error_buffer *err,
+                          int count,
+                          struct list_head *head)
+{
+       struct drm_i915_gem_object *obj;
+       int i = 0;
+
+       list_for_each_entry(obj, head, mm_list) {
+               err->size = obj->base.size;
+               err->name = obj->base.name;
+               err->seqno = obj->last_rendering_seqno;
+               err->gtt_offset = obj->gtt_offset;
+               err->read_domains = obj->base.read_domains;
+               err->write_domain = obj->base.write_domain;
+               err->fence_reg = obj->fence_reg;
+               err->pinned = 0;
+               if (obj->pin_count > 0)
+                       err->pinned = 1;
+               if (obj->user_pin_count > 0)
+                       err->pinned = -1;
+               err->tiling = obj->tiling_mode;
+               err->dirty = obj->dirty;
+               err->purgeable = obj->madv != I915_MADV_WILLNEED;
+               err->ring = obj->ring->id;
+
+               if (++i == count)
+                       break;
+
+               err++;
+       }
+
+       return i;
+}
+
 /**
  * i915_capture_error_state - capture an error record for later analysis
  * @dev: drm device
@@ -700,42 +734,35 @@ static void i915_capture_error_state(struct drm_device *dev)
        error->ringbuffer = i915_error_object_create(dev,
                        dev_priv->render_ring.gem_object);
 
-       /* Record buffers on the active list. */
+       /* Record buffers on the active and pinned lists. */
        error->active_bo = NULL;
-       error->active_bo_count = 0;
+       error->pinned_bo = NULL;
 
-       if (count)
+       error->active_bo_count = count;
+       list_for_each_entry(obj_priv, &dev_priv->mm.pinned_list, mm_list)
+               count++;
+       error->pinned_bo_count = count - error->active_bo_count;
+
+       if (count) {
                error->active_bo = kmalloc(sizeof(*error->active_bo)*count,
                                           GFP_ATOMIC);
-
-       if (error->active_bo) {
-               int i = 0;
-               list_for_each_entry(obj_priv, &dev_priv->mm.active_list, mm_list) {
-                       struct drm_gem_object *obj = &obj_priv->base;
-
-                       error->active_bo[i].size = obj->size;
-                       error->active_bo[i].name = obj->name;
-                       error->active_bo[i].seqno = obj_priv->last_rendering_seqno;
-                       error->active_bo[i].gtt_offset = obj_priv->gtt_offset;
-                       error->active_bo[i].read_domains = obj->read_domains;
-                       error->active_bo[i].write_domain = obj->write_domain;
-                       error->active_bo[i].fence_reg = obj_priv->fence_reg;
-                       error->active_bo[i].pinned = 0;
-                       if (obj_priv->pin_count > 0)
-                               error->active_bo[i].pinned = 1;
-                       if (obj_priv->user_pin_count > 0)
-                               error->active_bo[i].pinned = -1;
-                       error->active_bo[i].tiling = obj_priv->tiling_mode;
-                       error->active_bo[i].dirty = obj_priv->dirty;
-                       error->active_bo[i].purgeable = obj_priv->madv != I915_MADV_WILLNEED;
-                       error->active_bo[i].ring = obj_priv->ring->id;
-
-                       if (++i == count)
-                               break;
-               }
-               error->active_bo_count = i;
+               if (error->active_bo)
+                       error->pinned_bo =
+                               error->active_bo + error->active_bo_count;
        }
 
+       if (error->active_bo)
+               error->active_bo_count =
+                       capture_bo_list(error->active_bo,
+                                       error->active_bo_count,
+                                       &dev_priv->mm.active_list);
+
+       if (error->pinned_bo)
+               error->pinned_bo_count =
+                       capture_bo_list(error->pinned_bo,
+                                       error->pinned_bo_count,
+                                       &dev_priv->mm.pinned_list);
+
        do_gettimeofday(&error->time);
 
        error->overlay = intel_overlay_capture_error_state(dev);