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 4c8fae9..24a88ac 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 73a41f7..826c723 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 ef35037..bbcd5da 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);