1/** 2 * \file drm_info.c 3 * DRM info file implementations 4 * 5 * \author Ben Gamari <bgamari@gmail.com> 6 */ 7 8/* 9 * Created: Sun Dec 21 13:09:50 2008 by bgamari@gmail.com 10 * 11 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. 12 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 13 * Copyright 2008 Ben Gamari <bgamari@gmail.com> 14 * All Rights Reserved. 15 * 16 * Permission is hereby granted, free of charge, to any person obtaining a 17 * copy of this software and associated documentation files (the "Software"), 18 * to deal in the Software without restriction, including without limitation 19 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 20 * and/or sell copies of the Software, and to permit persons to whom the 21 * Software is furnished to do so, subject to the following conditions: 22 * 23 * The above copyright notice and this permission notice (including the next 24 * paragraph) shall be included in all copies or substantial portions of the 25 * Software. 26 * 27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 28 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 29 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 30 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 31 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 32 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 33 * OTHER DEALINGS IN THE SOFTWARE. 34 */ 35 36#include <linux/seq_file.h> 37#include "drmP.h" 38 39/** 40 * Called when "/proc/dri/.../name" is read. 41 * 42 * Prints the device name together with the bus id if available. 43 */ 44int drm_name_info(struct seq_file *m, void *data) 45{ 46 struct drm_info_node *node = (struct drm_info_node *) m->private; 47 struct drm_minor *minor = node->minor; 48 struct drm_device *dev = minor->dev; 49 struct drm_master *master = minor->master; 50 51 if (!master) 52 return 0; 53 54 if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) { 55 if (master->unique) { 56 seq_printf(m, "%s %s %s\n", 57 dev->driver->platform_device->name, 58 dev_name(dev->dev), master->unique); 59 } else { 60 seq_printf(m, "%s\n", 61 dev->driver->platform_device->name); 62 } 63 } else { 64 if (master->unique) { 65 seq_printf(m, "%s %s %s\n", 66 dev->driver->pci_driver.name, 67 dev_name(dev->dev), master->unique); 68 } else { 69 seq_printf(m, "%s %s\n", dev->driver->pci_driver.name, 70 dev_name(dev->dev)); 71 } 72 } 73 74 return 0; 75} 76 77/** 78 * Called when "/proc/dri/.../vm" is read. 79 * 80 * Prints information about all mappings in drm_device::maplist. 81 */ 82int drm_vm_info(struct seq_file *m, void *data) 83{ 84 struct drm_info_node *node = (struct drm_info_node *) m->private; 85 struct drm_device *dev = node->minor->dev; 86 struct drm_local_map *map; 87 struct drm_map_list *r_list; 88 89 /* Hardcoded from _DRM_FRAME_BUFFER, 90 _DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and 91 _DRM_SCATTER_GATHER and _DRM_CONSISTENT */ 92 const char *types[] = { "FB", "REG", "SHM", "AGP", "SG", "PCI" }; 93 const char *type; 94 int i; 95 96 mutex_lock(&dev->struct_mutex); 97 seq_printf(m, "slot offset size type flags address mtrr\n\n"); 98 i = 0; 99 list_for_each_entry(r_list, &dev->maplist, head) { 100 map = r_list->map; 101 if (!map) 102 continue; 103 if (map->type < 0 || map->type > 5) 104 type = "??"; 105 else 106 type = types[map->type]; 107 108 seq_printf(m, "%4d 0x%016llx 0x%08lx %4.4s 0x%02x 0x%08lx ", 109 i, 110 (unsigned long long)map->offset, 111 map->size, type, map->flags, 112 (unsigned long) r_list->user_token); 113 if (map->mtrr < 0) 114 seq_printf(m, "none\n"); 115 else 116 seq_printf(m, "%4d\n", map->mtrr); 117 i++; 118 } 119 mutex_unlock(&dev->struct_mutex); 120 return 0; 121} 122 123/** 124 * Called when "/proc/dri/.../queues" is read. 125 */ 126int drm_queues_info(struct seq_file *m, void *data) 127{ 128 struct drm_info_node *node = (struct drm_info_node *) m->private; 129 struct drm_device *dev = node->minor->dev; 130 int i; 131 struct drm_queue *q; 132 133 mutex_lock(&dev->struct_mutex); 134 seq_printf(m, " ctx/flags use fin" 135 " blk/rw/rwf wait flushed queued" 136 " locks\n\n"); 137 for (i = 0; i < dev->queue_count; i++) { 138 q = dev->queuelist[i]; 139 atomic_inc(&q->use_count); 140 seq_printf(m, "%5d/0x%03x %5d %5d" 141 " %5d/%c%c/%c%c%c %5Zd\n", 142 i, 143 q->flags, 144 atomic_read(&q->use_count), 145 atomic_read(&q->finalization), 146 atomic_read(&q->block_count), 147 atomic_read(&q->block_read) ? 'r' : '-', 148 atomic_read(&q->block_write) ? 'w' : '-', 149 waitqueue_active(&q->read_queue) ? 'r' : '-', 150 waitqueue_active(&q->write_queue) ? 'w' : '-', 151 waitqueue_active(&q->flush_queue) ? 'f' : '-', 152 DRM_BUFCOUNT(&q->waitlist)); 153 atomic_dec(&q->use_count); 154 } 155 mutex_unlock(&dev->struct_mutex); 156 return 0; 157} 158 159/** 160 * Called when "/proc/dri/.../bufs" is read. 161 */ 162int drm_bufs_info(struct seq_file *m, void *data) 163{ 164 struct drm_info_node *node = (struct drm_info_node *) m->private; 165 struct drm_device *dev = node->minor->dev; 166 struct drm_device_dma *dma; 167 int i, seg_pages; 168 169 mutex_lock(&dev->struct_mutex); 170 dma = dev->dma; 171 if (!dma) { 172 mutex_unlock(&dev->struct_mutex); 173 return 0; 174 } 175 176 seq_printf(m, " o size count free segs pages kB\n\n"); 177 for (i = 0; i <= DRM_MAX_ORDER; i++) { 178 if (dma->bufs[i].buf_count) { 179 seg_pages = dma->bufs[i].seg_count * (1 << dma->bufs[i].page_order); 180 seq_printf(m, "%2d %8d %5d %5d %5d %5d %5ld\n", 181 i, 182 dma->bufs[i].buf_size, 183 dma->bufs[i].buf_count, 184 atomic_read(&dma->bufs[i].freelist.count), 185 dma->bufs[i].seg_count, 186 seg_pages, 187 seg_pages * PAGE_SIZE / 1024); 188 } 189 } 190 seq_printf(m, "\n"); 191 for (i = 0; i < dma->buf_count; i++) { 192 if (i && !(i % 32)) 193 seq_printf(m, "\n"); 194 seq_printf(m, " %d", dma->buflist[i]->list); 195 } 196 seq_printf(m, "\n"); 197 mutex_unlock(&dev->struct_mutex); 198 return 0; 199} 200 201/** 202 * Called when "/proc/dri/.../vblank" is read. 203 */ 204int drm_vblank_info(struct seq_file *m, void *data) 205{ 206 struct drm_info_node *node = (struct drm_info_node *) m->private; 207 struct drm_device *dev = node->minor->dev; 208 int crtc; 209 210 mutex_lock(&dev->struct_mutex); 211 for (crtc = 0; crtc < dev->num_crtcs; crtc++) { 212 seq_printf(m, "CRTC %d enable: %d\n", 213 crtc, atomic_read(&dev->vblank_refcount[crtc])); 214 seq_printf(m, "CRTC %d counter: %d\n", 215 crtc, drm_vblank_count(dev, crtc)); 216 seq_printf(m, "CRTC %d last wait: %d\n", 217 crtc, dev->last_vblank_wait[crtc]); 218 seq_printf(m, "CRTC %d in modeset: %d\n", 219 crtc, dev->vblank_inmodeset[crtc]); 220 } 221 mutex_unlock(&dev->struct_mutex); 222 return 0; 223} 224 225/** 226 * Called when "/proc/dri/.../clients" is read. 227 * 228 */ 229int drm_clients_info(struct seq_file *m, void *data) 230{ 231 struct drm_info_node *node = (struct drm_info_node *) m->private; 232 struct drm_device *dev = node->minor->dev; 233 struct drm_file *priv; 234 235 mutex_lock(&dev->struct_mutex); 236 seq_printf(m, "a dev pid uid magic ioctls\n\n"); 237 list_for_each_entry(priv, &dev->filelist, lhead) { 238 seq_printf(m, "%c %3d %5d %5d %10u %10lu\n", 239 priv->authenticated ? 'y' : 'n', 240 priv->minor->index, 241 priv->pid, 242 priv->uid, priv->magic, priv->ioctl_count); 243 } 244 mutex_unlock(&dev->struct_mutex); 245 return 0; 246} 247 248 249int drm_gem_one_name_info(int id, void *ptr, void *data) 250{ 251 struct drm_gem_object *obj = ptr; 252 struct seq_file *m = data; 253 254 seq_printf(m, "name %d size %zd\n", obj->name, obj->size); 255 256 seq_printf(m, "%6d %8zd %7d %8d\n", 257 obj->name, obj->size, 258 atomic_read(&obj->handle_count), 259 atomic_read(&obj->refcount.refcount)); 260 return 0; 261} 262 263int drm_gem_name_info(struct seq_file *m, void *data) 264{ 265 struct drm_info_node *node = (struct drm_info_node *) m->private; 266 struct drm_device *dev = node->minor->dev; 267 268 seq_printf(m, " name size handles refcount\n"); 269 idr_for_each(&dev->object_name_idr, drm_gem_one_name_info, m); 270 return 0; 271} 272 273int drm_gem_object_info(struct seq_file *m, void* data) 274{ 275 struct drm_info_node *node = (struct drm_info_node *) m->private; 276 struct drm_device *dev = node->minor->dev; 277 278 seq_printf(m, "%d objects\n", atomic_read(&dev->object_count)); 279 seq_printf(m, "%d object bytes\n", atomic_read(&dev->object_memory)); 280 seq_printf(m, "%d pinned\n", atomic_read(&dev->pin_count)); 281 seq_printf(m, "%d pin bytes\n", atomic_read(&dev->pin_memory)); 282 seq_printf(m, "%d gtt bytes\n", atomic_read(&dev->gtt_memory)); 283 seq_printf(m, "%d gtt total\n", dev->gtt_total); 284 return 0; 285} 286 287#if DRM_DEBUG_CODE 288 289int drm_vma_info(struct seq_file *m, void *data) 290{ 291 struct drm_info_node *node = (struct drm_info_node *) m->private; 292 struct drm_device *dev = node->minor->dev; 293 struct drm_vma_entry *pt; 294 struct vm_area_struct *vma; 295#if defined(__i386__) 296 unsigned int pgprot; 297#endif 298 299 mutex_lock(&dev->struct_mutex); 300 seq_printf(m, "vma use count: %d, high_memory = %p, 0x%08llx\n", 301 atomic_read(&dev->vma_count), 302 high_memory, (u64)virt_to_phys(high_memory)); 303 304 list_for_each_entry(pt, &dev->vmalist, head) { 305 vma = pt->vma; 306 if (!vma) 307 continue; 308 seq_printf(m, 309 "\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx000", 310 pt->pid, vma->vm_start, vma->vm_end, 311 vma->vm_flags & VM_READ ? 'r' : '-', 312 vma->vm_flags & VM_WRITE ? 'w' : '-', 313 vma->vm_flags & VM_EXEC ? 'x' : '-', 314 vma->vm_flags & VM_MAYSHARE ? 's' : 'p', 315 vma->vm_flags & VM_LOCKED ? 'l' : '-', 316 vma->vm_flags & VM_IO ? 'i' : '-', 317 vma->vm_pgoff); 318 319#if defined(__i386__) 320 pgprot = pgprot_val(vma->vm_page_prot); 321 seq_printf(m, " %c%c%c%c%c%c%c%c%c", 322 pgprot & _PAGE_PRESENT ? 'p' : '-', 323 pgprot & _PAGE_RW ? 'w' : 'r', 324 pgprot & _PAGE_USER ? 'u' : 's', 325 pgprot & _PAGE_PWT ? 't' : 'b', 326 pgprot & _PAGE_PCD ? 'u' : 'c', 327 pgprot & _PAGE_ACCESSED ? 'a' : '-', 328 pgprot & _PAGE_DIRTY ? 'd' : '-', 329 pgprot & _PAGE_PSE ? 'm' : 'k', 330 pgprot & _PAGE_GLOBAL ? 'g' : 'l'); 331#endif 332 seq_printf(m, "\n"); 333 } 334 mutex_unlock(&dev->struct_mutex); 335 return 0; 336} 337 338#endif 339