Import 2.3.18pre1
[davej-history.git] / drivers / char / drm / proc.c
blob7db90aea8f43db7c89a435a6749a8ec4875d2fbd
1 /* proc.c -- /proc support for DRM -*- linux-c -*-
2 * Created: Mon Jan 11 09:48:47 1999 by faith@precisioninsight.com
3 * Revised: Fri Aug 20 11:31:48 1999 by faith@precisioninsight.com
5 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
6 * All Rights Reserved.
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
27 * $PI: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/generic/proc.c,v 1.4 1999/08/20 15:36:46 faith Exp $
28 * $XFree86$
32 #define __NO_VERSION__
33 #include "drmP.h"
35 static struct proc_dir_entry *drm_root = NULL;
36 static struct proc_dir_entry *drm_dev_root = NULL;
37 static char drm_slot_name[64];
39 static int drm_name_info(char *buf, char **start, off_t offset,
40 int len, int *eof, void *data);
41 static int drm_vm_info(char *buf, char **start, off_t offset,
42 int len, int *eof, void *data);
43 static int drm_clients_info(char *buf, char **start, off_t offset,
44 int len, int *eof, void *data);
45 static int drm_queues_info(char *buf, char **start, off_t offset,
46 int len, int *eof, void *data);
47 static int drm_bufs_info(char *buf, char **start, off_t offset,
48 int len, int *eof, void *data);
49 #if DRM_DEBUG_CODE
50 static int drm_vma_info(char *buf, char **start, off_t offset,
51 int len, int *eof, void *data);
52 #endif
53 #if DRM_DMA_HISTOGRAM
54 static int drm_histo_info(char *buf, char **start, off_t offset,
55 int len, int *eof, void *data);
56 #endif
58 struct drm_proc_list {
59 const char *name;
60 int (*f)(char *, char **, off_t, int, int *, void *);
61 } drm_proc_list[] = {
62 { "name", drm_name_info },
63 { "mem", drm_mem_info },
64 { "vm", drm_vm_info },
65 { "clients", drm_clients_info },
66 { "queues", drm_queues_info },
67 { "bufs", drm_bufs_info },
68 #if DRM_DEBUG_CODE
69 { "vma", drm_vma_info },
70 #endif
71 #if DRM_DMA_HISTOGRAM
72 { "histo", drm_histo_info },
73 #endif
75 #define DRM_PROC_ENTRIES (sizeof(drm_proc_list)/sizeof(drm_proc_list[0]))
77 int drm_proc_init(drm_device_t *dev)
79 struct proc_dir_entry *ent;
80 int i, j;
82 drm_root = create_proc_entry("video", S_IFDIR, NULL);
83 if (!drm_root) {
84 DRM_ERROR("Cannot create /proc/video\n");
85 return -1;
88 /* Instead of doing this search, we should
89 add some global support for /proc/video. */
90 for (i = 0; i < 8; i++) {
91 sprintf(drm_slot_name, "video/%d", i);
92 drm_dev_root = create_proc_entry(drm_slot_name, S_IFDIR, NULL);
93 if (!drm_dev_root) {
94 DRM_ERROR("Cannot create /proc/%s\n", drm_slot_name);
95 remove_proc_entry("video", NULL);
97 if (drm_dev_root->nlink == 2) break;
98 drm_dev_root = NULL;
100 if (!drm_dev_root) {
101 DRM_ERROR("Cannot find slot in /proc/video\n");
102 return -1;
105 for (i = 0; i < DRM_PROC_ENTRIES; i++) {
106 ent = create_proc_entry(drm_proc_list[i].name,
107 S_IFREG|S_IRUGO, drm_dev_root);
108 if (!ent) {
109 DRM_ERROR("Cannot create /proc/%s/%s\n",
110 drm_slot_name, drm_proc_list[i].name);
111 for (j = 0; j < i; j++)
112 remove_proc_entry(drm_proc_list[i].name,
113 drm_dev_root);
114 remove_proc_entry(drm_slot_name, NULL);
115 remove_proc_entry("video", NULL);
116 return -1;
118 ent->read_proc = drm_proc_list[i].f;
119 ent->data = dev;
122 return 0;
126 int drm_proc_cleanup(void)
128 int i;
130 if (drm_root) {
131 if (drm_dev_root) {
132 for (i = 0; i < DRM_PROC_ENTRIES; i++) {
133 remove_proc_entry(drm_proc_list[i].name,
134 drm_dev_root);
136 remove_proc_entry(drm_slot_name, NULL);
138 remove_proc_entry("video", NULL);
139 remove_proc_entry(DRM_NAME, NULL);
141 drm_root = drm_dev_root = NULL;
142 return 0;
145 static int drm_name_info(char *buf, char **start, off_t offset, int len,
146 int *eof, void *data)
148 drm_device_t *dev = (drm_device_t *)data;
150 if (offset > 0) return 0; /* no partial requests */
151 len = 0;
152 *eof = 1;
154 if (dev->unique) {
155 DRM_PROC_PRINT("%s 0x%x %s\n",
156 dev->name, dev->device, dev->unique);
157 } else {
158 DRM_PROC_PRINT("%s 0x%x\n", dev->name, dev->device);
160 return len;
163 static int _drm_vm_info(char *buf, char **start, off_t offset, int len,
164 int *eof, void *data)
166 drm_device_t *dev = (drm_device_t *)data;
167 drm_map_t *map;
168 const char *types[] = { "FB", "REG", "SHM" };
169 const char *type;
170 int i;
172 if (offset > 0) return 0; /* no partial requests */
173 len = 0;
174 *eof = 1;
175 DRM_PROC_PRINT("slot offset size type flags "
176 "address mtrr\n\n");
177 for (i = 0; i < dev->map_count; i++) {
178 map = dev->maplist[i];
179 if (map->type < 0 || map->type > 2) type = "??";
180 else type = types[map->type];
181 DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08lx ",
183 map->offset,
184 map->size,
185 type,
186 map->flags,
187 (unsigned long)map->handle);
188 if (map->mtrr < 0) {
189 DRM_PROC_PRINT("none\n");
190 } else {
191 DRM_PROC_PRINT("%4d\n", map->mtrr);
195 return len;
198 static int drm_vm_info(char *buf, char **start, off_t offset, int len,
199 int *eof, void *data)
201 drm_device_t *dev = (drm_device_t *)data;
202 int ret;
204 down(&dev->struct_sem);
205 ret = _drm_vm_info(buf, start, offset, len, eof, data);
206 up(&dev->struct_sem);
207 return ret;
211 static int _drm_queues_info(char *buf, char **start, off_t offset, int len,
212 int *eof, void *data)
214 drm_device_t *dev = (drm_device_t *)data;
215 int i;
216 drm_queue_t *q;
218 if (offset > 0) return 0; /* no partial requests */
219 len = 0;
220 *eof = 1;
221 DRM_PROC_PRINT(" ctx/flags use fin"
222 " blk/rw/rwf wait flushed queued"
223 " locks\n\n");
224 for (i = 0; i < dev->queue_count; i++) {
225 q = dev->queuelist[i];
226 atomic_inc(&q->use_count);
227 DRM_PROC_PRINT_RET(atomic_dec(&q->use_count),
228 "%5d/0x%03x %5d %5d"
229 " %5d/%c%c/%c%c%c %5d %10d %10d %10d\n",
231 q->flags,
232 atomic_read(&q->use_count),
233 atomic_read(&q->finalization),
234 atomic_read(&q->block_count),
235 atomic_read(&q->block_read) ? 'r' : '-',
236 atomic_read(&q->block_write) ? 'w' : '-',
237 waitqueue_active(&q->read_queue) ? 'r':'-',
238 waitqueue_active(&q->write_queue) ? 'w':'-',
239 waitqueue_active(&q->flush_queue) ? 'f':'-',
240 DRM_BUFCOUNT(&q->waitlist),
241 atomic_read(&q->total_flushed),
242 atomic_read(&q->total_queued),
243 atomic_read(&q->total_locks));
244 atomic_dec(&q->use_count);
247 return len;
250 static int drm_queues_info(char *buf, char **start, off_t offset, int len,
251 int *eof, void *data)
253 drm_device_t *dev = (drm_device_t *)data;
254 int ret;
256 down(&dev->struct_sem);
257 ret = _drm_queues_info(buf, start, offset, len, eof, data);
258 up(&dev->struct_sem);
259 return ret;
262 /* drm_bufs_info is called whenever a process reads
263 /dev/drm/<dev>/bufs. */
265 static int _drm_bufs_info(char *buf, char **start, off_t offset, int len,
266 int *eof, void *data)
268 drm_device_t *dev = (drm_device_t *)data;
269 drm_device_dma_t *dma = dev->dma;
270 int i;
272 if (!dma) return 0;
273 if (offset > 0) return 0; /* no partial requests */
274 len = 0;
275 *eof = 1;
276 DRM_PROC_PRINT(" o size count free segs pages kB\n\n");
277 for (i = 0; i <= DRM_MAX_ORDER; i++) {
278 if (dma->bufs[i].buf_count)
279 DRM_PROC_PRINT("%2d %8d %5d %5d %5d %5d %5ld\n",
281 dma->bufs[i].buf_size,
282 dma->bufs[i].buf_count,
283 atomic_read(&dma->bufs[i]
284 .freelist.count),
285 dma->bufs[i].seg_count,
286 dma->bufs[i].seg_count
287 *(1 << dma->bufs[i].page_order),
288 (dma->bufs[i].seg_count
289 * (1 << dma->bufs[i].page_order))
290 * PAGE_SIZE / 1024);
292 DRM_PROC_PRINT("\n");
293 for (i = 0; i < dma->buf_count; i++) {
294 if (i && !(i%32)) DRM_PROC_PRINT("\n");
295 DRM_PROC_PRINT(" %d", dma->buflist[i]->list);
297 DRM_PROC_PRINT("\n");
299 return len;
302 static int drm_bufs_info(char *buf, char **start, off_t offset, int len,
303 int *eof, void *data)
305 drm_device_t *dev = (drm_device_t *)data;
306 int ret;
308 down(&dev->struct_sem);
309 ret = _drm_bufs_info(buf, start, offset, len, eof, data);
310 up(&dev->struct_sem);
311 return ret;
315 static int _drm_clients_info(char *buf, char **start, off_t offset, int len,
316 int *eof, void *data)
318 drm_device_t *dev = (drm_device_t *)data;
319 drm_file_t *priv;
321 if (offset > 0) return 0; /* no partial requests */
322 len = 0;
323 *eof = 1;
324 DRM_PROC_PRINT("a dev pid uid magic ioctls\n\n");
325 for (priv = dev->file_first; priv; priv = priv->next) {
326 DRM_PROC_PRINT("%c %3d %5d %5d %10u %10lu\n",
327 priv->authenticated ? 'y' : 'n',
328 priv->minor,
329 priv->pid,
330 priv->uid,
331 priv->magic,
332 priv->ioctl_count);
335 return len;
338 static int drm_clients_info(char *buf, char **start, off_t offset, int len,
339 int *eof, void *data)
341 drm_device_t *dev = (drm_device_t *)data;
342 int ret;
344 down(&dev->struct_sem);
345 ret = _drm_clients_info(buf, start, offset, len, eof, data);
346 up(&dev->struct_sem);
347 return ret;
350 #if DRM_DEBUG_CODE
352 static int _drm_vma_info(char *buf, char **start, off_t offset, int len,
353 int *eof, void *data)
355 drm_device_t *dev = (drm_device_t *)data;
356 drm_vma_entry_t *pt;
357 pgd_t *pgd;
358 pmd_t *pmd;
359 pte_t *pte;
360 unsigned long i;
361 struct vm_area_struct *vma;
362 unsigned long address;
363 #if defined(__i386__)
364 unsigned int pgprot;
365 #endif
367 if (offset > 0) return 0; /* no partial requests */
368 len = 0;
369 *eof = 1;
370 DRM_PROC_PRINT("vma use count: %d, high_memory = %p, 0x%08lx\n",
371 atomic_read(&dev->vma_count),
372 high_memory, virt_to_phys(high_memory));
373 for (pt = dev->vmalist; pt; pt = pt->next) {
374 if (!(vma = pt->vma)) continue;
375 DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx",
376 pt->pid,
377 vma->vm_start,
378 vma->vm_end,
379 vma->vm_flags & VM_READ ? 'r' : '-',
380 vma->vm_flags & VM_WRITE ? 'w' : '-',
381 vma->vm_flags & VM_EXEC ? 'x' : '-',
382 vma->vm_flags & VM_MAYSHARE ? 's' : 'p',
383 vma->vm_flags & VM_LOCKED ? 'l' : '-',
384 vma->vm_flags & VM_IO ? 'i' : '-',
385 vma->vm_offset );
386 #if defined(__i386__)
387 pgprot = pgprot_val(vma->vm_page_prot);
388 DRM_PROC_PRINT(" %c%c%c%c%c%c%c%c%c",
389 pgprot & _PAGE_PRESENT ? 'p' : '-',
390 pgprot & _PAGE_RW ? 'w' : 'r',
391 pgprot & _PAGE_USER ? 'u' : 's',
392 pgprot & _PAGE_PWT ? 't' : 'b',
393 pgprot & _PAGE_PCD ? 'u' : 'c',
394 pgprot & _PAGE_ACCESSED ? 'a' : '-',
395 pgprot & _PAGE_DIRTY ? 'd' : '-',
396 pgprot & _PAGE_4M ? 'm' : 'k',
397 pgprot & _PAGE_GLOBAL ? 'g' : 'l' );
398 #endif
399 DRM_PROC_PRINT("\n");
400 for (i = vma->vm_start; i < vma->vm_end; i += PAGE_SIZE) {
401 pgd = pgd_offset(vma->vm_mm, i);
402 pmd = pmd_offset(pgd, i);
403 pte = pte_offset(pmd, i);
404 if (pte_present(*pte)) {
405 address = __pa(pte_page(*pte))
406 + (i & (PAGE_SIZE-1));
407 DRM_PROC_PRINT(" 0x%08lx -> 0x%08lx"
408 " %c%c%c%c%c\n",
410 address,
411 pte_read(*pte) ? 'r' : '-',
412 pte_write(*pte) ? 'w' : '-',
413 pte_exec(*pte) ? 'x' : '-',
414 pte_dirty(*pte) ? 'd' : '-',
415 pte_young(*pte) ? 'a' : '-' );
416 } else {
417 DRM_PROC_PRINT(" 0x%08lx\n", i);
422 return len;
425 static int drm_vma_info(char *buf, char **start, off_t offset, int len,
426 int *eof, void *data)
428 drm_device_t *dev = (drm_device_t *)data;
429 int ret;
431 down(&dev->struct_sem);
432 ret = _drm_vma_info(buf, start, offset, len, eof, data);
433 up(&dev->struct_sem);
434 return ret;
436 #endif
439 #if DRM_DMA_HISTOGRAM
440 static int _drm_histo_info(char *buf, char **start, off_t offset, int len,
441 int *eof, void *data)
443 drm_device_t *dev = (drm_device_t *)data;
444 drm_device_dma_t *dma = dev->dma;
445 int i;
446 unsigned long slot_value = DRM_DMA_HISTOGRAM_INITIAL;
447 unsigned long prev_value = 0;
448 drm_buf_t *buffer;
450 if (offset > 0) return 0; /* no partial requests */
451 len = 0;
452 *eof = 1;
454 DRM_PROC_PRINT("general statistics:\n");
455 DRM_PROC_PRINT("total %10u\n", atomic_read(&dev->histo.total));
456 DRM_PROC_PRINT("open %10u\n", atomic_read(&dev->total_open));
457 DRM_PROC_PRINT("close %10u\n", atomic_read(&dev->total_close));
458 DRM_PROC_PRINT("ioctl %10u\n", atomic_read(&dev->total_ioctl));
459 DRM_PROC_PRINT("irq %10u\n", atomic_read(&dev->total_irq));
460 DRM_PROC_PRINT("ctx %10u\n", atomic_read(&dev->total_ctx));
462 DRM_PROC_PRINT("\nlock statistics:\n");
463 DRM_PROC_PRINT("locks %10u\n", atomic_read(&dev->total_locks));
464 DRM_PROC_PRINT("unlocks %10u\n", atomic_read(&dev->total_unlocks));
465 DRM_PROC_PRINT("contends %10u\n", atomic_read(&dev->total_contends));
466 DRM_PROC_PRINT("sleeps %10u\n", atomic_read(&dev->total_sleeps));
469 if (dma) {
470 DRM_PROC_PRINT("\ndma statistics:\n");
471 DRM_PROC_PRINT("prio %10u\n",
472 atomic_read(&dma->total_prio));
473 DRM_PROC_PRINT("bytes %10u\n",
474 atomic_read(&dma->total_bytes));
475 DRM_PROC_PRINT("dmas %10u\n",
476 atomic_read(&dma->total_dmas));
477 DRM_PROC_PRINT("missed:\n");
478 DRM_PROC_PRINT(" dma %10u\n",
479 atomic_read(&dma->total_missed_dma));
480 DRM_PROC_PRINT(" lock %10u\n",
481 atomic_read(&dma->total_missed_lock));
482 DRM_PROC_PRINT(" free %10u\n",
483 atomic_read(&dma->total_missed_free));
484 DRM_PROC_PRINT(" sched %10u\n",
485 atomic_read(&dma->total_missed_sched));
486 DRM_PROC_PRINT("tried %10u\n",
487 atomic_read(&dma->total_tried));
488 DRM_PROC_PRINT("hit %10u\n",
489 atomic_read(&dma->total_hit));
490 DRM_PROC_PRINT("lost %10u\n",
491 atomic_read(&dma->total_lost));
493 buffer = dma->next_buffer;
494 if (buffer) {
495 DRM_PROC_PRINT("next_buffer %7d\n", buffer->idx);
496 } else {
497 DRM_PROC_PRINT("next_buffer none\n");
499 buffer = dma->this_buffer;
500 if (buffer) {
501 DRM_PROC_PRINT("this_buffer %7d\n", buffer->idx);
502 } else {
503 DRM_PROC_PRINT("this_buffer none\n");
508 DRM_PROC_PRINT("\nvalues:\n");
509 if (dev->lock.hw_lock) {
510 DRM_PROC_PRINT("lock 0x%08x\n",
511 dev->lock.hw_lock->lock);
512 } else {
513 DRM_PROC_PRINT("lock none\n");
515 DRM_PROC_PRINT("context_flag 0x%08x\n", dev->context_flag);
516 DRM_PROC_PRINT("interrupt_flag 0x%08x\n", dev->interrupt_flag);
517 DRM_PROC_PRINT("dma_flag 0x%08x\n", dev->dma_flag);
519 DRM_PROC_PRINT("queue_count %10d\n", dev->queue_count);
520 DRM_PROC_PRINT("last_context %10d\n", dev->last_context);
521 DRM_PROC_PRINT("last_switch %10lu\n", dev->last_switch);
522 DRM_PROC_PRINT("last_checked %10d\n", dev->last_checked);
525 DRM_PROC_PRINT("\n q2d d2c c2f"
526 " q2c q2f dma sch"
527 " ctx lacq lhld\n\n");
528 for (i = 0; i < DRM_DMA_HISTOGRAM_SLOTS; i++) {
529 DRM_PROC_PRINT("%s %10lu %10u %10u %10u %10u %10u"
530 " %10u %10u %10u %10u %10u\n",
531 i == DRM_DMA_HISTOGRAM_SLOTS - 1 ? ">=" : "< ",
532 i == DRM_DMA_HISTOGRAM_SLOTS - 1
533 ? prev_value : slot_value ,
535 atomic_read(&dev->histo
536 .queued_to_dispatched[i]),
537 atomic_read(&dev->histo
538 .dispatched_to_completed[i]),
539 atomic_read(&dev->histo
540 .completed_to_freed[i]),
542 atomic_read(&dev->histo
543 .queued_to_completed[i]),
544 atomic_read(&dev->histo
545 .queued_to_freed[i]),
546 atomic_read(&dev->histo.dma[i]),
547 atomic_read(&dev->histo.schedule[i]),
548 atomic_read(&dev->histo.ctx[i]),
549 atomic_read(&dev->histo.lacq[i]),
550 atomic_read(&dev->histo.lhld[i]));
551 prev_value = slot_value;
552 slot_value = DRM_DMA_HISTOGRAM_NEXT(slot_value);
554 return len;
557 static int drm_histo_info(char *buf, char **start, off_t offset, int len,
558 int *eof, void *data)
560 drm_device_t *dev = (drm_device_t *)data;
561 int ret;
563 down(&dev->struct_sem);
564 ret = _drm_histo_info(buf, start, offset, len, eof, data);
565 up(&dev->struct_sem);
566 return ret;
568 #endif