Commit 2bd160a1 authored by Chris Wilson's avatar Chris Wilson

drm/i915: Reduce i915_gem_objects to only show object information

No longer is knowing how much of the GTT (both mappable aperture and
beyond) relevant, and the output clutters the real information - that is
how many objects are allocated and bound (and by who) so that we can
quickly grasp if there is a leak.

v2: Relent, and rename pinned to indicate display only. Since the
display objects are semi-static and are of variable size, they are the
interesting objects to watch over time for aperture leaking. The other
pins are either static (such as the scratch page) or very short lived
(such as execbuf) and not part of the precious GGTT.
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/1471254551-25805-6-git-send-email-chris@chris-wilson.co.uk
parent 6da84829
...@@ -269,17 +269,6 @@ static int i915_gem_stolen_list_info(struct seq_file *m, void *data) ...@@ -269,17 +269,6 @@ static int i915_gem_stolen_list_info(struct seq_file *m, void *data)
return 0; return 0;
} }
#define count_objects(list, member) do { \
list_for_each_entry(obj, list, member) { \
size += i915_gem_obj_total_ggtt_size(obj); \
++count; \
if (obj->map_and_fenceable) { \
mappable_size += i915_gem_obj_ggtt_size(obj); \
++mappable_count; \
} \
} \
} while (0)
struct file_stats { struct file_stats {
struct drm_i915_file_private *file_priv; struct drm_i915_file_private *file_priv;
unsigned long count; unsigned long count;
...@@ -394,30 +383,16 @@ static void print_context_stats(struct seq_file *m, ...@@ -394,30 +383,16 @@ static void print_context_stats(struct seq_file *m,
print_file_stats(m, "[k]contexts", stats); print_file_stats(m, "[k]contexts", stats);
} }
#define count_vmas(list, member) do { \
list_for_each_entry(vma, list, member) { \
size += i915_gem_obj_total_ggtt_size(vma->obj); \
++count; \
if (vma->obj->map_and_fenceable) { \
mappable_size += i915_gem_obj_ggtt_size(vma->obj); \
++mappable_count; \
} \
} \
} while (0)
static int i915_gem_object_info(struct seq_file *m, void* data) static int i915_gem_object_info(struct seq_file *m, void* data)
{ {
struct drm_info_node *node = m->private; struct drm_info_node *node = m->private;
struct drm_device *dev = node->minor->dev; struct drm_device *dev = node->minor->dev;
struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt; struct i915_ggtt *ggtt = &dev_priv->ggtt;
u32 count, mappable_count, purgeable_count; u32 count, mapped_count, purgeable_count, dpy_count;
u64 size, mappable_size, purgeable_size; u64 size, mapped_size, purgeable_size, dpy_size;
unsigned long pin_mapped_count = 0, pin_mapped_purgeable_count = 0;
u64 pin_mapped_size = 0, pin_mapped_purgeable_size = 0;
struct drm_i915_gem_object *obj; struct drm_i915_gem_object *obj;
struct drm_file *file; struct drm_file *file;
struct i915_vma *vma;
int ret; int ret;
ret = mutex_lock_interruptible(&dev->struct_mutex); ret = mutex_lock_interruptible(&dev->struct_mutex);
...@@ -428,70 +403,51 @@ static int i915_gem_object_info(struct seq_file *m, void* data) ...@@ -428,70 +403,51 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
dev_priv->mm.object_count, dev_priv->mm.object_count,
dev_priv->mm.object_memory); dev_priv->mm.object_memory);
size = count = mappable_size = mappable_count = 0;
count_objects(&dev_priv->mm.bound_list, global_list);
seq_printf(m, "%u [%u] objects, %llu [%llu] bytes in gtt\n",
count, mappable_count, size, mappable_size);
size = count = mappable_size = mappable_count = 0;
count_vmas(&ggtt->base.active_list, vm_link);
seq_printf(m, " %u [%u] active objects, %llu [%llu] bytes\n",
count, mappable_count, size, mappable_size);
size = count = mappable_size = mappable_count = 0;
count_vmas(&ggtt->base.inactive_list, vm_link);
seq_printf(m, " %u [%u] inactive objects, %llu [%llu] bytes\n",
count, mappable_count, size, mappable_size);
size = count = purgeable_size = purgeable_count = 0; size = count = purgeable_size = purgeable_count = 0;
list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list) { list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list) {
size += obj->base.size, ++count; size += obj->base.size;
if (obj->madv == I915_MADV_DONTNEED) ++count;
purgeable_size += obj->base.size, ++purgeable_count;
if (obj->madv == I915_MADV_DONTNEED) {
purgeable_size += obj->base.size;
++purgeable_count;
}
if (obj->mapping) { if (obj->mapping) {
pin_mapped_count++; mapped_count++;
pin_mapped_size += obj->base.size; mapped_size += obj->base.size;
if (obj->pages_pin_count == 0) {
pin_mapped_purgeable_count++;
pin_mapped_purgeable_size += obj->base.size;
}
} }
} }
seq_printf(m, "%u unbound objects, %llu bytes\n", count, size); seq_printf(m, "%u unbound objects, %llu bytes\n", count, size);
size = count = mappable_size = mappable_count = 0; size = count = dpy_size = dpy_count = 0;
list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
if (obj->fault_mappable) { size += obj->base.size;
size += i915_gem_obj_ggtt_size(obj); ++count;
++count;
}
if (obj->pin_display) { if (obj->pin_display) {
mappable_size += i915_gem_obj_ggtt_size(obj); dpy_size += obj->base.size;
++mappable_count; ++dpy_count;
} }
if (obj->madv == I915_MADV_DONTNEED) { if (obj->madv == I915_MADV_DONTNEED) {
purgeable_size += obj->base.size; purgeable_size += obj->base.size;
++purgeable_count; ++purgeable_count;
} }
if (obj->mapping) { if (obj->mapping) {
pin_mapped_count++; mapped_count++;
pin_mapped_size += obj->base.size; mapped_size += obj->base.size;
if (obj->pages_pin_count == 0) {
pin_mapped_purgeable_count++;
pin_mapped_purgeable_size += obj->base.size;
}
} }
} }
seq_printf(m, "%u bound objects, %llu bytes\n",
count, size);
seq_printf(m, "%u purgeable objects, %llu bytes\n", seq_printf(m, "%u purgeable objects, %llu bytes\n",
purgeable_count, purgeable_size); purgeable_count, purgeable_size);
seq_printf(m, "%u pinned mappable objects, %llu bytes\n", seq_printf(m, "%u mapped objects, %llu bytes\n",
mappable_count, mappable_size); mapped_count, mapped_size);
seq_printf(m, "%u fault mappable objects, %llu bytes\n", seq_printf(m, "%u display objects (pinned), %llu bytes\n",
count, size); dpy_count, dpy_size);
seq_printf(m,
"%lu [%lu] pin mapped objects, %llu [%llu] bytes [purgeable]\n",
pin_mapped_count, pin_mapped_purgeable_count,
pin_mapped_size, pin_mapped_purgeable_size);
seq_printf(m, "%llu [%llu] gtt total\n", seq_printf(m, "%llu [%llu] gtt total\n",
ggtt->base.total, ggtt->mappable_end - ggtt->base.start); ggtt->base.total, ggtt->mappable_end - ggtt->base.start);
......
...@@ -475,130 +475,6 @@ struct sdvo_device_mapping { ...@@ -475,130 +475,6 @@ struct sdvo_device_mapping {
u8 ddc_pin; u8 ddc_pin;
}; };
struct intel_display_error_state;
struct drm_i915_error_state {
struct kref ref;
struct timeval time;
char error_msg[128];
bool simulated;
int iommu;
u32 reset_count;
u32 suspend_count;
/* Generic register state */
u32 eir;
u32 pgtbl_er;
u32 ier;
u32 gtier[4];
u32 ccid;
u32 derrmr;
u32 forcewake;
u32 error; /* gen6+ */
u32 err_int; /* gen7 */
u32 fault_data0; /* gen8, gen9 */
u32 fault_data1; /* gen8, gen9 */
u32 done_reg;
u32 gac_eco;
u32 gam_ecochk;
u32 gab_ctl;
u32 gfx_mode;
u32 extra_instdone[I915_NUM_INSTDONE_REG];
u64 fence[I915_MAX_NUM_FENCES];
struct intel_overlay_error_state *overlay;
struct intel_display_error_state *display;
struct drm_i915_error_object *semaphore_obj;
struct drm_i915_error_engine {
int engine_id;
/* Software tracked state */
bool waiting;
int num_waiters;
int hangcheck_score;
enum intel_engine_hangcheck_action hangcheck_action;
struct i915_address_space *vm;
int num_requests;
/* our own tracking of ring head and tail */
u32 cpu_ring_head;
u32 cpu_ring_tail;
u32 last_seqno;
u32 semaphore_seqno[I915_NUM_ENGINES - 1];
/* Register state */
u32 start;
u32 tail;
u32 head;
u32 ctl;
u32 hws;
u32 ipeir;
u32 ipehr;
u32 instdone;
u32 bbstate;
u32 instpm;
u32 instps;
u32 seqno;
u64 bbaddr;
u64 acthd;
u32 fault_reg;
u64 faddr;
u32 rc_psmi; /* sleep state */
u32 semaphore_mboxes[I915_NUM_ENGINES - 1];
struct drm_i915_error_object {
int page_count;
u64 gtt_offset;
u32 *pages[0];
} *ringbuffer, *batchbuffer, *wa_batchbuffer, *ctx, *hws_page;
struct drm_i915_error_object *wa_ctx;
struct drm_i915_error_request {
long jiffies;
u32 seqno;
u32 head;
u32 tail;
} *requests;
struct drm_i915_error_waiter {
char comm[TASK_COMM_LEN];
pid_t pid;
u32 seqno;
} *waiters;
struct {
u32 gfx_mode;
union {
u64 pdp[4];
u32 pp_dir_base;
};
} vm_info;
pid_t pid;
char comm[TASK_COMM_LEN];
} engine[I915_NUM_ENGINES];
struct drm_i915_error_buffer {
u32 size;
u32 name;
u32 rseqno[I915_NUM_ENGINES], wseqno;
u64 gtt_offset;
u32 read_domains;
u32 write_domain;
s32 fence_reg:I915_MAX_NUM_FENCE_BITS;
u32 tiling:2;
u32 dirty:1;
u32 purgeable:1;
u32 userptr:1;
s32 engine:4;
u32 cache_level:3;
} *active_bo[I915_NUM_ENGINES], *pinned_bo;
u32 active_bo_count[I915_NUM_ENGINES], pinned_bo_count;
struct i915_address_space *active_vm[I915_NUM_ENGINES];
};
struct intel_connector; struct intel_connector;
struct intel_encoder; struct intel_encoder;
struct intel_crtc_state; struct intel_crtc_state;
...@@ -823,6 +699,131 @@ struct intel_device_info { ...@@ -823,6 +699,131 @@ struct intel_device_info {
#undef DEFINE_FLAG #undef DEFINE_FLAG
#undef SEP_SEMICOLON #undef SEP_SEMICOLON
struct intel_display_error_state;
struct drm_i915_error_state {
struct kref ref;
struct timeval time;
char error_msg[128];
bool simulated;
int iommu;
u32 reset_count;
u32 suspend_count;
struct intel_device_info device_info;
/* Generic register state */
u32 eir;
u32 pgtbl_er;
u32 ier;
u32 gtier[4];
u32 ccid;
u32 derrmr;
u32 forcewake;
u32 error; /* gen6+ */
u32 err_int; /* gen7 */
u32 fault_data0; /* gen8, gen9 */
u32 fault_data1; /* gen8, gen9 */
u32 done_reg;
u32 gac_eco;
u32 gam_ecochk;
u32 gab_ctl;
u32 gfx_mode;
u32 extra_instdone[I915_NUM_INSTDONE_REG];
u64 fence[I915_MAX_NUM_FENCES];
struct intel_overlay_error_state *overlay;
struct intel_display_error_state *display;
struct drm_i915_error_object *semaphore_obj;
struct drm_i915_error_engine {
int engine_id;
/* Software tracked state */
bool waiting;
int num_waiters;
int hangcheck_score;
enum intel_engine_hangcheck_action hangcheck_action;
struct i915_address_space *vm;
int num_requests;
/* our own tracking of ring head and tail */
u32 cpu_ring_head;
u32 cpu_ring_tail;
u32 last_seqno;
u32 semaphore_seqno[I915_NUM_ENGINES - 1];
/* Register state */
u32 start;
u32 tail;
u32 head;
u32 ctl;
u32 hws;
u32 ipeir;
u32 ipehr;
u32 instdone;
u32 bbstate;
u32 instpm;
u32 instps;
u32 seqno;
u64 bbaddr;
u64 acthd;
u32 fault_reg;
u64 faddr;
u32 rc_psmi; /* sleep state */
u32 semaphore_mboxes[I915_NUM_ENGINES - 1];
struct drm_i915_error_object {
int page_count;
u64 gtt_offset;
u32 *pages[0];
} *ringbuffer, *batchbuffer, *wa_batchbuffer, *ctx, *hws_page;
struct drm_i915_error_object *wa_ctx;
struct drm_i915_error_request {
long jiffies;
u32 seqno;
u32 head;
u32 tail;
} *requests;
struct drm_i915_error_waiter {
char comm[TASK_COMM_LEN];
pid_t pid;
u32 seqno;
} *waiters;
struct {
u32 gfx_mode;
union {
u64 pdp[4];
u32 pp_dir_base;
};
} vm_info;
pid_t pid;
char comm[TASK_COMM_LEN];
} engine[I915_NUM_ENGINES];
struct drm_i915_error_buffer {
u32 size;
u32 name;
u32 rseqno[I915_NUM_ENGINES], wseqno;
u64 gtt_offset;
u32 read_domains;
u32 write_domain;
s32 fence_reg:I915_MAX_NUM_FENCE_BITS;
u32 tiling:2;
u32 dirty:1;
u32 purgeable:1;
u32 userptr:1;
s32 engine:4;
u32 cache_level:3;
} *active_bo[I915_NUM_ENGINES], *pinned_bo;
u32 active_bo_count[I915_NUM_ENGINES], pinned_bo_count;
struct i915_address_space *active_vm[I915_NUM_ENGINES];
};
enum i915_cache_level { enum i915_cache_level {
I915_CACHE_NONE = 0, I915_CACHE_NONE = 0,
I915_CACHE_LLC, /* also used for snoopable memory on non-LLC */ I915_CACHE_LLC, /* also used for snoopable memory on non-LLC */
......
...@@ -312,6 +312,16 @@ static void print_error_obj(struct drm_i915_error_state_buf *m, ...@@ -312,6 +312,16 @@ static void print_error_obj(struct drm_i915_error_state_buf *m,
} }
} }
static void err_print_capabilities(struct drm_i915_error_state_buf *m,
const struct intel_device_info *info)
{
#define PRINT_FLAG(x) err_printf(m, #x ": %s\n", yesno(info->x))
#define SEP_SEMICOLON ;
DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG, SEP_SEMICOLON);
#undef PRINT_FLAG
#undef SEP_SEMICOLON
}
int i915_error_state_to_str(struct drm_i915_error_state_buf *m, int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
const struct i915_error_state_file_priv *error_priv) const struct i915_error_state_file_priv *error_priv)
{ {
...@@ -331,6 +341,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, ...@@ -331,6 +341,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
err_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec, err_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec,
error->time.tv_usec); error->time.tv_usec);
err_printf(m, "Kernel: " UTS_RELEASE "\n"); err_printf(m, "Kernel: " UTS_RELEASE "\n");
err_print_capabilities(m, &error->device_info);
max_hangcheck_score = 0; max_hangcheck_score = 0;
for (i = 0; i < ARRAY_SIZE(error->engine); i++) { for (i = 0; i < ARRAY_SIZE(error->engine); i++) {
if (error->engine[i].hangcheck_score > max_hangcheck_score) if (error->engine[i].hangcheck_score > max_hangcheck_score)
...@@ -1362,6 +1373,10 @@ static void i915_capture_gen_state(struct drm_i915_private *dev_priv, ...@@ -1362,6 +1373,10 @@ static void i915_capture_gen_state(struct drm_i915_private *dev_priv,
#endif #endif
error->reset_count = i915_reset_count(&dev_priv->gpu_error); error->reset_count = i915_reset_count(&dev_priv->gpu_error);
error->suspend_count = dev_priv->suspend_count; error->suspend_count = dev_priv->suspend_count;
memcpy(&error->device_info,
INTEL_INFO(dev_priv),
sizeof(error->device_info));
} }
/** /**
......
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