Commit | Line | Data |
---|---|---|
1da177e4 | 1 | /** |
b5e89ed5 | 2 | * \file drm_proc.c |
1da177e4 LT |
3 | * /proc support for DRM |
4 | * | |
5 | * \author Rickard E. (Rik) Faith <faith@valinux.com> | |
6 | * \author Gareth Hughes <gareth@valinux.com> | |
7 | * | |
8 | * \par Acknowledgements: | |
9 | * Matthew J Sottek <matthew.j.sottek@intel.com> sent in a patch to fix | |
10 | * the problem with the proc files not outputting all their information. | |
11 | */ | |
12 | ||
13 | /* | |
14 | * Created: Mon Jan 11 09:48:47 1999 by faith@valinux.com | |
15 | * | |
16 | * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. | |
17 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. | |
18 | * All Rights Reserved. | |
19 | * | |
20 | * Permission is hereby granted, free of charge, to any person obtaining a | |
21 | * copy of this software and associated documentation files (the "Software"), | |
22 | * to deal in the Software without restriction, including without limitation | |
23 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
24 | * and/or sell copies of the Software, and to permit persons to whom the | |
25 | * Software is furnished to do so, subject to the following conditions: | |
26 | * | |
27 | * The above copyright notice and this permission notice (including the next | |
28 | * paragraph) shall be included in all copies or substantial portions of the | |
29 | * Software. | |
30 | * | |
31 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
32 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
33 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
34 | * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
35 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
36 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
37 | * OTHER DEALINGS IN THE SOFTWARE. | |
38 | */ | |
39 | ||
40 | #include "drmP.h" | |
41 | ||
b5e89ed5 DA |
42 | static int drm_name_info(char *buf, char **start, off_t offset, |
43 | int request, int *eof, void *data); | |
44 | static int drm_vm_info(char *buf, char **start, off_t offset, | |
45 | int request, int *eof, void *data); | |
46 | static int drm_clients_info(char *buf, char **start, off_t offset, | |
47 | int request, int *eof, void *data); | |
48 | static int drm_queues_info(char *buf, char **start, off_t offset, | |
49 | int request, int *eof, void *data); | |
50 | static int drm_bufs_info(char *buf, char **start, off_t offset, | |
51 | int request, int *eof, void *data); | |
fede5c91 EA |
52 | static int drm_vblank_info(char *buf, char **start, off_t offset, |
53 | int request, int *eof, void *data); | |
673a394b EA |
54 | static int drm_gem_name_info(char *buf, char **start, off_t offset, |
55 | int request, int *eof, void *data); | |
56 | static int drm_gem_object_info(char *buf, char **start, off_t offset, | |
57 | int request, int *eof, void *data); | |
1da177e4 | 58 | #if DRM_DEBUG_CODE |
b5e89ed5 DA |
59 | static int drm_vma_info(char *buf, char **start, off_t offset, |
60 | int request, int *eof, void *data); | |
1da177e4 LT |
61 | #endif |
62 | ||
63 | /** | |
64 | * Proc file list. | |
65 | */ | |
c94f7029 | 66 | static struct drm_proc_list { |
1da177e4 | 67 | const char *name; /**< file name */ |
b5e89ed5 | 68 | int (*f) (char *, char **, off_t, int, int *, void *); /**< proc callback*/ |
673a394b | 69 | u32 driver_features; /**< Required driver features for this entry */ |
1da177e4 | 70 | } drm_proc_list[] = { |
673a394b EA |
71 | {"name", drm_name_info, 0}, |
72 | {"mem", drm_mem_info, 0}, | |
73 | {"vm", drm_vm_info, 0}, | |
74 | {"clients", drm_clients_info, 0}, | |
75 | {"queues", drm_queues_info, 0}, | |
76 | {"bufs", drm_bufs_info, 0}, | |
fede5c91 | 77 | {"vblank", drm_vblank_info, 0}, |
673a394b EA |
78 | {"gem_names", drm_gem_name_info, DRIVER_GEM}, |
79 | {"gem_objects", drm_gem_object_info, DRIVER_GEM}, | |
1da177e4 | 80 | #if DRM_DEBUG_CODE |
e96e33ee | 81 | {"vma", drm_vma_info}, |
1da177e4 LT |
82 | #endif |
83 | }; | |
b5e89ed5 | 84 | |
8311d570 | 85 | #define DRM_PROC_ENTRIES ARRAY_SIZE(drm_proc_list) |
1da177e4 LT |
86 | |
87 | /** | |
88 | * Initialize the DRI proc filesystem for a device. | |
89 | * | |
90 | * \param dev DRM device. | |
91 | * \param minor device minor number. | |
92 | * \param root DRI proc dir entry. | |
93 | * \param dev_root resulting DRI device proc dir entry. | |
94 | * \return root entry pointer on success, or NULL on failure. | |
b5e89ed5 | 95 | * |
1da177e4 LT |
96 | * Create the DRI proc root entry "/proc/dri", the device proc root entry |
97 | * "/proc/dri/%minor%/", and each entry in proc_list as | |
98 | * "/proc/dri/%minor%/%name%". | |
99 | */ | |
2c14f28b DA |
100 | int drm_proc_init(struct drm_minor *minor, int minor_id, |
101 | struct proc_dir_entry *root) | |
1da177e4 | 102 | { |
673a394b | 103 | struct drm_device *dev = minor->dev; |
1da177e4 | 104 | struct proc_dir_entry *ent; |
673a394b | 105 | int i, j, ret; |
b5e89ed5 | 106 | char name[64]; |
1da177e4 | 107 | |
2c14f28b DA |
108 | sprintf(name, "%d", minor_id); |
109 | minor->dev_root = proc_mkdir(name, root); | |
110 | if (!minor->dev_root) { | |
1da177e4 LT |
111 | DRM_ERROR("Cannot create /proc/dri/%s\n", name); |
112 | return -1; | |
113 | } | |
114 | ||
115 | for (i = 0; i < DRM_PROC_ENTRIES; i++) { | |
673a394b EA |
116 | u32 features = drm_proc_list[i].driver_features; |
117 | ||
118 | if (features != 0 && | |
119 | (dev->driver->driver_features & features) != features) | |
120 | continue; | |
121 | ||
1da177e4 | 122 | ent = create_proc_entry(drm_proc_list[i].name, |
2c14f28b | 123 | S_IFREG | S_IRUGO, minor->dev_root); |
1da177e4 LT |
124 | if (!ent) { |
125 | DRM_ERROR("Cannot create /proc/dri/%s/%s\n", | |
126 | name, drm_proc_list[i].name); | |
673a394b EA |
127 | ret = -1; |
128 | goto fail; | |
1da177e4 LT |
129 | } |
130 | ent->read_proc = drm_proc_list[i].f; | |
2c14f28b | 131 | ent->data = minor; |
1da177e4 LT |
132 | } |
133 | ||
673a394b EA |
134 | if (dev->driver->proc_init) { |
135 | ret = dev->driver->proc_init(minor); | |
136 | if (ret) { | |
137 | DRM_ERROR("DRM: Driver failed to initialize " | |
138 | "/proc/dri.\n"); | |
139 | goto fail; | |
140 | } | |
141 | } | |
142 | ||
1da177e4 | 143 | return 0; |
673a394b EA |
144 | fail: |
145 | ||
146 | for (j = 0; j < i; j++) | |
147 | remove_proc_entry(drm_proc_list[i].name, | |
148 | minor->dev_root); | |
149 | remove_proc_entry(name, root); | |
150 | minor->dev_root = NULL; | |
151 | return ret; | |
1da177e4 LT |
152 | } |
153 | ||
1da177e4 LT |
154 | /** |
155 | * Cleanup the proc filesystem resources. | |
156 | * | |
157 | * \param minor device minor number. | |
158 | * \param root DRI proc dir entry. | |
159 | * \param dev_root DRI device proc dir entry. | |
160 | * \return always zero. | |
161 | * | |
162 | * Remove all proc entries created by proc_init(). | |
163 | */ | |
2c14f28b | 164 | int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root) |
1da177e4 | 165 | { |
673a394b | 166 | struct drm_device *dev = minor->dev; |
b5e89ed5 | 167 | int i; |
1da177e4 LT |
168 | char name[64]; |
169 | ||
2c14f28b | 170 | if (!root || !minor->dev_root) |
b5e89ed5 | 171 | return 0; |
1da177e4 | 172 | |
673a394b EA |
173 | if (dev->driver->proc_cleanup) |
174 | dev->driver->proc_cleanup(minor); | |
175 | ||
1da177e4 | 176 | for (i = 0; i < DRM_PROC_ENTRIES; i++) |
2c14f28b DA |
177 | remove_proc_entry(drm_proc_list[i].name, minor->dev_root); |
178 | sprintf(name, "%d", minor->index); | |
1da177e4 LT |
179 | remove_proc_entry(name, root); |
180 | ||
181 | return 0; | |
182 | } | |
183 | ||
184 | /** | |
185 | * Called when "/proc/dri/.../name" is read. | |
b5e89ed5 | 186 | * |
1da177e4 LT |
187 | * \param buf output buffer. |
188 | * \param start start of output data. | |
189 | * \param offset requested start offset. | |
190 | * \param request requested number of bytes. | |
191 | * \param eof whether there is no more data to return. | |
192 | * \param data private data. | |
193 | * \return number of written bytes. | |
b5e89ed5 | 194 | * |
1da177e4 LT |
195 | * Prints the device name together with the bus id if available. |
196 | */ | |
197 | static int drm_name_info(char *buf, char **start, off_t offset, int request, | |
b5e89ed5 | 198 | int *eof, void *data) |
1da177e4 | 199 | { |
2c14f28b | 200 | struct drm_minor *minor = (struct drm_minor *) data; |
7c1c2871 | 201 | struct drm_master *master = minor->master; |
2c14f28b | 202 | struct drm_device *dev = minor->dev; |
b5e89ed5 | 203 | int len = 0; |
1da177e4 LT |
204 | |
205 | if (offset > DRM_PROC_LIMIT) { | |
206 | *eof = 1; | |
207 | return 0; | |
208 | } | |
209 | ||
7c1c2871 DA |
210 | if (!master) |
211 | return 0; | |
212 | ||
1da177e4 | 213 | *start = &buf[offset]; |
b5e89ed5 | 214 | *eof = 0; |
1da177e4 | 215 | |
7c1c2871 | 216 | if (master->unique) { |
1da177e4 | 217 | DRM_PROC_PRINT("%s %s %s\n", |
b5e89ed5 | 218 | dev->driver->pci_driver.name, |
7c1c2871 | 219 | pci_name(dev->pdev), master->unique); |
1da177e4 | 220 | } else { |
b5e89ed5 DA |
221 | DRM_PROC_PRINT("%s %s\n", dev->driver->pci_driver.name, |
222 | pci_name(dev->pdev)); | |
1da177e4 LT |
223 | } |
224 | ||
b5e89ed5 DA |
225 | if (len > request + offset) |
226 | return request; | |
1da177e4 LT |
227 | *eof = 1; |
228 | return len - offset; | |
229 | } | |
230 | ||
231 | /** | |
232 | * Called when "/proc/dri/.../vm" is read. | |
b5e89ed5 | 233 | * |
1da177e4 LT |
234 | * \param buf output buffer. |
235 | * \param start start of output data. | |
236 | * \param offset requested start offset. | |
237 | * \param request requested number of bytes. | |
238 | * \param eof whether there is no more data to return. | |
239 | * \param data private data. | |
240 | * \return number of written bytes. | |
b5e89ed5 | 241 | * |
1da177e4 LT |
242 | * Prints information about all mappings in drm_device::maplist. |
243 | */ | |
244 | static int drm__vm_info(char *buf, char **start, off_t offset, int request, | |
b5e89ed5 | 245 | int *eof, void *data) |
1da177e4 | 246 | { |
2c14f28b DA |
247 | struct drm_minor *minor = (struct drm_minor *) data; |
248 | struct drm_device *dev = minor->dev; | |
b5e89ed5 | 249 | int len = 0; |
f77d390c | 250 | struct drm_local_map *map; |
55910517 | 251 | struct drm_map_list *r_list; |
1da177e4 | 252 | |
b5e89ed5 DA |
253 | /* Hardcoded from _DRM_FRAME_BUFFER, |
254 | _DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and | |
255 | _DRM_SCATTER_GATHER and _DRM_CONSISTENT */ | |
256 | const char *types[] = { "FB", "REG", "SHM", "AGP", "SG", "PCI" }; | |
257 | const char *type; | |
258 | int i; | |
1da177e4 LT |
259 | |
260 | if (offset > DRM_PROC_LIMIT) { | |
261 | *eof = 1; | |
262 | return 0; | |
263 | } | |
264 | ||
265 | *start = &buf[offset]; | |
b5e89ed5 | 266 | *eof = 0; |
1da177e4 LT |
267 | |
268 | DRM_PROC_PRINT("slot offset size type flags " | |
269 | "address mtrr\n\n"); | |
270 | i = 0; | |
bd1b331f | 271 | list_for_each_entry(r_list, &dev->maplist, head) { |
1da177e4 | 272 | map = r_list->map; |
b5e89ed5 | 273 | if (!map) |
2d0f9eaf DA |
274 | continue; |
275 | if (map->type < 0 || map->type > 5) | |
276 | type = "??"; | |
b5e89ed5 | 277 | else |
2d0f9eaf | 278 | type = types[map->type]; |
41c2e75e | 279 | DRM_PROC_PRINT("%4d 0x%08llx 0x%08lx %4.4s 0x%02x 0x%08lx ", |
1da177e4 | 280 | i, |
41c2e75e | 281 | (unsigned long long)map->offset, |
bd1b331f | 282 | map->size, type, map->flags, |
8562b3f2 | 283 | (unsigned long) r_list->user_token); |
1da177e4 LT |
284 | if (map->mtrr < 0) { |
285 | DRM_PROC_PRINT("none\n"); | |
286 | } else { | |
287 | DRM_PROC_PRINT("%4d\n", map->mtrr); | |
288 | } | |
289 | i++; | |
bd1b331f | 290 | } |
1da177e4 | 291 | |
b5e89ed5 DA |
292 | if (len > request + offset) |
293 | return request; | |
1da177e4 LT |
294 | *eof = 1; |
295 | return len - offset; | |
296 | } | |
297 | ||
298 | /** | |
30e2fb18 | 299 | * Simply calls _vm_info() while holding the drm_device::struct_mutex lock. |
1da177e4 LT |
300 | */ |
301 | static int drm_vm_info(char *buf, char **start, off_t offset, int request, | |
b5e89ed5 | 302 | int *eof, void *data) |
1da177e4 | 303 | { |
2c14f28b DA |
304 | struct drm_minor *minor = (struct drm_minor *) data; |
305 | struct drm_device *dev = minor->dev; | |
b5e89ed5 | 306 | int ret; |
1da177e4 | 307 | |
30e2fb18 | 308 | mutex_lock(&dev->struct_mutex); |
1da177e4 | 309 | ret = drm__vm_info(buf, start, offset, request, eof, data); |
30e2fb18 | 310 | mutex_unlock(&dev->struct_mutex); |
1da177e4 LT |
311 | return ret; |
312 | } | |
313 | ||
314 | /** | |
315 | * Called when "/proc/dri/.../queues" is read. | |
b5e89ed5 | 316 | * |
1da177e4 LT |
317 | * \param buf output buffer. |
318 | * \param start start of output data. | |
319 | * \param offset requested start offset. | |
320 | * \param request requested number of bytes. | |
321 | * \param eof whether there is no more data to return. | |
322 | * \param data private data. | |
323 | * \return number of written bytes. | |
324 | */ | |
325 | static int drm__queues_info(char *buf, char **start, off_t offset, | |
b5e89ed5 | 326 | int request, int *eof, void *data) |
1da177e4 | 327 | { |
2c14f28b DA |
328 | struct drm_minor *minor = (struct drm_minor *) data; |
329 | struct drm_device *dev = minor->dev; | |
b5e89ed5 DA |
330 | int len = 0; |
331 | int i; | |
cdd55a29 | 332 | struct drm_queue *q; |
1da177e4 LT |
333 | |
334 | if (offset > DRM_PROC_LIMIT) { | |
335 | *eof = 1; | |
336 | return 0; | |
337 | } | |
338 | ||
339 | *start = &buf[offset]; | |
b5e89ed5 | 340 | *eof = 0; |
1da177e4 LT |
341 | |
342 | DRM_PROC_PRINT(" ctx/flags use fin" | |
343 | " blk/rw/rwf wait flushed queued" | |
344 | " locks\n\n"); | |
345 | for (i = 0; i < dev->queue_count; i++) { | |
346 | q = dev->queuelist[i]; | |
347 | atomic_inc(&q->use_count); | |
348 | DRM_PROC_PRINT_RET(atomic_dec(&q->use_count), | |
349 | "%5d/0x%03x %5d %5d" | |
350 | " %5d/%c%c/%c%c%c %5Zd\n", | |
351 | i, | |
352 | q->flags, | |
353 | atomic_read(&q->use_count), | |
354 | atomic_read(&q->finalization), | |
355 | atomic_read(&q->block_count), | |
356 | atomic_read(&q->block_read) ? 'r' : '-', | |
357 | atomic_read(&q->block_write) ? 'w' : '-', | |
b5e89ed5 DA |
358 | waitqueue_active(&q->read_queue) ? 'r' : '-', |
359 | waitqueue_active(&q-> | |
360 | write_queue) ? 'w' : '-', | |
361 | waitqueue_active(&q-> | |
362 | flush_queue) ? 'f' : '-', | |
1da177e4 LT |
363 | DRM_BUFCOUNT(&q->waitlist)); |
364 | atomic_dec(&q->use_count); | |
365 | } | |
366 | ||
b5e89ed5 DA |
367 | if (len > request + offset) |
368 | return request; | |
1da177e4 LT |
369 | *eof = 1; |
370 | return len - offset; | |
371 | } | |
372 | ||
373 | /** | |
30e2fb18 | 374 | * Simply calls _queues_info() while holding the drm_device::struct_mutex lock. |
1da177e4 LT |
375 | */ |
376 | static int drm_queues_info(char *buf, char **start, off_t offset, int request, | |
b5e89ed5 | 377 | int *eof, void *data) |
1da177e4 | 378 | { |
2c14f28b DA |
379 | struct drm_minor *minor = (struct drm_minor *) data; |
380 | struct drm_device *dev = minor->dev; | |
b5e89ed5 | 381 | int ret; |
1da177e4 | 382 | |
30e2fb18 | 383 | mutex_lock(&dev->struct_mutex); |
1da177e4 | 384 | ret = drm__queues_info(buf, start, offset, request, eof, data); |
30e2fb18 | 385 | mutex_unlock(&dev->struct_mutex); |
1da177e4 LT |
386 | return ret; |
387 | } | |
388 | ||
389 | /** | |
390 | * Called when "/proc/dri/.../bufs" is read. | |
b5e89ed5 | 391 | * |
1da177e4 LT |
392 | * \param buf output buffer. |
393 | * \param start start of output data. | |
394 | * \param offset requested start offset. | |
395 | * \param request requested number of bytes. | |
396 | * \param eof whether there is no more data to return. | |
397 | * \param data private data. | |
398 | * \return number of written bytes. | |
399 | */ | |
400 | static int drm__bufs_info(char *buf, char **start, off_t offset, int request, | |
b5e89ed5 | 401 | int *eof, void *data) |
1da177e4 | 402 | { |
2c14f28b DA |
403 | struct drm_minor *minor = (struct drm_minor *) data; |
404 | struct drm_device *dev = minor->dev; | |
b5e89ed5 | 405 | int len = 0; |
cdd55a29 | 406 | struct drm_device_dma *dma = dev->dma; |
b5e89ed5 | 407 | int i; |
1da177e4 LT |
408 | |
409 | if (!dma || offset > DRM_PROC_LIMIT) { | |
410 | *eof = 1; | |
411 | return 0; | |
412 | } | |
413 | ||
414 | *start = &buf[offset]; | |
b5e89ed5 | 415 | *eof = 0; |
1da177e4 LT |
416 | |
417 | DRM_PROC_PRINT(" o size count free segs pages kB\n\n"); | |
418 | for (i = 0; i <= DRM_MAX_ORDER; i++) { | |
419 | if (dma->bufs[i].buf_count) | |
420 | DRM_PROC_PRINT("%2d %8d %5d %5d %5d %5d %5ld\n", | |
421 | i, | |
422 | dma->bufs[i].buf_size, | |
423 | dma->bufs[i].buf_count, | |
424 | atomic_read(&dma->bufs[i] | |
425 | .freelist.count), | |
426 | dma->bufs[i].seg_count, | |
427 | dma->bufs[i].seg_count | |
b5e89ed5 | 428 | * (1 << dma->bufs[i].page_order), |
1da177e4 LT |
429 | (dma->bufs[i].seg_count |
430 | * (1 << dma->bufs[i].page_order)) | |
431 | * PAGE_SIZE / 1024); | |
432 | } | |
433 | DRM_PROC_PRINT("\n"); | |
434 | for (i = 0; i < dma->buf_count; i++) { | |
b5e89ed5 DA |
435 | if (i && !(i % 32)) |
436 | DRM_PROC_PRINT("\n"); | |
1da177e4 LT |
437 | DRM_PROC_PRINT(" %d", dma->buflist[i]->list); |
438 | } | |
439 | DRM_PROC_PRINT("\n"); | |
440 | ||
b5e89ed5 DA |
441 | if (len > request + offset) |
442 | return request; | |
1da177e4 LT |
443 | *eof = 1; |
444 | return len - offset; | |
445 | } | |
446 | ||
447 | /** | |
30e2fb18 | 448 | * Simply calls _bufs_info() while holding the drm_device::struct_mutex lock. |
1da177e4 LT |
449 | */ |
450 | static int drm_bufs_info(char *buf, char **start, off_t offset, int request, | |
b5e89ed5 | 451 | int *eof, void *data) |
1da177e4 | 452 | { |
2c14f28b DA |
453 | struct drm_minor *minor = (struct drm_minor *) data; |
454 | struct drm_device *dev = minor->dev; | |
b5e89ed5 | 455 | int ret; |
1da177e4 | 456 | |
30e2fb18 | 457 | mutex_lock(&dev->struct_mutex); |
1da177e4 | 458 | ret = drm__bufs_info(buf, start, offset, request, eof, data); |
30e2fb18 | 459 | mutex_unlock(&dev->struct_mutex); |
1da177e4 LT |
460 | return ret; |
461 | } | |
462 | ||
fede5c91 EA |
463 | /** |
464 | * Called when "/proc/dri/.../vblank" is read. | |
465 | * | |
466 | * \param buf output buffer. | |
467 | * \param start start of output data. | |
468 | * \param offset requested start offset. | |
469 | * \param request requested number of bytes. | |
470 | * \param eof whether there is no more data to return. | |
471 | * \param data private data. | |
472 | * \return number of written bytes. | |
473 | */ | |
474 | static int drm__vblank_info(char *buf, char **start, off_t offset, int request, | |
475 | int *eof, void *data) | |
476 | { | |
477 | struct drm_minor *minor = (struct drm_minor *) data; | |
478 | struct drm_device *dev = minor->dev; | |
479 | int len = 0; | |
480 | int crtc; | |
481 | ||
482 | if (offset > DRM_PROC_LIMIT) { | |
483 | *eof = 1; | |
484 | return 0; | |
485 | } | |
486 | ||
487 | *start = &buf[offset]; | |
488 | *eof = 0; | |
489 | ||
490 | for (crtc = 0; crtc < dev->num_crtcs; crtc++) { | |
491 | DRM_PROC_PRINT("CRTC %d enable: %d\n", | |
492 | crtc, atomic_read(&dev->vblank_refcount[crtc])); | |
493 | DRM_PROC_PRINT("CRTC %d counter: %d\n", | |
494 | crtc, drm_vblank_count(dev, crtc)); | |
495 | DRM_PROC_PRINT("CRTC %d last wait: %d\n", | |
496 | crtc, dev->last_vblank_wait[crtc]); | |
497 | DRM_PROC_PRINT("CRTC %d in modeset: %d\n", | |
498 | crtc, dev->vblank_inmodeset[crtc]); | |
499 | } | |
500 | ||
501 | if (len > request + offset) | |
502 | return request; | |
503 | *eof = 1; | |
504 | return len - offset; | |
505 | } | |
506 | ||
507 | /** | |
508 | * Simply calls _vblank_info() while holding the drm_device::struct_mutex lock. | |
509 | */ | |
510 | static int drm_vblank_info(char *buf, char **start, off_t offset, int request, | |
511 | int *eof, void *data) | |
512 | { | |
513 | struct drm_minor *minor = (struct drm_minor *) data; | |
514 | struct drm_device *dev = minor->dev; | |
515 | int ret; | |
516 | ||
517 | mutex_lock(&dev->struct_mutex); | |
518 | ret = drm__vblank_info(buf, start, offset, request, eof, data); | |
519 | mutex_unlock(&dev->struct_mutex); | |
520 | return ret; | |
521 | } | |
522 | ||
1da177e4 LT |
523 | /** |
524 | * Called when "/proc/dri/.../clients" is read. | |
b5e89ed5 | 525 | * |
1da177e4 LT |
526 | * \param buf output buffer. |
527 | * \param start start of output data. | |
528 | * \param offset requested start offset. | |
529 | * \param request requested number of bytes. | |
530 | * \param eof whether there is no more data to return. | |
531 | * \param data private data. | |
532 | * \return number of written bytes. | |
533 | */ | |
534 | static int drm__clients_info(char *buf, char **start, off_t offset, | |
b5e89ed5 | 535 | int request, int *eof, void *data) |
1da177e4 | 536 | { |
2c14f28b DA |
537 | struct drm_minor *minor = (struct drm_minor *) data; |
538 | struct drm_device *dev = minor->dev; | |
b5e89ed5 | 539 | int len = 0; |
84b1fd10 | 540 | struct drm_file *priv; |
1da177e4 LT |
541 | |
542 | if (offset > DRM_PROC_LIMIT) { | |
543 | *eof = 1; | |
544 | return 0; | |
545 | } | |
546 | ||
547 | *start = &buf[offset]; | |
b5e89ed5 | 548 | *eof = 0; |
1da177e4 LT |
549 | |
550 | DRM_PROC_PRINT("a dev pid uid magic ioctls\n\n"); | |
bd1b331f | 551 | list_for_each_entry(priv, &dev->filelist, lhead) { |
1da177e4 LT |
552 | DRM_PROC_PRINT("%c %3d %5d %5d %10u %10lu\n", |
553 | priv->authenticated ? 'y' : 'n', | |
2c14f28b | 554 | priv->minor->index, |
1da177e4 | 555 | priv->pid, |
b5e89ed5 | 556 | priv->uid, priv->magic, priv->ioctl_count); |
1da177e4 LT |
557 | } |
558 | ||
b5e89ed5 DA |
559 | if (len > request + offset) |
560 | return request; | |
1da177e4 LT |
561 | *eof = 1; |
562 | return len - offset; | |
563 | } | |
564 | ||
565 | /** | |
30e2fb18 | 566 | * Simply calls _clients_info() while holding the drm_device::struct_mutex lock. |
1da177e4 LT |
567 | */ |
568 | static int drm_clients_info(char *buf, char **start, off_t offset, | |
b5e89ed5 | 569 | int request, int *eof, void *data) |
1da177e4 | 570 | { |
2c14f28b DA |
571 | struct drm_minor *minor = (struct drm_minor *) data; |
572 | struct drm_device *dev = minor->dev; | |
b5e89ed5 | 573 | int ret; |
1da177e4 | 574 | |
30e2fb18 | 575 | mutex_lock(&dev->struct_mutex); |
1da177e4 | 576 | ret = drm__clients_info(buf, start, offset, request, eof, data); |
30e2fb18 | 577 | mutex_unlock(&dev->struct_mutex); |
1da177e4 LT |
578 | return ret; |
579 | } | |
580 | ||
673a394b EA |
581 | struct drm_gem_name_info_data { |
582 | int len; | |
583 | char *buf; | |
584 | int eof; | |
585 | }; | |
586 | ||
587 | static int drm_gem_one_name_info(int id, void *ptr, void *data) | |
588 | { | |
589 | struct drm_gem_object *obj = ptr; | |
590 | struct drm_gem_name_info_data *nid = data; | |
591 | ||
1ae87786 | 592 | DRM_INFO("name %d size %zd\n", obj->name, obj->size); |
673a394b EA |
593 | if (nid->eof) |
594 | return 0; | |
595 | ||
596 | nid->len += sprintf(&nid->buf[nid->len], | |
1ae87786 | 597 | "%6d %8zd %7d %8d\n", |
673a394b EA |
598 | obj->name, obj->size, |
599 | atomic_read(&obj->handlecount.refcount), | |
600 | atomic_read(&obj->refcount.refcount)); | |
601 | if (nid->len > DRM_PROC_LIMIT) { | |
602 | nid->eof = 1; | |
603 | return 0; | |
604 | } | |
605 | return 0; | |
606 | } | |
607 | ||
608 | static int drm_gem_name_info(char *buf, char **start, off_t offset, | |
609 | int request, int *eof, void *data) | |
610 | { | |
611 | struct drm_minor *minor = (struct drm_minor *) data; | |
612 | struct drm_device *dev = minor->dev; | |
613 | struct drm_gem_name_info_data nid; | |
614 | ||
615 | if (offset > DRM_PROC_LIMIT) { | |
616 | *eof = 1; | |
617 | return 0; | |
618 | } | |
619 | ||
620 | nid.len = sprintf(buf, " name size handles refcount\n"); | |
621 | nid.buf = buf; | |
622 | nid.eof = 0; | |
623 | idr_for_each(&dev->object_name_idr, drm_gem_one_name_info, &nid); | |
624 | ||
625 | *start = &buf[offset]; | |
626 | *eof = 0; | |
627 | if (nid.len > request + offset) | |
628 | return request; | |
629 | *eof = 1; | |
630 | return nid.len - offset; | |
631 | } | |
632 | ||
633 | static int drm_gem_object_info(char *buf, char **start, off_t offset, | |
634 | int request, int *eof, void *data) | |
635 | { | |
636 | struct drm_minor *minor = (struct drm_minor *) data; | |
637 | struct drm_device *dev = minor->dev; | |
638 | int len = 0; | |
639 | ||
640 | if (offset > DRM_PROC_LIMIT) { | |
641 | *eof = 1; | |
642 | return 0; | |
643 | } | |
644 | ||
645 | *start = &buf[offset]; | |
646 | *eof = 0; | |
647 | DRM_PROC_PRINT("%d objects\n", atomic_read(&dev->object_count)); | |
648 | DRM_PROC_PRINT("%d object bytes\n", atomic_read(&dev->object_memory)); | |
649 | DRM_PROC_PRINT("%d pinned\n", atomic_read(&dev->pin_count)); | |
650 | DRM_PROC_PRINT("%d pin bytes\n", atomic_read(&dev->pin_memory)); | |
651 | DRM_PROC_PRINT("%d gtt bytes\n", atomic_read(&dev->gtt_memory)); | |
652 | DRM_PROC_PRINT("%d gtt total\n", dev->gtt_total); | |
653 | if (len > request + offset) | |
654 | return request; | |
655 | *eof = 1; | |
656 | return len - offset; | |
657 | } | |
658 | ||
1da177e4 LT |
659 | #if DRM_DEBUG_CODE |
660 | ||
661 | static int drm__vma_info(char *buf, char **start, off_t offset, int request, | |
b5e89ed5 | 662 | int *eof, void *data) |
1da177e4 | 663 | { |
2c14f28b DA |
664 | struct drm_minor *minor = (struct drm_minor *) data; |
665 | struct drm_device *dev = minor->dev; | |
b5e89ed5 | 666 | int len = 0; |
8fc2fdf4 | 667 | struct drm_vma_entry *pt; |
1da177e4 LT |
668 | struct vm_area_struct *vma; |
669 | #if defined(__i386__) | |
b5e89ed5 | 670 | unsigned int pgprot; |
1da177e4 LT |
671 | #endif |
672 | ||
673 | if (offset > DRM_PROC_LIMIT) { | |
674 | *eof = 1; | |
675 | return 0; | |
676 | } | |
677 | ||
678 | *start = &buf[offset]; | |
b5e89ed5 | 679 | *eof = 0; |
1da177e4 LT |
680 | |
681 | DRM_PROC_PRINT("vma use count: %d, high_memory = %p, 0x%08lx\n", | |
682 | atomic_read(&dev->vma_count), | |
683 | high_memory, virt_to_phys(high_memory)); | |
bd1b331f | 684 | list_for_each_entry(pt, &dev->vmalist, head) { |
b5e89ed5 DA |
685 | if (!(vma = pt->vma)) |
686 | continue; | |
1545085a | 687 | DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx000", |
1da177e4 LT |
688 | pt->pid, |
689 | vma->vm_start, | |
690 | vma->vm_end, | |
b5e89ed5 DA |
691 | vma->vm_flags & VM_READ ? 'r' : '-', |
692 | vma->vm_flags & VM_WRITE ? 'w' : '-', | |
693 | vma->vm_flags & VM_EXEC ? 'x' : '-', | |
1da177e4 | 694 | vma->vm_flags & VM_MAYSHARE ? 's' : 'p', |
b5e89ed5 DA |
695 | vma->vm_flags & VM_LOCKED ? 'l' : '-', |
696 | vma->vm_flags & VM_IO ? 'i' : '-', | |
1545085a | 697 | vma->vm_pgoff); |
1da177e4 LT |
698 | |
699 | #if defined(__i386__) | |
700 | pgprot = pgprot_val(vma->vm_page_prot); | |
701 | DRM_PROC_PRINT(" %c%c%c%c%c%c%c%c%c", | |
b5e89ed5 DA |
702 | pgprot & _PAGE_PRESENT ? 'p' : '-', |
703 | pgprot & _PAGE_RW ? 'w' : 'r', | |
704 | pgprot & _PAGE_USER ? 'u' : 's', | |
705 | pgprot & _PAGE_PWT ? 't' : 'b', | |
706 | pgprot & _PAGE_PCD ? 'u' : 'c', | |
1da177e4 | 707 | pgprot & _PAGE_ACCESSED ? 'a' : '-', |
b5e89ed5 DA |
708 | pgprot & _PAGE_DIRTY ? 'd' : '-', |
709 | pgprot & _PAGE_PSE ? 'm' : 'k', | |
710 | pgprot & _PAGE_GLOBAL ? 'g' : 'l'); | |
1da177e4 LT |
711 | #endif |
712 | DRM_PROC_PRINT("\n"); | |
713 | } | |
714 | ||
b5e89ed5 DA |
715 | if (len > request + offset) |
716 | return request; | |
1da177e4 LT |
717 | *eof = 1; |
718 | return len - offset; | |
719 | } | |
720 | ||
721 | static int drm_vma_info(char *buf, char **start, off_t offset, int request, | |
b5e89ed5 | 722 | int *eof, void *data) |
1da177e4 | 723 | { |
2c14f28b DA |
724 | struct drm_minor *minor = (struct drm_minor *) data; |
725 | struct drm_device *dev = minor->dev; | |
b5e89ed5 | 726 | int ret; |
1da177e4 | 727 | |
30e2fb18 | 728 | mutex_lock(&dev->struct_mutex); |
1da177e4 | 729 | ret = drm__vma_info(buf, start, offset, request, eof, data); |
30e2fb18 | 730 | mutex_unlock(&dev->struct_mutex); |
1da177e4 LT |
731 | return ret; |
732 | } | |
733 | #endif |