at v2.6.14 542 lines 15 kB view raw
1/** 2 * \file drm_proc.h 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#define DRM_PROC_ENTRIES (sizeof(drm_proc_list)/sizeof(drm_proc_list[0])) 75 76/** 77 * Initialize the DRI proc filesystem for a device. 78 * 79 * \param dev DRM device. 80 * \param minor device minor number. 81 * \param root DRI proc dir entry. 82 * \param dev_root resulting DRI device proc dir entry. 83 * \return root entry pointer on success, or NULL on failure. 84 * 85 * Create the DRI proc root entry "/proc/dri", the device proc root entry 86 * "/proc/dri/%minor%/", and each entry in proc_list as 87 * "/proc/dri/%minor%/%name%". 88 */ 89int drm_proc_init(drm_device_t *dev, int minor, 90 struct proc_dir_entry *root, 91 struct proc_dir_entry **dev_root) 92{ 93 struct proc_dir_entry *ent; 94 int i, j; 95 char name[64]; 96 97 sprintf(name, "%d", minor); 98 *dev_root = proc_mkdir(name, root); 99 if (!*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, *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 *dev_root); 113 remove_proc_entry(name, root); 114 return -1; 115 } 116 ent->read_proc = drm_proc_list[i].f; 117 ent->data = dev; 118 } 119 120 return 0; 121} 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(int minor, struct proc_dir_entry *root, 135 struct proc_dir_entry *dev_root) 136{ 137 int i; 138 char name[64]; 139 140 if (!root || !dev_root) return 0; 141 142 for (i = 0; i < DRM_PROC_ENTRIES; i++) 143 remove_proc_entry(drm_proc_list[i].name, dev_root); 144 sprintf(name, "%d", minor); 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 drm_device_t *dev = (drm_device_t *)data; 167 int len = 0; 168 169 if (offset > DRM_PROC_LIMIT) { 170 *eof = 1; 171 return 0; 172 } 173 174 *start = &buf[offset]; 175 *eof = 0; 176 177 if (dev->unique) { 178 DRM_PROC_PRINT("%s %s %s\n", 179 dev->driver->pci_driver.name, pci_name(dev->pdev), dev->unique); 180 } else { 181 DRM_PROC_PRINT("%s %s\n", dev->driver->pci_driver.name, pci_name(dev->pdev)); 182 } 183 184 if (len > request + offset) return request; 185 *eof = 1; 186 return len - offset; 187} 188 189/** 190 * Called when "/proc/dri/.../vm" is read. 191 * 192 * \param buf output buffer. 193 * \param start start of output data. 194 * \param offset requested start offset. 195 * \param request requested number of bytes. 196 * \param eof whether there is no more data to return. 197 * \param data private data. 198 * \return number of written bytes. 199 * 200 * Prints information about all mappings in drm_device::maplist. 201 */ 202static int drm__vm_info(char *buf, char **start, off_t offset, int request, 203 int *eof, void *data) 204{ 205 drm_device_t *dev = (drm_device_t *)data; 206 int len = 0; 207 drm_map_t *map; 208 drm_map_list_t *r_list; 209 struct list_head *list; 210 211 /* Hardcoded from _DRM_FRAME_BUFFER, 212 _DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and 213 _DRM_SCATTER_GATHER and _DRM_CONSISTENT */ 214 const char *types[] = { "FB", "REG", "SHM", "AGP", "SG", "PCI" }; 215 const char *type; 216 int i; 217 218 if (offset > DRM_PROC_LIMIT) { 219 *eof = 1; 220 return 0; 221 } 222 223 *start = &buf[offset]; 224 *eof = 0; 225 226 DRM_PROC_PRINT("slot offset size type flags " 227 "address mtrr\n\n"); 228 i = 0; 229 if (dev->maplist != NULL) list_for_each(list, &dev->maplist->head) { 230 r_list = list_entry(list, drm_map_list_t, head); 231 map = r_list->map; 232 if(!map) 233 continue; 234 if (map->type < 0 || map->type > 5) 235 type = "??"; 236 else 237 type = types[map->type]; 238 DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08x ", 239 i, 240 map->offset, 241 map->size, 242 type, 243 map->flags, 244 r_list->user_token); 245 if (map->mtrr < 0) { 246 DRM_PROC_PRINT("none\n"); 247 } else { 248 DRM_PROC_PRINT("%4d\n", map->mtrr); 249 } 250 i++; 251 } 252 253 if (len > request + offset) return request; 254 *eof = 1; 255 return len - offset; 256} 257 258/** 259 * Simply calls _vm_info() while holding the drm_device::struct_sem lock. 260 */ 261static int drm_vm_info(char *buf, char **start, off_t offset, int request, 262 int *eof, void *data) 263{ 264 drm_device_t *dev = (drm_device_t *)data; 265 int ret; 266 267 down(&dev->struct_sem); 268 ret = drm__vm_info(buf, start, offset, request, eof, data); 269 up(&dev->struct_sem); 270 return ret; 271} 272 273/** 274 * Called when "/proc/dri/.../queues" is read. 275 * 276 * \param buf output buffer. 277 * \param start start of output data. 278 * \param offset requested start offset. 279 * \param request requested number of bytes. 280 * \param eof whether there is no more data to return. 281 * \param data private data. 282 * \return number of written bytes. 283 */ 284static int drm__queues_info(char *buf, char **start, off_t offset, 285 int request, int *eof, void *data) 286{ 287 drm_device_t *dev = (drm_device_t *)data; 288 int len = 0; 289 int i; 290 drm_queue_t *q; 291 292 if (offset > DRM_PROC_LIMIT) { 293 *eof = 1; 294 return 0; 295 } 296 297 *start = &buf[offset]; 298 *eof = 0; 299 300 DRM_PROC_PRINT(" ctx/flags use fin" 301 " blk/rw/rwf wait flushed queued" 302 " locks\n\n"); 303 for (i = 0; i < dev->queue_count; i++) { 304 q = dev->queuelist[i]; 305 atomic_inc(&q->use_count); 306 DRM_PROC_PRINT_RET(atomic_dec(&q->use_count), 307 "%5d/0x%03x %5d %5d" 308 " %5d/%c%c/%c%c%c %5Zd\n", 309 i, 310 q->flags, 311 atomic_read(&q->use_count), 312 atomic_read(&q->finalization), 313 atomic_read(&q->block_count), 314 atomic_read(&q->block_read) ? 'r' : '-', 315 atomic_read(&q->block_write) ? 'w' : '-', 316 waitqueue_active(&q->read_queue) ? 'r':'-', 317 waitqueue_active(&q->write_queue) ? 'w':'-', 318 waitqueue_active(&q->flush_queue) ? 'f':'-', 319 DRM_BUFCOUNT(&q->waitlist)); 320 atomic_dec(&q->use_count); 321 } 322 323 if (len > request + offset) return request; 324 *eof = 1; 325 return len - offset; 326} 327 328/** 329 * Simply calls _queues_info() while holding the drm_device::struct_sem lock. 330 */ 331static int drm_queues_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__queues_info(buf, start, offset, request, eof, data); 339 up(&dev->struct_sem); 340 return ret; 341} 342 343/** 344 * Called when "/proc/dri/.../bufs" is read. 345 * 346 * \param buf output buffer. 347 * \param start start of output data. 348 * \param offset requested start offset. 349 * \param request requested number of bytes. 350 * \param eof whether there is no more data to return. 351 * \param data private data. 352 * \return number of written bytes. 353 */ 354static int drm__bufs_info(char *buf, char **start, off_t offset, int request, 355 int *eof, void *data) 356{ 357 drm_device_t *dev = (drm_device_t *)data; 358 int len = 0; 359 drm_device_dma_t *dma = dev->dma; 360 int i; 361 362 if (!dma || offset > DRM_PROC_LIMIT) { 363 *eof = 1; 364 return 0; 365 } 366 367 *start = &buf[offset]; 368 *eof = 0; 369 370 DRM_PROC_PRINT(" o size count free segs pages kB\n\n"); 371 for (i = 0; i <= DRM_MAX_ORDER; i++) { 372 if (dma->bufs[i].buf_count) 373 DRM_PROC_PRINT("%2d %8d %5d %5d %5d %5d %5ld\n", 374 i, 375 dma->bufs[i].buf_size, 376 dma->bufs[i].buf_count, 377 atomic_read(&dma->bufs[i] 378 .freelist.count), 379 dma->bufs[i].seg_count, 380 dma->bufs[i].seg_count 381 *(1 << dma->bufs[i].page_order), 382 (dma->bufs[i].seg_count 383 * (1 << dma->bufs[i].page_order)) 384 * PAGE_SIZE / 1024); 385 } 386 DRM_PROC_PRINT("\n"); 387 for (i = 0; i < dma->buf_count; i++) { 388 if (i && !(i%32)) DRM_PROC_PRINT("\n"); 389 DRM_PROC_PRINT(" %d", dma->buflist[i]->list); 390 } 391 DRM_PROC_PRINT("\n"); 392 393 if (len > request + offset) return request; 394 *eof = 1; 395 return len - offset; 396} 397 398/** 399 * Simply calls _bufs_info() while holding the drm_device::struct_sem lock. 400 */ 401static int drm_bufs_info(char *buf, char **start, off_t offset, int request, 402 int *eof, void *data) 403{ 404 drm_device_t *dev = (drm_device_t *)data; 405 int ret; 406 407 down(&dev->struct_sem); 408 ret = drm__bufs_info(buf, start, offset, request, eof, data); 409 up(&dev->struct_sem); 410 return ret; 411} 412 413/** 414 * Called when "/proc/dri/.../clients" is read. 415 * 416 * \param buf output buffer. 417 * \param start start of output data. 418 * \param offset requested start offset. 419 * \param request requested number of bytes. 420 * \param eof whether there is no more data to return. 421 * \param data private data. 422 * \return number of written bytes. 423 */ 424static int drm__clients_info(char *buf, char **start, off_t offset, 425 int request, int *eof, void *data) 426{ 427 drm_device_t *dev = (drm_device_t *)data; 428 int len = 0; 429 drm_file_t *priv; 430 431 if (offset > DRM_PROC_LIMIT) { 432 *eof = 1; 433 return 0; 434 } 435 436 *start = &buf[offset]; 437 *eof = 0; 438 439 DRM_PROC_PRINT("a dev pid uid magic ioctls\n\n"); 440 for (priv = dev->file_first; priv; priv = priv->next) { 441 DRM_PROC_PRINT("%c %3d %5d %5d %10u %10lu\n", 442 priv->authenticated ? 'y' : 'n', 443 priv->minor, 444 priv->pid, 445 priv->uid, 446 priv->magic, 447 priv->ioctl_count); 448 } 449 450 if (len > request + offset) return request; 451 *eof = 1; 452 return len - offset; 453} 454 455/** 456 * Simply calls _clients_info() while holding the drm_device::struct_sem lock. 457 */ 458static int drm_clients_info(char *buf, char **start, off_t offset, 459 int request, int *eof, void *data) 460{ 461 drm_device_t *dev = (drm_device_t *)data; 462 int ret; 463 464 down(&dev->struct_sem); 465 ret = drm__clients_info(buf, start, offset, request, eof, data); 466 up(&dev->struct_sem); 467 return ret; 468} 469 470#if DRM_DEBUG_CODE 471 472static int drm__vma_info(char *buf, char **start, off_t offset, int request, 473 int *eof, void *data) 474{ 475 drm_device_t *dev = (drm_device_t *)data; 476 int len = 0; 477 drm_vma_entry_t *pt; 478 struct vm_area_struct *vma; 479#if defined(__i386__) 480 unsigned int pgprot; 481#endif 482 483 if (offset > DRM_PROC_LIMIT) { 484 *eof = 1; 485 return 0; 486 } 487 488 *start = &buf[offset]; 489 *eof = 0; 490 491 DRM_PROC_PRINT("vma use count: %d, high_memory = %p, 0x%08lx\n", 492 atomic_read(&dev->vma_count), 493 high_memory, virt_to_phys(high_memory)); 494 for (pt = dev->vmalist; pt; pt = pt->next) { 495 if (!(vma = pt->vma)) continue; 496 DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx", 497 pt->pid, 498 vma->vm_start, 499 vma->vm_end, 500 vma->vm_flags & VM_READ ? 'r' : '-', 501 vma->vm_flags & VM_WRITE ? 'w' : '-', 502 vma->vm_flags & VM_EXEC ? 'x' : '-', 503 vma->vm_flags & VM_MAYSHARE ? 's' : 'p', 504 vma->vm_flags & VM_LOCKED ? 'l' : '-', 505 vma->vm_flags & VM_IO ? 'i' : '-', 506 VM_OFFSET(vma)); 507 508#if defined(__i386__) 509 pgprot = pgprot_val(vma->vm_page_prot); 510 DRM_PROC_PRINT(" %c%c%c%c%c%c%c%c%c", 511 pgprot & _PAGE_PRESENT ? 'p' : '-', 512 pgprot & _PAGE_RW ? 'w' : 'r', 513 pgprot & _PAGE_USER ? 'u' : 's', 514 pgprot & _PAGE_PWT ? 't' : 'b', 515 pgprot & _PAGE_PCD ? 'u' : 'c', 516 pgprot & _PAGE_ACCESSED ? 'a' : '-', 517 pgprot & _PAGE_DIRTY ? 'd' : '-', 518 pgprot & _PAGE_PSE ? 'm' : 'k', 519 pgprot & _PAGE_GLOBAL ? 'g' : 'l' ); 520#endif 521 DRM_PROC_PRINT("\n"); 522 } 523 524 if (len > request + offset) return request; 525 *eof = 1; 526 return len - offset; 527} 528 529static int drm_vma_info(char *buf, char **start, off_t offset, int request, 530 int *eof, void *data) 531{ 532 drm_device_t *dev = (drm_device_t *)data; 533 int ret; 534 535 down(&dev->struct_sem); 536 ret = drm__vma_info(buf, start, offset, request, eof, data); 537 up(&dev->struct_sem); 538 return ret; 539} 540#endif 541 542