OSDN Git Service

Merge commit 'origin/drm-gem' into modesetting-gem
[android-x86/external-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 static int drm_gem_name_info(char *buf, char **start, off_t offset,
55                              int request, int *eof, void *data);
56 static int drm_gem_object_info(char *buf, char **start, off_t offset,
57                                int request, int *eof, void *data);
58 #if DRM_DEBUG_CODE
59 static int drm_vma_info(char *buf, char **start, off_t offset,
60                         int request, int *eof, void *data);
61 #endif
62
63 /**
64  * Proc file list.
65  */
66 static struct drm_proc_list {
67         const char *name;       /**< file name */
68         int (*f) (char *, char **, off_t, int, int *, void *);          /**< proc callback*/
69 } drm_proc_list[] = {
70         {"name", drm_name_info},
71         {"mem", drm_mem_info},
72         {"vm", drm_vm_info},
73         {"clients", drm_clients_info},
74         {"queues", drm_queues_info},
75         {"bufs", drm_bufs_info},
76         {"objects", drm_objects_info},
77         {"gem_names", drm_gem_name_info},
78         {"gem_objects", drm_gem_object_info},
79 #if DRM_DEBUG_CODE
80         {"vma", drm_vma_info},
81 #endif
82 };
83
84 #define DRM_PROC_ENTRIES ARRAY_SIZE(drm_proc_list)
85
86 /**
87  * Initialize the DRI proc filesystem for a device.
88  *
89  * \param dev DRM device.
90  * \param minor device minor number.
91  * \param root DRI proc dir entry.
92  * \param dev_root resulting DRI device proc dir entry.
93  * \return root entry pointer on success, or NULL on failure.
94  *
95  * Create the DRI proc root entry "/proc/dri", the device proc root entry
96  * "/proc/dri/%minor%/", and each entry in proc_list as
97  * "/proc/dri/%minor%/%name%".
98  */
99 int drm_proc_init(struct drm_minor *minor, int minor_id,
100                   struct proc_dir_entry *root)
101 {
102         struct proc_dir_entry *ent;
103         int i, j;
104         char name[64];
105
106         sprintf(name, "%d", minor_id);
107         minor->dev_root = proc_mkdir(name, root);
108         if (!minor->dev_root) {
109                 DRM_ERROR("Cannot create /proc/dri/%s\n", name);
110                 return -1;
111         }
112
113         for (i = 0; i < DRM_PROC_ENTRIES; i++) {
114                 ent = create_proc_entry(drm_proc_list[i].name,
115                                         S_IFREG | S_IRUGO, minor->dev_root);
116                 if (!ent) {
117                         DRM_ERROR("Cannot create /proc/dri/%s/%s\n",
118                                   name, drm_proc_list[i].name);
119                         for (j = 0; j < i; j++)
120                                 remove_proc_entry(drm_proc_list[i].name,
121                                                   minor->dev_root);
122                         remove_proc_entry(name, root);
123                         minor->dev_root = NULL;
124                         return -1;
125                 }
126                 ent->read_proc = drm_proc_list[i].f;
127                 ent->data = minor;
128         }
129         return 0;
130 }
131
132 /**
133  * Cleanup the proc filesystem resources.
134  *
135  * \param minor device minor number.
136  * \param root DRI proc dir entry.
137  * \param dev_root DRI device proc dir entry.
138  * \return always zero.
139  *
140  * Remove all proc entries created by proc_init().
141  */
142 int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root)
143 {
144         int i;
145         char name[64];
146
147         if (!root || !minor->dev_root)
148                 return 0;
149
150         for (i = 0; i < DRM_PROC_ENTRIES; i++)
151                 remove_proc_entry(drm_proc_list[i].name, minor->dev_root);
152         sprintf(name, "%d", minor->index);
153         remove_proc_entry(name, root);
154
155         return 0;
156 }
157
158 /**
159  * Called when "/proc/dri/.../name" is read.
160  *
161  * \param buf output buffer.
162  * \param start start of output data.
163  * \param offset requested start offset.
164  * \param request requested number of bytes.
165  * \param eof whether there is no more data to return.
166  * \param data private data.
167  * \return number of written bytes.
168  *
169  * Prints the device name together with the bus id if available.
170  */
171 static int drm_name_info(char *buf, char **start, off_t offset, int request,
172                          int *eof, void *data)
173 {
174         struct drm_minor *minor = (struct drm_minor *) data; 
175         struct drm_master *master = minor->master;
176         struct drm_device *dev = minor->dev;
177         int len = 0;
178
179         if (offset > DRM_PROC_LIMIT) {
180                 *eof = 1;
181                 return 0;
182         }
183
184         if (!master)
185                 return 0;
186
187         *start = &buf[offset];
188         *eof = 0;
189
190         if (master->unique) {
191                 DRM_PROC_PRINT("%s %s %s\n",
192                                dev->driver->pci_driver.name,
193                                pci_name(dev->pdev), master->unique);
194         } else {
195                 DRM_PROC_PRINT("%s %s\n", dev->driver->pci_driver.name,
196                                pci_name(dev->pdev));
197         }
198
199         if (len > request + offset)
200                 return request;
201         *eof = 1;
202         return len - offset;
203 }
204
205 /**
206  * Called when "/proc/dri/.../vm" is read.
207  *
208  * \param buf output buffer.
209  * \param start start of output data.
210  * \param offset requested start offset.
211  * \param request requested number of bytes.
212  * \param eof whether there is no more data to return.
213  * \param data private data.
214  * \return number of written bytes.
215  *
216  * Prints information about all mappings in drm_device::maplist.
217  */
218 static int drm__vm_info(char *buf, char **start, off_t offset, int request,
219                         int *eof, void *data)
220 {
221         struct drm_minor *minor = (struct drm_minor *) data; 
222         struct drm_device *dev = minor->dev;
223         int len = 0;
224         struct drm_map *map;
225         struct drm_map_list *r_list;
226
227         /* Hardcoded from _DRM_FRAME_BUFFER,
228            _DRM_REGISTERS, _DRM_SHM, _DRM_AGP,
229            _DRM_SCATTER_GATHER, and _DRM_CONSISTENT. */
230         const char *types[] = { "FB", "REG", "SHM", "AGP", "SG", "PCI" };
231         const char *type;
232         int i;
233
234         if (offset > DRM_PROC_LIMIT) {
235                 *eof = 1;
236                 return 0;
237         }
238
239         *start = &buf[offset];
240         *eof = 0;
241
242         DRM_PROC_PRINT("slot     offset       size type flags    "
243                        "address mtrr\n\n");
244         i = 0;
245         list_for_each_entry(r_list, &dev->maplist, head) {
246                 map = r_list->map;
247                 if (!map)
248                         continue;
249                 if (map->type < 0 || map->type > 5)
250                         type = "??";
251                 else
252                         type = types[map->type];
253                 DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s  0x%02x 0x%08lx ",
254                                i,
255                                map->offset,
256                                map->size, type, map->flags,
257                                (unsigned long) r_list->user_token);
258
259                 if (map->mtrr < 0) {
260                         DRM_PROC_PRINT("none\n");
261                 } else {
262                         DRM_PROC_PRINT("%4d\n", map->mtrr);
263                 }
264                 i++;
265         }
266
267         if (len > request + offset)
268                 return request;
269         *eof = 1;
270         return len - offset;
271 }
272
273 /**
274  * Simply calls _vm_info() while holding the drm_device::struct_mutex lock.
275  */
276 static int drm_vm_info(char *buf, char **start, off_t offset, int request,
277                        int *eof, void *data)
278 {
279         struct drm_minor *minor = (struct drm_minor *) data; 
280         struct drm_device *dev = minor->dev;
281         int ret;
282
283         mutex_lock(&dev->struct_mutex);
284         ret = drm__vm_info(buf, start, offset, request, eof, data);
285         mutex_unlock(&dev->struct_mutex);
286         return ret;
287 }
288
289 /**
290  * Called when "/proc/dri/.../queues" is read.
291  *
292  * \param buf output buffer.
293  * \param start start of output data.
294  * \param offset requested start offset.
295  * \param request requested number of bytes.
296  * \param eof whether there is no more data to return.
297  * \param data private data.
298  * \return number of written bytes.
299  */
300 static int drm__queues_info(char *buf, char **start, off_t offset,
301                             int request, int *eof, void *data)
302 {
303         struct drm_minor *minor = (struct drm_minor *) data; 
304         struct drm_device *dev = minor->dev;
305         int len = 0;
306         int i;
307         struct drm_queue *q;
308
309         if (offset > DRM_PROC_LIMIT) {
310                 *eof = 1;
311                 return 0;
312         }
313
314         *start = &buf[offset];
315         *eof = 0;
316
317         DRM_PROC_PRINT("  ctx/flags   use   fin"
318                        "   blk/rw/rwf  wait    flushed     queued"
319                        "      locks\n\n");
320         for (i = 0; i < dev->queue_count; i++) {
321                 q = dev->queuelist[i];
322                 atomic_inc(&q->use_count);
323                 DRM_PROC_PRINT_RET(atomic_dec(&q->use_count),
324                                    "%5d/0x%03x %5d %5d"
325                                    " %5d/%c%c/%c%c%c %5Zd\n",
326                                    i,
327                                    q->flags,
328                                    atomic_read(&q->use_count),
329                                    atomic_read(&q->finalization),
330                                    atomic_read(&q->block_count),
331                                    atomic_read(&q->block_read) ? 'r' : '-',
332                                    atomic_read(&q->block_write) ? 'w' : '-',
333                                    waitqueue_active(&q->read_queue) ? 'r' : '-',
334                                    waitqueue_active(&q->
335                                                     write_queue) ? 'w' : '-',
336                                    waitqueue_active(&q->
337                                                     flush_queue) ? 'f' : '-',
338                                    DRM_BUFCOUNT(&q->waitlist));
339                 atomic_dec(&q->use_count);
340         }
341
342         if (len > request + offset)
343                 return request;
344         *eof = 1;
345         return len - offset;
346 }
347
348 /**
349  * Simply calls _queues_info() while holding the drm_device::struct_mutex lock.
350  */
351 static int drm_queues_info(char *buf, char **start, off_t offset, int request,
352                            int *eof, void *data)
353 {
354         struct drm_minor *minor = (struct drm_minor *) data; 
355         struct drm_device *dev = minor->dev;
356         int ret;
357
358         mutex_lock(&dev->struct_mutex);
359         ret = drm__queues_info(buf, start, offset, request, eof, data);
360         mutex_unlock(&dev->struct_mutex);
361         return ret;
362 }
363
364 /**
365  * Called when "/proc/dri/.../bufs" is read.
366  *
367  * \param buf output buffer.
368  * \param start start of output data.
369  * \param offset requested start offset.
370  * \param request requested number of bytes.
371  * \param eof whether there is no more data to return.
372  * \param data private data.
373  * \return number of written bytes.
374  */
375 static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
376                           int *eof, void *data)
377 {
378         struct drm_minor *minor = (struct drm_minor *) data; 
379         struct drm_device *dev = minor->dev;
380         int len = 0;
381         struct drm_device_dma *dma = dev->dma;
382         int i;
383
384         if (!dma || offset > DRM_PROC_LIMIT) {
385                 *eof = 1;
386                 return 0;
387         }
388
389         *start = &buf[offset];
390         *eof = 0;
391
392         DRM_PROC_PRINT(" o     size count  free  segs pages    kB\n\n");
393         for (i = 0; i <= DRM_MAX_ORDER; i++) {
394                 if (dma->bufs[i].buf_count)
395                         DRM_PROC_PRINT("%2d %8d %5d %5d %5d %5d %5ld\n",
396                                        i,
397                                        dma->bufs[i].buf_size,
398                                        dma->bufs[i].buf_count,
399                                        atomic_read(&dma->bufs[i]
400                                                    .freelist.count),
401                                        dma->bufs[i].seg_count,
402                                        dma->bufs[i].seg_count
403                                        * (1 << dma->bufs[i].page_order),
404                                        (dma->bufs[i].seg_count
405                                         * (1 << dma->bufs[i].page_order))
406                                        * PAGE_SIZE / 1024);
407         }
408         DRM_PROC_PRINT("\n");
409         for (i = 0; i < dma->buf_count; i++) {
410                 if (i && !(i % 32))
411                         DRM_PROC_PRINT("\n");
412                 DRM_PROC_PRINT(" %d", dma->buflist[i]->list);
413         }
414         DRM_PROC_PRINT("\n");
415
416         if (len > request + offset)
417                 return request;
418         *eof = 1;
419         return len - offset;
420 }
421
422 /**
423  * Simply calls _bufs_info() while holding the drm_device::struct_mutex lock.
424  */
425 static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
426                          int *eof, void *data)
427 {
428         struct drm_minor *minor = (struct drm_minor *) data; 
429         struct drm_device *dev = minor->dev;
430         int ret;
431
432         mutex_lock(&dev->struct_mutex);
433         ret = drm__bufs_info(buf, start, offset, request, eof, data);
434         mutex_unlock(&dev->struct_mutex);
435         return ret;
436 }
437
438 /**
439  * Called when "/proc/dri/.../objects" is read.
440  *
441  * \param buf output buffer.
442  * \param start start of output data.
443  * \param offset requested start offset.
444  * \param request requested number of bytes.
445  * \param eof whether there is no more data to return.
446  * \param data private data.
447  * \return number of written bytes.
448  */
449 static int drm__objects_info(char *buf, char **start, off_t offset, int request,
450                           int *eof, void *data)
451 {
452         struct drm_minor *minor = (struct drm_minor *) data; 
453         struct drm_device *dev = minor->dev;
454         int len = 0;
455         struct drm_buffer_manager *bm = &dev->bm;
456         struct drm_fence_manager *fm = &dev->fm;
457         uint64_t used_mem;
458         uint64_t used_emer;
459         uint64_t low_mem;
460         uint64_t high_mem;
461         uint64_t emer_mem;
462
463         if (offset > DRM_PROC_LIMIT) {
464                 *eof = 1;
465                 return 0;
466         }
467
468         *start = &buf[offset];
469         *eof = 0;
470
471         DRM_PROC_PRINT("Object accounting:\n\n");
472         if (fm->initialized) {
473                 DRM_PROC_PRINT("Number of active fence objects: %d.\n",
474                                atomic_read(&fm->count));
475         } else {
476                 DRM_PROC_PRINT("Fence objects are not supported by this driver\n");
477         }
478
479         if (bm->initialized) {
480                 DRM_PROC_PRINT("Number of active buffer objects: %d.\n\n",
481                                atomic_read(&bm->count));
482         }
483         DRM_PROC_PRINT("Memory accounting:\n\n");
484         if (bm->initialized) {
485                 DRM_PROC_PRINT("Number of locked GATT pages: %lu.\n", bm->cur_pages);
486         } else {
487                 DRM_PROC_PRINT("Buffer objects are not supported by this driver.\n");
488         }
489
490         drm_query_memctl(&used_mem, &used_emer, &low_mem, &high_mem, &emer_mem);
491
492         if (used_mem > 16*PAGE_SIZE) {
493                 DRM_PROC_PRINT("Used object memory is %lu pages.\n",
494                                (unsigned long) (used_mem >> PAGE_SHIFT));
495         } else {
496                 DRM_PROC_PRINT("Used object memory is %lu bytes.\n",
497                                (unsigned long) used_mem);
498         }
499         if (used_emer > 16*PAGE_SIZE) {
500                 DRM_PROC_PRINT("Used emergency memory is %lu pages.\n",
501                                (unsigned long) (used_emer >> PAGE_SHIFT));
502         } else {
503                 DRM_PROC_PRINT("Used emergency memory is %lu bytes.\n\n",
504                                (unsigned long) used_emer);
505         }
506         DRM_PROC_PRINT("Soft object memory usage threshold is %lu pages.\n",
507                        (unsigned long) (low_mem >> PAGE_SHIFT));
508         DRM_PROC_PRINT("Hard object memory usage threshold is %lu pages.\n",
509                        (unsigned long) (high_mem >> PAGE_SHIFT));
510         DRM_PROC_PRINT("Emergency root only memory usage threshold is %lu pages.\n",
511                        (unsigned long) (emer_mem >> PAGE_SHIFT));
512
513         DRM_PROC_PRINT("\n");
514
515         if (len > request + offset)
516                 return request;
517         *eof = 1;
518         return len - offset;
519 }
520
521 /**
522  * Simply calls _objects_info() while holding the drm_device::struct_mutex lock.
523  */
524 static int drm_objects_info(char *buf, char **start, off_t offset, int request,
525                          int *eof, void *data)
526 {
527         struct drm_minor *minor = (struct drm_minor *) data; 
528         struct drm_device *dev = minor->dev;
529         int ret;
530
531         mutex_lock(&dev->struct_mutex);
532         ret = drm__objects_info(buf, start, offset, request, eof, data);
533         mutex_unlock(&dev->struct_mutex);
534         return ret;
535 }
536
537 /**
538  * Called when "/proc/dri/.../clients" is read.
539  *
540  * \param buf output buffer.
541  * \param start start of output data.
542  * \param offset requested start offset.
543  * \param request requested number of bytes.
544  * \param eof whether there is no more data to return.
545  * \param data private data.
546  * \return number of written bytes.
547  */
548 static int drm__clients_info(char *buf, char **start, off_t offset,
549                              int request, int *eof, void *data)
550 {
551         struct drm_minor *minor = (struct drm_minor *) data; 
552         struct drm_device *dev = minor->dev;
553         int len = 0;
554         struct drm_file *priv;
555
556         if (offset > DRM_PROC_LIMIT) {
557                 *eof = 1;
558                 return 0;
559         }
560
561         *start = &buf[offset];
562         *eof = 0;
563
564         DRM_PROC_PRINT("a dev   pid    uid      magic     ioctls\n\n");
565         list_for_each_entry(priv, &dev->filelist, lhead) {
566                 DRM_PROC_PRINT("%c %3d %5d %5d %10u %10lu\n",
567                                priv->authenticated ? 'y' : 'n',
568                                priv->minor->index,
569                                priv->pid,
570                                priv->uid, priv->magic, priv->ioctl_count);
571         }
572
573         if (len > request + offset)
574                 return request;
575         *eof = 1;
576         return len - offset;
577 }
578
579 /**
580  * Simply calls _clients_info() while holding the drm_device::struct_mutex lock.
581  */
582 static int drm_clients_info(char *buf, char **start, off_t offset,
583                             int request, int *eof, void *data)
584 {
585         struct drm_minor *minor = (struct drm_minor *) data; 
586         struct drm_device *dev = minor->dev;
587         int ret;
588
589         mutex_lock(&dev->struct_mutex);
590         ret = drm__clients_info(buf, start, offset, request, eof, data);
591         mutex_unlock(&dev->struct_mutex);
592         return ret;
593 }
594
595 struct drm_gem_name_info_data {
596         int                     len;
597         char                    *buf;
598         int                     eof;
599 };
600
601 static int drm_gem_one_name_info(int id, void *ptr, void *data)
602 {
603         struct drm_gem_object *obj = ptr;
604         struct drm_gem_name_info_data   *nid = data;
605
606         DRM_INFO("name %d size %d\n", obj->name, obj->size);
607         if (nid->eof)
608                 return 0;
609
610         nid->len += sprintf(&nid->buf[nid->len],
611                             "%6d%9d%8d%9d\n",
612                             obj->name, obj->size,
613                             atomic_read(&obj->handlecount.refcount),
614                             atomic_read(&obj->refcount.refcount));
615         if (nid->len > DRM_PROC_LIMIT) {
616                 nid->eof = 1;
617                 return 0;
618         }
619         return 0;
620 }
621
622 static int drm_gem_name_info(char *buf, char **start, off_t offset,
623                              int request, int *eof, void *data)
624 {
625         struct drm_minor *minor = (struct drm_minor *) data;
626         struct drm_device *dev = minor->dev;
627         struct drm_gem_name_info_data nid;
628
629         if (offset > DRM_PROC_LIMIT) {
630                 *eof = 1;
631                 return 0;
632         }
633
634         nid.len = sprintf(buf, "  name     size handles refcount\n");
635         nid.buf = buf;
636         nid.eof = 0;
637         idr_for_each(&dev->object_name_idr, drm_gem_one_name_info, &nid);
638
639         *start = &buf[offset];
640         *eof = 0;
641         if (nid.len > request + offset)
642                 return request;
643         *eof = 1;
644         return nid.len - offset;
645 }
646
647 static int drm_gem_object_info(char *buf, char **start, off_t offset,
648                                int request, int *eof, void *data)
649 {
650         struct drm_minor *minor = (struct drm_minor *) data;
651         struct drm_device *dev = minor->dev;
652         int len = 0;
653
654         if (offset > DRM_PROC_LIMIT) {
655                 *eof = 1;
656                 return 0;
657         }
658
659         *start = &buf[offset];
660         *eof = 0;
661         DRM_PROC_PRINT("%d objects\n", atomic_read(&dev->object_count));
662         DRM_PROC_PRINT("%d object bytes\n", atomic_read(&dev->object_memory));
663         DRM_PROC_PRINT("%d pinned\n", atomic_read(&dev->pin_count));
664         DRM_PROC_PRINT("%d pin bytes\n", atomic_read(&dev->pin_memory));
665         DRM_PROC_PRINT("%d gtt bytes\n", atomic_read(&dev->gtt_memory));
666         DRM_PROC_PRINT("%d gtt total\n", dev->gtt_total);
667         if (len > request + offset)
668                 return request;
669         *eof = 1;
670         return len - offset;
671 }
672
673 #if DRM_DEBUG_CODE
674
675 static int drm__vma_info(char *buf, char **start, off_t offset, int request,
676                          int *eof, void *data)
677 {
678         struct drm_minor *minor = (struct drm_minor *) data; 
679         struct drm_device *dev = minor->dev;
680         int len = 0;
681         struct drm_vma_entry *pt;
682         struct vm_area_struct *vma;
683 #if defined(__i386__)
684         unsigned int pgprot;
685 #endif
686
687         if (offset > DRM_PROC_LIMIT) {
688                 *eof = 1;
689                 return 0;
690         }
691
692         *start = &buf[offset];
693         *eof = 0;
694
695         DRM_PROC_PRINT("vma use count: %d, high_memory = %p, 0x%08lx\n",
696                        atomic_read(&dev->vma_count),
697                        high_memory, virt_to_phys(high_memory));
698         list_for_each_entry(pt, &dev->vmalist, head) {
699                 if (!(vma = pt->vma))
700                         continue;
701                 DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx000",
702                                pt->pid,
703                                vma->vm_start,
704                                vma->vm_end,
705                                vma->vm_flags & VM_READ ? 'r' : '-',
706                                vma->vm_flags & VM_WRITE ? 'w' : '-',
707                                vma->vm_flags & VM_EXEC ? 'x' : '-',
708                                vma->vm_flags & VM_MAYSHARE ? 's' : 'p',
709                                vma->vm_flags & VM_LOCKED ? 'l' : '-',
710                                vma->vm_flags & VM_IO ? 'i' : '-',
711                                vma->vm_pgoff);
712
713 #if defined(__i386__)
714                 pgprot = pgprot_val(vma->vm_page_prot);
715                 DRM_PROC_PRINT(" %c%c%c%c%c%c%c%c%c",
716                                pgprot & _PAGE_PRESENT ? 'p' : '-',
717                                pgprot & _PAGE_RW ? 'w' : 'r',
718                                pgprot & _PAGE_USER ? 'u' : 's',
719                                pgprot & _PAGE_PWT ? 't' : 'b',
720                                pgprot & _PAGE_PCD ? 'u' : 'c',
721                                pgprot & _PAGE_ACCESSED ? 'a' : '-',
722                                pgprot & _PAGE_DIRTY ? 'd' : '-',
723                                pgprot & _PAGE_PSE ? 'm' : 'k',
724                                pgprot & _PAGE_GLOBAL ? 'g' : 'l');
725 #endif
726                 DRM_PROC_PRINT("\n");
727         }
728
729         if (len > request + offset)
730                 return request;
731         *eof = 1;
732         return len - offset;
733 }
734
735 static int drm_vma_info(char *buf, char **start, off_t offset, int request,
736                         int *eof, void *data)
737 {
738         struct drm_minor *minor = (struct drm_minor *) data; 
739         struct drm_device *dev = minor->dev;
740         int ret;
741
742         mutex_lock(&dev->struct_mutex);
743         ret = drm__vma_info(buf, start, offset, request, eof, data);
744         mutex_unlock(&dev->struct_mutex);
745         return ret;
746 }
747 #endif