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); | |
673a394b EA |
52 | static int drm_gem_name_info(char *buf, char **start, off_t offset, |
53 | int request, int *eof, void *data); | |
54 | static int drm_gem_object_info(char *buf, char **start, off_t offset, | |
55 | int request, int *eof, void *data); | |
1da177e4 | 56 | #if DRM_DEBUG_CODE |
b5e89ed5 DA |
57 | static int drm_vma_info(char *buf, char **start, off_t offset, |
58 | int request, int *eof, void *data); | |
1da177e4 LT |
59 | #endif |
60 | ||
61 | /** | |
62 | * Proc file list. | |
63 | */ | |
c94f7029 | 64 | static struct drm_proc_list { |
1da177e4 | 65 | const char *name; /**< file name */ |
b5e89ed5 | 66 | int (*f) (char *, char **, off_t, int, int *, void *); /**< proc callback*/ |
673a394b | 67 | u32 driver_features; /**< Required driver features for this entry */ |
1da177e4 | 68 | } drm_proc_list[] = { |
673a394b EA |
69 | {"name", drm_name_info, 0}, |
70 | {"mem", drm_mem_info, 0}, | |
71 | {"vm", drm_vm_info, 0}, | |
72 | {"clients", drm_clients_info, 0}, | |
73 | {"queues", drm_queues_info, 0}, | |
74 | {"bufs", drm_bufs_info, 0}, | |
75 | {"gem_names", drm_gem_name_info, DRIVER_GEM}, | |
76 | {"gem_objects", drm_gem_object_info, DRIVER_GEM}, | |
1da177e4 | 77 | #if DRM_DEBUG_CODE |
e96e33ee | 78 | {"vma", drm_vma_info}, |
1da177e4 LT |
79 | #endif |
80 | }; | |
b5e89ed5 | 81 | |
8311d570 | 82 | #define DRM_PROC_ENTRIES ARRAY_SIZE(drm_proc_list) |
1da177e4 LT |
83 | |
84 | /** | |
85 | * Initialize the DRI proc filesystem for a device. | |
86 | * | |
87 | * \param dev DRM device. | |
88 | * \param minor device minor number. | |
89 | * \param root DRI proc dir entry. | |
90 | * \param dev_root resulting DRI device proc dir entry. | |
91 | * \return root entry pointer on success, or NULL on failure. | |
b5e89ed5 | 92 | * |
1da177e4 LT |
93 | * Create the DRI proc root entry "/proc/dri", the device proc root entry |
94 | * "/proc/dri/%minor%/", and each entry in proc_list as | |
95 | * "/proc/dri/%minor%/%name%". | |
96 | */ | |
2c14f28b DA |
97 | int drm_proc_init(struct drm_minor *minor, int minor_id, |
98 | struct proc_dir_entry *root) | |
1da177e4 | 99 | { |
673a394b | 100 | struct drm_device *dev = minor->dev; |
1da177e4 | 101 | struct proc_dir_entry *ent; |
673a394b | 102 | int i, j, ret; |
b5e89ed5 | 103 | char name[64]; |
1da177e4 | 104 | |
2c14f28b DA |
105 | sprintf(name, "%d", minor_id); |
106 | minor->dev_root = proc_mkdir(name, root); | |
107 | if (!minor->dev_root) { | |
1da177e4 LT |
108 | DRM_ERROR("Cannot create /proc/dri/%s\n", name); |
109 | return -1; | |
110 | } | |
111 | ||
112 | for (i = 0; i < DRM_PROC_ENTRIES; i++) { | |
673a394b EA |
113 | u32 features = drm_proc_list[i].driver_features; |
114 | ||
115 | if (features != 0 && | |
116 | (dev->driver->driver_features & features) != features) | |
117 | continue; | |
118 | ||
1da177e4 | 119 | ent = create_proc_entry(drm_proc_list[i].name, |
2c14f28b | 120 | S_IFREG | S_IRUGO, minor->dev_root); |
1da177e4 LT |
121 | if (!ent) { |
122 | DRM_ERROR("Cannot create /proc/dri/%s/%s\n", | |
123 | name, drm_proc_list[i].name); | |
673a394b EA |
124 | ret = -1; |
125 | goto fail; | |
1da177e4 LT |
126 | } |
127 | ent->read_proc = drm_proc_list[i].f; | |
2c14f28b | 128 | ent->data = minor; |
1da177e4 LT |
129 | } |
130 | ||
673a394b EA |
131 | if (dev->driver->proc_init) { |
132 | ret = dev->driver->proc_init(minor); | |
133 | if (ret) { | |
134 | DRM_ERROR("DRM: Driver failed to initialize " | |
135 | "/proc/dri.\n"); | |
136 | goto fail; | |
137 | } | |
138 | } | |
139 | ||
1da177e4 | 140 | return 0; |
673a394b EA |
141 | fail: |
142 | ||
143 | for (j = 0; j < i; j++) | |
144 | remove_proc_entry(drm_proc_list[i].name, | |
145 | minor->dev_root); | |
146 | remove_proc_entry(name, root); | |
147 | minor->dev_root = NULL; | |
148 | return ret; | |
1da177e4 LT |
149 | } |
150 | ||
1da177e4 LT |
151 | /** |
152 | * Cleanup the proc filesystem resources. | |
153 | * | |
154 | * \param minor device minor number. | |
155 | * \param root DRI proc dir entry. | |
156 | * \param dev_root DRI device proc dir entry. | |
157 | * \return always zero. | |
158 | * | |
159 | * Remove all proc entries created by proc_init(). | |
160 | */ | |
2c14f28b | 161 | int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root) |
1da177e4 | 162 | { |
673a394b | 163 | struct drm_device *dev = minor->dev; |
b5e89ed5 | 164 | int i; |
1da177e4 LT |
165 | char name[64]; |
166 | ||
2c14f28b | 167 | if (!root || !minor->dev_root) |
b5e89ed5 | 168 | return 0; |
1da177e4 | 169 | |
673a394b EA |
170 | if (dev->driver->proc_cleanup) |
171 | dev->driver->proc_cleanup(minor); | |
172 | ||
1da177e4 | 173 | for (i = 0; i < DRM_PROC_ENTRIES; i++) |
2c14f28b DA |
174 | remove_proc_entry(drm_proc_list[i].name, minor->dev_root); |
175 | sprintf(name, "%d", minor->index); | |
1da177e4 LT |
176 | remove_proc_entry(name, root); |
177 | ||
178 | return 0; | |
179 | } | |
180 | ||
181 | /** | |
182 | * Called when "/proc/dri/.../name" is read. | |
b5e89ed5 | 183 | * |
1da177e4 LT |
184 | * \param buf output buffer. |
185 | * \param start start of output data. | |
186 | * \param offset requested start offset. | |
187 | * \param request requested number of bytes. | |
188 | * \param eof whether there is no more data to return. | |
189 | * \param data private data. | |
190 | * \return number of written bytes. | |
b5e89ed5 | 191 | * |
1da177e4 LT |
192 | * Prints the device name together with the bus id if available. |
193 | */ | |
194 | static int drm_name_info(char *buf, char **start, off_t offset, int request, | |
b5e89ed5 | 195 | int *eof, void *data) |
1da177e4 | 196 | { |
2c14f28b DA |
197 | struct drm_minor *minor = (struct drm_minor *) data; |
198 | struct drm_device *dev = minor->dev; | |
b5e89ed5 | 199 | int len = 0; |
1da177e4 LT |
200 | |
201 | if (offset > DRM_PROC_LIMIT) { | |
202 | *eof = 1; | |
203 | return 0; | |
204 | } | |
205 | ||
206 | *start = &buf[offset]; | |
b5e89ed5 | 207 | *eof = 0; |
1da177e4 LT |
208 | |
209 | if (dev->unique) { | |
210 | DRM_PROC_PRINT("%s %s %s\n", | |
b5e89ed5 DA |
211 | dev->driver->pci_driver.name, |
212 | pci_name(dev->pdev), dev->unique); | |
1da177e4 | 213 | } else { |
b5e89ed5 DA |
214 | DRM_PROC_PRINT("%s %s\n", dev->driver->pci_driver.name, |
215 | pci_name(dev->pdev)); | |
1da177e4 LT |
216 | } |
217 | ||
b5e89ed5 DA |
218 | if (len > request + offset) |
219 | return request; | |
1da177e4 LT |
220 | *eof = 1; |
221 | return len - offset; | |
222 | } | |
223 | ||
224 | /** | |
225 | * Called when "/proc/dri/.../vm" is read. | |
b5e89ed5 | 226 | * |
1da177e4 LT |
227 | * \param buf output buffer. |
228 | * \param start start of output data. | |
229 | * \param offset requested start offset. | |
230 | * \param request requested number of bytes. | |
231 | * \param eof whether there is no more data to return. | |
232 | * \param data private data. | |
233 | * \return number of written bytes. | |
b5e89ed5 | 234 | * |
1da177e4 LT |
235 | * Prints information about all mappings in drm_device::maplist. |
236 | */ | |
237 | static int drm__vm_info(char *buf, char **start, off_t offset, int request, | |
b5e89ed5 | 238 | int *eof, void *data) |
1da177e4 | 239 | { |
2c14f28b DA |
240 | struct drm_minor *minor = (struct drm_minor *) data; |
241 | struct drm_device *dev = minor->dev; | |
b5e89ed5 | 242 | int len = 0; |
c60ce623 | 243 | struct drm_map *map; |
55910517 | 244 | struct drm_map_list *r_list; |
1da177e4 | 245 | |
b5e89ed5 DA |
246 | /* Hardcoded from _DRM_FRAME_BUFFER, |
247 | _DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and | |
248 | _DRM_SCATTER_GATHER and _DRM_CONSISTENT */ | |
249 | const char *types[] = { "FB", "REG", "SHM", "AGP", "SG", "PCI" }; | |
250 | const char *type; | |
251 | int i; | |
1da177e4 LT |
252 | |
253 | if (offset > DRM_PROC_LIMIT) { | |
254 | *eof = 1; | |
255 | return 0; | |
256 | } | |
257 | ||
258 | *start = &buf[offset]; | |
b5e89ed5 | 259 | *eof = 0; |
1da177e4 LT |
260 | |
261 | DRM_PROC_PRINT("slot offset size type flags " | |
262 | "address mtrr\n\n"); | |
263 | i = 0; | |
bd1b331f | 264 | list_for_each_entry(r_list, &dev->maplist, head) { |
1da177e4 | 265 | map = r_list->map; |
b5e89ed5 | 266 | if (!map) |
2d0f9eaf DA |
267 | continue; |
268 | if (map->type < 0 || map->type > 5) | |
269 | type = "??"; | |
b5e89ed5 | 270 | else |
2d0f9eaf | 271 | type = types[map->type]; |
8562b3f2 | 272 | DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08lx ", |
1da177e4 LT |
273 | i, |
274 | map->offset, | |
bd1b331f | 275 | map->size, type, map->flags, |
8562b3f2 | 276 | (unsigned long) r_list->user_token); |
1da177e4 LT |
277 | if (map->mtrr < 0) { |
278 | DRM_PROC_PRINT("none\n"); | |
279 | } else { | |
280 | DRM_PROC_PRINT("%4d\n", map->mtrr); | |
281 | } | |
282 | i++; | |
bd1b331f | 283 | } |
1da177e4 | 284 | |
b5e89ed5 DA |
285 | if (len > request + offset) |
286 | return request; | |
1da177e4 LT |
287 | *eof = 1; |
288 | return len - offset; | |
289 | } | |
290 | ||
291 | /** | |
30e2fb18 | 292 | * Simply calls _vm_info() while holding the drm_device::struct_mutex lock. |
1da177e4 LT |
293 | */ |
294 | static int drm_vm_info(char *buf, char **start, off_t offset, int request, | |
b5e89ed5 | 295 | int *eof, void *data) |
1da177e4 | 296 | { |
2c14f28b DA |
297 | struct drm_minor *minor = (struct drm_minor *) data; |
298 | struct drm_device *dev = minor->dev; | |
b5e89ed5 | 299 | int ret; |
1da177e4 | 300 | |
30e2fb18 | 301 | mutex_lock(&dev->struct_mutex); |
1da177e4 | 302 | ret = drm__vm_info(buf, start, offset, request, eof, data); |
30e2fb18 | 303 | mutex_unlock(&dev->struct_mutex); |
1da177e4 LT |
304 | return ret; |
305 | } | |
306 | ||
307 | /** | |
308 | * Called when "/proc/dri/.../queues" is read. | |
b5e89ed5 | 309 | * |
1da177e4 LT |
310 | * \param buf output buffer. |
311 | * \param start start of output data. | |
312 | * \param offset requested start offset. | |
313 | * \param request requested number of bytes. | |
314 | * \param eof whether there is no more data to return. | |
315 | * \param data private data. | |
316 | * \return number of written bytes. | |
317 | */ | |
318 | static int drm__queues_info(char *buf, char **start, off_t offset, | |
b5e89ed5 | 319 | int request, int *eof, void *data) |
1da177e4 | 320 | { |
2c14f28b DA |
321 | struct drm_minor *minor = (struct drm_minor *) data; |
322 | struct drm_device *dev = minor->dev; | |
b5e89ed5 DA |
323 | int len = 0; |
324 | int i; | |
cdd55a29 | 325 | struct drm_queue *q; |
1da177e4 LT |
326 | |
327 | if (offset > DRM_PROC_LIMIT) { | |
328 | *eof = 1; | |
329 | return 0; | |
330 | } | |
331 | ||
332 | *start = &buf[offset]; | |
b5e89ed5 | 333 | *eof = 0; |
1da177e4 LT |
334 | |
335 | DRM_PROC_PRINT(" ctx/flags use fin" | |
336 | " blk/rw/rwf wait flushed queued" | |
337 | " locks\n\n"); | |
338 | for (i = 0; i < dev->queue_count; i++) { | |
339 | q = dev->queuelist[i]; | |
340 | atomic_inc(&q->use_count); | |
341 | DRM_PROC_PRINT_RET(atomic_dec(&q->use_count), | |
342 | "%5d/0x%03x %5d %5d" | |
343 | " %5d/%c%c/%c%c%c %5Zd\n", | |
344 | i, | |
345 | q->flags, | |
346 | atomic_read(&q->use_count), | |
347 | atomic_read(&q->finalization), | |
348 | atomic_read(&q->block_count), | |
349 | atomic_read(&q->block_read) ? 'r' : '-', | |
350 | atomic_read(&q->block_write) ? 'w' : '-', | |
b5e89ed5 DA |
351 | waitqueue_active(&q->read_queue) ? 'r' : '-', |
352 | waitqueue_active(&q-> | |
353 | write_queue) ? 'w' : '-', | |
354 | waitqueue_active(&q-> | |
355 | flush_queue) ? 'f' : '-', | |
1da177e4 LT |
356 | DRM_BUFCOUNT(&q->waitlist)); |
357 | atomic_dec(&q->use_count); | |
358 | } | |
359 | ||
b5e89ed5 DA |
360 | if (len > request + offset) |
361 | return request; | |
1da177e4 LT |
362 | *eof = 1; |
363 | return len - offset; | |
364 | } | |
365 | ||
366 | /** | |
30e2fb18 | 367 | * Simply calls _queues_info() while holding the drm_device::struct_mutex lock. |
1da177e4 LT |
368 | */ |
369 | static int drm_queues_info(char *buf, char **start, off_t offset, int request, | |
b5e89ed5 | 370 | int *eof, void *data) |
1da177e4 | 371 | { |
2c14f28b DA |
372 | struct drm_minor *minor = (struct drm_minor *) data; |
373 | struct drm_device *dev = minor->dev; | |
b5e89ed5 | 374 | int ret; |
1da177e4 | 375 | |
30e2fb18 | 376 | mutex_lock(&dev->struct_mutex); |
1da177e4 | 377 | ret = drm__queues_info(buf, start, offset, request, eof, data); |
30e2fb18 | 378 | mutex_unlock(&dev->struct_mutex); |
1da177e4 LT |
379 | return ret; |
380 | } | |
381 | ||
382 | /** | |
383 | * Called when "/proc/dri/.../bufs" is read. | |
b5e89ed5 | 384 | * |
1da177e4 LT |
385 | * \param buf output buffer. |
386 | * \param start start of output data. | |
387 | * \param offset requested start offset. | |
388 | * \param request requested number of bytes. | |
389 | * \param eof whether there is no more data to return. | |
390 | * \param data private data. | |
391 | * \return number of written bytes. | |
392 | */ | |
393 | static int drm__bufs_info(char *buf, char **start, off_t offset, int request, | |
b5e89ed5 | 394 | int *eof, void *data) |
1da177e4 | 395 | { |
2c14f28b DA |
396 | struct drm_minor *minor = (struct drm_minor *) data; |
397 | struct drm_device *dev = minor->dev; | |
b5e89ed5 | 398 | int len = 0; |
cdd55a29 | 399 | struct drm_device_dma *dma = dev->dma; |
b5e89ed5 | 400 | int i; |
1da177e4 LT |
401 | |
402 | if (!dma || offset > DRM_PROC_LIMIT) { | |
403 | *eof = 1; | |
404 | return 0; | |
405 | } | |
406 | ||
407 | *start = &buf[offset]; | |
b5e89ed5 | 408 | *eof = 0; |
1da177e4 LT |
409 | |
410 | DRM_PROC_PRINT(" o size count free segs pages kB\n\n"); | |
411 | for (i = 0; i <= DRM_MAX_ORDER; i++) { | |
412 | if (dma->bufs[i].buf_count) | |
413 | DRM_PROC_PRINT("%2d %8d %5d %5d %5d %5d %5ld\n", | |
414 | i, | |
415 | dma->bufs[i].buf_size, | |
416 | dma->bufs[i].buf_count, | |
417 | atomic_read(&dma->bufs[i] | |
418 | .freelist.count), | |
419 | dma->bufs[i].seg_count, | |
420 | dma->bufs[i].seg_count | |
b5e89ed5 | 421 | * (1 << dma->bufs[i].page_order), |
1da177e4 LT |
422 | (dma->bufs[i].seg_count |
423 | * (1 << dma->bufs[i].page_order)) | |
424 | * PAGE_SIZE / 1024); | |
425 | } | |
426 | DRM_PROC_PRINT("\n"); | |
427 | for (i = 0; i < dma->buf_count; i++) { | |
b5e89ed5 DA |
428 | if (i && !(i % 32)) |
429 | DRM_PROC_PRINT("\n"); | |
1da177e4 LT |
430 | DRM_PROC_PRINT(" %d", dma->buflist[i]->list); |
431 | } | |
432 | DRM_PROC_PRINT("\n"); | |
433 | ||
b5e89ed5 DA |
434 | if (len > request + offset) |
435 | return request; | |
1da177e4 LT |
436 | *eof = 1; |
437 | return len - offset; | |
438 | } | |
439 | ||
440 | /** | |
30e2fb18 | 441 | * Simply calls _bufs_info() while holding the drm_device::struct_mutex lock. |
1da177e4 LT |
442 | */ |
443 | static int drm_bufs_info(char *buf, char **start, off_t offset, int request, | |
b5e89ed5 | 444 | int *eof, void *data) |
1da177e4 | 445 | { |
2c14f28b DA |
446 | struct drm_minor *minor = (struct drm_minor *) data; |
447 | struct drm_device *dev = minor->dev; | |
b5e89ed5 | 448 | int ret; |
1da177e4 | 449 | |
30e2fb18 | 450 | mutex_lock(&dev->struct_mutex); |
1da177e4 | 451 | ret = drm__bufs_info(buf, start, offset, request, eof, data); |
30e2fb18 | 452 | mutex_unlock(&dev->struct_mutex); |
1da177e4 LT |
453 | return ret; |
454 | } | |
455 | ||
456 | /** | |
457 | * Called when "/proc/dri/.../clients" is read. | |
b5e89ed5 | 458 | * |
1da177e4 LT |
459 | * \param buf output buffer. |
460 | * \param start start of output data. | |
461 | * \param offset requested start offset. | |
462 | * \param request requested number of bytes. | |
463 | * \param eof whether there is no more data to return. | |
464 | * \param data private data. | |
465 | * \return number of written bytes. | |
466 | */ | |
467 | static int drm__clients_info(char *buf, char **start, off_t offset, | |
b5e89ed5 | 468 | int request, int *eof, void *data) |
1da177e4 | 469 | { |
2c14f28b DA |
470 | struct drm_minor *minor = (struct drm_minor *) data; |
471 | struct drm_device *dev = minor->dev; | |
b5e89ed5 | 472 | int len = 0; |
84b1fd10 | 473 | struct drm_file *priv; |
1da177e4 LT |
474 | |
475 | if (offset > DRM_PROC_LIMIT) { | |
476 | *eof = 1; | |
477 | return 0; | |
478 | } | |
479 | ||
480 | *start = &buf[offset]; | |
b5e89ed5 | 481 | *eof = 0; |
1da177e4 LT |
482 | |
483 | DRM_PROC_PRINT("a dev pid uid magic ioctls\n\n"); | |
bd1b331f | 484 | list_for_each_entry(priv, &dev->filelist, lhead) { |
1da177e4 LT |
485 | DRM_PROC_PRINT("%c %3d %5d %5d %10u %10lu\n", |
486 | priv->authenticated ? 'y' : 'n', | |
2c14f28b | 487 | priv->minor->index, |
1da177e4 | 488 | priv->pid, |
b5e89ed5 | 489 | priv->uid, priv->magic, priv->ioctl_count); |
1da177e4 LT |
490 | } |
491 | ||
b5e89ed5 DA |
492 | if (len > request + offset) |
493 | return request; | |
1da177e4 LT |
494 | *eof = 1; |
495 | return len - offset; | |
496 | } | |
497 | ||
498 | /** | |
30e2fb18 | 499 | * Simply calls _clients_info() while holding the drm_device::struct_mutex lock. |
1da177e4 LT |
500 | */ |
501 | static int drm_clients_info(char *buf, char **start, off_t offset, | |
b5e89ed5 | 502 | int request, int *eof, void *data) |
1da177e4 | 503 | { |
2c14f28b DA |
504 | struct drm_minor *minor = (struct drm_minor *) data; |
505 | struct drm_device *dev = minor->dev; | |
b5e89ed5 | 506 | int ret; |
1da177e4 | 507 | |
30e2fb18 | 508 | mutex_lock(&dev->struct_mutex); |
1da177e4 | 509 | ret = drm__clients_info(buf, start, offset, request, eof, data); |
30e2fb18 | 510 | mutex_unlock(&dev->struct_mutex); |
1da177e4 LT |
511 | return ret; |
512 | } | |
513 | ||
673a394b EA |
514 | struct drm_gem_name_info_data { |
515 | int len; | |
516 | char *buf; | |
517 | int eof; | |
518 | }; | |
519 | ||
520 | static int drm_gem_one_name_info(int id, void *ptr, void *data) | |
521 | { | |
522 | struct drm_gem_object *obj = ptr; | |
523 | struct drm_gem_name_info_data *nid = data; | |
524 | ||
1ae87786 | 525 | DRM_INFO("name %d size %zd\n", obj->name, obj->size); |
673a394b EA |
526 | if (nid->eof) |
527 | return 0; | |
528 | ||
529 | nid->len += sprintf(&nid->buf[nid->len], | |
1ae87786 | 530 | "%6d %8zd %7d %8d\n", |
673a394b EA |
531 | obj->name, obj->size, |
532 | atomic_read(&obj->handlecount.refcount), | |
533 | atomic_read(&obj->refcount.refcount)); | |
534 | if (nid->len > DRM_PROC_LIMIT) { | |
535 | nid->eof = 1; | |
536 | return 0; | |
537 | } | |
538 | return 0; | |
539 | } | |
540 | ||
541 | static int drm_gem_name_info(char *buf, char **start, off_t offset, | |
542 | int request, int *eof, void *data) | |
543 | { | |
544 | struct drm_minor *minor = (struct drm_minor *) data; | |
545 | struct drm_device *dev = minor->dev; | |
546 | struct drm_gem_name_info_data nid; | |
547 | ||
548 | if (offset > DRM_PROC_LIMIT) { | |
549 | *eof = 1; | |
550 | return 0; | |
551 | } | |
552 | ||
553 | nid.len = sprintf(buf, " name size handles refcount\n"); | |
554 | nid.buf = buf; | |
555 | nid.eof = 0; | |
556 | idr_for_each(&dev->object_name_idr, drm_gem_one_name_info, &nid); | |
557 | ||
558 | *start = &buf[offset]; | |
559 | *eof = 0; | |
560 | if (nid.len > request + offset) | |
561 | return request; | |
562 | *eof = 1; | |
563 | return nid.len - offset; | |
564 | } | |
565 | ||
566 | static int drm_gem_object_info(char *buf, char **start, off_t offset, | |
567 | int request, int *eof, void *data) | |
568 | { | |
569 | struct drm_minor *minor = (struct drm_minor *) data; | |
570 | struct drm_device *dev = minor->dev; | |
571 | int len = 0; | |
572 | ||
573 | if (offset > DRM_PROC_LIMIT) { | |
574 | *eof = 1; | |
575 | return 0; | |
576 | } | |
577 | ||
578 | *start = &buf[offset]; | |
579 | *eof = 0; | |
580 | DRM_PROC_PRINT("%d objects\n", atomic_read(&dev->object_count)); | |
581 | DRM_PROC_PRINT("%d object bytes\n", atomic_read(&dev->object_memory)); | |
582 | DRM_PROC_PRINT("%d pinned\n", atomic_read(&dev->pin_count)); | |
583 | DRM_PROC_PRINT("%d pin bytes\n", atomic_read(&dev->pin_memory)); | |
584 | DRM_PROC_PRINT("%d gtt bytes\n", atomic_read(&dev->gtt_memory)); | |
585 | DRM_PROC_PRINT("%d gtt total\n", dev->gtt_total); | |
586 | if (len > request + offset) | |
587 | return request; | |
588 | *eof = 1; | |
589 | return len - offset; | |
590 | } | |
591 | ||
1da177e4 LT |
592 | #if DRM_DEBUG_CODE |
593 | ||
594 | static int drm__vma_info(char *buf, char **start, off_t offset, int request, | |
b5e89ed5 | 595 | int *eof, void *data) |
1da177e4 | 596 | { |
2c14f28b DA |
597 | struct drm_minor *minor = (struct drm_minor *) data; |
598 | struct drm_device *dev = minor->dev; | |
b5e89ed5 | 599 | int len = 0; |
8fc2fdf4 | 600 | struct drm_vma_entry *pt; |
1da177e4 LT |
601 | struct vm_area_struct *vma; |
602 | #if defined(__i386__) | |
b5e89ed5 | 603 | unsigned int pgprot; |
1da177e4 LT |
604 | #endif |
605 | ||
606 | if (offset > DRM_PROC_LIMIT) { | |
607 | *eof = 1; | |
608 | return 0; | |
609 | } | |
610 | ||
611 | *start = &buf[offset]; | |
b5e89ed5 | 612 | *eof = 0; |
1da177e4 LT |
613 | |
614 | DRM_PROC_PRINT("vma use count: %d, high_memory = %p, 0x%08lx\n", | |
615 | atomic_read(&dev->vma_count), | |
616 | high_memory, virt_to_phys(high_memory)); | |
bd1b331f | 617 | list_for_each_entry(pt, &dev->vmalist, head) { |
b5e89ed5 DA |
618 | if (!(vma = pt->vma)) |
619 | continue; | |
1545085a | 620 | DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx000", |
1da177e4 LT |
621 | pt->pid, |
622 | vma->vm_start, | |
623 | vma->vm_end, | |
b5e89ed5 DA |
624 | vma->vm_flags & VM_READ ? 'r' : '-', |
625 | vma->vm_flags & VM_WRITE ? 'w' : '-', | |
626 | vma->vm_flags & VM_EXEC ? 'x' : '-', | |
1da177e4 | 627 | vma->vm_flags & VM_MAYSHARE ? 's' : 'p', |
b5e89ed5 DA |
628 | vma->vm_flags & VM_LOCKED ? 'l' : '-', |
629 | vma->vm_flags & VM_IO ? 'i' : '-', | |
1545085a | 630 | vma->vm_pgoff); |
1da177e4 LT |
631 | |
632 | #if defined(__i386__) | |
633 | pgprot = pgprot_val(vma->vm_page_prot); | |
634 | DRM_PROC_PRINT(" %c%c%c%c%c%c%c%c%c", | |
b5e89ed5 DA |
635 | pgprot & _PAGE_PRESENT ? 'p' : '-', |
636 | pgprot & _PAGE_RW ? 'w' : 'r', | |
637 | pgprot & _PAGE_USER ? 'u' : 's', | |
638 | pgprot & _PAGE_PWT ? 't' : 'b', | |
639 | pgprot & _PAGE_PCD ? 'u' : 'c', | |
1da177e4 | 640 | pgprot & _PAGE_ACCESSED ? 'a' : '-', |
b5e89ed5 DA |
641 | pgprot & _PAGE_DIRTY ? 'd' : '-', |
642 | pgprot & _PAGE_PSE ? 'm' : 'k', | |
643 | pgprot & _PAGE_GLOBAL ? 'g' : 'l'); | |
1da177e4 LT |
644 | #endif |
645 | DRM_PROC_PRINT("\n"); | |
646 | } | |
647 | ||
b5e89ed5 DA |
648 | if (len > request + offset) |
649 | return request; | |
1da177e4 LT |
650 | *eof = 1; |
651 | return len - offset; | |
652 | } | |
653 | ||
654 | static int drm_vma_info(char *buf, char **start, off_t offset, int request, | |
b5e89ed5 | 655 | int *eof, void *data) |
1da177e4 | 656 | { |
2c14f28b DA |
657 | struct drm_minor *minor = (struct drm_minor *) data; |
658 | struct drm_device *dev = minor->dev; | |
b5e89ed5 | 659 | int ret; |
1da177e4 | 660 | |
30e2fb18 | 661 | mutex_lock(&dev->struct_mutex); |
1da177e4 | 662 | ret = drm__vma_info(buf, start, offset, request, eof, data); |
30e2fb18 | 663 | mutex_unlock(&dev->struct_mutex); |
1da177e4 LT |
664 | return ret; |
665 | } | |
666 | #endif |