1 /* proc.c -- /proc support for DRM -*- linux-c -*-
2 * Created: Mon Jan 11 09:48:47 1999 by faith@precisioninsight.com
3 * Revised: Sun Feb 13 23:41:04 2000 by kevin@precisioninsight.com
5 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
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
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 * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/proc.c,v 1.6 2000/02/23 04:47:30 martin Exp $
31 #define __NO_VERSION__
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);
49 static int drm_vma_info(char *buf, char **start, off_t offset,
50 int len, int *eof, void *data);
53 static int drm_histo_info(char *buf, char **start, off_t offset,
54 int len, int *eof, void *data);
57 struct drm_proc_list {
59 int (*f)(char *, char **, off_t, int, int *, void *);
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 },
68 { "vma", drm_vma_info },
71 { "histo", drm_histo_info },
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;
81 drm_root = create_proc_entry("dri", S_IFDIR, NULL);
83 DRM_ERROR("Cannot create /proc/dri\n");
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);
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;
100 DRM_ERROR("Cannot find slot in /proc/dri\n");
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);
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,
113 remove_proc_entry(drm_slot_name, NULL);
114 remove_proc_entry("dri", NULL);
117 ent->read_proc = drm_proc_list[i].f;
125 int drm_proc_cleanup(void)
131 for (i = 0; i < DRM_PROC_ENTRIES; i++) {
132 remove_proc_entry(drm_proc_list[i].name,
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;
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 */
154 DRM_PROC_PRINT("%s 0x%x %s\n",
155 dev->name, dev->device, dev->unique);
157 DRM_PROC_PRINT("%s 0x%x\n", dev->name, dev->device);
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;
167 /* Hardcoded from _DRM_FRAME_BUFFER,
168 _DRM_REGISTERS, _DRM_SHM, and
170 const char *types[] = { "FB", "REG", "SHM", "AGP" };
174 if (offset > 0) return 0; /* no partial requests */
177 DRM_PROC_PRINT("slot offset size type flags "
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 ",
189 (unsigned long)map->handle);
191 DRM_PROC_PRINT("none\n");
193 DRM_PROC_PRINT("%4d\n", map->mtrr);
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;
206 down(&dev->struct_sem);
207 ret = _drm_vm_info(buf, start, offset, len, eof, data);
208 up(&dev->struct_sem);
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;
220 if (offset > 0) return 0; /* no partial requests */
223 DRM_PROC_PRINT(" ctx/flags use fin"
224 " blk/rw/rwf wait flushed queued"
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),
231 " %5d/%c%c/%c%c%c %5d %10d %10d %10d\n",
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);
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;
258 down(&dev->struct_sem);
259 ret = _drm_queues_info(buf, start, offset, len, eof, data);
260 up(&dev->struct_sem);
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;
275 if (offset > 0) return 0; /* no partial requests */
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]
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))
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");
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;
310 down(&dev->struct_sem);
311 ret = _drm_bufs_info(buf, start, offset, len, eof, data);
312 up(&dev->struct_sem);
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;
323 if (offset > 0) return 0; /* no partial requests */
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',
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;
346 down(&dev->struct_sem);
347 ret = _drm_clients_info(buf, start, offset, len, eof, data);
348 up(&dev->struct_sem);
354 static int _drm_vma_info(char *buf, char **start, off_t offset, int len,
355 int *eof, void *data)
357 drm_device_t *dev = (drm_device_t *)data;
363 struct vm_area_struct *vma;
364 unsigned long address;
365 #if defined(__i386__)
369 if (offset > 0) return 0; /* no partial requests */
372 DRM_PROC_PRINT("vma use count: %d, high_memory = %p, 0x%08lx\n",
373 atomic_read(&dev->vma_count),
374 high_memory, virt_to_phys(high_memory));
375 for (pt = dev->vmalist; pt; pt = pt->next) {
376 if (!(vma = pt->vma)) continue;
377 DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx",
381 vma->vm_flags & VM_READ ? 'r' : '-',
382 vma->vm_flags & VM_WRITE ? 'w' : '-',
383 vma->vm_flags & VM_EXEC ? 'x' : '-',
384 vma->vm_flags & VM_MAYSHARE ? 's' : 'p',
385 vma->vm_flags & VM_LOCKED ? 'l' : '-',
386 vma->vm_flags & VM_IO ? 'i' : '-',
389 #if defined(__i386__)
390 pgprot = pgprot_val(vma->vm_page_prot);
391 DRM_PROC_PRINT(" %c%c%c%c%c%c%c%c%c",
392 pgprot & _PAGE_PRESENT ? 'p' : '-',
393 pgprot & _PAGE_RW ? 'w' : 'r',
394 pgprot & _PAGE_USER ? 'u' : 's',
395 pgprot & _PAGE_PWT ? 't' : 'b',
396 pgprot & _PAGE_PCD ? 'u' : 'c',
397 pgprot & _PAGE_ACCESSED ? 'a' : '-',
398 pgprot & _PAGE_DIRTY ? 'd' : '-',
399 pgprot & _PAGE_PSE ? 'm' : 'k',
400 pgprot & _PAGE_GLOBAL ? 'g' : 'l' );
402 DRM_PROC_PRINT("\n");
403 for (i = vma->vm_start; i < vma->vm_end; i += PAGE_SIZE) {
404 pgd = pgd_offset(vma->vm_mm, i);
405 pmd = pmd_offset(pgd, i);
406 pte = pte_offset(pmd, i);
407 if (pte_present(*pte)) {
408 address = __pa(pte_page(*pte))
409 + (i & (PAGE_SIZE-1));
410 DRM_PROC_PRINT(" 0x%08lx -> 0x%08lx"
414 pte_read(*pte) ? 'r' : '-',
415 pte_write(*pte) ? 'w' : '-',
416 pte_exec(*pte) ? 'x' : '-',
417 pte_dirty(*pte) ? 'd' : '-',
418 pte_young(*pte) ? 'a' : '-' );
420 DRM_PROC_PRINT(" 0x%08lx\n", i);
428 static int drm_vma_info(char *buf, char **start, off_t offset, int len,
429 int *eof, void *data)
431 drm_device_t *dev = (drm_device_t *)data;
434 down(&dev->struct_sem);
435 ret = _drm_vma_info(buf, start, offset, len, eof, data);
436 up(&dev->struct_sem);
442 #if DRM_DMA_HISTOGRAM
443 static int _drm_histo_info(char *buf, char **start, off_t offset, int len,
444 int *eof, void *data)
446 drm_device_t *dev = (drm_device_t *)data;
447 drm_device_dma_t *dma = dev->dma;
449 unsigned long slot_value = DRM_DMA_HISTOGRAM_INITIAL;
450 unsigned long prev_value = 0;
453 if (offset > 0) return 0; /* no partial requests */
457 DRM_PROC_PRINT("general statistics:\n");
458 DRM_PROC_PRINT("total %10u\n", atomic_read(&dev->histo.total));
459 DRM_PROC_PRINT("open %10u\n", atomic_read(&dev->total_open));
460 DRM_PROC_PRINT("close %10u\n", atomic_read(&dev->total_close));
461 DRM_PROC_PRINT("ioctl %10u\n", atomic_read(&dev->total_ioctl));
462 DRM_PROC_PRINT("irq %10u\n", atomic_read(&dev->total_irq));
463 DRM_PROC_PRINT("ctx %10u\n", atomic_read(&dev->total_ctx));
465 DRM_PROC_PRINT("\nlock statistics:\n");
466 DRM_PROC_PRINT("locks %10u\n", atomic_read(&dev->total_locks));
467 DRM_PROC_PRINT("unlocks %10u\n", atomic_read(&dev->total_unlocks));
468 DRM_PROC_PRINT("contends %10u\n", atomic_read(&dev->total_contends));
469 DRM_PROC_PRINT("sleeps %10u\n", atomic_read(&dev->total_sleeps));
473 DRM_PROC_PRINT("\ndma statistics:\n");
474 DRM_PROC_PRINT("prio %10u\n",
475 atomic_read(&dma->total_prio));
476 DRM_PROC_PRINT("bytes %10u\n",
477 atomic_read(&dma->total_bytes));
478 DRM_PROC_PRINT("dmas %10u\n",
479 atomic_read(&dma->total_dmas));
480 DRM_PROC_PRINT("missed:\n");
481 DRM_PROC_PRINT(" dma %10u\n",
482 atomic_read(&dma->total_missed_dma));
483 DRM_PROC_PRINT(" lock %10u\n",
484 atomic_read(&dma->total_missed_lock));
485 DRM_PROC_PRINT(" free %10u\n",
486 atomic_read(&dma->total_missed_free));
487 DRM_PROC_PRINT(" sched %10u\n",
488 atomic_read(&dma->total_missed_sched));
489 DRM_PROC_PRINT("tried %10u\n",
490 atomic_read(&dma->total_tried));
491 DRM_PROC_PRINT("hit %10u\n",
492 atomic_read(&dma->total_hit));
493 DRM_PROC_PRINT("lost %10u\n",
494 atomic_read(&dma->total_lost));
496 buffer = dma->next_buffer;
498 DRM_PROC_PRINT("next_buffer %7d\n", buffer->idx);
500 DRM_PROC_PRINT("next_buffer none\n");
502 buffer = dma->this_buffer;
504 DRM_PROC_PRINT("this_buffer %7d\n", buffer->idx);
506 DRM_PROC_PRINT("this_buffer none\n");
511 DRM_PROC_PRINT("\nvalues:\n");
512 if (dev->lock.hw_lock) {
513 DRM_PROC_PRINT("lock 0x%08x\n",
514 dev->lock.hw_lock->lock);
516 DRM_PROC_PRINT("lock none\n");
518 DRM_PROC_PRINT("context_flag 0x%08x\n", dev->context_flag);
519 DRM_PROC_PRINT("interrupt_flag 0x%08x\n", dev->interrupt_flag);
520 DRM_PROC_PRINT("dma_flag 0x%08x\n", dev->dma_flag);
522 DRM_PROC_PRINT("queue_count %10d\n", dev->queue_count);
523 DRM_PROC_PRINT("last_context %10d\n", dev->last_context);
524 DRM_PROC_PRINT("last_switch %10lu\n", dev->last_switch);
525 DRM_PROC_PRINT("last_checked %10d\n", dev->last_checked);
528 DRM_PROC_PRINT("\n q2d d2c c2f"
530 " ctx lacq lhld\n\n");
531 for (i = 0; i < DRM_DMA_HISTOGRAM_SLOTS; i++) {
532 DRM_PROC_PRINT("%s %10lu %10u %10u %10u %10u %10u"
533 " %10u %10u %10u %10u %10u\n",
534 i == DRM_DMA_HISTOGRAM_SLOTS - 1 ? ">=" : "< ",
535 i == DRM_DMA_HISTOGRAM_SLOTS - 1
536 ? prev_value : slot_value ,
538 atomic_read(&dev->histo
539 .queued_to_dispatched[i]),
540 atomic_read(&dev->histo
541 .dispatched_to_completed[i]),
542 atomic_read(&dev->histo
543 .completed_to_freed[i]),
545 atomic_read(&dev->histo
546 .queued_to_completed[i]),
547 atomic_read(&dev->histo
548 .queued_to_freed[i]),
549 atomic_read(&dev->histo.dma[i]),
550 atomic_read(&dev->histo.schedule[i]),
551 atomic_read(&dev->histo.ctx[i]),
552 atomic_read(&dev->histo.lacq[i]),
553 atomic_read(&dev->histo.lhld[i]));
554 prev_value = slot_value;
555 slot_value = DRM_DMA_HISTOGRAM_NEXT(slot_value);
560 static int drm_histo_info(char *buf, char **start, off_t offset, int len,
561 int *eof, void *data)
563 drm_device_t *dev = (drm_device_t *)data;
566 down(&dev->struct_sem);
567 ret = _drm_histo_info(buf, start, offset, len, eof, data);
568 up(&dev->struct_sem);