aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_proc.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2008-05-28 20:09:59 -0400
committerDave Airlie <airlied@redhat.com>2008-07-13 20:45:01 -0400
commitc0e09200dc0813972442e550a5905a132768e56c (patch)
treed38e635a30ff8b0a2b98b9d7f97cab1501f8209e /drivers/gpu/drm/drm_proc.c
parentbce7f793daec3e65ec5c5705d2457b81fe7b5725 (diff)
drm: reorganise drm tree to be more future proof.
With the coming of kernel based modesetting and the memory manager stuff, the everything in one directory approach was getting very ugly and starting to be unmanageable. This restructures the drm along the lines of other kernel components. It creates a drivers/gpu/drm directory and moves the hw drivers into subdirectores. It moves the includes into an include/drm, and sets up the unifdef for the userspace headers we should be exporting. Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/drm_proc.c')
-rw-r--r--drivers/gpu/drm/drm_proc.c557
1 files changed, 557 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_proc.c b/drivers/gpu/drm/drm_proc.c
new file mode 100644
index 00000000000..93b1e0475c9
--- /dev/null
+++ b/drivers/gpu/drm/drm_proc.c
@@ -0,0 +1,557 @@
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
42static int drm_name_info(char *buf, char **start, off_t offset,
43 int request, int *eof, void *data);
44static int drm_vm_info(char *buf, char **start, off_t offset,
45 int request, int *eof, void *data);
46static int drm_clients_info(char *buf, char **start, off_t offset,
47 int request, int *eof, void *data);
48static int drm_queues_info(char *buf, char **start, off_t offset,
49 int request, int *eof, void *data);
50static int drm_bufs_info(char *buf, char **start, off_t offset,
51 int request, int *eof, void *data);
52#if DRM_DEBUG_CODE
53static int drm_vma_info(char *buf, char **start, off_t offset,
54 int request, int *eof, void *data);
55#endif
56
57/**
58 * Proc file list.
59 */
60static struct drm_proc_list {
61 const char *name; /**< file name */
62 int (*f) (char *, char **, off_t, int, int *, void *); /**< proc callback*/
63} drm_proc_list[] = {
64 {"name", drm_name_info},
65 {"mem", drm_mem_info},
66 {"vm", drm_vm_info},
67 {"clients", drm_clients_info},
68 {"queues", drm_queues_info},
69 {"bufs", drm_bufs_info},
70#if DRM_DEBUG_CODE
71 {"vma", drm_vma_info},
72#endif
73};
74
75#define DRM_PROC_ENTRIES ARRAY_SIZE(drm_proc_list)
76
77/**
78 * Initialize the DRI proc filesystem for a device.
79 *
80 * \param dev DRM device.
81 * \param minor device minor number.
82 * \param root DRI proc dir entry.
83 * \param dev_root resulting DRI device proc dir entry.
84 * \return root entry pointer on success, or NULL on failure.
85 *
86 * Create the DRI proc root entry "/proc/dri", the device proc root entry
87 * "/proc/dri/%minor%/", and each entry in proc_list as
88 * "/proc/dri/%minor%/%name%".
89 */
90int drm_proc_init(struct drm_minor *minor, int minor_id,
91 struct proc_dir_entry *root)
92{
93 struct proc_dir_entry *ent;
94 int i, j;
95 char name[64];
96
97 sprintf(name, "%d", minor_id);
98 minor->dev_root = proc_mkdir(name, root);
99 if (!minor->dev_root) {
100 DRM_ERROR("Cannot create /proc/dri/%s\n", name);
101 return -1;
102 }
103
104 for (i = 0; i < DRM_PROC_ENTRIES; i++) {
105 ent = create_proc_entry(drm_proc_list[i].name,
106 S_IFREG | S_IRUGO, minor->dev_root);
107 if (!ent) {
108 DRM_ERROR("Cannot create /proc/dri/%s/%s\n",
109 name, drm_proc_list[i].name);
110 for (j = 0; j < i; j++)
111 remove_proc_entry(drm_proc_list[i].name,
112 minor->dev_root);
113 remove_proc_entry(name, root);
114 minor->dev_root = NULL;
115 return -1;
116 }
117 ent->read_proc = drm_proc_list[i].f;
118 ent->data = minor;
119 }
120
121 return 0;
122}
123
124/**
125 * Cleanup the proc filesystem resources.
126 *
127 * \param minor device minor number.
128 * \param root DRI proc dir entry.
129 * \param dev_root DRI device proc dir entry.
130 * \return always zero.
131 *
132 * Remove all proc entries created by proc_init().
133 */
134int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root)
135{
136 int i;
137 char name[64];
138
139 if (!root || !minor->dev_root)
140 return 0;
141
142 for (i = 0; i < DRM_PROC_ENTRIES; i++)
143 remove_proc_entry(drm_proc_list[i].name, minor->dev_root);
144 sprintf(name, "%d", minor->index);
145 remove_proc_entry(name, root);
146
147 return 0;
148}
149
150/**
151 * Called when "/proc/dri/.../name" is read.
152 *
153 * \param buf output buffer.
154 * \param start start of output data.
155 * \param offset requested start offset.
156 * \param request requested number of bytes.
157 * \param eof whether there is no more data to return.
158 * \param data private data.
159 * \return number of written bytes.
160 *
161 * Prints the device name together with the bus id if available.
162 */
163static int drm_name_info(char *buf, char **start, off_t offset, int request,
164 int *eof, void *data)
165{
166 struct drm_minor *minor = (struct drm_minor *) data;
167 struct drm_device *dev = minor->dev;
168 int len = 0;
169
170 if (offset > DRM_PROC_LIMIT) {
171 *eof = 1;
172 return 0;
173 }
174
175 *start = &buf[offset];
176 *eof = 0;
177
178 if (dev->unique) {
179 DRM_PROC_PRINT("%s %s %s\n",
180 dev->driver->pci_driver.name,
181 pci_name(dev->pdev), dev->unique);
182 } else {
183 DRM_PROC_PRINT("%s %s\n", dev->driver->pci_driver.name,
184 pci_name(dev->pdev));
185 }
186
187 if (len > request + offset)
188 return request;
189 *eof = 1;
190 return len - offset;
191}
192
193/**
194 * Called when "/proc/dri/.../vm" is read.
195 *
196 * \param buf output buffer.
197 * \param start start of output data.
198 * \param offset requested start offset.
199 * \param request requested number of bytes.
200 * \param eof whether there is no more data to return.
201 * \param data private data.
202 * \return number of written bytes.
203 *
204 * Prints information about all mappings in drm_device::maplist.
205 */
206static int drm__vm_info(char *buf, char **start, off_t offset, int request,
207 int *eof, void *data)
208{
209 struct drm_minor *minor = (struct drm_minor *) data;
210 struct drm_device *dev = minor->dev;
211 int len = 0;
212 struct drm_map *map;
213 struct drm_map_list *r_list;
214
215 /* Hardcoded from _DRM_FRAME_BUFFER,
216 _DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and
217 _DRM_SCATTER_GATHER and _DRM_CONSISTENT */
218 const char *types[] = { "FB", "REG", "SHM", "AGP", "SG", "PCI" };
219 const char *type;
220 int i;
221
222 if (offset > DRM_PROC_LIMIT) {
223 *eof = 1;
224 return 0;
225 }
226
227 *start = &buf[offset];
228 *eof = 0;
229
230 DRM_PROC_PRINT("slot offset size type flags "
231 "address mtrr\n\n");
232 i = 0;
233 list_for_each_entry(r_list, &dev->maplist, head) {
234 map = r_list->map;
235 if (!map)
236 continue;
237 if (map->type < 0 || map->type > 5)
238 type = "??";
239 else
240 type = types[map->type];
241 DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08lx ",
242 i,
243 map->offset,
244 map->size, type, map->flags,
245 (unsigned long) r_list->user_token);
246 if (map->mtrr < 0) {
247 DRM_PROC_PRINT("none\n");
248 } else {
249 DRM_PROC_PRINT("%4d\n", map->mtrr);
250 }
251 i++;
252 }
253
254 if (len > request + offset)
255 return request;
256 *eof = 1;
257 return len - offset;
258}
259
260/**
261 * Simply calls _vm_info() while holding the drm_device::struct_mutex lock.
262 */
263static int drm_vm_info(char *buf, char **start, off_t offset, int request,
264 int *eof, void *data)
265{
266 struct drm_minor *minor = (struct drm_minor *) data;
267 struct drm_device *dev = minor->dev;
268 int ret;
269
270 mutex_lock(&dev->struct_mutex);
271 ret = drm__vm_info(buf, start, offset, request, eof, data);
272 mutex_unlock(&dev->struct_mutex);
273 return ret;
274}
275
276/**
277 * Called when "/proc/dri/.../queues" is read.
278 *
279 * \param buf output buffer.
280 * \param start start of output data.
281 * \param offset requested start offset.
282 * \param request requested number of bytes.
283 * \param eof whether there is no more data to return.
284 * \param data private data.
285 * \return number of written bytes.
286 */
287static int drm__queues_info(char *buf, char **start, off_t offset,
288 int request, int *eof, void *data)
289{
290 struct drm_minor *minor = (struct drm_minor *) data;
291 struct drm_device *dev = minor->dev;
292 int len = 0;
293 int i;
294 struct drm_queue *q;
295
296 if (offset > DRM_PROC_LIMIT) {
297 *eof = 1;
298 return 0;
299 }
300
301 *start = &buf[offset];
302 *eof = 0;
303
304 DRM_PROC_PRINT(" ctx/flags use fin"
305 " blk/rw/rwf wait flushed queued"
306 " locks\n\n");
307 for (i = 0; i < dev->queue_count; i++) {
308 q = dev->queuelist[i];
309 atomic_inc(&q->use_count);
310 DRM_PROC_PRINT_RET(atomic_dec(&q->use_count),
311 "%5d/0x%03x %5d %5d"
312 " %5d/%c%c/%c%c%c %5Zd\n",
313 i,
314 q->flags,
315 atomic_read(&q->use_count),
316 atomic_read(&q->finalization),
317 atomic_read(&q->block_count),
318 atomic_read(&q->block_read) ? 'r' : '-',
319 atomic_read(&q->block_write) ? 'w' : '-',
320 waitqueue_active(&q->read_queue) ? 'r' : '-',
321 waitqueue_active(&q->
322 write_queue) ? 'w' : '-',
323 waitqueue_active(&q->
324 flush_queue) ? 'f' : '-',
325 DRM_BUFCOUNT(&q->waitlist));
326 atomic_dec(&q->use_count);
327 }
328
329 if (len > request + offset)
330 return request;
331 *eof = 1;
332 return len - offset;
333}
334
335/**
336 * Simply calls _queues_info() while holding the drm_device::struct_mutex lock.
337 */
338static int drm_queues_info(char *buf, char **start, off_t offset, int request,
339 int *eof, void *data)
340{
341 struct drm_minor *minor = (struct drm_minor *) data;
342 struct drm_device *dev = minor->dev;
343 int ret;
344
345 mutex_lock(&dev->struct_mutex);
346 ret = drm__queues_info(buf, start, offset, request, eof, data);
347 mutex_unlock(&dev->struct_mutex);
348 return ret;
349}
350
351/**
352 * Called when "/proc/dri/.../bufs" is read.
353 *
354 * \param buf output buffer.
355 * \param start start of output data.
356 * \param offset requested start offset.
357 * \param request requested number of bytes.
358 * \param eof whether there is no more data to return.
359 * \param data private data.
360 * \return number of written bytes.
361 */
362static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
363 int *eof, void *data)
364{
365 struct drm_minor *minor = (struct drm_minor *) data;
366 struct drm_device *dev = minor->dev;
367 int len = 0;
368 struct drm_device_dma *dma = dev->dma;
369 int i;
370
371 if (!dma || offset > DRM_PROC_LIMIT) {
372 *eof = 1;
373 return 0;
374 }
375
376 *start = &buf[offset];
377 *eof = 0;
378
379 DRM_PROC_PRINT(" o size count free segs pages kB\n\n");
380 for (i = 0; i <= DRM_MAX_ORDER; i++) {
381 if (dma->bufs[i].buf_count)
382 DRM_PROC_PRINT("%2d %8d %5d %5d %5d %5d %5ld\n",
383 i,
384 dma->bufs[i].buf_size,
385 dma->bufs[i].buf_count,
386 atomic_read(&dma->bufs[i]
387 .freelist.count),
388 dma->bufs[i].seg_count,
389 dma->bufs[i].seg_count
390 * (1 << dma->bufs[i].page_order),
391 (dma->bufs[i].seg_count
392 * (1 << dma->bufs[i].page_order))
393 * PAGE_SIZE / 1024);
394 }
395 DRM_PROC_PRINT("\n");
396 for (i = 0; i < dma->buf_count; i++) {
397 if (i && !(i % 32))
398 DRM_PROC_PRINT("\n");
399 DRM_PROC_PRINT(" %d", dma->buflist[i]->list);
400 }
401 DRM_PROC_PRINT("\n");
402
403 if (len > request + offset)
404 return request;
405 *eof = 1;
406 return len - offset;
407}
408
409/**
410 * Simply calls _bufs_info() while holding the drm_device::struct_mutex lock.
411 */
412static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
413 int *eof, void *data)
414{
415 struct drm_minor *minor = (struct drm_minor *) data;
416 struct drm_device *dev = minor->dev;
417 int ret;
418
419 mutex_lock(&dev->struct_mutex);
420 ret = drm__bufs_info(buf, start, offset, request, eof, data);
421 mutex_unlock(&dev->struct_mutex);
422 return ret;
423}
424
425/**
426 * Called when "/proc/dri/.../clients" is read.
427 *
428 * \param buf output buffer.
429 * \param start start of output data.
430 * \param offset requested start offset.
431 * \param request requested number of bytes.
432 * \param eof whether there is no more data to return.
433 * \param data private data.
434 * \return number of written bytes.
435 */
436static int drm__clients_info(char *buf, char **start, off_t offset,
437 int request, int *eof, void *data)
438{
439 struct drm_minor *minor = (struct drm_minor *) data;
440 struct drm_device *dev = minor->dev;
441 int len = 0;
442 struct drm_file *priv;
443
444 if (offset > DRM_PROC_LIMIT) {
445 *eof = 1;
446 return 0;
447 }
448
449 *start = &buf[offset];
450 *eof = 0;
451
452 DRM_PROC_PRINT("a dev pid uid magic ioctls\n\n");
453 list_for_each_entry(priv, &dev->filelist, lhead) {
454 DRM_PROC_PRINT("%c %3d %5d %5d %10u %10lu\n",
455 priv->authenticated ? 'y' : 'n',
456 priv->minor->index,
457 priv->pid,
458 priv->uid, priv->magic, priv->ioctl_count);
459 }
460
461 if (len > request + offset)
462 return request;
463 *eof = 1;
464 return len - offset;
465}
466
467/**
468 * Simply calls _clients_info() while holding the drm_device::struct_mutex lock.
469 */
470static int drm_clients_info(char *buf, char **start, off_t offset,
471 int request, int *eof, void *data)
472{
473 struct drm_minor *minor = (struct drm_minor *) data;
474 struct drm_device *dev = minor->dev;
475 int ret;
476
477 mutex_lock(&dev->struct_mutex);
478 ret = drm__clients_info(buf, start, offset, request, eof, data);
479 mutex_unlock(&dev->struct_mutex);
480 return ret;
481}
482
483#if DRM_DEBUG_CODE
484
485static int drm__vma_info(char *buf, char **start, off_t offset, int request,
486 int *eof, void *data)
487{
488 struct drm_minor *minor = (struct drm_minor *) data;
489 struct drm_device *dev = minor->dev;
490 int len = 0;
491 struct drm_vma_entry *pt;
492 struct vm_area_struct *vma;
493#if defined(__i386__)
494 unsigned int pgprot;
495#endif
496
497 if (offset > DRM_PROC_LIMIT) {
498 *eof = 1;
499 return 0;
500 }
501
502 *start = &buf[offset];
503 *eof = 0;
504
505 DRM_PROC_PRINT("vma use count: %d, high_memory = %p, 0x%08lx\n",
506 atomic_read(&dev->vma_count),
507 high_memory, virt_to_phys(high_memory));
508 list_for_each_entry(pt, &dev->vmalist, head) {
509 if (!(vma = pt->vma))
510 continue;
511 DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx000",
512 pt->pid,
513 vma->vm_start,
514 vma->vm_end,
515 vma->vm_flags & VM_READ ? 'r' : '-',
516 vma->vm_flags & VM_WRITE ? 'w' : '-',
517 vma->vm_flags & VM_EXEC ? 'x' : '-',
518 vma->vm_flags & VM_MAYSHARE ? 's' : 'p',
519 vma->vm_flags & VM_LOCKED ? 'l' : '-',
520 vma->vm_flags & VM_IO ? 'i' : '-',
521 vma->vm_pgoff);
522
523#if defined(__i386__)
524 pgprot = pgprot_val(vma->vm_page_prot);
525 DRM_PROC_PRINT(" %c%c%c%c%c%c%c%c%c",
526 pgprot & _PAGE_PRESENT ? 'p' : '-',
527 pgprot & _PAGE_RW ? 'w' : 'r',
528 pgprot & _PAGE_USER ? 'u' : 's',
529 pgprot & _PAGE_PWT ? 't' : 'b',
530 pgprot & _PAGE_PCD ? 'u' : 'c',
531 pgprot & _PAGE_ACCESSED ? 'a' : '-',
532 pgprot & _PAGE_DIRTY ? 'd' : '-',
533 pgprot & _PAGE_PSE ? 'm' : 'k',
534 pgprot & _PAGE_GLOBAL ? 'g' : 'l');
535#endif
536 DRM_PROC_PRINT("\n");
537 }
538
539 if (len > request + offset)
540 return request;
541 *eof = 1;
542 return len - offset;
543}
544
545static int drm_vma_info(char *buf, char **start, off_t offset, int request,
546 int *eof, void *data)
547{
548 struct drm_minor *minor = (struct drm_minor *) data;
549 struct drm_device *dev = minor->dev;
550 int ret;
551
552 mutex_lock(&dev->struct_mutex);
553 ret = drm__vma_info(buf, start, offset, request, eof, data);
554 mutex_unlock(&dev->struct_mutex);
555 return ret;
556}
557#endif