diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem_debugfs.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_debugfs.c | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_debugfs.c b/drivers/gpu/drm/i915/i915_gem_debugfs.c new file mode 100644 index 00000000000..a1ac0c5e730 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_gem_debugfs.c | |||
@@ -0,0 +1,263 @@ | |||
1 | /* | ||
2 | * Copyright © 2008 Intel Corporation | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice (including the next | ||
12 | * paragraph) shall be included in all copies or substantial portions of the | ||
13 | * Software. | ||
14 | * | ||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
21 | * IN THE SOFTWARE. | ||
22 | * | ||
23 | * Authors: | ||
24 | * Eric Anholt <eric@anholt.net> | ||
25 | * Keith Packard <keithp@keithp.com> | ||
26 | * | ||
27 | */ | ||
28 | |||
29 | #include <linux/seq_file.h> | ||
30 | #include "drmP.h" | ||
31 | #include "drm.h" | ||
32 | #include "i915_drm.h" | ||
33 | #include "i915_drv.h" | ||
34 | |||
35 | #define DRM_I915_RING_DEBUG 1 | ||
36 | |||
37 | |||
38 | #if defined(CONFIG_DEBUG_FS) | ||
39 | |||
40 | #define ACTIVE_LIST 1 | ||
41 | #define FLUSHING_LIST 2 | ||
42 | #define INACTIVE_LIST 3 | ||
43 | |||
44 | static const char *get_pin_flag(struct drm_i915_gem_object *obj_priv) | ||
45 | { | ||
46 | if (obj_priv->user_pin_count > 0) | ||
47 | return "P"; | ||
48 | else if (obj_priv->pin_count > 0) | ||
49 | return "p"; | ||
50 | else | ||
51 | return " "; | ||
52 | } | ||
53 | |||
54 | static const char *get_tiling_flag(struct drm_i915_gem_object *obj_priv) | ||
55 | { | ||
56 | switch (obj_priv->tiling_mode) { | ||
57 | default: | ||
58 | case I915_TILING_NONE: return " "; | ||
59 | case I915_TILING_X: return "X"; | ||
60 | case I915_TILING_Y: return "Y"; | ||
61 | } | ||
62 | } | ||
63 | |||
64 | static int i915_gem_object_list_info(struct seq_file *m, void *data) | ||
65 | { | ||
66 | struct drm_info_node *node = (struct drm_info_node *) m->private; | ||
67 | uintptr_t list = (uintptr_t) node->info_ent->data; | ||
68 | struct list_head *head; | ||
69 | struct drm_device *dev = node->minor->dev; | ||
70 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
71 | struct drm_i915_gem_object *obj_priv; | ||
72 | spinlock_t *lock = NULL; | ||
73 | |||
74 | switch (list) { | ||
75 | case ACTIVE_LIST: | ||
76 | seq_printf(m, "Active:\n"); | ||
77 | lock = &dev_priv->mm.active_list_lock; | ||
78 | spin_lock(lock); | ||
79 | head = &dev_priv->mm.active_list; | ||
80 | break; | ||
81 | case INACTIVE_LIST: | ||
82 | seq_printf(m, "Inctive:\n"); | ||
83 | head = &dev_priv->mm.inactive_list; | ||
84 | break; | ||
85 | case FLUSHING_LIST: | ||
86 | seq_printf(m, "Flushing:\n"); | ||
87 | head = &dev_priv->mm.flushing_list; | ||
88 | break; | ||
89 | default: | ||
90 | DRM_INFO("Ooops, unexpected list\n"); | ||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | list_for_each_entry(obj_priv, head, list) | ||
95 | { | ||
96 | struct drm_gem_object *obj = obj_priv->obj; | ||
97 | |||
98 | seq_printf(m, " %p: %s %08x %08x %d", | ||
99 | obj, | ||
100 | get_pin_flag(obj_priv), | ||
101 | obj->read_domains, obj->write_domain, | ||
102 | obj_priv->last_rendering_seqno); | ||
103 | |||
104 | if (obj->name) | ||
105 | seq_printf(m, " (name: %d)", obj->name); | ||
106 | if (obj_priv->fence_reg != I915_FENCE_REG_NONE) | ||
107 | seq_printf(m, " (fence: %d\n", obj_priv->fence_reg); | ||
108 | seq_printf(m, "\n"); | ||
109 | } | ||
110 | |||
111 | if (lock) | ||
112 | spin_unlock(lock); | ||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | static int i915_gem_request_info(struct seq_file *m, void *data) | ||
117 | { | ||
118 | struct drm_info_node *node = (struct drm_info_node *) m->private; | ||
119 | struct drm_device *dev = node->minor->dev; | ||
120 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
121 | struct drm_i915_gem_request *gem_request; | ||
122 | |||
123 | seq_printf(m, "Request:\n"); | ||
124 | list_for_each_entry(gem_request, &dev_priv->mm.request_list, list) { | ||
125 | seq_printf(m, " %d @ %d\n", | ||
126 | gem_request->seqno, | ||
127 | (int) (jiffies - gem_request->emitted_jiffies)); | ||
128 | } | ||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | static int i915_gem_seqno_info(struct seq_file *m, void *data) | ||
133 | { | ||
134 | struct drm_info_node *node = (struct drm_info_node *) m->private; | ||
135 | struct drm_device *dev = node->minor->dev; | ||
136 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
137 | |||
138 | if (dev_priv->hw_status_page != NULL) { | ||
139 | seq_printf(m, "Current sequence: %d\n", | ||
140 | i915_get_gem_seqno(dev)); | ||
141 | } else { | ||
142 | seq_printf(m, "Current sequence: hws uninitialized\n"); | ||
143 | } | ||
144 | seq_printf(m, "Waiter sequence: %d\n", | ||
145 | dev_priv->mm.waiting_gem_seqno); | ||
146 | seq_printf(m, "IRQ sequence: %d\n", dev_priv->mm.irq_gem_seqno); | ||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | |||
151 | static int i915_interrupt_info(struct seq_file *m, void *data) | ||
152 | { | ||
153 | struct drm_info_node *node = (struct drm_info_node *) m->private; | ||
154 | struct drm_device *dev = node->minor->dev; | ||
155 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
156 | |||
157 | seq_printf(m, "Interrupt enable: %08x\n", | ||
158 | I915_READ(IER)); | ||
159 | seq_printf(m, "Interrupt identity: %08x\n", | ||
160 | I915_READ(IIR)); | ||
161 | seq_printf(m, "Interrupt mask: %08x\n", | ||
162 | I915_READ(IMR)); | ||
163 | seq_printf(m, "Pipe A stat: %08x\n", | ||
164 | I915_READ(PIPEASTAT)); | ||
165 | seq_printf(m, "Pipe B stat: %08x\n", | ||
166 | I915_READ(PIPEBSTAT)); | ||
167 | seq_printf(m, "Interrupts received: %d\n", | ||
168 | atomic_read(&dev_priv->irq_received)); | ||
169 | if (dev_priv->hw_status_page != NULL) { | ||
170 | seq_printf(m, "Current sequence: %d\n", | ||
171 | i915_get_gem_seqno(dev)); | ||
172 | } else { | ||
173 | seq_printf(m, "Current sequence: hws uninitialized\n"); | ||
174 | } | ||
175 | seq_printf(m, "Waiter sequence: %d\n", | ||
176 | dev_priv->mm.waiting_gem_seqno); | ||
177 | seq_printf(m, "IRQ sequence: %d\n", | ||
178 | dev_priv->mm.irq_gem_seqno); | ||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | static int i915_gem_fence_regs_info(struct seq_file *m, void *data) | ||
183 | { | ||
184 | struct drm_info_node *node = (struct drm_info_node *) m->private; | ||
185 | struct drm_device *dev = node->minor->dev; | ||
186 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
187 | int i; | ||
188 | |||
189 | seq_printf(m, "Reserved fences = %d\n", dev_priv->fence_reg_start); | ||
190 | seq_printf(m, "Total fences = %d\n", dev_priv->num_fence_regs); | ||
191 | for (i = 0; i < dev_priv->num_fence_regs; i++) { | ||
192 | struct drm_gem_object *obj = dev_priv->fence_regs[i].obj; | ||
193 | |||
194 | if (obj == NULL) { | ||
195 | seq_printf(m, "Fenced object[%2d] = unused\n", i); | ||
196 | } else { | ||
197 | struct drm_i915_gem_object *obj_priv; | ||
198 | |||
199 | obj_priv = obj->driver_private; | ||
200 | seq_printf(m, "Fenced object[%2d] = %p: %s " | ||
201 | "%08x %08zx %08x %s %08x %08x %d", | ||
202 | i, obj, get_pin_flag(obj_priv), | ||
203 | obj_priv->gtt_offset, | ||
204 | obj->size, obj_priv->stride, | ||
205 | get_tiling_flag(obj_priv), | ||
206 | obj->read_domains, obj->write_domain, | ||
207 | obj_priv->last_rendering_seqno); | ||
208 | if (obj->name) | ||
209 | seq_printf(m, " (name: %d)", obj->name); | ||
210 | seq_printf(m, "\n"); | ||
211 | } | ||
212 | } | ||
213 | |||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | static int i915_hws_info(struct seq_file *m, void *data) | ||
218 | { | ||
219 | struct drm_info_node *node = (struct drm_info_node *) m->private; | ||
220 | struct drm_device *dev = node->minor->dev; | ||
221 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
222 | int i; | ||
223 | volatile u32 *hws; | ||
224 | |||
225 | hws = (volatile u32 *)dev_priv->hw_status_page; | ||
226 | if (hws == NULL) | ||
227 | return 0; | ||
228 | |||
229 | for (i = 0; i < 4096 / sizeof(u32) / 4; i += 4) { | ||
230 | seq_printf(m, "0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n", | ||
231 | i * 4, | ||
232 | hws[i], hws[i + 1], hws[i + 2], hws[i + 3]); | ||
233 | } | ||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | static struct drm_info_list i915_gem_debugfs_list[] = { | ||
238 | {"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST}, | ||
239 | {"i915_gem_flushing", i915_gem_object_list_info, 0, (void *) FLUSHING_LIST}, | ||
240 | {"i915_gem_inactive", i915_gem_object_list_info, 0, (void *) INACTIVE_LIST}, | ||
241 | {"i915_gem_request", i915_gem_request_info, 0}, | ||
242 | {"i915_gem_seqno", i915_gem_seqno_info, 0}, | ||
243 | {"i915_gem_fence_regs", i915_gem_fence_regs_info, 0}, | ||
244 | {"i915_gem_interrupt", i915_interrupt_info, 0}, | ||
245 | {"i915_gem_hws", i915_hws_info, 0}, | ||
246 | }; | ||
247 | #define I915_GEM_DEBUGFS_ENTRIES ARRAY_SIZE(i915_gem_debugfs_list) | ||
248 | |||
249 | int i915_gem_debugfs_init(struct drm_minor *minor) | ||
250 | { | ||
251 | return drm_debugfs_create_files(i915_gem_debugfs_list, | ||
252 | I915_GEM_DEBUGFS_ENTRIES, | ||
253 | minor->debugfs_root, minor); | ||
254 | } | ||
255 | |||
256 | void i915_gem_debugfs_cleanup(struct drm_minor *minor) | ||
257 | { | ||
258 | drm_debugfs_remove_files(i915_gem_debugfs_list, | ||
259 | I915_GEM_DEBUGFS_ENTRIES, minor); | ||
260 | } | ||
261 | |||
262 | #endif /* CONFIG_DEBUG_FS */ | ||
263 | |||