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