NV50: basic fbcon + misc fixes
[platform/upstream/libdrm.git] / linux-core / drm_proc.c
1 /**
2  * \file drm_proc.c
3  * /proc support for DRM
4  *
5  * \author Rickard E. (Rik) Faith <faith@valinux.com>
6  * \author Gareth Hughes <gareth@valinux.com>
7  *
8  * \par Acknowledgements:
9  *    Matthew J Sottek <matthew.j.sottek@intel.com> sent in a patch to fix
10  *    the problem with the proc files not outputting all their information.
11  */
12
13 /*
14  * Created: Mon Jan 11 09:48:47 1999 by faith@valinux.com
15  *
16  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
17  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
18  * All Rights Reserved.
19  *
20  * Permission is hereby granted, free of charge, to any person obtaining a
21  * copy of this software and associated documentation files (the "Software"),
22  * to deal in the Software without restriction, including without limitation
23  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
24  * and/or sell copies of the Software, and to permit persons to whom the
25  * Software is furnished to do so, subject to the following conditions:
26  *
27  * The above copyright notice and this permission notice (including the next
28  * paragraph) shall be included in all copies or substantial portions of the
29  * Software.
30  *
31  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
34  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
35  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
36  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
37  * OTHER DEALINGS IN THE SOFTWARE.
38  */
39
40 #include "drmP.h"
41
42 static int drm_name_info(char *buf, char **start, off_t offset,
43                          int request, int *eof, void *data);
44 static int drm_vm_info(char *buf, char **start, off_t offset,
45                        int request, int *eof, void *data);
46 static int drm_clients_info(char *buf, char **start, off_t offset,
47                             int request, int *eof, void *data);
48 static int drm_queues_info(char *buf, char **start, off_t offset,
49                            int request, int *eof, void *data);
50 static int drm_bufs_info(char *buf, char **start, off_t offset,
51                          int request, int *eof, void *data);
52 static int drm_objects_info(char *buf, char **start, off_t offset,
53                          int request, int *eof, void *data);
54 #if DRM_DEBUG_CODE
55 static int drm_vma_info(char *buf, char **start, off_t offset,
56                         int request, int *eof, void *data);
57 #endif
58
59 /**
60  * Proc file list.
61  */
62 static struct drm_proc_list {
63         const char *name;       /**< file name */
64         int (*f) (char *, char **, off_t, int, int *, void *);          /**< proc callback*/
65 } drm_proc_list[] = {
66         {"name", drm_name_info},
67         {"mem", drm_mem_info},
68         {"vm", drm_vm_info},
69         {"clients", drm_clients_info},
70         {"queues", drm_queues_info},
71         {"bufs", drm_bufs_info},
72         {"objects", drm_objects_info},
73 #if DRM_DEBUG_CODE
74         {"vma", drm_vma_info},
75 #endif
76 };
77
78 #define DRM_PROC_ENTRIES ARRAY_SIZE(drm_proc_list)
79
80 /**
81  * Initialize the DRI proc filesystem for a device.
82  *
83  * \param dev DRM device.
84  * \param minor device minor number.
85  * \param root DRI proc dir entry.
86  * \param dev_root resulting DRI device proc dir entry.
87  * \return root entry pointer on success, or NULL on failure.
88  *
89  * Create the DRI proc root entry "/proc/dri", the device proc root entry
90  * "/proc/dri/%minor%/", and each entry in proc_list as
91  * "/proc/dri/%minor%/%name%".
92  */
93 int drm_proc_init(struct drm_minor *minor, int minor_id,
94                   struct proc_dir_entry *root)
95 {
96         struct proc_dir_entry *ent;
97         int i, j;
98         char name[64];
99
100         sprintf(name, "%d", minor_id);
101         minor->dev_root = proc_mkdir(name, root);
102         if (!minor->dev_root) {
103                 DRM_ERROR("Cannot create /proc/dri/%s\n", name);
104                 return -1;
105         }
106
107         for (i = 0; i < DRM_PROC_ENTRIES; i++) {
108                 ent = create_proc_entry(drm_proc_list[i].name,
109                                         S_IFREG | S_IRUGO, minor->dev_root);
110                 if (!ent) {
111                         DRM_ERROR("Cannot create /proc/dri/%s/%s\n",
112                                   name, drm_proc_list[i].name);
113                         for (j = 0; j < i; j++)
114                                 remove_proc_entry(drm_proc_list[i].name,
115                                                   minor->dev_root);
116                         remove_proc_entry(name, root);
117                         minor->dev_root = NULL;
118                         return -1;
119                 }
120                 ent->read_proc = drm_proc_list[i].f;
121                 ent->data = minor;
122         }
123         return 0;
124 }
125
126 /**
127  * Cleanup the proc filesystem resources.
128  *
129  * \param minor device minor number.
130  * \param root DRI proc dir entry.
131  * \param dev_root DRI device proc dir entry.
132  * \return always zero.
133  *
134  * Remove all proc entries created by proc_init().
135  */
136 int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root)
137 {
138         int i;
139         char name[64];
140
141         if (!root || !minor->dev_root)
142                 return 0;
143
144         for (i = 0; i < DRM_PROC_ENTRIES; i++)
145                 remove_proc_entry(drm_proc_list[i].name, minor->dev_root);
146         sprintf(name, "%d", minor->index);
147         remove_proc_entry(name, root);
148
149         return 0;
150 }
151
152 /**
153  * Called when "/proc/dri/.../name" is read.
154  *
155  * \param buf output buffer.
156  * \param start start of output data.
157  * \param offset requested start offset.
158  * \param request requested number of bytes.
159  * \param eof whether there is no more data to return.
160  * \param data private data.
161  * \return number of written bytes.
162  *
163  * Prints the device name together with the bus id if available.
164  */
165 static int drm_name_info(char *buf, char **start, off_t offset, int request,
166                          int *eof, void *data)
167 {
168         struct drm_minor *minor = (struct drm_minor *) data; 
169         struct drm_master *master = minor->master;
170         struct drm_device *dev = minor->dev;
171         int len = 0;
172
173         if (offset > DRM_PROC_LIMIT) {
174                 *eof = 1;
175                 return 0;
176         }
177
178         if (!master)
179                 return 0;
180
181         *start = &buf[offset];
182         *eof = 0;
183
184         if (master->unique) {
185                 DRM_PROC_PRINT("%s %s %s\n",
186                                dev->driver->pci_driver.name,
187                                pci_name(dev->pdev), master->unique);
188         } else {
189                 DRM_PROC_PRINT("%s %s\n", dev->driver->pci_driver.name,
190                                pci_name(dev->pdev));
191         }
192
193         if (len > request + offset)
194                 return request;
195         *eof = 1;
196         return len - offset;
197 }
198
199 /**
200  * Called when "/proc/dri/.../vm" is read.
201  *
202  * \param buf output buffer.
203  * \param start start of output data.
204  * \param offset requested start offset.
205  * \param request requested number of bytes.
206  * \param eof whether there is no more data to return.
207  * \param data private data.
208  * \return number of written bytes.
209  *
210  * Prints information about all mappings in drm_device::maplist.
211  */
212 static int drm__vm_info(char *buf, char **start, off_t offset, int request,
213                         int *eof, void *data)
214 {
215         struct drm_minor *minor = (struct drm_minor *) data; 
216         struct drm_device *dev = minor->dev;
217         int len = 0;
218         struct drm_map *map;
219         struct drm_map_list *r_list;
220
221         /* Hardcoded from _DRM_FRAME_BUFFER,
222            _DRM_REGISTERS, _DRM_SHM, _DRM_AGP,
223            _DRM_SCATTER_GATHER, and _DRM_CONSISTENT. */
224         const char *types[] = { "FB", "REG", "SHM", "AGP", "SG", "PCI" };
225         const char *type;
226         int i;
227
228         if (offset > DRM_PROC_LIMIT) {
229                 *eof = 1;
230                 return 0;
231         }
232
233         *start = &buf[offset];
234         *eof = 0;
235
236         DRM_PROC_PRINT("slot     offset       size type flags    "
237                        "address mtrr\n\n");
238         i = 0;
239         list_for_each_entry(r_list, &dev->maplist, head) {
240                 map = r_list->map;
241                 if (!map)
242                         continue;
243                 if (map->type < 0 || map->type > 5)
244                         type = "??";
245                 else
246                         type = types[map->type];
247                 DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s  0x%02x 0x%08lx ",
248                                i,
249                                map->offset,
250                                map->size, type, map->flags,
251                                (unsigned long) r_list->user_token);
252
253                 if (map->mtrr < 0) {
254                         DRM_PROC_PRINT("none\n");
255                 } else {
256                         DRM_PROC_PRINT("%4d\n", map->mtrr);
257                 }
258                 i++;
259         }
260
261         if (len > request + offset)
262                 return request;
263         *eof = 1;
264         return len - offset;
265 }
266
267 /**
268  * Simply calls _vm_info() while holding the drm_device::struct_mutex lock.
269  */
270 static int drm_vm_info(char *buf, char **start, off_t offset, int request,
271                        int *eof, void *data)
272 {
273         struct drm_minor *minor = (struct drm_minor *) data; 
274         struct drm_device *dev = minor->dev;
275         int ret;
276
277         mutex_lock(&dev->struct_mutex);
278         ret = drm__vm_info(buf, start, offset, request, eof, data);
279         mutex_unlock(&dev->struct_mutex);
280         return ret;
281 }
282
283 /**
284  * Called when "/proc/dri/.../queues" is read.
285  *
286  * \param buf output buffer.
287  * \param start start of output data.
288  * \param offset requested start offset.
289  * \param request requested number of bytes.
290  * \param eof whether there is no more data to return.
291  * \param data private data.
292  * \return number of written bytes.
293  */
294 static int drm__queues_info(char *buf, char **start, off_t offset,
295                             int request, int *eof, void *data)
296 {
297         struct drm_minor *minor = (struct drm_minor *) data; 
298         struct drm_device *dev = minor->dev;
299         int len = 0;
300         int i;
301         struct drm_queue *q;
302
303         if (offset > DRM_PROC_LIMIT) {
304                 *eof = 1;
305                 return 0;
306         }
307
308         *start = &buf[offset];
309         *eof = 0;
310
311         DRM_PROC_PRINT("  ctx/flags   use   fin"
312                        "   blk/rw/rwf  wait    flushed     queued"
313                        "      locks\n\n");
314         for (i = 0; i < dev->queue_count; i++) {
315                 q = dev->queuelist[i];
316                 atomic_inc(&q->use_count);
317                 DRM_PROC_PRINT_RET(atomic_dec(&q->use_count),
318                                    "%5d/0x%03x %5d %5d"
319                                    " %5d/%c%c/%c%c%c %5Zd\n",
320                                    i,
321                                    q->flags,
322                                    atomic_read(&q->use_count),
323                                    atomic_read(&q->finalization),
324                                    atomic_read(&q->block_count),
325                                    atomic_read(&q->block_read) ? 'r' : '-',
326                                    atomic_read(&q->block_write) ? 'w' : '-',
327                                    waitqueue_active(&q->read_queue) ? 'r' : '-',
328                                    waitqueue_active(&q->
329                                                     write_queue) ? 'w' : '-',
330                                    waitqueue_active(&q->
331                                                     flush_queue) ? 'f' : '-',
332                                    DRM_BUFCOUNT(&q->waitlist));
333                 atomic_dec(&q->use_count);
334         }
335
336         if (len > request + offset)
337                 return request;
338         *eof = 1;
339         return len - offset;
340 }
341
342 /**
343  * Simply calls _queues_info() while holding the drm_device::struct_mutex lock.
344  */
345 static int drm_queues_info(char *buf, char **start, off_t offset, int request,
346                            int *eof, void *data)
347 {
348         struct drm_minor *minor = (struct drm_minor *) data; 
349         struct drm_device *dev = minor->dev;
350         int ret;
351
352         mutex_lock(&dev->struct_mutex);
353         ret = drm__queues_info(buf, start, offset, request, eof, data);
354         mutex_unlock(&dev->struct_mutex);
355         return ret;
356 }
357
358 /**
359  * Called when "/proc/dri/.../bufs" is read.
360  *
361  * \param buf output buffer.
362  * \param start start of output data.
363  * \param offset requested start offset.
364  * \param request requested number of bytes.
365  * \param eof whether there is no more data to return.
366  * \param data private data.
367  * \return number of written bytes.
368  */
369 static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
370                           int *eof, void *data)
371 {
372         struct drm_minor *minor = (struct drm_minor *) data; 
373         struct drm_device *dev = minor->dev;
374         int len = 0;
375         struct drm_device_dma *dma = dev->dma;
376         int i;
377
378         if (!dma || offset > DRM_PROC_LIMIT) {
379                 *eof = 1;
380                 return 0;
381         }
382
383         *start = &buf[offset];
384         *eof = 0;
385
386         DRM_PROC_PRINT(" o     size count  free  segs pages    kB\n\n");
387         for (i = 0; i <= DRM_MAX_ORDER; i++) {
388                 if (dma->bufs[i].buf_count)
389                         DRM_PROC_PRINT("%2d %8d %5d %5d %5d %5d %5ld\n",
390                                        i,
391                                        dma->bufs[i].buf_size,
392                                        dma->bufs[i].buf_count,
393                                        atomic_read(&dma->bufs[i]
394                                                    .freelist.count),
395                                        dma->bufs[i].seg_count,
396                                        dma->bufs[i].seg_count
397                                        * (1 << dma->bufs[i].page_order),
398                                        (dma->bufs[i].seg_count
399                                         * (1 << dma->bufs[i].page_order))
400                                        * PAGE_SIZE / 1024);
401         }
402         DRM_PROC_PRINT("\n");
403         for (i = 0; i < dma->buf_count; i++) {
404                 if (i && !(i % 32))
405                         DRM_PROC_PRINT("\n");
406                 DRM_PROC_PRINT(" %d", dma->buflist[i]->list);
407         }
408         DRM_PROC_PRINT("\n");
409
410         if (len > request + offset)
411                 return request;
412         *eof = 1;
413         return len - offset;
414 }
415
416 /**
417  * Simply calls _bufs_info() while holding the drm_device::struct_mutex lock.
418  */
419 static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
420                          int *eof, void *data)
421 {
422         struct drm_minor *minor = (struct drm_minor *) data; 
423         struct drm_device *dev = minor->dev;
424         int ret;
425
426         mutex_lock(&dev->struct_mutex);
427         ret = drm__bufs_info(buf, start, offset, request, eof, data);
428         mutex_unlock(&dev->struct_mutex);
429         return ret;
430 }
431
432 /**
433  * Called when "/proc/dri/.../objects" is read.
434  *
435  * \param buf output buffer.
436  * \param start start of output data.
437  * \param offset requested start offset.
438  * \param request requested number of bytes.
439  * \param eof whether there is no more data to return.
440  * \param data private data.
441  * \return number of written bytes.
442  */
443 static int drm__objects_info(char *buf, char **start, off_t offset, int request,
444                           int *eof, void *data)
445 {
446         struct drm_minor *minor = (struct drm_minor *) data; 
447         struct drm_device *dev = minor->dev;
448         int len = 0;
449         struct drm_buffer_manager *bm = &dev->bm;
450         struct drm_fence_manager *fm = &dev->fm;
451         uint64_t used_mem;
452         uint64_t used_emer;
453         uint64_t low_mem;
454         uint64_t high_mem;
455         uint64_t emer_mem;
456
457         if (offset > DRM_PROC_LIMIT) {
458                 *eof = 1;
459                 return 0;
460         }
461
462         *start = &buf[offset];
463         *eof = 0;
464
465         DRM_PROC_PRINT("Object accounting:\n\n");
466         if (fm->initialized) {
467                 DRM_PROC_PRINT("Number of active fence objects: %d.\n",
468                                atomic_read(&fm->count));
469         } else {
470                 DRM_PROC_PRINT("Fence objects are not supported by this driver\n");
471         }
472
473         if (bm->initialized) {
474                 DRM_PROC_PRINT("Number of active buffer objects: %d.\n\n",
475                                atomic_read(&bm->count));
476         }
477         DRM_PROC_PRINT("Memory accounting:\n\n");
478         if (bm->initialized) {
479                 DRM_PROC_PRINT("Number of locked GATT pages: %lu.\n", bm->cur_pages);
480         } else {
481                 DRM_PROC_PRINT("Buffer objects are not supported by this driver.\n");
482         }
483
484         drm_query_memctl(&used_mem, &used_emer, &low_mem, &high_mem, &emer_mem);
485
486         if (used_mem > 16*PAGE_SIZE) {
487                 DRM_PROC_PRINT("Used object memory is %lu pages.\n",
488                                (unsigned long) (used_mem >> PAGE_SHIFT));
489         } else {
490                 DRM_PROC_PRINT("Used object memory is %lu bytes.\n",
491                                (unsigned long) used_mem);
492         }
493         if (used_emer > 16*PAGE_SIZE) {
494                 DRM_PROC_PRINT("Used emergency memory is %lu pages.\n",
495                                (unsigned long) (used_emer >> PAGE_SHIFT));
496         } else {
497                 DRM_PROC_PRINT("Used emergency memory is %lu bytes.\n\n",
498                                (unsigned long) used_emer);
499         }
500         DRM_PROC_PRINT("Soft object memory usage threshold is %lu pages.\n",
501                        (unsigned long) (low_mem >> PAGE_SHIFT));
502         DRM_PROC_PRINT("Hard object memory usage threshold is %lu pages.\n",
503                        (unsigned long) (high_mem >> PAGE_SHIFT));
504         DRM_PROC_PRINT("Emergency root only memory usage threshold is %lu pages.\n",
505                        (unsigned long) (emer_mem >> PAGE_SHIFT));
506
507         DRM_PROC_PRINT("\n");
508
509         if (len > request + offset)
510                 return request;
511         *eof = 1;
512         return len - offset;
513 }
514
515 /**
516  * Simply calls _objects_info() while holding the drm_device::struct_mutex lock.
517  */
518 static int drm_objects_info(char *buf, char **start, off_t offset, int request,
519                          int *eof, void *data)
520 {
521         struct drm_minor *minor = (struct drm_minor *) data; 
522         struct drm_device *dev = minor->dev;
523         int ret;
524
525         mutex_lock(&dev->struct_mutex);
526         ret = drm__objects_info(buf, start, offset, request, eof, data);
527         mutex_unlock(&dev->struct_mutex);
528         return ret;
529 }
530
531 /**
532  * Called when "/proc/dri/.../clients" is read.
533  *
534  * \param buf output buffer.
535  * \param start start of output data.
536  * \param offset requested start offset.
537  * \param request requested number of bytes.
538  * \param eof whether there is no more data to return.
539  * \param data private data.
540  * \return number of written bytes.
541  */
542 static int drm__clients_info(char *buf, char **start, off_t offset,
543                              int request, int *eof, void *data)
544 {
545         struct drm_minor *minor = (struct drm_minor *) data; 
546         struct drm_device *dev = minor->dev;
547         int len = 0;
548         struct drm_file *priv;
549
550         if (offset > DRM_PROC_LIMIT) {
551                 *eof = 1;
552                 return 0;
553         }
554
555         *start = &buf[offset];
556         *eof = 0;
557
558         DRM_PROC_PRINT("a dev   pid    uid      magic     ioctls\n\n");
559         list_for_each_entry(priv, &dev->filelist, lhead) {
560                 DRM_PROC_PRINT("%c %3d %5d %5d %10u %10lu\n",
561                                priv->authenticated ? 'y' : 'n',
562                                priv->minor->index,
563                                priv->pid,
564                                priv->uid, priv->magic, priv->ioctl_count);
565         }
566
567         if (len > request + offset)
568                 return request;
569         *eof = 1;
570         return len - offset;
571 }
572
573 /**
574  * Simply calls _clients_info() while holding the drm_device::struct_mutex lock.
575  */
576 static int drm_clients_info(char *buf, char **start, off_t offset,
577                             int request, int *eof, void *data)
578 {
579         struct drm_minor *minor = (struct drm_minor *) data; 
580         struct drm_device *dev = minor->dev;
581         int ret;
582
583         mutex_lock(&dev->struct_mutex);
584         ret = drm__clients_info(buf, start, offset, request, eof, data);
585         mutex_unlock(&dev->struct_mutex);
586         return ret;
587 }
588
589 #if DRM_DEBUG_CODE
590
591 static int drm__vma_info(char *buf, char **start, off_t offset, int request,
592                          int *eof, void *data)
593 {
594         struct drm_minor *minor = (struct drm_minor *) data; 
595         struct drm_device *dev = minor->dev;
596         int len = 0;
597         struct drm_vma_entry *pt;
598         struct vm_area_struct *vma;
599 #if defined(__i386__)
600         unsigned int pgprot;
601 #endif
602
603         if (offset > DRM_PROC_LIMIT) {
604                 *eof = 1;
605                 return 0;
606         }
607
608         *start = &buf[offset];
609         *eof = 0;
610
611         DRM_PROC_PRINT("vma use count: %d, high_memory = %p, 0x%08lx\n",
612                        atomic_read(&dev->vma_count),
613                        high_memory, virt_to_phys(high_memory));
614         list_for_each_entry(pt, &dev->vmalist, head) {
615                 if (!(vma = pt->vma))
616                         continue;
617                 DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx000",
618                                pt->pid,
619                                vma->vm_start,
620                                vma->vm_end,
621                                vma->vm_flags & VM_READ ? 'r' : '-',
622                                vma->vm_flags & VM_WRITE ? 'w' : '-',
623                                vma->vm_flags & VM_EXEC ? 'x' : '-',
624                                vma->vm_flags & VM_MAYSHARE ? 's' : 'p',
625                                vma->vm_flags & VM_LOCKED ? 'l' : '-',
626                                vma->vm_flags & VM_IO ? 'i' : '-',
627                                vma->vm_pgoff);
628
629 #if defined(__i386__)
630                 pgprot = pgprot_val(vma->vm_page_prot);
631                 DRM_PROC_PRINT(" %c%c%c%c%c%c%c%c%c",
632                                pgprot & _PAGE_PRESENT ? 'p' : '-',
633                                pgprot & _PAGE_RW ? 'w' : 'r',
634                                pgprot & _PAGE_USER ? 'u' : 's',
635                                pgprot & _PAGE_PWT ? 't' : 'b',
636                                pgprot & _PAGE_PCD ? 'u' : 'c',
637                                pgprot & _PAGE_ACCESSED ? 'a' : '-',
638                                pgprot & _PAGE_DIRTY ? 'd' : '-',
639                                pgprot & _PAGE_PSE ? 'm' : 'k',
640                                pgprot & _PAGE_GLOBAL ? 'g' : 'l');
641 #endif
642                 DRM_PROC_PRINT("\n");
643         }
644
645         if (len > request + offset)
646                 return request;
647         *eof = 1;
648         return len - offset;
649 }
650
651 static int drm_vma_info(char *buf, char **start, off_t offset, int request,
652                         int *eof, void *data)
653 {
654         struct drm_minor *minor = (struct drm_minor *) data; 
655         struct drm_device *dev = minor->dev;
656         int ret;
657
658         mutex_lock(&dev->struct_mutex);
659         ret = drm__vma_info(buf, start, offset, request, eof, data);
660         mutex_unlock(&dev->struct_mutex);
661         return ret;
662 }
663 #endif