drm/i915: Display fence register state in debugfs i915_gem_fence_regs node.
[safe/jmp/linux-2.6] / drivers / gpu / drm / i915 / i915_gem_debugfs.c
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
73         switch (list) {
74         case ACTIVE_LIST:
75                 seq_printf(m, "Active:\n");
76                 head = &dev_priv->mm.active_list;
77                 break;
78         case INACTIVE_LIST:
79                 seq_printf(m, "Inctive:\n");
80                 head = &dev_priv->mm.inactive_list;
81                 break;
82         case FLUSHING_LIST:
83                 seq_printf(m, "Flushing:\n");
84                 head = &dev_priv->mm.flushing_list;
85                 break;
86         default:
87                 DRM_INFO("Ooops, unexpected list\n");
88                 return 0;
89         }
90
91         list_for_each_entry(obj_priv, head, list)
92         {
93                 struct drm_gem_object *obj = obj_priv->obj;
94
95                 seq_printf(m, "    %p: %s %08x %08x %d",
96                            obj,
97                            get_pin_flag(obj_priv),
98                            obj->read_domains, obj->write_domain,
99                            obj_priv->last_rendering_seqno);
100
101                 if (obj->name)
102                         seq_printf(m, " (name: %d)", obj->name);
103                 if (obj_priv->fence_reg != I915_FENCE_REG_NONE)
104                         seq_printf(m, " (fence: %d\n", obj_priv->fence_reg);
105                 seq_printf(m, "\n");
106         }
107         return 0;
108 }
109
110 static int i915_gem_request_info(struct seq_file *m, void *data)
111 {
112         struct drm_info_node *node = (struct drm_info_node *) m->private;
113         struct drm_device *dev = node->minor->dev;
114         drm_i915_private_t *dev_priv = dev->dev_private;
115         struct drm_i915_gem_request *gem_request;
116
117         seq_printf(m, "Request:\n");
118         list_for_each_entry(gem_request, &dev_priv->mm.request_list, list) {
119                 seq_printf(m, "    %d @ %d\n",
120                            gem_request->seqno,
121                            (int) (jiffies - gem_request->emitted_jiffies));
122         }
123         return 0;
124 }
125
126 static int i915_gem_seqno_info(struct seq_file *m, void *data)
127 {
128         struct drm_info_node *node = (struct drm_info_node *) m->private;
129         struct drm_device *dev = node->minor->dev;
130         drm_i915_private_t *dev_priv = dev->dev_private;
131
132         if (dev_priv->hw_status_page != NULL) {
133                 seq_printf(m, "Current sequence: %d\n",
134                            i915_get_gem_seqno(dev));
135         } else {
136                 seq_printf(m, "Current sequence: hws uninitialized\n");
137         }
138         seq_printf(m, "Waiter sequence:  %d\n",
139                         dev_priv->mm.waiting_gem_seqno);
140         seq_printf(m, "IRQ sequence:     %d\n", dev_priv->mm.irq_gem_seqno);
141         return 0;
142 }
143
144
145 static int i915_interrupt_info(struct seq_file *m, void *data)
146 {
147         struct drm_info_node *node = (struct drm_info_node *) m->private;
148         struct drm_device *dev = node->minor->dev;
149         drm_i915_private_t *dev_priv = dev->dev_private;
150
151         seq_printf(m, "Interrupt enable:    %08x\n",
152                    I915_READ(IER));
153         seq_printf(m, "Interrupt identity:  %08x\n",
154                    I915_READ(IIR));
155         seq_printf(m, "Interrupt mask:      %08x\n",
156                    I915_READ(IMR));
157         seq_printf(m, "Pipe A stat:         %08x\n",
158                    I915_READ(PIPEASTAT));
159         seq_printf(m, "Pipe B stat:         %08x\n",
160                    I915_READ(PIPEBSTAT));
161         seq_printf(m, "Interrupts received: %d\n",
162                    atomic_read(&dev_priv->irq_received));
163         if (dev_priv->hw_status_page != NULL) {
164                 seq_printf(m, "Current sequence:    %d\n",
165                            i915_get_gem_seqno(dev));
166         } else {
167                 seq_printf(m, "Current sequence:    hws uninitialized\n");
168         }
169         seq_printf(m, "Waiter sequence:     %d\n",
170                    dev_priv->mm.waiting_gem_seqno);
171         seq_printf(m, "IRQ sequence:        %d\n",
172                    dev_priv->mm.irq_gem_seqno);
173         return 0;
174 }
175
176 static int i915_gem_fence_regs_info(struct seq_file *m, void *data)
177 {
178         struct drm_info_node *node = (struct drm_info_node *) m->private;
179         struct drm_device *dev = node->minor->dev;
180         drm_i915_private_t *dev_priv = dev->dev_private;
181         int i;
182
183         seq_printf(m, "Reserved fences = %d\n", dev_priv->fence_reg_start);
184         seq_printf(m, "Total fences = %d\n", dev_priv->num_fence_regs);
185         for (i = 0; i < dev_priv->num_fence_regs; i++) {
186                 struct drm_gem_object *obj = dev_priv->fence_regs[i].obj;
187
188                 if (obj == NULL) {
189                         seq_printf(m, "Fenced object[%2d] = unused\n", i);
190                 } else {
191                         struct drm_i915_gem_object *obj_priv;
192
193                         obj_priv = obj->driver_private;
194                         seq_printf(m, "Fenced object[%2d] = %p: %s "
195                                    "%08x %08x %08x %s %08x %08x %d",
196                                    i, obj, get_pin_flag(obj_priv),
197                                    obj_priv->gtt_offset,
198                                    obj->size, obj_priv->stride,
199                                    get_tiling_flag(obj_priv),
200                                    obj->read_domains, obj->write_domain,
201                                    obj_priv->last_rendering_seqno);
202                         if (obj->name)
203                                 seq_printf(m, " (name: %d)", obj->name);
204                         seq_printf(m, "\n");
205                 }
206         }
207
208         return 0;
209 }
210
211 static int i915_hws_info(struct seq_file *m, void *data)
212 {
213         struct drm_info_node *node = (struct drm_info_node *) m->private;
214         struct drm_device *dev = node->minor->dev;
215         drm_i915_private_t *dev_priv = dev->dev_private;
216         int i;
217         volatile u32 *hws;
218
219         hws = (volatile u32 *)dev_priv->hw_status_page;
220         if (hws == NULL)
221                 return 0;
222
223         for (i = 0; i < 4096 / sizeof(u32) / 4; i += 4) {
224                 seq_printf(m, "0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
225                            i * 4,
226                            hws[i], hws[i + 1], hws[i + 2], hws[i + 3]);
227         }
228         return 0;
229 }
230
231 static struct drm_info_list i915_gem_debugfs_list[] = {
232         {"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST},
233         {"i915_gem_flushing", i915_gem_object_list_info, 0, (void *) FLUSHING_LIST},
234         {"i915_gem_inactive", i915_gem_object_list_info, 0, (void *) INACTIVE_LIST},
235         {"i915_gem_request", i915_gem_request_info, 0},
236         {"i915_gem_seqno", i915_gem_seqno_info, 0},
237         {"i915_gem_fence_regs", i915_gem_fence_regs_info, 0},
238         {"i915_gem_interrupt", i915_interrupt_info, 0},
239         {"i915_gem_hws", i915_hws_info, 0},
240 };
241 #define I915_GEM_DEBUGFS_ENTRIES ARRAY_SIZE(i915_gem_debugfs_list)
242
243 int i915_gem_debugfs_init(struct drm_minor *minor)
244 {
245         return drm_debugfs_create_files(i915_gem_debugfs_list,
246                                         I915_GEM_DEBUGFS_ENTRIES,
247                                         minor->debugfs_root, minor);
248 }
249
250 void i915_gem_debugfs_cleanup(struct drm_minor *minor)
251 {
252         drm_debugfs_remove_files(i915_gem_debugfs_list,
253                                  I915_GEM_DEBUGFS_ENTRIES, minor);
254 }
255
256 #endif /* CONFIG_DEBUG_FS */
257