Ok. I didn't make 2.4.0 in 2000. Tough. I tried, but we had some
[davej-history.git] / drivers / char / drm / proc.c
blobca062a09bd0d016a0dadb3872efdda2b78c2ff86
1 /* proc.c -- /proc support for DRM -*- linux-c -*-
2 * Created: Mon Jan 11 09:48:47 1999 by faith@precisioninsight.com
4 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
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 * Authors:
28 * Rickard E. (Rik) Faith <faith@valinux.com>
31 #define __NO_VERSION__
32 #include "drmP.h"
34 static struct proc_dir_entry *drm_root = NULL;
35 static struct proc_dir_entry *drm_dev_root = NULL;
36 static char drm_slot_name[64];
38 static int drm_name_info(char *buf, char **start, off_t offset,
39 int len, int *eof, void *data);
40 static int drm_vm_info(char *buf, char **start, off_t offset,
41 int len, int *eof, void *data);
42 static int drm_clients_info(char *buf, char **start, off_t offset,
43 int len, int *eof, void *data);
44 static int drm_queues_info(char *buf, char **start, off_t offset,
45 int len, int *eof, void *data);
46 static int drm_bufs_info(char *buf, char **start, off_t offset,
47 int len, int *eof, void *data);
48 #if DRM_DEBUG_CODE
49 static int drm_vma_info(char *buf, char **start, off_t offset,
50 int len, int *eof, void *data);
51 #endif
52 #if DRM_DMA_HISTOGRAM
53 static int drm_histo_info(char *buf, char **start, off_t offset,
54 int len, int *eof, void *data);
55 #endif
57 struct drm_proc_list {
58 const char *name;
59 int (*f)(char *, char **, off_t, int, int *, void *);
60 } drm_proc_list[] = {
61 { "name", drm_name_info },
62 { "mem", drm_mem_info },
63 { "vm", drm_vm_info },
64 { "clients", drm_clients_info },
65 { "queues", drm_queues_info },
66 { "bufs", drm_bufs_info },
67 #if DRM_DEBUG_CODE
68 { "vma", drm_vma_info },
69 #endif
70 #if DRM_DMA_HISTOGRAM
71 { "histo", drm_histo_info },
72 #endif
74 #define DRM_PROC_ENTRIES (sizeof(drm_proc_list)/sizeof(drm_proc_list[0]))
76 int drm_proc_init(drm_device_t *dev)
78 struct proc_dir_entry *ent;
79 int i, j;
81 drm_root = create_proc_entry("dri", S_IFDIR, NULL);
82 if (!drm_root) {
83 DRM_ERROR("Cannot create /proc/dri\n");
84 return -1;
87 /* Instead of doing this search, we should
88 add some global support for /proc/dri. */
89 for (i = 0; i < 8; i++) {
90 sprintf(drm_slot_name, "dri/%d", i);
91 drm_dev_root = create_proc_entry(drm_slot_name, S_IFDIR, NULL);
92 if (!drm_dev_root) {
93 DRM_ERROR("Cannot create /proc/%s\n", drm_slot_name);
94 remove_proc_entry("dri", NULL);
96 if (drm_dev_root->nlink == 2) break;
97 drm_dev_root = NULL;
99 if (!drm_dev_root) {
100 DRM_ERROR("Cannot find slot in /proc/dri\n");
101 return -1;
104 for (i = 0; i < DRM_PROC_ENTRIES; i++) {
105 ent = create_proc_entry(drm_proc_list[i].name,
106 S_IFREG|S_IRUGO, drm_dev_root);
107 if (!ent) {
108 DRM_ERROR("Cannot create /proc/%s/%s\n",
109 drm_slot_name, drm_proc_list[i].name);
110 for (j = 0; j < i; j++)
111 remove_proc_entry(drm_proc_list[i].name,
112 drm_dev_root);
113 remove_proc_entry(drm_slot_name, NULL);
114 remove_proc_entry("dri", NULL);
115 return -1;
117 ent->read_proc = drm_proc_list[i].f;
118 ent->data = dev;
121 return 0;
125 int drm_proc_cleanup(void)
127 int i;
129 if (drm_root) {
130 if (drm_dev_root) {
131 for (i = 0; i < DRM_PROC_ENTRIES; i++) {
132 remove_proc_entry(drm_proc_list[i].name,
133 drm_dev_root);
135 remove_proc_entry(drm_slot_name, NULL);
137 remove_proc_entry("dri", NULL);
138 remove_proc_entry(DRM_NAME, NULL);
140 drm_root = drm_dev_root = NULL;
141 return 0;
144 static int drm_name_info(char *buf, char **start, off_t offset, int len,
145 int *eof, void *data)
147 drm_device_t *dev = (drm_device_t *)data;
149 if (offset > 0) return 0; /* no partial requests */
150 len = 0;
151 *eof = 1;
153 if (dev->unique) {
154 DRM_PROC_PRINT("%s 0x%x %s\n",
155 dev->name, dev->device, dev->unique);
156 } else {
157 DRM_PROC_PRINT("%s 0x%x\n", dev->name, dev->device);
159 return len;
162 static int _drm_vm_info(char *buf, char **start, off_t offset, int len,
163 int *eof, void *data)
165 drm_device_t *dev = (drm_device_t *)data;
166 drm_map_t *map;
167 /* Hardcoded from _DRM_FRAME_BUFFER,
168 _DRM_REGISTERS, _DRM_SHM, and
169 _DRM_AGP. */
170 const char *types[] = { "FB", "REG", "SHM", "AGP" };
171 const char *type;
172 int i;
174 if (offset > 0) return 0; /* no partial requests */
175 len = 0;
176 *eof = 1;
177 DRM_PROC_PRINT("slot offset size type flags "
178 "address mtrr\n\n");
179 for (i = 0; i < dev->map_count; i++) {
180 map = dev->maplist[i];
181 if (map->type < 0 || map->type > 3) type = "??";
182 else type = types[map->type];
183 DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08lx ",
185 map->offset,
186 map->size,
187 type,
188 map->flags,
189 (unsigned long)map->handle);
190 if (map->mtrr < 0) {
191 DRM_PROC_PRINT("none\n");
192 } else {
193 DRM_PROC_PRINT("%4d\n", map->mtrr);
197 return len;
200 static int drm_vm_info(char *buf, char **start, off_t offset, int len,
201 int *eof, void *data)
203 drm_device_t *dev = (drm_device_t *)data;
204 int ret;
206 down(&dev->struct_sem);
207 ret = _drm_vm_info(buf, start, offset, len, eof, data);
208 up(&dev->struct_sem);
209 return ret;
213 static int _drm_queues_info(char *buf, char **start, off_t offset, int len,
214 int *eof, void *data)
216 drm_device_t *dev = (drm_device_t *)data;
217 int i;
218 drm_queue_t *q;
220 if (offset > 0) return 0; /* no partial requests */
221 len = 0;
222 *eof = 1;
223 DRM_PROC_PRINT(" ctx/flags use fin"
224 " blk/rw/rwf wait flushed queued"
225 " locks\n\n");
226 for (i = 0; i < dev->queue_count; i++) {
227 q = dev->queuelist[i];
228 atomic_inc(&q->use_count);
229 DRM_PROC_PRINT_RET(atomic_dec(&q->use_count),
230 "%5d/0x%03x %5d %5d"
231 " %5d/%c%c/%c%c%c %5Zd %10d %10d %10d\n",
233 q->flags,
234 atomic_read(&q->use_count),
235 atomic_read(&q->finalization),
236 atomic_read(&q->block_count),
237 atomic_read(&q->block_read) ? 'r' : '-',
238 atomic_read(&q->block_write) ? 'w' : '-',
239 waitqueue_active(&q->read_queue) ? 'r':'-',
240 waitqueue_active(&q->write_queue) ? 'w':'-',
241 waitqueue_active(&q->flush_queue) ? 'f':'-',
242 DRM_BUFCOUNT(&q->waitlist),
243 atomic_read(&q->total_flushed),
244 atomic_read(&q->total_queued),
245 atomic_read(&q->total_locks));
246 atomic_dec(&q->use_count);
249 return len;
252 static int drm_queues_info(char *buf, char **start, off_t offset, int len,
253 int *eof, void *data)
255 drm_device_t *dev = (drm_device_t *)data;
256 int ret;
258 down(&dev->struct_sem);
259 ret = _drm_queues_info(buf, start, offset, len, eof, data);
260 up(&dev->struct_sem);
261 return ret;
264 /* drm_bufs_info is called whenever a process reads
265 /dev/drm/<dev>/bufs. */
267 static int _drm_bufs_info(char *buf, char **start, off_t offset, int len,
268 int *eof, void *data)
270 drm_device_t *dev = (drm_device_t *)data;
271 drm_device_dma_t *dma = dev->dma;
272 int i;
274 if (!dma) return 0;
275 if (offset > 0) return 0; /* no partial requests */
276 len = 0;
277 *eof = 1;
278 DRM_PROC_PRINT(" o size count free segs pages kB\n\n");
279 for (i = 0; i <= DRM_MAX_ORDER; i++) {
280 if (dma->bufs[i].buf_count)
281 DRM_PROC_PRINT("%2d %8d %5d %5d %5d %5d %5ld\n",
283 dma->bufs[i].buf_size,
284 dma->bufs[i].buf_count,
285 atomic_read(&dma->bufs[i]
286 .freelist.count),
287 dma->bufs[i].seg_count,
288 dma->bufs[i].seg_count
289 *(1 << dma->bufs[i].page_order),
290 (dma->bufs[i].seg_count
291 * (1 << dma->bufs[i].page_order))
292 * PAGE_SIZE / 1024);
294 DRM_PROC_PRINT("\n");
295 for (i = 0; i < dma->buf_count; i++) {
296 if (i && !(i%32)) DRM_PROC_PRINT("\n");
297 DRM_PROC_PRINT(" %d", dma->buflist[i]->list);
299 DRM_PROC_PRINT("\n");
301 return len;
304 static int drm_bufs_info(char *buf, char **start, off_t offset, int len,
305 int *eof, void *data)
307 drm_device_t *dev = (drm_device_t *)data;
308 int ret;
310 down(&dev->struct_sem);
311 ret = _drm_bufs_info(buf, start, offset, len, eof, data);
312 up(&dev->struct_sem);
313 return ret;
317 static int _drm_clients_info(char *buf, char **start, off_t offset, int len,
318 int *eof, void *data)
320 drm_device_t *dev = (drm_device_t *)data;
321 drm_file_t *priv;
323 if (offset > 0) return 0; /* no partial requests */
324 len = 0;
325 *eof = 1;
326 DRM_PROC_PRINT("a dev pid uid magic ioctls\n\n");
327 for (priv = dev->file_first; priv; priv = priv->next) {
328 DRM_PROC_PRINT("%c %3d %5d %5d %10u %10lu\n",
329 priv->authenticated ? 'y' : 'n',
330 priv->minor,
331 priv->pid,
332 priv->uid,
333 priv->magic,
334 priv->ioctl_count);
337 return len;
340 static int drm_clients_info(char *buf, char **start, off_t offset, int len,
341 int *eof, void *data)
343 drm_device_t *dev = (drm_device_t *)data;
344 int ret;
346 down(&dev->struct_sem);
347 ret = _drm_clients_info(buf, start, offset, len, eof, data);
348 up(&dev->struct_sem);
349 return ret;
352 #if DRM_DEBUG_CODE
354 #define DRM_VMA_VERBOSE 0
356 static int _drm_vma_info(char *buf, char **start, off_t offset, int len,
357 int *eof, void *data)
359 drm_device_t *dev = (drm_device_t *)data;
360 drm_vma_entry_t *pt;
361 struct vm_area_struct *vma;
362 #if DRM_VMA_VERBOSE
363 unsigned long i;
364 unsigned long address;
365 pgd_t *pgd;
366 pmd_t *pmd;
367 pte_t *pte;
368 #endif
369 #if defined(__i386__)
370 unsigned int pgprot;
371 #endif
373 if (offset > 0) return 0; /* no partial requests */
374 len = 0;
375 *eof = 1;
376 DRM_PROC_PRINT("vma use count: %d, high_memory = %p, 0x%08lx\n",
377 atomic_read(&dev->vma_count),
378 high_memory, virt_to_phys(high_memory));
379 for (pt = dev->vmalist; pt; pt = pt->next) {
380 if (!(vma = pt->vma)) continue;
381 DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx",
382 pt->pid,
383 vma->vm_start,
384 vma->vm_end,
385 vma->vm_flags & VM_READ ? 'r' : '-',
386 vma->vm_flags & VM_WRITE ? 'w' : '-',
387 vma->vm_flags & VM_EXEC ? 'x' : '-',
388 vma->vm_flags & VM_MAYSHARE ? 's' : 'p',
389 vma->vm_flags & VM_LOCKED ? 'l' : '-',
390 vma->vm_flags & VM_IO ? 'i' : '-',
391 VM_OFFSET(vma));
393 #if defined(__i386__)
394 pgprot = pgprot_val(vma->vm_page_prot);
395 DRM_PROC_PRINT(" %c%c%c%c%c%c%c%c%c",
396 pgprot & _PAGE_PRESENT ? 'p' : '-',
397 pgprot & _PAGE_RW ? 'w' : 'r',
398 pgprot & _PAGE_USER ? 'u' : 's',
399 pgprot & _PAGE_PWT ? 't' : 'b',
400 pgprot & _PAGE_PCD ? 'u' : 'c',
401 pgprot & _PAGE_ACCESSED ? 'a' : '-',
402 pgprot & _PAGE_DIRTY ? 'd' : '-',
403 pgprot & _PAGE_PSE ? 'm' : 'k',
404 pgprot & _PAGE_GLOBAL ? 'g' : 'l' );
405 #endif
406 DRM_PROC_PRINT("\n");
407 #if 0
408 for (i = vma->vm_start; i < vma->vm_end; i += PAGE_SIZE) {
409 pgd = pgd_offset(vma->vm_mm, i);
410 pmd = pmd_offset(pgd, i);
411 pte = pte_offset(pmd, i);
412 if (pte_present(*pte)) {
413 address = __pa(pte_page(*pte))
414 + (i & (PAGE_SIZE-1));
415 DRM_PROC_PRINT(" 0x%08lx -> 0x%08lx"
416 " %c%c%c%c%c\n",
418 address,
419 pte_read(*pte) ? 'r' : '-',
420 pte_write(*pte) ? 'w' : '-',
421 pte_exec(*pte) ? 'x' : '-',
422 pte_dirty(*pte) ? 'd' : '-',
423 pte_young(*pte) ? 'a' : '-' );
424 } else {
425 DRM_PROC_PRINT(" 0x%08lx\n", i);
428 #endif
431 return len;
434 static int drm_vma_info(char *buf, char **start, off_t offset, int len,
435 int *eof, void *data)
437 drm_device_t *dev = (drm_device_t *)data;
438 int ret;
440 down(&dev->struct_sem);
441 ret = _drm_vma_info(buf, start, offset, len, eof, data);
442 up(&dev->struct_sem);
443 return ret;
445 #endif
448 #if DRM_DMA_HISTOGRAM
449 static int _drm_histo_info(char *buf, char **start, off_t offset, int len,
450 int *eof, void *data)
452 drm_device_t *dev = (drm_device_t *)data;
453 drm_device_dma_t *dma = dev->dma;
454 int i;
455 unsigned long slot_value = DRM_DMA_HISTOGRAM_INITIAL;
456 unsigned long prev_value = 0;
457 drm_buf_t *buffer;
459 if (offset > 0) return 0; /* no partial requests */
460 len = 0;
461 *eof = 1;
463 DRM_PROC_PRINT("general statistics:\n");
464 DRM_PROC_PRINT("total %10u\n", atomic_read(&dev->histo.total));
465 DRM_PROC_PRINT("open %10u\n", atomic_read(&dev->total_open));
466 DRM_PROC_PRINT("close %10u\n", atomic_read(&dev->total_close));
467 DRM_PROC_PRINT("ioctl %10u\n", atomic_read(&dev->total_ioctl));
468 DRM_PROC_PRINT("irq %10u\n", atomic_read(&dev->total_irq));
469 DRM_PROC_PRINT("ctx %10u\n", atomic_read(&dev->total_ctx));
471 DRM_PROC_PRINT("\nlock statistics:\n");
472 DRM_PROC_PRINT("locks %10u\n", atomic_read(&dev->total_locks));
473 DRM_PROC_PRINT("unlocks %10u\n", atomic_read(&dev->total_unlocks));
474 DRM_PROC_PRINT("contends %10u\n", atomic_read(&dev->total_contends));
475 DRM_PROC_PRINT("sleeps %10u\n", atomic_read(&dev->total_sleeps));
478 if (dma) {
479 DRM_PROC_PRINT("\ndma statistics:\n");
480 DRM_PROC_PRINT("prio %10u\n",
481 atomic_read(&dma->total_prio));
482 DRM_PROC_PRINT("bytes %10u\n",
483 atomic_read(&dma->total_bytes));
484 DRM_PROC_PRINT("dmas %10u\n",
485 atomic_read(&dma->total_dmas));
486 DRM_PROC_PRINT("missed:\n");
487 DRM_PROC_PRINT(" dma %10u\n",
488 atomic_read(&dma->total_missed_dma));
489 DRM_PROC_PRINT(" lock %10u\n",
490 atomic_read(&dma->total_missed_lock));
491 DRM_PROC_PRINT(" free %10u\n",
492 atomic_read(&dma->total_missed_free));
493 DRM_PROC_PRINT(" sched %10u\n",
494 atomic_read(&dma->total_missed_sched));
495 DRM_PROC_PRINT("tried %10u\n",
496 atomic_read(&dma->total_tried));
497 DRM_PROC_PRINT("hit %10u\n",
498 atomic_read(&dma->total_hit));
499 DRM_PROC_PRINT("lost %10u\n",
500 atomic_read(&dma->total_lost));
502 buffer = dma->next_buffer;
503 if (buffer) {
504 DRM_PROC_PRINT("next_buffer %7d\n", buffer->idx);
505 } else {
506 DRM_PROC_PRINT("next_buffer none\n");
508 buffer = dma->this_buffer;
509 if (buffer) {
510 DRM_PROC_PRINT("this_buffer %7d\n", buffer->idx);
511 } else {
512 DRM_PROC_PRINT("this_buffer none\n");
517 DRM_PROC_PRINT("\nvalues:\n");
518 if (dev->lock.hw_lock) {
519 DRM_PROC_PRINT("lock 0x%08x\n",
520 dev->lock.hw_lock->lock);
521 } else {
522 DRM_PROC_PRINT("lock none\n");
524 DRM_PROC_PRINT("context_flag 0x%08lx\n", dev->context_flag);
525 DRM_PROC_PRINT("interrupt_flag 0x%08lx\n", dev->interrupt_flag);
526 DRM_PROC_PRINT("dma_flag 0x%08lx\n", dev->dma_flag);
528 DRM_PROC_PRINT("queue_count %10d\n", dev->queue_count);
529 DRM_PROC_PRINT("last_context %10d\n", dev->last_context);
530 DRM_PROC_PRINT("last_switch %10lu\n", dev->last_switch);
531 DRM_PROC_PRINT("last_checked %10d\n", dev->last_checked);
534 DRM_PROC_PRINT("\n q2d d2c c2f"
535 " q2c q2f dma sch"
536 " ctx lacq lhld\n\n");
537 for (i = 0; i < DRM_DMA_HISTOGRAM_SLOTS; i++) {
538 DRM_PROC_PRINT("%s %10lu %10u %10u %10u %10u %10u"
539 " %10u %10u %10u %10u %10u\n",
540 i == DRM_DMA_HISTOGRAM_SLOTS - 1 ? ">=" : "< ",
541 i == DRM_DMA_HISTOGRAM_SLOTS - 1
542 ? prev_value : slot_value ,
544 atomic_read(&dev->histo
545 .queued_to_dispatched[i]),
546 atomic_read(&dev->histo
547 .dispatched_to_completed[i]),
548 atomic_read(&dev->histo
549 .completed_to_freed[i]),
551 atomic_read(&dev->histo
552 .queued_to_completed[i]),
553 atomic_read(&dev->histo
554 .queued_to_freed[i]),
555 atomic_read(&dev->histo.dma[i]),
556 atomic_read(&dev->histo.schedule[i]),
557 atomic_read(&dev->histo.ctx[i]),
558 atomic_read(&dev->histo.lacq[i]),
559 atomic_read(&dev->histo.lhld[i]));
560 prev_value = slot_value;
561 slot_value = DRM_DMA_HISTOGRAM_NEXT(slot_value);
563 return len;
566 static int drm_histo_info(char *buf, char **start, off_t offset, int len,
567 int *eof, void *data)
569 drm_device_t *dev = (drm_device_t *)data;
570 int ret;
572 down(&dev->struct_sem);
573 ret = _drm_histo_info(buf, start, offset, len, eof, data);
574 up(&dev->struct_sem);
575 return ret;
577 #endif