File: /usr/src/linux/drivers/char/drm/drm_proc.h
1 /* drm_proc.h -- /proc support for DRM -*- linux-c -*-
2 * Created: Mon Jan 11 09:48:47 1999 by faith@valinux.com
3 *
4 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6 * All Rights Reserved.
7 *
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:
14 *
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.
18 *
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 * VA LINUX SYSTEMS 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
25 * OTHER DEALINGS IN THE SOFTWARE.
26 *
27 * Authors:
28 * Rickard E. (Rik) Faith <faith@valinux.com>
29 * Gareth Hughes <gareth@valinux.com>
30 *
31 * Acknowledgements:
32 * Matthew J Sottek <matthew.j.sottek@intel.com> sent in a patch to fix
33 * the problem with the proc files not outputting all their information.
34 */
35
36 #define __NO_VERSION__
37 #include "drmP.h"
38
39 static int DRM(name_info)(char *buf, char **start, off_t offset,
40 int request, int *eof, void *data);
41 static int DRM(vm_info)(char *buf, char **start, off_t offset,
42 int request, int *eof, void *data);
43 static int DRM(clients_info)(char *buf, char **start, off_t offset,
44 int request, int *eof, void *data);
45 static int DRM(queues_info)(char *buf, char **start, off_t offset,
46 int request, int *eof, void *data);
47 static int DRM(bufs_info)(char *buf, char **start, off_t offset,
48 int request, int *eof, void *data);
49 #if DRM_DEBUG_CODE
50 static int DRM(vma_info)(char *buf, char **start, off_t offset,
51 int request, int *eof, void *data);
52 #endif
53 #if __HAVE_DMA_HISTOGRAM
54 static int DRM(histo_info)(char *buf, char **start, off_t offset,
55 int request, int *eof, void *data);
56 #endif
57
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 __HAVE_DMA_HISTOGRAM
72 { "histo", DRM(histo_info) },
73 #endif
74 };
75 #define DRM_PROC_ENTRIES (sizeof(DRM(proc_list))/sizeof(DRM(proc_list)[0]))
76
77 struct proc_dir_entry *DRM(proc_init)(drm_device_t *dev, int minor,
78 struct proc_dir_entry *root,
79 struct proc_dir_entry **dev_root)
80 {
81 struct proc_dir_entry *ent;
82 int i, j;
83 char name[64];
84
85 if (!minor) root = create_proc_entry("dri", S_IFDIR, NULL);
86 if (!root) {
87 DRM_ERROR("Cannot create /proc/dri\n");
88 return NULL;
89 }
90
91 sprintf(name, "%d", minor);
92 *dev_root = create_proc_entry(name, S_IFDIR, root);
93 if (!*dev_root) {
94 DRM_ERROR("Cannot create /proc/%s\n", name);
95 return NULL;
96 }
97
98 for (i = 0; i < DRM_PROC_ENTRIES; i++) {
99 ent = create_proc_entry(DRM(proc_list)[i].name,
100 S_IFREG|S_IRUGO, *dev_root);
101 if (!ent) {
102 DRM_ERROR("Cannot create /proc/dri/%s/%s\n",
103 name, DRM(proc_list)[i].name);
104 for (j = 0; j < i; j++)
105 remove_proc_entry(DRM(proc_list)[i].name,
106 *dev_root);
107 remove_proc_entry(name, root);
108 if (!minor) remove_proc_entry("dri", NULL);
109 return NULL;
110 }
111 ent->read_proc = DRM(proc_list)[i].f;
112 ent->data = dev;
113 }
114
115 return root;
116 }
117
118
119 int DRM(proc_cleanup)(int minor, struct proc_dir_entry *root,
120 struct proc_dir_entry *dev_root)
121 {
122 int i;
123 char name[64];
124
125 if (!root || !dev_root) return 0;
126
127 for (i = 0; i < DRM_PROC_ENTRIES; i++)
128 remove_proc_entry(DRM(proc_list)[i].name, dev_root);
129 sprintf(name, "%d", minor);
130 remove_proc_entry(name, root);
131 if (!minor) remove_proc_entry("dri", NULL);
132
133 return 0;
134 }
135
136 static int DRM(name_info)(char *buf, char **start, off_t offset, int request,
137 int *eof, void *data)
138 {
139 drm_device_t *dev = (drm_device_t *)data;
140 int len = 0;
141
142 if (offset > DRM_PROC_LIMIT) {
143 *eof = 1;
144 return 0;
145 }
146
147 *start = &buf[offset];
148 *eof = 0;
149
150 if (dev->unique) {
151 DRM_PROC_PRINT("%s 0x%x %s\n",
152 dev->name, dev->device, dev->unique);
153 } else {
154 DRM_PROC_PRINT("%s 0x%x\n", dev->name, dev->device);
155 }
156
157 if (len > request + offset) return request;
158 *eof = 1;
159 return len - offset;
160 }
161
162 static int DRM(_vm_info)(char *buf, char **start, off_t offset, int request,
163 int *eof, void *data)
164 {
165 drm_device_t *dev = (drm_device_t *)data;
166 int len = 0;
167 drm_map_t *map;
168 drm_map_list_t *r_list;
169 struct list_head *list;
170
171 /* Hardcoded from _DRM_FRAME_BUFFER,
172 _DRM_REGISTERS, _DRM_SHM, and
173 _DRM_AGP. */
174 const char *types[] = { "FB", "REG", "SHM", "AGP" };
175 const char *type;
176 int i;
177
178 if (offset > DRM_PROC_LIMIT) {
179 *eof = 1;
180 return 0;
181 }
182
183 *start = &buf[offset];
184 *eof = 0;
185
186 DRM_PROC_PRINT("slot offset size type flags "
187 "address mtrr\n\n");
188 i = 0;
189 list_for_each(list, &dev->maplist->head) {
190 r_list = (drm_map_list_t *)list;
191 map = r_list->map;
192 if(!map) continue;
193 if (map->type < 0 || map->type > 3) type = "??";
194 else type = types[map->type];
195 DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08lx ",
196 i,
197 map->offset,
198 map->size,
199 type,
200 map->flags,
201 (unsigned long)map->handle);
202 if (map->mtrr < 0) {
203 DRM_PROC_PRINT("none\n");
204 } else {
205 DRM_PROC_PRINT("%4d\n", map->mtrr);
206 }
207 i++;
208 }
209
210 if (len > request + offset) return request;
211 *eof = 1;
212 return len - offset;
213 }
214
215 static int DRM(vm_info)(char *buf, char **start, off_t offset, int request,
216 int *eof, void *data)
217 {
218 drm_device_t *dev = (drm_device_t *)data;
219 int ret;
220
221 down(&dev->struct_sem);
222 ret = DRM(_vm_info)(buf, start, offset, request, eof, data);
223 up(&dev->struct_sem);
224 return ret;
225 }
226
227
228 static int DRM(_queues_info)(char *buf, char **start, off_t offset,
229 int request, int *eof, void *data)
230 {
231 drm_device_t *dev = (drm_device_t *)data;
232 int len = 0;
233 int i;
234 drm_queue_t *q;
235
236 if (offset > DRM_PROC_LIMIT) {
237 *eof = 1;
238 return 0;
239 }
240
241 *start = &buf[offset];
242 *eof = 0;
243
244 DRM_PROC_PRINT(" ctx/flags use fin"
245 " blk/rw/rwf wait flushed queued"
246 " locks\n\n");
247 for (i = 0; i < dev->queue_count; i++) {
248 q = dev->queuelist[i];
249 atomic_inc(&q->use_count);
250 DRM_PROC_PRINT_RET(atomic_dec(&q->use_count),
251 "%5d/0x%03x %5d %5d"
252 " %5d/%c%c/%c%c%c %5Zd\n",
253 i,
254 q->flags,
255 atomic_read(&q->use_count),
256 atomic_read(&q->finalization),
257 atomic_read(&q->block_count),
258 atomic_read(&q->block_read) ? 'r' : '-',
259 atomic_read(&q->block_write) ? 'w' : '-',
260 waitqueue_active(&q->read_queue) ? 'r':'-',
261 waitqueue_active(&q->write_queue) ? 'w':'-',
262 waitqueue_active(&q->flush_queue) ? 'f':'-',
263 DRM_BUFCOUNT(&q->waitlist));
264 atomic_dec(&q->use_count);
265 }
266
267 if (len > request + offset) return request;
268 *eof = 1;
269 return len - offset;
270 }
271
272 static int DRM(queues_info)(char *buf, char **start, off_t offset, int request,
273 int *eof, void *data)
274 {
275 drm_device_t *dev = (drm_device_t *)data;
276 int ret;
277
278 down(&dev->struct_sem);
279 ret = DRM(_queues_info)(buf, start, offset, request, eof, data);
280 up(&dev->struct_sem);
281 return ret;
282 }
283
284 /* drm_bufs_info is called whenever a process reads
285 /dev/dri/<dev>/bufs. */
286
287 static int DRM(_bufs_info)(char *buf, char **start, off_t offset, int request,
288 int *eof, void *data)
289 {
290 drm_device_t *dev = (drm_device_t *)data;
291 int len = 0;
292 drm_device_dma_t *dma = dev->dma;
293 int i;
294
295 if (!dma || offset > DRM_PROC_LIMIT) {
296 *eof = 1;
297 return 0;
298 }
299
300 *start = &buf[offset];
301 *eof = 0;
302
303 DRM_PROC_PRINT(" o size count free segs pages kB\n\n");
304 for (i = 0; i <= DRM_MAX_ORDER; i++) {
305 if (dma->bufs[i].buf_count)
306 DRM_PROC_PRINT("%2d %8d %5d %5d %5d %5d %5ld\n",
307 i,
308 dma->bufs[i].buf_size,
309 dma->bufs[i].buf_count,
310 atomic_read(&dma->bufs[i]
311 .freelist.count),
312 dma->bufs[i].seg_count,
313 dma->bufs[i].seg_count
314 *(1 << dma->bufs[i].page_order),
315 (dma->bufs[i].seg_count
316 * (1 << dma->bufs[i].page_order))
317 * PAGE_SIZE / 1024);
318 }
319 DRM_PROC_PRINT("\n");
320 for (i = 0; i < dma->buf_count; i++) {
321 if (i && !(i%32)) DRM_PROC_PRINT("\n");
322 DRM_PROC_PRINT(" %d", dma->buflist[i]->list);
323 }
324 DRM_PROC_PRINT("\n");
325
326 if (len > request + offset) return request;
327 *eof = 1;
328 return len - offset;
329 }
330
331 static int DRM(bufs_info)(char *buf, char **start, off_t offset, int request,
332 int *eof, void *data)
333 {
334 drm_device_t *dev = (drm_device_t *)data;
335 int ret;
336
337 down(&dev->struct_sem);
338 ret = DRM(_bufs_info)(buf, start, offset, request, eof, data);
339 up(&dev->struct_sem);
340 return ret;
341 }
342
343
344 static int DRM(_clients_info)(char *buf, char **start, off_t offset,
345 int request, int *eof, void *data)
346 {
347 drm_device_t *dev = (drm_device_t *)data;
348 int len = 0;
349 drm_file_t *priv;
350
351 if (offset > DRM_PROC_LIMIT) {
352 *eof = 1;
353 return 0;
354 }
355
356 *start = &buf[offset];
357 *eof = 0;
358
359 DRM_PROC_PRINT("a dev pid uid magic ioctls\n\n");
360 for (priv = dev->file_first; priv; priv = priv->next) {
361 DRM_PROC_PRINT("%c %3d %5d %5d %10u %10lu\n",
362 priv->authenticated ? 'y' : 'n',
363 priv->minor,
364 priv->pid,
365 priv->uid,
366 priv->magic,
367 priv->ioctl_count);
368 }
369
370 if (len > request + offset) return request;
371 *eof = 1;
372 return len - offset;
373 }
374
375 static int DRM(clients_info)(char *buf, char **start, off_t offset,
376 int request, int *eof, void *data)
377 {
378 drm_device_t *dev = (drm_device_t *)data;
379 int ret;
380
381 down(&dev->struct_sem);
382 ret = DRM(_clients_info)(buf, start, offset, request, eof, data);
383 up(&dev->struct_sem);
384 return ret;
385 }
386
387 #if DRM_DEBUG_CODE
388
389 #define DRM_VMA_VERBOSE 0
390
391 static int DRM(_vma_info)(char *buf, char **start, off_t offset, int request,
392 int *eof, void *data)
393 {
394 drm_device_t *dev = (drm_device_t *)data;
395 int len = 0;
396 drm_vma_entry_t *pt;
397 struct vm_area_struct *vma;
398 #if DRM_VMA_VERBOSE
399 unsigned long i;
400 unsigned long address;
401 pgd_t *pgd;
402 pmd_t *pmd;
403 pte_t *pte;
404 #endif
405 #if defined(__i386__)
406 unsigned int pgprot;
407 #endif
408
409 if (offset > DRM_PROC_LIMIT) {
410 *eof = 1;
411 return 0;
412 }
413
414 *start = &buf[offset];
415 *eof = 0;
416
417 DRM_PROC_PRINT("vma use count: %d, high_memory = %p, 0x%08lx\n",
418 atomic_read(&dev->vma_count),
419 high_memory, virt_to_phys(high_memory));
420 for (pt = dev->vmalist; pt; pt = pt->next) {
421 if (!(vma = pt->vma)) continue;
422 DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx",
423 pt->pid,
424 vma->vm_start,
425 vma->vm_end,
426 vma->vm_flags & VM_READ ? 'r' : '-',
427 vma->vm_flags & VM_WRITE ? 'w' : '-',
428 vma->vm_flags & VM_EXEC ? 'x' : '-',
429 vma->vm_flags & VM_MAYSHARE ? 's' : 'p',
430 vma->vm_flags & VM_LOCKED ? 'l' : '-',
431 vma->vm_flags & VM_IO ? 'i' : '-',
432 VM_OFFSET(vma));
433
434 #if defined(__i386__)
435 pgprot = pgprot_val(vma->vm_page_prot);
436 DRM_PROC_PRINT(" %c%c%c%c%c%c%c%c%c",
437 pgprot & _PAGE_PRESENT ? 'p' : '-',
438 pgprot & _PAGE_RW ? 'w' : 'r',
439 pgprot & _PAGE_USER ? 'u' : 's',
440 pgprot & _PAGE_PWT ? 't' : 'b',
441 pgprot & _PAGE_PCD ? 'u' : 'c',
442 pgprot & _PAGE_ACCESSED ? 'a' : '-',
443 pgprot & _PAGE_DIRTY ? 'd' : '-',
444 pgprot & _PAGE_PSE ? 'm' : 'k',
445 pgprot & _PAGE_GLOBAL ? 'g' : 'l' );
446 #endif
447 DRM_PROC_PRINT("\n");
448 #if 0
449 for (i = vma->vm_start; i < vma->vm_end; i += PAGE_SIZE) {
450 pgd = pgd_offset(vma->vm_mm, i);
451 pmd = pmd_offset(pgd, i);
452 pte = pte_offset(pmd, i);
453 if (pte_present(*pte)) {
454 address = __pa(pte_page(*pte))
455 + (i & (PAGE_SIZE-1));
456 DRM_PROC_PRINT(" 0x%08lx -> 0x%08lx"
457 " %c%c%c%c%c\n",
458 i,
459 address,
460 pte_read(*pte) ? 'r' : '-',
461 pte_write(*pte) ? 'w' : '-',
462 pte_exec(*pte) ? 'x' : '-',
463 pte_dirty(*pte) ? 'd' : '-',
464 pte_young(*pte) ? 'a' : '-' );
465 } else {
466 DRM_PROC_PRINT(" 0x%08lx\n", i);
467 }
468 }
469 #endif
470 }
471
472 if (len > request + offset) return request;
473 *eof = 1;
474 return len - offset;
475 }
476
477 static int DRM(vma_info)(char *buf, char **start, off_t offset, int request,
478 int *eof, void *data)
479 {
480 drm_device_t *dev = (drm_device_t *)data;
481 int ret;
482
483 down(&dev->struct_sem);
484 ret = DRM(_vma_info)(buf, start, offset, request, eof, data);
485 up(&dev->struct_sem);
486 return ret;
487 }
488 #endif
489
490
491 #if __HAVE_DMA_HISTOGRAM
492 static int DRM(_histo_info)(char *buf, char **start, off_t offset, int request,
493 int *eof, void *data)
494 {
495 drm_device_t *dev = (drm_device_t *)data;
496 int len = 0;
497 drm_device_dma_t *dma = dev->dma;
498 int i;
499 unsigned long slot_value = DRM_DMA_HISTOGRAM_INITIAL;
500 unsigned long prev_value = 0;
501 drm_buf_t *buffer;
502
503 if (offset > DRM_PROC_LIMIT) {
504 *eof = 1;
505 return 0;
506 }
507
508 *start = &buf[offset];
509 *eof = 0;
510
511 DRM_PROC_PRINT("general statistics:\n");
512 DRM_PROC_PRINT("total %10u\n", atomic_read(&dev->histo.total));
513 DRM_PROC_PRINT("open %10u\n",
514 atomic_read(&dev->counts[_DRM_STAT_OPENS]));
515 DRM_PROC_PRINT("close %10u\n",
516 atomic_read(&dev->counts[_DRM_STAT_CLOSES]));
517 DRM_PROC_PRINT("ioctl %10u\n",
518 atomic_read(&dev->counts[_DRM_STAT_IOCTLS]));
519
520 DRM_PROC_PRINT("\nlock statistics:\n");
521 DRM_PROC_PRINT("locks %10u\n",
522 atomic_read(&dev->counts[_DRM_STAT_LOCKS]));
523 DRM_PROC_PRINT("unlocks %10u\n",
524 atomic_read(&dev->counts[_DRM_STAT_UNLOCKS]));
525
526 if (dma) {
527 #if 0
528 DRM_PROC_PRINT("\ndma statistics:\n");
529 DRM_PROC_PRINT("prio %10u\n",
530 atomic_read(&dma->total_prio));
531 DRM_PROC_PRINT("bytes %10u\n",
532 atomic_read(&dma->total_bytes));
533 DRM_PROC_PRINT("dmas %10u\n",
534 atomic_read(&dma->total_dmas));
535 DRM_PROC_PRINT("missed:\n");
536 DRM_PROC_PRINT(" dma %10u\n",
537 atomic_read(&dma->total_missed_dma));
538 DRM_PROC_PRINT(" lock %10u\n",
539 atomic_read(&dma->total_missed_lock));
540 DRM_PROC_PRINT(" free %10u\n",
541 atomic_read(&dma->total_missed_free));
542 DRM_PROC_PRINT(" sched %10u\n",
543 atomic_read(&dma->total_missed_sched));
544 DRM_PROC_PRINT("tried %10u\n",
545 atomic_read(&dma->total_tried));
546 DRM_PROC_PRINT("hit %10u\n",
547 atomic_read(&dma->total_hit));
548 DRM_PROC_PRINT("lost %10u\n",
549 atomic_read(&dma->total_lost));
550 #endif
551
552 buffer = dma->next_buffer;
553 if (buffer) {
554 DRM_PROC_PRINT("next_buffer %7d\n", buffer->idx);
555 } else {
556 DRM_PROC_PRINT("next_buffer none\n");
557 }
558 buffer = dma->this_buffer;
559 if (buffer) {
560 DRM_PROC_PRINT("this_buffer %7d\n", buffer->idx);
561 } else {
562 DRM_PROC_PRINT("this_buffer none\n");
563 }
564 }
565
566
567 DRM_PROC_PRINT("\nvalues:\n");
568 if (dev->lock.hw_lock) {
569 DRM_PROC_PRINT("lock 0x%08x\n",
570 dev->lock.hw_lock->lock);
571 } else {
572 DRM_PROC_PRINT("lock none\n");
573 }
574 DRM_PROC_PRINT("context_flag 0x%08lx\n", dev->context_flag);
575 DRM_PROC_PRINT("interrupt_flag 0x%08lx\n", dev->interrupt_flag);
576 DRM_PROC_PRINT("dma_flag 0x%08lx\n", dev->dma_flag);
577
578 DRM_PROC_PRINT("queue_count %10d\n", dev->queue_count);
579 DRM_PROC_PRINT("last_context %10d\n", dev->last_context);
580 DRM_PROC_PRINT("last_switch %10lu\n", dev->last_switch);
581 DRM_PROC_PRINT("last_checked %10d\n", dev->last_checked);
582
583
584 DRM_PROC_PRINT("\n q2d d2c c2f"
585 " q2c q2f dma sch"
586 " ctx lacq lhld\n\n");
587 for (i = 0; i < DRM_DMA_HISTOGRAM_SLOTS; i++) {
588 DRM_PROC_PRINT("%s %10lu %10u %10u %10u %10u %10u"
589 " %10u %10u %10u %10u %10u\n",
590 i == DRM_DMA_HISTOGRAM_SLOTS - 1 ? ">=" : "< ",
591 i == DRM_DMA_HISTOGRAM_SLOTS - 1
592 ? prev_value : slot_value ,
593
594 atomic_read(&dev->histo
595 .queued_to_dispatched[i]),
596 atomic_read(&dev->histo
597 .dispatched_to_completed[i]),
598 atomic_read(&dev->histo
599 .completed_to_freed[i]),
600
601 atomic_read(&dev->histo
602 .queued_to_completed[i]),
603 atomic_read(&dev->histo
604 .queued_to_freed[i]),
605 atomic_read(&dev->histo.dma[i]),
606 atomic_read(&dev->histo.schedule[i]),
607 atomic_read(&dev->histo.ctx[i]),
608 atomic_read(&dev->histo.lacq[i]),
609 atomic_read(&dev->histo.lhld[i]));
610 prev_value = slot_value;
611 slot_value = DRM_DMA_HISTOGRAM_NEXT(slot_value);
612 }
613
614 if (len > request + offset) return request;
615 *eof = 1;
616 return len - offset;
617 }
618
619 static int DRM(histo_info)(char *buf, char **start, off_t offset, int request,
620 int *eof, void *data)
621 {
622 drm_device_t *dev = (drm_device_t *)data;
623 int ret;
624
625 down(&dev->struct_sem);
626 ret = DRM(_histo_info)(buf, start, offset, request, eof, data);
627 up(&dev->struct_sem);
628 return ret;
629 }
630 #endif
631