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 <drm/drmP.h> 38#include <drm/drm_gem.h> 39 40#include "drm_internal.h" 41#include "drm_legacy.h" 42 43/** 44 * Called when "/proc/dri/.../name" is read. 45 * 46 * Prints the device name together with the bus id if available. 47 */ 48int drm_name_info(struct seq_file *m, void *data) 49{ 50 struct drm_info_node *node = (struct drm_info_node *) m->private; 51 struct drm_minor *minor = node->minor; 52 struct drm_device *dev = minor->dev; 53 struct drm_master *master = minor->master; 54 if (!master) 55 return 0; 56 57 if (master->unique) { 58 seq_printf(m, "%s %s %s\n", 59 dev->driver->name, 60 dev_name(dev->dev), master->unique); 61 } else { 62 seq_printf(m, "%s %s\n", 63 dev->driver->name, dev_name(dev->dev)); 64 } 65 return 0; 66} 67 68/** 69 * Called when "/proc/dri/.../vm" is read. 70 * 71 * Prints information about all mappings in drm_device::maplist. 72 */ 73int drm_vm_info(struct seq_file *m, void *data) 74{ 75 struct drm_info_node *node = (struct drm_info_node *) m->private; 76 struct drm_device *dev = node->minor->dev; 77 struct drm_local_map *map; 78 struct drm_map_list *r_list; 79 80 /* Hardcoded from _DRM_FRAME_BUFFER, 81 _DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and 82 _DRM_SCATTER_GATHER and _DRM_CONSISTENT */ 83 const char *types[] = { "FB", "REG", "SHM", "AGP", "SG", "PCI" }; 84 const char *type; 85 int i; 86 87 mutex_lock(&dev->struct_mutex); 88 seq_printf(m, "slot offset size type flags address mtrr\n\n"); 89 i = 0; 90 list_for_each_entry(r_list, &dev->maplist, head) { 91 map = r_list->map; 92 if (!map) 93 continue; 94 if (map->type < 0 || map->type > 5) 95 type = "??"; 96 else 97 type = types[map->type]; 98 99 seq_printf(m, "%4d 0x%016llx 0x%08lx %4.4s 0x%02x 0x%08lx ", 100 i, 101 (unsigned long long)map->offset, 102 map->size, type, map->flags, 103 (unsigned long) r_list->user_token); 104 if (map->mtrr < 0) 105 seq_printf(m, "none\n"); 106 else 107 seq_printf(m, "%4d\n", map->mtrr); 108 i++; 109 } 110 mutex_unlock(&dev->struct_mutex); 111 return 0; 112} 113 114/** 115 * Called when "/proc/dri/.../bufs" is read. 116 */ 117int drm_bufs_info(struct seq_file *m, void *data) 118{ 119 struct drm_info_node *node = (struct drm_info_node *) m->private; 120 struct drm_device *dev = node->minor->dev; 121 struct drm_device_dma *dma; 122 int i, seg_pages; 123 124 mutex_lock(&dev->struct_mutex); 125 dma = dev->dma; 126 if (!dma) { 127 mutex_unlock(&dev->struct_mutex); 128 return 0; 129 } 130 131 seq_printf(m, " o size count free segs pages kB\n\n"); 132 for (i = 0; i <= DRM_MAX_ORDER; i++) { 133 if (dma->bufs[i].buf_count) { 134 seg_pages = dma->bufs[i].seg_count * (1 << dma->bufs[i].page_order); 135 seq_printf(m, "%2d %8d %5d %5d %5d %5d %5ld\n", 136 i, 137 dma->bufs[i].buf_size, 138 dma->bufs[i].buf_count, 139 0, 140 dma->bufs[i].seg_count, 141 seg_pages, 142 seg_pages * PAGE_SIZE / 1024); 143 } 144 } 145 seq_printf(m, "\n"); 146 for (i = 0; i < dma->buf_count; i++) { 147 if (i && !(i % 32)) 148 seq_printf(m, "\n"); 149 seq_printf(m, " %d", dma->buflist[i]->list); 150 } 151 seq_printf(m, "\n"); 152 mutex_unlock(&dev->struct_mutex); 153 return 0; 154} 155 156/** 157 * Called when "/proc/dri/.../clients" is read. 158 * 159 */ 160int drm_clients_info(struct seq_file *m, void *data) 161{ 162 struct drm_info_node *node = (struct drm_info_node *) m->private; 163 struct drm_device *dev = node->minor->dev; 164 struct drm_file *priv; 165 166 seq_printf(m, 167 "%20s %5s %3s master a %5s %10s\n", 168 "command", 169 "pid", 170 "dev", 171 "uid", 172 "magic"); 173 174 /* dev->filelist is sorted youngest first, but we want to present 175 * oldest first (i.e. kernel, servers, clients), so walk backwardss. 176 */ 177 mutex_lock(&dev->struct_mutex); 178 list_for_each_entry_reverse(priv, &dev->filelist, lhead) { 179 struct task_struct *task; 180 181 rcu_read_lock(); /* locks pid_task()->comm */ 182 task = pid_task(priv->pid, PIDTYPE_PID); 183 seq_printf(m, "%20s %5d %3d %c %c %5d %10u\n", 184 task ? task->comm : "<unknown>", 185 pid_vnr(priv->pid), 186 priv->minor->index, 187 priv->is_master ? 'y' : 'n', 188 priv->authenticated ? 'y' : 'n', 189 from_kuid_munged(seq_user_ns(m), priv->uid), 190 priv->magic); 191 rcu_read_unlock(); 192 } 193 mutex_unlock(&dev->struct_mutex); 194 return 0; 195} 196 197 198static int drm_gem_one_name_info(int id, void *ptr, void *data) 199{ 200 struct drm_gem_object *obj = ptr; 201 struct seq_file *m = data; 202 203 seq_printf(m, "%6d %8zd %7d %8d\n", 204 obj->name, obj->size, 205 obj->handle_count, 206 atomic_read(&obj->refcount.refcount)); 207 return 0; 208} 209 210int drm_gem_name_info(struct seq_file *m, void *data) 211{ 212 struct drm_info_node *node = (struct drm_info_node *) m->private; 213 struct drm_device *dev = node->minor->dev; 214 215 seq_printf(m, " name size handles refcount\n"); 216 217 mutex_lock(&dev->object_name_lock); 218 idr_for_each(&dev->object_name_idr, drm_gem_one_name_info, m); 219 mutex_unlock(&dev->object_name_lock); 220 221 return 0; 222} 223