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