OSDN Git Service

Merge commit 'origin/drm-gem' into modesetting-gem
[android-x86/external-libdrm.git] / linux-core / i915_gem_proc.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 "drmP.h"
30 #include "drm.h"
31 #include "drm_compat.h"
32 #include "i915_drm.h"
33 #include "i915_drv.h"
34
35 static int i915_gem_active_info(char *buf, char **start, off_t offset,
36                                 int request, int *eof, void *data)
37 {
38         struct drm_minor *minor = (struct drm_minor *) data;
39         struct drm_device *dev = minor->dev;
40         struct drm_i915_private *dev_priv = dev->dev_private;
41         struct drm_i915_gem_object *obj_priv;
42         int len = 0;
43
44         if (offset > DRM_PROC_LIMIT) {
45                 *eof = 1;
46                 return 0;
47         }
48
49         *start = &buf[offset];
50         *eof = 0;
51         DRM_PROC_PRINT("Active:\n");
52         list_for_each_entry(obj_priv, &dev_priv->mm.active_list,
53                             list)
54         {
55                 struct drm_gem_object *obj = obj_priv->obj;
56                 if (obj->name) {
57                         DRM_PROC_PRINT("    %p(%d): %08x %08x %d\n",
58                                        obj, obj->name,
59                                        obj->read_domains, obj->write_domain,
60                                        obj_priv->last_rendering_seqno);
61                 } else {
62                         DRM_PROC_PRINT("       %p: %08x %08x %d\n",
63                                        obj,
64                                        obj->read_domains, obj->write_domain,
65                                        obj_priv->last_rendering_seqno);
66                 }
67         }
68         if (len > request + offset)
69                 return request;
70         *eof = 1;
71         return len - offset;
72 }
73
74 static int i915_gem_flushing_info(char *buf, char **start, off_t offset,
75                                   int request, int *eof, void *data)
76 {
77         struct drm_minor *minor = (struct drm_minor *) data;
78         struct drm_device *dev = minor->dev;
79         struct drm_i915_private *dev_priv = dev->dev_private;
80         struct drm_i915_gem_object *obj_priv;
81         int len = 0;
82
83         if (offset > DRM_PROC_LIMIT) {
84                 *eof = 1;
85                 return 0;
86         }
87
88         *start = &buf[offset];
89         *eof = 0;
90         DRM_PROC_PRINT("Flushing:\n");
91         list_for_each_entry(obj_priv, &dev_priv->mm.flushing_list,
92                             list)
93         {
94                 struct drm_gem_object *obj = obj_priv->obj;
95                 if (obj->name) {
96                         DRM_PROC_PRINT("    %p(%d): %08x %08x %d\n",
97                                        obj, obj->name,
98                                        obj->read_domains, obj->write_domain,
99                                        obj_priv->last_rendering_seqno);
100                 } else {
101                         DRM_PROC_PRINT("       %p: %08x %08x %d\n", obj,
102                                        obj->read_domains, obj->write_domain,
103                                        obj_priv->last_rendering_seqno);
104                 }
105         }
106         if (len > request + offset)
107                 return request;
108         *eof = 1;
109         return len - offset;
110 }
111
112 static int i915_gem_inactive_info(char *buf, char **start, off_t offset,
113                                   int request, int *eof, void *data)
114 {
115         struct drm_minor *minor = (struct drm_minor *) data;
116         struct drm_device *dev = minor->dev;
117         struct drm_i915_private *dev_priv = dev->dev_private;
118         struct drm_i915_gem_object *obj_priv;
119         int len = 0;
120
121         if (offset > DRM_PROC_LIMIT) {
122                 *eof = 1;
123                 return 0;
124         }
125
126         *start = &buf[offset];
127         *eof = 0;
128         DRM_PROC_PRINT("Inactive:\n");
129         list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list,
130                             list)
131         {
132                 struct drm_gem_object *obj = obj_priv->obj;
133                 if (obj->name) {
134                         DRM_PROC_PRINT("    %p(%d): %08x %08x %d\n",
135                                        obj, obj->name,
136                                        obj->read_domains, obj->write_domain,
137                                        obj_priv->last_rendering_seqno);
138                 } else {
139                         DRM_PROC_PRINT("       %p: %08x %08x %d\n", obj,
140                                        obj->read_domains, obj->write_domain,
141                                        obj_priv->last_rendering_seqno);
142                 }
143         }
144         if (len > request + offset)
145                 return request;
146         *eof = 1;
147         return len - offset;
148 }
149
150 static int i915_gem_request_info(char *buf, char **start, off_t offset,
151                                  int request, int *eof, void *data)
152 {
153         struct drm_minor *minor = (struct drm_minor *) data;
154         struct drm_device *dev = minor->dev;
155         struct drm_i915_private *dev_priv = dev->dev_private;
156         struct drm_i915_gem_request *gem_request;
157         int len = 0;
158
159         if (offset > DRM_PROC_LIMIT) {
160                 *eof = 1;
161                 return 0;
162         }
163
164         *start = &buf[offset];
165         *eof = 0;
166         DRM_PROC_PRINT("Request:\n");
167         list_for_each_entry(gem_request, &dev_priv->mm.request_list,
168                             list)
169         {
170                 DRM_PROC_PRINT("    %d @ %d %08x\n",
171                                gem_request->seqno,
172                                (int) (jiffies - gem_request->emitted_jiffies),
173                                gem_request->flush_domains);
174         }
175         if (len > request + offset)
176                 return request;
177         *eof = 1;
178         return len - offset;
179 }
180
181 static int i915_gem_seqno_info(char *buf, char **start, off_t offset,
182                                int request, int *eof, void *data)
183 {
184         struct drm_minor *minor = (struct drm_minor *) data;
185         struct drm_device *dev = minor->dev;
186         struct drm_i915_private *dev_priv = dev->dev_private;
187         int len = 0;
188
189         if (offset > DRM_PROC_LIMIT) {
190                 *eof = 1;
191                 return 0;
192         }
193
194         *start = &buf[offset];
195         *eof = 0;
196         DRM_PROC_PRINT("Current sequence: %d\n", i915_get_gem_seqno(dev));
197         DRM_PROC_PRINT("Waiter sequence:  %d\n",
198                        dev_priv->mm.waiting_gem_seqno);
199         DRM_PROC_PRINT("IRQ sequence:     %d\n", dev_priv->mm.irq_gem_seqno);
200         if (len > request + offset)
201                 return request;
202         *eof = 1;
203         return len - offset;
204 }
205
206
207 static int i915_interrupt_info(char *buf, char **start, off_t offset,
208                                int request, int *eof, void *data)
209 {
210         struct drm_minor *minor = (struct drm_minor *) data;
211         struct drm_device *dev = minor->dev;
212         struct drm_i915_private *dev_priv = dev->dev_private;
213         int len = 0;
214
215         if (offset > DRM_PROC_LIMIT) {
216                 *eof = 1;
217                 return 0;
218         }
219
220         *start = &buf[offset];
221         *eof = 0;
222         DRM_PROC_PRINT("Interrupt enable:    %08x\n",
223                        I915_READ(IER));
224         DRM_PROC_PRINT("Interrupt identity:  %08x\n",
225                        I915_READ(IIR));
226         DRM_PROC_PRINT("Interrupt mask:      %08x\n",
227                        I915_READ(IMR));
228         DRM_PROC_PRINT("Pipe A stat:         %08x\n",
229                        I915_READ(PIPEASTAT));
230         DRM_PROC_PRINT("Pipe B stat:         %08x\n",
231                        I915_READ(PIPEBSTAT));
232         DRM_PROC_PRINT("Interrupts received: %d\n",
233                        atomic_read(&dev_priv->irq_received));
234         DRM_PROC_PRINT("Current sequence:    %d\n",
235                        i915_get_gem_seqno(dev));
236         DRM_PROC_PRINT("Waiter sequence:     %d\n",
237                        dev_priv->mm.waiting_gem_seqno);
238         DRM_PROC_PRINT("IRQ sequence:        %d\n",
239                        dev_priv->mm.irq_gem_seqno);
240         if (len > request + offset)
241                 return request;
242         *eof = 1;
243         return len - offset;
244 }
245
246 static struct drm_proc_list {
247         /** file name */
248         const char *name;
249         /** proc callback*/
250         int (*f) (char *, char **, off_t, int, int *, void *);
251 } i915_gem_proc_list[] = {
252         {"i915_gem_active", i915_gem_active_info},
253         {"i915_gem_flushing", i915_gem_flushing_info},
254         {"i915_gem_inactive", i915_gem_inactive_info},
255         {"i915_gem_request", i915_gem_request_info},
256         {"i915_gem_seqno", i915_gem_seqno_info},
257         {"i915_gem_interrupt", i915_interrupt_info},
258 };
259
260 #define I915_GEM_PROC_ENTRIES ARRAY_SIZE(i915_gem_proc_list)
261
262 int i915_gem_proc_init(struct drm_minor *minor)
263 {
264         struct proc_dir_entry *ent;
265         int i, j;
266
267         for (i = 0; i < I915_GEM_PROC_ENTRIES; i++) {
268                 ent = create_proc_entry(i915_gem_proc_list[i].name,
269                                         S_IFREG | S_IRUGO, minor->dev_root);
270                 if (!ent) {
271                         DRM_ERROR("Cannot create /proc/dri/.../%s\n",
272                                   i915_gem_proc_list[i].name);
273                         for (j = 0; j < i; j++)
274                                 remove_proc_entry(i915_gem_proc_list[i].name,
275                                                   minor->dev_root);
276                         return -1;
277                 }
278                 ent->read_proc = i915_gem_proc_list[i].f;
279                 ent->data = minor;
280         }
281         return 0;
282 }
283
284 void i915_gem_proc_cleanup(struct drm_minor *minor)
285 {
286         int i;
287
288         if (!minor->dev_root)
289                 return;
290
291         for (i = 0; i < I915_GEM_PROC_ENTRIES; i++)
292                 remove_proc_entry(i915_gem_proc_list[i].name, minor->dev_root);
293 }