Commit c724e8a9 authored by Chris Wilson's avatar Chris Wilson

drm/i915: Capture pinned buffers on error

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: default avatarChris Wilson <chris@chris-wilson.co.uk>
parent 3143a2bf
......@@ -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);
if (error->active_bo)
print_error_buffers(m, "Active",
error->active_bo,
error->active_bo_count);
seq_printf(m, "\n");
}
}
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]) {
......
......@@ -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;
};
......
......@@ -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,41 +734,34 @@ 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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment