Commit 28a62277e06f93729d0340d9659153dcfbdbe16d

Authored by Ben Gamari
Committed by Eric Anholt
1 parent 40a5f0decd

drm: Convert proc files to seq_file and introduce debugfs

The old mechanism to formatting proc files is extremely ugly. The
seq_file API was designed specifically for cases like this and greatly
simplifies the process.

Also, most of the files in /proc really don't belong there. This patch
introduces the infrastructure for putting these into debugfs and exposes
all of the proc files in debugfs as well.

Signed-off-by: Ben Gamari <bgamari@gmail.com>
Signed-off-by: Eric Anholt <eric@anholt.net>

Showing 7 changed files with 776 additions and 615 deletions Side-by-side Diff

drivers/gpu/drm/Makefile
... ... @@ -10,7 +10,8 @@
10 10 drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \
11 11 drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \
12 12 drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o \
13   - drm_crtc.o drm_crtc_helper.o drm_modes.o drm_edid.o
  13 + drm_crtc.o drm_crtc_helper.o drm_modes.o drm_edid.o \
  14 + drm_info.o drm_debugfs.o
14 15  
15 16 drm-$(CONFIG_COMPAT) += drm_ioc32.o
16 17  
drivers/gpu/drm/drm_debugfs.c
  1 +/**
  2 + * \file drm_debugfs.c
  3 + * debugfs support for DRM
  4 + *
  5 + * \author Ben Gamari <bgamari@gmail.com>
  6 + */
  7 +
  8 +/*
  9 + * Created: Sun Dec 21 13:08:50 2008 by bgamari@gmail.com
  10 + *
  11 + * Copyright 2008 Ben Gamari <bgamari@gmail.com>
  12 + *
  13 + * Permission is hereby granted, free of charge, to any person obtaining a
  14 + * copy of this software and associated documentation files (the "Software"),
  15 + * to deal in the Software without restriction, including without limitation
  16 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  17 + * and/or sell copies of the Software, and to permit persons to whom the
  18 + * Software is furnished to do so, subject to the following conditions:
  19 + *
  20 + * The above copyright notice and this permission notice (including the next
  21 + * paragraph) shall be included in all copies or substantial portions of the
  22 + * Software.
  23 + *
  24 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  25 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  26 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  27 + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  28 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  29 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  30 + * OTHER DEALINGS IN THE SOFTWARE.
  31 + */
  32 +
  33 +#include <linux/debugfs.h>
  34 +#include <linux/seq_file.h>
  35 +#include "drmP.h"
  36 +
  37 +#if defined(CONFIG_DEBUG_FS)
  38 +
  39 +/***************************************************
  40 + * Initialization, etc.
  41 + **************************************************/
  42 +
  43 +static struct drm_info_list drm_debugfs_list[] = {
  44 + {"name", drm_name_info, 0},
  45 + {"vm", drm_vm_info, 0},
  46 + {"clients", drm_clients_info, 0},
  47 + {"queues", drm_queues_info, 0},
  48 + {"bufs", drm_bufs_info, 0},
  49 + {"gem_names", drm_gem_name_info, DRIVER_GEM},
  50 + {"gem_objects", drm_gem_object_info, DRIVER_GEM},
  51 +#if DRM_DEBUG_CODE
  52 + {"vma", drm_vma_info, 0},
  53 +#endif
  54 +};
  55 +#define DRM_DEBUGFS_ENTRIES ARRAY_SIZE(drm_debugfs_list)
  56 +
  57 +
  58 +static int drm_debugfs_open(struct inode *inode, struct file *file)
  59 +{
  60 + struct drm_info_node *node = inode->i_private;
  61 +
  62 + return single_open(file, node->info_ent->show, node);
  63 +}
  64 +
  65 +
  66 +static const struct file_operations drm_debugfs_fops = {
  67 + .owner = THIS_MODULE,
  68 + .open = drm_debugfs_open,
  69 + .read = seq_read,
  70 + .llseek = seq_lseek,
  71 + .release = single_release,
  72 +};
  73 +
  74 +
  75 +/**
  76 + * Initialize a given set of debugfs files for a device
  77 + *
  78 + * \param files The array of files to create
  79 + * \param count The number of files given
  80 + * \param root DRI debugfs dir entry.
  81 + * \param minor device minor number
  82 + * \return Zero on success, non-zero on failure
  83 + *
  84 + * Create a given set of debugfs files represented by an array of
  85 + * gdm_debugfs_lists in the given root directory.
  86 + */
  87 +int drm_debugfs_create_files(struct drm_info_list *files, int count,
  88 + struct dentry *root, struct drm_minor *minor)
  89 +{
  90 + struct drm_device *dev = minor->dev;
  91 + struct dentry *ent;
  92 + struct drm_info_node *tmp;
  93 + char name[64];
  94 + int i, ret;
  95 +
  96 + for (i = 0; i < count; i++) {
  97 + u32 features = files[i].driver_features;
  98 +
  99 + if (features != 0 &&
  100 + (dev->driver->driver_features & features) != features)
  101 + continue;
  102 +
  103 + tmp = drm_alloc(sizeof(struct drm_info_node),
  104 + _DRM_DRIVER);
  105 + ent = debugfs_create_file(files[i].name, S_IFREG | S_IRUGO,
  106 + root, tmp, &drm_debugfs_fops);
  107 + if (!ent) {
  108 + DRM_ERROR("Cannot create /debugfs/dri/%s/%s\n",
  109 + name, files[i].name);
  110 + drm_free(tmp, sizeof(struct drm_info_node),
  111 + _DRM_DRIVER);
  112 + ret = -1;
  113 + goto fail;
  114 + }
  115 +
  116 + tmp->minor = minor;
  117 + tmp->dent = ent;
  118 + tmp->info_ent = &files[i];
  119 + list_add(&(tmp->list), &(minor->debugfs_nodes.list));
  120 + }
  121 + return 0;
  122 +
  123 +fail:
  124 + drm_debugfs_remove_files(files, count, minor);
  125 + return ret;
  126 +}
  127 +EXPORT_SYMBOL(drm_debugfs_create_files);
  128 +
  129 +/**
  130 + * Initialize the DRI debugfs filesystem for a device
  131 + *
  132 + * \param dev DRM device
  133 + * \param minor device minor number
  134 + * \param root DRI debugfs dir entry.
  135 + *
  136 + * Create the DRI debugfs root entry "/debugfs/dri", the device debugfs root entry
  137 + * "/debugfs/dri/%minor%/", and each entry in debugfs_list as
  138 + * "/debugfs/dri/%minor%/%name%".
  139 + */
  140 +int drm_debugfs_init(struct drm_minor *minor, int minor_id,
  141 + struct dentry *root)
  142 +{
  143 + struct drm_device *dev = minor->dev;
  144 + char name[64];
  145 + int ret;
  146 +
  147 + INIT_LIST_HEAD(&minor->debugfs_nodes.list);
  148 + sprintf(name, "%d", minor_id);
  149 + minor->debugfs_root = debugfs_create_dir(name, root);
  150 + if (!minor->debugfs_root) {
  151 + DRM_ERROR("Cannot create /debugfs/dri/%s\n", name);
  152 + return -1;
  153 + }
  154 +
  155 + ret = drm_debugfs_create_files(drm_debugfs_list, DRM_DEBUGFS_ENTRIES,
  156 + minor->debugfs_root, minor);
  157 + if (ret) {
  158 + debugfs_remove(minor->debugfs_root);
  159 + minor->debugfs_root = NULL;
  160 + DRM_ERROR("Failed to create core drm debugfs files\n");
  161 + return ret;
  162 + }
  163 +
  164 + if (dev->driver->debugfs_init) {
  165 + ret = dev->driver->debugfs_init(minor);
  166 + if (ret) {
  167 + DRM_ERROR("DRM: Driver failed to initialize "
  168 + "/debugfs/dri.\n");
  169 + return ret;
  170 + }
  171 + }
  172 + return 0;
  173 +}
  174 +
  175 +
  176 +/**
  177 + * Remove a list of debugfs files
  178 + *
  179 + * \param files The list of files
  180 + * \param count The number of files
  181 + * \param minor The minor of which we should remove the files
  182 + * \return always zero.
  183 + *
  184 + * Remove all debugfs entries created by debugfs_init().
  185 + */
  186 +int drm_debugfs_remove_files(struct drm_info_list *files, int count,
  187 + struct drm_minor *minor)
  188 +{
  189 + struct list_head *pos, *q;
  190 + struct drm_info_node *tmp;
  191 + int i;
  192 +
  193 + for (i = 0; i < count; i++) {
  194 + list_for_each_safe(pos, q, &minor->debugfs_nodes.list) {
  195 + tmp = list_entry(pos, struct drm_info_node, list);
  196 + if (tmp->info_ent == &files[i]) {
  197 + debugfs_remove(tmp->dent);
  198 + list_del(pos);
  199 + drm_free(tmp, sizeof(struct drm_info_node),
  200 + _DRM_DRIVER);
  201 + }
  202 + }
  203 + }
  204 + return 0;
  205 +}
  206 +EXPORT_SYMBOL(drm_debugfs_remove_files);
  207 +
  208 +/**
  209 + * Cleanup the debugfs filesystem resources.
  210 + *
  211 + * \param minor device minor number.
  212 + * \return always zero.
  213 + *
  214 + * Remove all debugfs entries created by debugfs_init().
  215 + */
  216 +int drm_debugfs_cleanup(struct drm_minor *minor)
  217 +{
  218 + struct drm_device *dev = minor->dev;
  219 +
  220 + if (!minor->debugfs_root)
  221 + return 0;
  222 +
  223 + if (dev->driver->debugfs_cleanup)
  224 + dev->driver->debugfs_cleanup(minor);
  225 +
  226 + drm_debugfs_remove_files(drm_debugfs_list, DRM_DEBUGFS_ENTRIES, minor);
  227 +
  228 + debugfs_remove(minor->debugfs_root);
  229 + minor->debugfs_root = NULL;
  230 +
  231 + return 0;
  232 +}
  233 +
  234 +#endif /* CONFIG_DEBUG_FS */
drivers/gpu/drm/drm_drv.c
... ... @@ -46,9 +46,11 @@
46 46 * OTHER DEALINGS IN THE SOFTWARE.
47 47 */
48 48  
  49 +#include <linux/debugfs.h>
49 50 #include "drmP.h"
50 51 #include "drm_core.h"
51 52  
  53 +
52 54 static int drm_version(struct drm_device *dev, void *data,
53 55 struct drm_file *file_priv);
54 56  
... ... @@ -178,7 +180,7 @@
178 180  
179 181 /* Clear AGP information */
180 182 if (drm_core_has_AGP(dev) && dev->agp &&
181   - !drm_core_check_feature(dev, DRIVER_MODESET)) {
  183 + !drm_core_check_feature(dev, DRIVER_MODESET)) {
182 184 struct drm_agp_mem *entry, *tempe;
183 185  
184 186 /* Remove AGP resources, but leave dev->agp
... ... @@ -382,6 +384,13 @@
382 384 goto err_p3;
383 385 }
384 386  
  387 + drm_debugfs_root = debugfs_create_dir("dri", NULL);
  388 + if (!drm_debugfs_root) {
  389 + DRM_ERROR("Cannot create /debugfs/dri\n");
  390 + ret = -1;
  391 + goto err_p3;
  392 + }
  393 +
385 394 drm_mem_init();
386 395  
387 396 DRM_INFO("Initialized %s %d.%d.%d %s\n",
... ... @@ -400,6 +409,7 @@
400 409 static void __exit drm_core_exit(void)
401 410 {
402 411 remove_proc_entry("dri", NULL);
  412 + debugfs_remove(drm_debugfs_root);
403 413 drm_sysfs_destroy();
404 414  
405 415 unregister_chrdev(DRM_MAJOR, "drm");
drivers/gpu/drm/drm_info.c
  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 + */
  44 +int 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 (master->unique) {
  55 + seq_printf(m, "%s %s %s\n",
  56 + dev->driver->pci_driver.name,
  57 + pci_name(dev->pdev), master->unique);
  58 + } else {
  59 + seq_printf(m, "%s %s\n", dev->driver->pci_driver.name,
  60 + pci_name(dev->pdev));
  61 + }
  62 +
  63 + return 0;
  64 +}
  65 +
  66 +/**
  67 + * Called when "/proc/dri/.../vm" is read.
  68 + *
  69 + * Prints information about all mappings in drm_device::maplist.
  70 + */
  71 +int drm_vm_info(struct seq_file *m, void *data)
  72 +{
  73 + struct drm_info_node *node = (struct drm_info_node *) m->private;
  74 + struct drm_device *dev = node->minor->dev;
  75 + struct drm_map *map;
  76 + struct drm_map_list *r_list;
  77 +
  78 + /* Hardcoded from _DRM_FRAME_BUFFER,
  79 + _DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and
  80 + _DRM_SCATTER_GATHER and _DRM_CONSISTENT */
  81 + const char *types[] = { "FB", "REG", "SHM", "AGP", "SG", "PCI" };
  82 + const char *type;
  83 + int i;
  84 +
  85 + mutex_lock(&dev->struct_mutex);
  86 + seq_printf(m, "slot offset size type flags address mtrr\n\n");
  87 + i = 0;
  88 + list_for_each_entry(r_list, &dev->maplist, head) {
  89 + map = r_list->map;
  90 + if (!map)
  91 + continue;
  92 + if (map->type < 0 || map->type > 5)
  93 + type = "??";
  94 + else
  95 + type = types[map->type];
  96 +
  97 + seq_printf(m, "%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08lx ",
  98 + i,
  99 + map->offset,
  100 + map->size, type, map->flags,
  101 + (unsigned long) r_list->user_token);
  102 + if (map->mtrr < 0)
  103 + seq_printf(m, "none\n");
  104 + else
  105 + seq_printf(m, "%4d\n", map->mtrr);
  106 + i++;
  107 + }
  108 + mutex_unlock(&dev->struct_mutex);
  109 + return 0;
  110 +}
  111 +
  112 +/**
  113 + * Called when "/proc/dri/.../queues" is read.
  114 + */
  115 +int drm_queues_info(struct seq_file *m, void *data)
  116 +{
  117 + struct drm_info_node *node = (struct drm_info_node *) m->private;
  118 + struct drm_device *dev = node->minor->dev;
  119 + int i;
  120 + struct drm_queue *q;
  121 +
  122 + mutex_lock(&dev->struct_mutex);
  123 + seq_printf(m, " ctx/flags use fin"
  124 + " blk/rw/rwf wait flushed queued"
  125 + " locks\n\n");
  126 + for (i = 0; i < dev->queue_count; i++) {
  127 + q = dev->queuelist[i];
  128 + atomic_inc(&q->use_count);
  129 + seq_printf(m, "%5d/0x%03x %5d %5d"
  130 + " %5d/%c%c/%c%c%c %5Zd\n",
  131 + i,
  132 + q->flags,
  133 + atomic_read(&q->use_count),
  134 + atomic_read(&q->finalization),
  135 + atomic_read(&q->block_count),
  136 + atomic_read(&q->block_read) ? 'r' : '-',
  137 + atomic_read(&q->block_write) ? 'w' : '-',
  138 + waitqueue_active(&q->read_queue) ? 'r' : '-',
  139 + waitqueue_active(&q->write_queue) ? 'w' : '-',
  140 + waitqueue_active(&q->flush_queue) ? 'f' : '-',
  141 + DRM_BUFCOUNT(&q->waitlist));
  142 + atomic_dec(&q->use_count);
  143 + }
  144 + mutex_unlock(&dev->struct_mutex);
  145 + return 0;
  146 +}
  147 +
  148 +/**
  149 + * Called when "/proc/dri/.../bufs" is read.
  150 + */
  151 +int drm_bufs_info(struct seq_file *m, void *data)
  152 +{
  153 + struct drm_info_node *node = (struct drm_info_node *) m->private;
  154 + struct drm_device *dev = node->minor->dev;
  155 + struct drm_device_dma *dma;
  156 + int i, seg_pages;
  157 +
  158 + mutex_lock(&dev->struct_mutex);
  159 + dma = dev->dma;
  160 + if (!dma) {
  161 + mutex_unlock(&dev->struct_mutex);
  162 + return 0;
  163 + }
  164 +
  165 + seq_printf(m, " o size count free segs pages kB\n\n");
  166 + for (i = 0; i <= DRM_MAX_ORDER; i++) {
  167 + if (dma->bufs[i].buf_count) {
  168 + seg_pages = dma->bufs[i].seg_count * (1 << dma->bufs[i].page_order);
  169 + seq_printf(m, "%2d %8d %5d %5d %5d %5d %5ld\n",
  170 + i,
  171 + dma->bufs[i].buf_size,
  172 + dma->bufs[i].buf_count,
  173 + atomic_read(&dma->bufs[i].freelist.count),
  174 + dma->bufs[i].seg_count,
  175 + seg_pages,
  176 + seg_pages * PAGE_SIZE / 1024);
  177 + }
  178 + }
  179 + seq_printf(m, "\n");
  180 + for (i = 0; i < dma->buf_count; i++) {
  181 + if (i && !(i % 32))
  182 + seq_printf(m, "\n");
  183 + seq_printf(m, " %d", dma->buflist[i]->list);
  184 + }
  185 + seq_printf(m, "\n");
  186 + mutex_unlock(&dev->struct_mutex);
  187 + return 0;
  188 +}
  189 +
  190 +/**
  191 + * Called when "/proc/dri/.../vblank" is read.
  192 + */
  193 +int drm_vblank_info(struct seq_file *m, void *data)
  194 +{
  195 + struct drm_info_node *node = (struct drm_info_node *) m->private;
  196 + struct drm_device *dev = node->minor->dev;
  197 + int crtc;
  198 +
  199 + mutex_lock(&dev->struct_mutex);
  200 + for (crtc = 0; crtc < dev->num_crtcs; crtc++) {
  201 + seq_printf(m, "CRTC %d enable: %d\n",
  202 + crtc, atomic_read(&dev->vblank_refcount[crtc]));
  203 + seq_printf(m, "CRTC %d counter: %d\n",
  204 + crtc, drm_vblank_count(dev, crtc));
  205 + seq_printf(m, "CRTC %d last wait: %d\n",
  206 + crtc, dev->last_vblank_wait[crtc]);
  207 + seq_printf(m, "CRTC %d in modeset: %d\n",
  208 + crtc, dev->vblank_inmodeset[crtc]);
  209 + }
  210 + mutex_unlock(&dev->struct_mutex);
  211 + return 0;
  212 +}
  213 +
  214 +/**
  215 + * Called when "/proc/dri/.../clients" is read.
  216 + *
  217 + */
  218 +int drm_clients_info(struct seq_file *m, void *data)
  219 +{
  220 + struct drm_info_node *node = (struct drm_info_node *) m->private;
  221 + struct drm_device *dev = node->minor->dev;
  222 + struct drm_file *priv;
  223 +
  224 + mutex_lock(&dev->struct_mutex);
  225 + seq_printf(m, "a dev pid uid magic ioctls\n\n");
  226 + list_for_each_entry(priv, &dev->filelist, lhead) {
  227 + seq_printf(m, "%c %3d %5d %5d %10u %10lu\n",
  228 + priv->authenticated ? 'y' : 'n',
  229 + priv->minor->index,
  230 + priv->pid,
  231 + priv->uid, priv->magic, priv->ioctl_count);
  232 + }
  233 + mutex_unlock(&dev->struct_mutex);
  234 + return 0;
  235 +}
  236 +
  237 +
  238 +int drm_gem_one_name_info(int id, void *ptr, void *data)
  239 +{
  240 + struct drm_gem_object *obj = ptr;
  241 + struct seq_file *m = data;
  242 +
  243 + seq_printf(m, "name %d size %zd\n", obj->name, obj->size);
  244 +
  245 + seq_printf(m, "%6d %8zd %7d %8d\n",
  246 + obj->name, obj->size,
  247 + atomic_read(&obj->handlecount.refcount),
  248 + atomic_read(&obj->refcount.refcount));
  249 + return 0;
  250 +}
  251 +
  252 +int drm_gem_name_info(struct seq_file *m, void *data)
  253 +{
  254 + struct drm_info_node *node = (struct drm_info_node *) m->private;
  255 + struct drm_device *dev = node->minor->dev;
  256 +
  257 + seq_printf(m, " name size handles refcount\n");
  258 + idr_for_each(&dev->object_name_idr, drm_gem_one_name_info, m);
  259 + return 0;
  260 +}
  261 +
  262 +int drm_gem_object_info(struct seq_file *m, void* data)
  263 +{
  264 + struct drm_info_node *node = (struct drm_info_node *) m->private;
  265 + struct drm_device *dev = node->minor->dev;
  266 +
  267 + seq_printf(m, "%d objects\n", atomic_read(&dev->object_count));
  268 + seq_printf(m, "%d object bytes\n", atomic_read(&dev->object_memory));
  269 + seq_printf(m, "%d pinned\n", atomic_read(&dev->pin_count));
  270 + seq_printf(m, "%d pin bytes\n", atomic_read(&dev->pin_memory));
  271 + seq_printf(m, "%d gtt bytes\n", atomic_read(&dev->gtt_memory));
  272 + seq_printf(m, "%d gtt total\n", dev->gtt_total);
  273 + return 0;
  274 +}
  275 +
  276 +#if DRM_DEBUG_CODE
  277 +
  278 +int drm_vma_info(struct seq_file *m, void *data)
  279 +{
  280 + struct drm_info_node *node = (struct drm_info_node *) m->private;
  281 + struct drm_device *dev = node->minor->dev;
  282 + struct drm_vma_entry *pt;
  283 + struct vm_area_struct *vma;
  284 +#if defined(__i386__)
  285 + unsigned int pgprot;
  286 +#endif
  287 +
  288 + mutex_lock(&dev->struct_mutex);
  289 + seq_printf(m, "vma use count: %d, high_memory = %p, 0x%08lx\n",
  290 + atomic_read(&dev->vma_count),
  291 + high_memory, virt_to_phys(high_memory));
  292 +
  293 + list_for_each_entry(pt, &dev->vmalist, head) {
  294 + vma = pt->vma;
  295 + if (!vma)
  296 + continue;
  297 + seq_printf(m,
  298 + "\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx000",
  299 + pt->pid, vma->vm_start, vma->vm_end,
  300 + vma->vm_flags & VM_READ ? 'r' : '-',
  301 + vma->vm_flags & VM_WRITE ? 'w' : '-',
  302 + vma->vm_flags & VM_EXEC ? 'x' : '-',
  303 + vma->vm_flags & VM_MAYSHARE ? 's' : 'p',
  304 + vma->vm_flags & VM_LOCKED ? 'l' : '-',
  305 + vma->vm_flags & VM_IO ? 'i' : '-',
  306 + vma->vm_pgoff);
  307 +
  308 +#if defined(__i386__)
  309 + pgprot = pgprot_val(vma->vm_page_prot);
  310 + seq_printf(m, " %c%c%c%c%c%c%c%c%c",
  311 + pgprot & _PAGE_PRESENT ? 'p' : '-',
  312 + pgprot & _PAGE_RW ? 'w' : 'r',
  313 + pgprot & _PAGE_USER ? 'u' : 's',
  314 + pgprot & _PAGE_PWT ? 't' : 'b',
  315 + pgprot & _PAGE_PCD ? 'u' : 'c',
  316 + pgprot & _PAGE_ACCESSED ? 'a' : '-',
  317 + pgprot & _PAGE_DIRTY ? 'd' : '-',
  318 + pgprot & _PAGE_PSE ? 'm' : 'k',
  319 + pgprot & _PAGE_GLOBAL ? 'g' : 'l');
  320 +#endif
  321 + seq_printf(m, "\n");
  322 + }
  323 + mutex_unlock(&dev->struct_mutex);
  324 + return 0;
  325 +}
  326 +
  327 +#endif
drivers/gpu/drm/drm_proc.c
... ... @@ -37,698 +37,196 @@
37 37 * OTHER DEALINGS IN THE SOFTWARE.
38 38 */
39 39  
  40 +#include <linux/seq_file.h>
40 41 #include "drmP.h"
41 42  
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_vblank_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 43  
  44 +/***************************************************
  45 + * Initialization, etc.
  46 + **************************************************/
  47 +
63 48 /**
64 49 * Proc file list.
65 50 */
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   - u32 driver_features; /**< Required driver features for this entry */
70   -} drm_proc_list[] = {
  51 +static struct drm_info_list drm_proc_list[] = {
71 52 {"name", drm_name_info, 0},
72   - {"mem", drm_mem_info, 0},
73 53 {"vm", drm_vm_info, 0},
74 54 {"clients", drm_clients_info, 0},
75 55 {"queues", drm_queues_info, 0},
76 56 {"bufs", drm_bufs_info, 0},
77   - {"vblank", drm_vblank_info, 0},
78 57 {"gem_names", drm_gem_name_info, DRIVER_GEM},
79 58 {"gem_objects", drm_gem_object_info, DRIVER_GEM},
80 59 #if DRM_DEBUG_CODE
81   - {"vma", drm_vma_info},
  60 + {"vma", drm_vma_info, 0},
82 61 #endif
83 62 };
84   -
85 63 #define DRM_PROC_ENTRIES ARRAY_SIZE(drm_proc_list)
86 64  
  65 +static int drm_proc_open(struct inode *inode, struct file *file)
  66 +{
  67 + struct drm_info_node* node = PDE(inode)->data;
  68 +
  69 + return single_open(file, node->info_ent->show, node);
  70 +}
  71 +
  72 +static const struct file_operations drm_proc_fops = {
  73 + .owner = THIS_MODULE,
  74 + .open = drm_proc_open,
  75 + .read = seq_read,
  76 + .llseek = seq_lseek,
  77 + .release = single_release,
  78 +};
  79 +
  80 +
87 81 /**
88   - * Initialize the DRI proc filesystem for a device.
  82 + * Initialize a given set of proc files for a device
89 83 *
90   - * \param dev DRM device.
91   - * \param minor device minor number.
  84 + * \param files The array of files to create
  85 + * \param count The number of files given
92 86 * \param root DRI proc dir entry.
93   - * \param dev_root resulting DRI device proc dir entry.
94   - * \return root entry pointer on success, or NULL on failure.
  87 + * \param minor device minor number
  88 + * \return Zero on success, non-zero on failure
95 89 *
96   - * Create the DRI proc root entry "/proc/dri", the device proc root entry
97   - * "/proc/dri/%minor%/", and each entry in proc_list as
98   - * "/proc/dri/%minor%/%name%".
  90 + * Create a given set of proc files represented by an array of
  91 + * gdm_proc_lists in the given root directory.
99 92 */
100   -int drm_proc_init(struct drm_minor *minor, int minor_id,
101   - struct proc_dir_entry *root)
  93 +int drm_proc_create_files(struct drm_info_list *files, int count,
  94 + struct proc_dir_entry *root, struct drm_minor *minor)
102 95 {
103 96 struct drm_device *dev = minor->dev;
104 97 struct proc_dir_entry *ent;
105   - int i, j, ret;
  98 + struct drm_info_node *tmp;
106 99 char name[64];
  100 + int i, ret;
107 101  
108   - sprintf(name, "%d", minor_id);
109   - minor->dev_root = proc_mkdir(name, root);
110   - if (!minor->dev_root) {
111   - DRM_ERROR("Cannot create /proc/dri/%s\n", name);
112   - return -1;
113   - }
  102 + for (i = 0; i < count; i++) {
  103 + u32 features = files[i].driver_features;
114 104  
115   - for (i = 0; i < DRM_PROC_ENTRIES; i++) {
116   - u32 features = drm_proc_list[i].driver_features;
117   -
118 105 if (features != 0 &&
119 106 (dev->driver->driver_features & features) != features)
120 107 continue;
121 108  
122   - ent = create_proc_entry(drm_proc_list[i].name,
123   - S_IFREG | S_IRUGO, minor->dev_root);
  109 + tmp = drm_alloc(sizeof(struct drm_info_node), _DRM_DRIVER);
  110 + ent = create_proc_entry(files[i].name, S_IFREG | S_IRUGO, root);
124 111 if (!ent) {
125 112 DRM_ERROR("Cannot create /proc/dri/%s/%s\n",
126   - name, drm_proc_list[i].name);
  113 + name, files[i].name);
  114 + drm_free(tmp, sizeof(struct drm_info_node),
  115 + _DRM_DRIVER);
127 116 ret = -1;
128 117 goto fail;
129 118 }
130   - ent->read_proc = drm_proc_list[i].f;
131   - ent->data = minor;
132   - }
133 119  
134   - if (dev->driver->proc_init) {
135   - ret = dev->driver->proc_init(minor);
136   - if (ret) {
137   - DRM_ERROR("DRM: Driver failed to initialize "
138   - "/proc/dri.\n");
139   - goto fail;
140   - }
  120 + ent->proc_fops = &drm_proc_fops;
  121 + ent->data = tmp;
  122 + tmp->minor = minor;
  123 + tmp->info_ent = &files[i];
  124 + list_add(&(tmp->list), &(minor->proc_nodes.list));
141 125 }
142   -
143 126 return 0;
144   - fail:
145 127  
146   - for (j = 0; j < i; j++)
147   - remove_proc_entry(drm_proc_list[i].name,
148   - minor->dev_root);
149   - remove_proc_entry(name, root);
150   - minor->dev_root = NULL;
  128 +fail:
  129 + for (i = 0; i < count; i++)
  130 + remove_proc_entry(drm_proc_list[i].name, minor->proc_root);
151 131 return ret;
152 132 }
153 133  
154 134 /**
155   - * Cleanup the proc filesystem resources.
  135 + * Initialize the DRI proc filesystem for a device
156 136 *
157   - * \param minor device minor number.
  137 + * \param dev DRM device
  138 + * \param minor device minor number
158 139 * \param root DRI proc dir entry.
159   - * \param dev_root DRI device proc dir entry.
160   - * \return always zero.
  140 + * \param dev_root resulting DRI device proc dir entry.
  141 + * \return root entry pointer on success, or NULL on failure.
161 142 *
162   - * Remove all proc entries created by proc_init().
  143 + * Create the DRI proc root entry "/proc/dri", the device proc root entry
  144 + * "/proc/dri/%minor%/", and each entry in proc_list as
  145 + * "/proc/dri/%minor%/%name%".
163 146 */
164   -int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root)
  147 +int drm_proc_init(struct drm_minor *minor, int minor_id,
  148 + struct proc_dir_entry *root)
165 149 {
166 150 struct drm_device *dev = minor->dev;
167   - int i;
168 151 char name[64];
  152 + int ret;
169 153  
170   - if (!root || !minor->dev_root)
171   - return 0;
172   -
173   - if (dev->driver->proc_cleanup)
174   - dev->driver->proc_cleanup(minor);
175   -
176   - for (i = 0; i < DRM_PROC_ENTRIES; i++)
177   - remove_proc_entry(drm_proc_list[i].name, minor->dev_root);
178   - sprintf(name, "%d", minor->index);
179   - remove_proc_entry(name, root);
180   -
181   - return 0;
182   -}
183   -
184   -/**
185   - * Called when "/proc/dri/.../name" is read.
186   - *
187   - * \param buf output buffer.
188   - * \param start start of output data.
189   - * \param offset requested start offset.
190   - * \param request requested number of bytes.
191   - * \param eof whether there is no more data to return.
192   - * \param data private data.
193   - * \return number of written bytes.
194   - *
195   - * Prints the device name together with the bus id if available.
196   - */
197   -static int drm_name_info(char *buf, char **start, off_t offset, int request,
198   - int *eof, void *data)
199   -{
200   - struct drm_minor *minor = (struct drm_minor *) data;
201   - struct drm_master *master = minor->master;
202   - struct drm_device *dev = minor->dev;
203   - int len = 0;
204   -
205   - if (offset > DRM_PROC_LIMIT) {
206   - *eof = 1;
207   - return 0;
  154 + INIT_LIST_HEAD(&minor->proc_nodes.list);
  155 + sprintf(name, "%d", minor_id);
  156 + minor->proc_root = proc_mkdir(name, root);
  157 + if (!minor->proc_root) {
  158 + DRM_ERROR("Cannot create /proc/dri/%s\n", name);
  159 + return -1;
208 160 }
209 161  
210   - if (!master)
211   - return 0;
212   -
213   - *start = &buf[offset];
214   - *eof = 0;
215   -
216   - if (master->unique) {
217   - DRM_PROC_PRINT("%s %s %s\n",
218   - dev->driver->pci_driver.name,
219   - pci_name(dev->pdev), master->unique);
220   - } else {
221   - DRM_PROC_PRINT("%s %s\n", dev->driver->pci_driver.name,
222   - pci_name(dev->pdev));
  162 + ret = drm_proc_create_files(drm_proc_list, DRM_PROC_ENTRIES,
  163 + minor->proc_root, minor);
  164 + if (ret) {
  165 + remove_proc_entry(name, root);
  166 + minor->proc_root = NULL;
  167 + DRM_ERROR("Failed to create core drm proc files\n");
  168 + return ret;
223 169 }
224 170  
225   - if (len > request + offset)
226   - return request;
227   - *eof = 1;
228   - return len - offset;
229   -}
230   -
231   -/**
232   - * Called when "/proc/dri/.../vm" is read.
233   - *
234   - * \param buf output buffer.
235   - * \param start start of output data.
236   - * \param offset requested start offset.
237   - * \param request requested number of bytes.
238   - * \param eof whether there is no more data to return.
239   - * \param data private data.
240   - * \return number of written bytes.
241   - *
242   - * Prints information about all mappings in drm_device::maplist.
243   - */
244   -static int drm__vm_info(char *buf, char **start, off_t offset, int request,
245   - int *eof, void *data)
246   -{
247   - struct drm_minor *minor = (struct drm_minor *) data;
248   - struct drm_device *dev = minor->dev;
249   - int len = 0;
250   - struct drm_map *map;
251   - struct drm_map_list *r_list;
252   -
253   - /* Hardcoded from _DRM_FRAME_BUFFER,
254   - _DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and
255   - _DRM_SCATTER_GATHER and _DRM_CONSISTENT */
256   - const char *types[] = { "FB", "REG", "SHM", "AGP", "SG", "PCI" };
257   - const char *type;
258   - int i;
259   -
260   - if (offset > DRM_PROC_LIMIT) {
261   - *eof = 1;
262   - return 0;
263   - }
264   -
265   - *start = &buf[offset];
266   - *eof = 0;
267   -
268   - DRM_PROC_PRINT("slot offset size type flags "
269   - "address mtrr\n\n");
270   - i = 0;
271   - list_for_each_entry(r_list, &dev->maplist, head) {
272   - map = r_list->map;
273   - if (!map)
274   - continue;
275   - if (map->type < 0 || map->type > 5)
276   - type = "??";
277   - else
278   - type = types[map->type];
279   - DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08lx ",
280   - i,
281   - map->offset,
282   - map->size, type, map->flags,
283   - (unsigned long) r_list->user_token);
284   - if (map->mtrr < 0) {
285   - DRM_PROC_PRINT("none\n");
286   - } else {
287   - DRM_PROC_PRINT("%4d\n", map->mtrr);
  171 + if (dev->driver->proc_init) {
  172 + ret = dev->driver->proc_init(minor);
  173 + if (ret) {
  174 + DRM_ERROR("DRM: Driver failed to initialize "
  175 + "/proc/dri.\n");
  176 + return ret;
288 177 }
289   - i++;
290 178 }
291   -
292   - if (len > request + offset)
293   - return request;
294   - *eof = 1;
295   - return len - offset;
  179 + return 0;
296 180 }
297 181  
298   -/**
299   - * Simply calls _vm_info() while holding the drm_device::struct_mutex lock.
300   - */
301   -static int drm_vm_info(char *buf, char **start, off_t offset, int request,
302   - int *eof, void *data)
  182 +int drm_proc_remove_files(struct drm_info_list *files, int count,
  183 + struct drm_minor *minor)
303 184 {
304   - struct drm_minor *minor = (struct drm_minor *) data;
305   - struct drm_device *dev = minor->dev;
306   - int ret;
307   -
308   - mutex_lock(&dev->struct_mutex);
309   - ret = drm__vm_info(buf, start, offset, request, eof, data);
310   - mutex_unlock(&dev->struct_mutex);
311   - return ret;
312   -}
313   -
314   -/**
315   - * Called when "/proc/dri/.../queues" is read.
316   - *
317   - * \param buf output buffer.
318   - * \param start start of output data.
319   - * \param offset requested start offset.
320   - * \param request requested number of bytes.
321   - * \param eof whether there is no more data to return.
322   - * \param data private data.
323   - * \return number of written bytes.
324   - */
325   -static int drm__queues_info(char *buf, char **start, off_t offset,
326   - int request, int *eof, void *data)
327   -{
328   - struct drm_minor *minor = (struct drm_minor *) data;
329   - struct drm_device *dev = minor->dev;
330   - int len = 0;
  185 + struct list_head *pos, *q;
  186 + struct drm_info_node *tmp;
331 187 int i;
332   - struct drm_queue *q;
333 188  
334   - if (offset > DRM_PROC_LIMIT) {
335   - *eof = 1;
336   - return 0;
  189 + for (i = 0; i < count; i++) {
  190 + list_for_each_safe(pos, q, &minor->proc_nodes.list) {
  191 + tmp = list_entry(pos, struct drm_info_node, list);
  192 + if (tmp->info_ent == &files[i]) {
  193 + remove_proc_entry(files[i].name,
  194 + minor->proc_root);
  195 + list_del(pos);
  196 + drm_free(tmp, sizeof(struct drm_info_node),
  197 + _DRM_DRIVER);
  198 + }
  199 + }
337 200 }
338   -
339   - *start = &buf[offset];
340   - *eof = 0;
341   -
342   - DRM_PROC_PRINT(" ctx/flags use fin"
343   - " blk/rw/rwf wait flushed queued"
344   - " locks\n\n");
345   - for (i = 0; i < dev->queue_count; i++) {
346   - q = dev->queuelist[i];
347   - atomic_inc(&q->use_count);
348   - DRM_PROC_PRINT_RET(atomic_dec(&q->use_count),
349   - "%5d/0x%03x %5d %5d"
350   - " %5d/%c%c/%c%c%c %5Zd\n",
351   - i,
352   - q->flags,
353   - atomic_read(&q->use_count),
354   - atomic_read(&q->finalization),
355   - atomic_read(&q->block_count),
356   - atomic_read(&q->block_read) ? 'r' : '-',
357   - atomic_read(&q->block_write) ? 'w' : '-',
358   - waitqueue_active(&q->read_queue) ? 'r' : '-',
359   - waitqueue_active(&q->
360   - write_queue) ? 'w' : '-',
361   - waitqueue_active(&q->
362   - flush_queue) ? 'f' : '-',
363   - DRM_BUFCOUNT(&q->waitlist));
364   - atomic_dec(&q->use_count);
365   - }
366   -
367   - if (len > request + offset)
368   - return request;
369   - *eof = 1;
370   - return len - offset;
  201 + return 0;
371 202 }
372 203  
373 204 /**
374   - * Simply calls _queues_info() while holding the drm_device::struct_mutex lock.
375   - */
376   -static int drm_queues_info(char *buf, char **start, off_t offset, int request,
377   - int *eof, void *data)
378   -{
379   - struct drm_minor *minor = (struct drm_minor *) data;
380   - struct drm_device *dev = minor->dev;
381   - int ret;
382   -
383   - mutex_lock(&dev->struct_mutex);
384   - ret = drm__queues_info(buf, start, offset, request, eof, data);
385   - mutex_unlock(&dev->struct_mutex);
386   - return ret;
387   -}
388   -
389   -/**
390   - * Called when "/proc/dri/.../bufs" is read.
  205 + * Cleanup the proc filesystem resources.
391 206 *
392   - * \param buf output buffer.
393   - * \param start start of output data.
394   - * \param offset requested start offset.
395   - * \param request requested number of bytes.
396   - * \param eof whether there is no more data to return.
397   - * \param data private data.
398   - * \return number of written bytes.
399   - */
400   -static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
401   - int *eof, void *data)
402   -{
403   - struct drm_minor *minor = (struct drm_minor *) data;
404   - struct drm_device *dev = minor->dev;
405   - int len = 0;
406   - struct drm_device_dma *dma = dev->dma;
407   - int i;
408   -
409   - if (!dma || offset > DRM_PROC_LIMIT) {
410   - *eof = 1;
411   - return 0;
412   - }
413   -
414   - *start = &buf[offset];
415   - *eof = 0;
416   -
417   - DRM_PROC_PRINT(" o size count free segs pages kB\n\n");
418   - for (i = 0; i <= DRM_MAX_ORDER; i++) {
419   - if (dma->bufs[i].buf_count)
420   - DRM_PROC_PRINT("%2d %8d %5d %5d %5d %5d %5ld\n",
421   - i,
422   - dma->bufs[i].buf_size,
423   - dma->bufs[i].buf_count,
424   - atomic_read(&dma->bufs[i]
425   - .freelist.count),
426   - dma->bufs[i].seg_count,
427   - dma->bufs[i].seg_count
428   - * (1 << dma->bufs[i].page_order),
429   - (dma->bufs[i].seg_count
430   - * (1 << dma->bufs[i].page_order))
431   - * PAGE_SIZE / 1024);
432   - }
433   - DRM_PROC_PRINT("\n");
434   - for (i = 0; i < dma->buf_count; i++) {
435   - if (i && !(i % 32))
436   - DRM_PROC_PRINT("\n");
437   - DRM_PROC_PRINT(" %d", dma->buflist[i]->list);
438   - }
439   - DRM_PROC_PRINT("\n");
440   -
441   - if (len > request + offset)
442   - return request;
443   - *eof = 1;
444   - return len - offset;
445   -}
446   -
447   -/**
448   - * Simply calls _bufs_info() while holding the drm_device::struct_mutex lock.
449   - */
450   -static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
451   - int *eof, void *data)
452   -{
453   - struct drm_minor *minor = (struct drm_minor *) data;
454   - struct drm_device *dev = minor->dev;
455   - int ret;
456   -
457   - mutex_lock(&dev->struct_mutex);
458   - ret = drm__bufs_info(buf, start, offset, request, eof, data);
459   - mutex_unlock(&dev->struct_mutex);
460   - return ret;
461   -}
462   -
463   -/**
464   - * Called when "/proc/dri/.../vblank" is read.
  207 + * \param minor device minor number.
  208 + * \param root DRI proc dir entry.
  209 + * \param dev_root DRI device proc dir entry.
  210 + * \return always zero.
465 211 *
466   - * \param buf output buffer.
467   - * \param start start of output data.
468   - * \param offset requested start offset.
469   - * \param request requested number of bytes.
470   - * \param eof whether there is no more data to return.
471   - * \param data private data.
472   - * \return number of written bytes.
  212 + * Remove all proc entries created by proc_init().
473 213 */
474   -static int drm__vblank_info(char *buf, char **start, off_t offset, int request,
475   - int *eof, void *data)
  214 +int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root)
476 215 {
477   - struct drm_minor *minor = (struct drm_minor *) data;
478 216 struct drm_device *dev = minor->dev;
479   - int len = 0;
480   - int crtc;
  217 + char name[64];
481 218  
482   - if (offset > DRM_PROC_LIMIT) {
483   - *eof = 1;
  219 + if (!root || !minor->proc_root)
484 220 return 0;
485   - }
486 221  
487   - *start = &buf[offset];
488   - *eof = 0;
  222 + if (dev->driver->proc_cleanup)
  223 + dev->driver->proc_cleanup(minor);
489 224  
490   - for (crtc = 0; crtc < dev->num_crtcs; crtc++) {
491   - DRM_PROC_PRINT("CRTC %d enable: %d\n",
492   - crtc, atomic_read(&dev->vblank_refcount[crtc]));
493   - DRM_PROC_PRINT("CRTC %d counter: %d\n",
494   - crtc, drm_vblank_count(dev, crtc));
495   - DRM_PROC_PRINT("CRTC %d last wait: %d\n",
496   - crtc, dev->last_vblank_wait[crtc]);
497   - DRM_PROC_PRINT("CRTC %d in modeset: %d\n",
498   - crtc, dev->vblank_inmodeset[crtc]);
499   - }
  225 + drm_proc_remove_files(drm_proc_list, DRM_PROC_ENTRIES, minor);
500 226  
501   - if (len > request + offset)
502   - return request;
503   - *eof = 1;
504   - return len - offset;
505   -}
  227 + sprintf(name, "%d", minor->index);
  228 + remove_proc_entry(name, root);
506 229  
507   -/**
508   - * Simply calls _vblank_info() while holding the drm_device::struct_mutex lock.
509   - */
510   -static int drm_vblank_info(char *buf, char **start, off_t offset, int request,
511   - int *eof, void *data)
512   -{
513   - struct drm_minor *minor = (struct drm_minor *) data;
514   - struct drm_device *dev = minor->dev;
515   - int ret;
516   -
517   - mutex_lock(&dev->struct_mutex);
518   - ret = drm__vblank_info(buf, start, offset, request, eof, data);
519   - mutex_unlock(&dev->struct_mutex);
520   - return ret;
521   -}
522   -
523   -/**
524   - * Called when "/proc/dri/.../clients" is read.
525   - *
526   - * \param buf output buffer.
527   - * \param start start of output data.
528   - * \param offset requested start offset.
529   - * \param request requested number of bytes.
530   - * \param eof whether there is no more data to return.
531   - * \param data private data.
532   - * \return number of written bytes.
533   - */
534   -static int drm__clients_info(char *buf, char **start, off_t offset,
535   - int request, int *eof, void *data)
536   -{
537   - struct drm_minor *minor = (struct drm_minor *) data;
538   - struct drm_device *dev = minor->dev;
539   - int len = 0;
540   - struct drm_file *priv;
541   -
542   - if (offset > DRM_PROC_LIMIT) {
543   - *eof = 1;
544   - return 0;
545   - }
546   -
547   - *start = &buf[offset];
548   - *eof = 0;
549   -
550   - DRM_PROC_PRINT("a dev pid uid magic ioctls\n\n");
551   - list_for_each_entry(priv, &dev->filelist, lhead) {
552   - DRM_PROC_PRINT("%c %3d %5d %5d %10u %10lu\n",
553   - priv->authenticated ? 'y' : 'n',
554   - priv->minor->index,
555   - priv->pid,
556   - priv->uid, priv->magic, priv->ioctl_count);
557   - }
558   -
559   - if (len > request + offset)
560   - return request;
561   - *eof = 1;
562   - return len - offset;
563   -}
564   -
565   -/**
566   - * Simply calls _clients_info() while holding the drm_device::struct_mutex lock.
567   - */
568   -static int drm_clients_info(char *buf, char **start, off_t offset,
569   - int request, int *eof, void *data)
570   -{
571   - struct drm_minor *minor = (struct drm_minor *) data;
572   - struct drm_device *dev = minor->dev;
573   - int ret;
574   -
575   - mutex_lock(&dev->struct_mutex);
576   - ret = drm__clients_info(buf, start, offset, request, eof, data);
577   - mutex_unlock(&dev->struct_mutex);
578   - return ret;
579   -}
580   -
581   -struct drm_gem_name_info_data {
582   - int len;
583   - char *buf;
584   - int eof;
585   -};
586   -
587   -static int drm_gem_one_name_info(int id, void *ptr, void *data)
588   -{
589   - struct drm_gem_object *obj = ptr;
590   - struct drm_gem_name_info_data *nid = data;
591   -
592   - DRM_INFO("name %d size %zd\n", obj->name, obj->size);
593   - if (nid->eof)
594   - return 0;
595   -
596   - nid->len += sprintf(&nid->buf[nid->len],
597   - "%6d %8zd %7d %8d\n",
598   - obj->name, obj->size,
599   - atomic_read(&obj->handlecount.refcount),
600   - atomic_read(&obj->refcount.refcount));
601   - if (nid->len > DRM_PROC_LIMIT) {
602   - nid->eof = 1;
603   - return 0;
604   - }
605 230 return 0;
606 231 }
607   -
608   -static int drm_gem_name_info(char *buf, char **start, off_t offset,
609   - int request, int *eof, void *data)
610   -{
611   - struct drm_minor *minor = (struct drm_minor *) data;
612   - struct drm_device *dev = minor->dev;
613   - struct drm_gem_name_info_data nid;
614   -
615   - if (offset > DRM_PROC_LIMIT) {
616   - *eof = 1;
617   - return 0;
618   - }
619   -
620   - nid.len = sprintf(buf, " name size handles refcount\n");
621   - nid.buf = buf;
622   - nid.eof = 0;
623   - idr_for_each(&dev->object_name_idr, drm_gem_one_name_info, &nid);
624   -
625   - *start = &buf[offset];
626   - *eof = 0;
627   - if (nid.len > request + offset)
628   - return request;
629   - *eof = 1;
630   - return nid.len - offset;
631   -}
632   -
633   -static int drm_gem_object_info(char *buf, char **start, off_t offset,
634   - int request, int *eof, void *data)
635   -{
636   - struct drm_minor *minor = (struct drm_minor *) data;
637   - struct drm_device *dev = minor->dev;
638   - int len = 0;
639   -
640   - if (offset > DRM_PROC_LIMIT) {
641   - *eof = 1;
642   - return 0;
643   - }
644   -
645   - *start = &buf[offset];
646   - *eof = 0;
647   - DRM_PROC_PRINT("%d objects\n", atomic_read(&dev->object_count));
648   - DRM_PROC_PRINT("%d object bytes\n", atomic_read(&dev->object_memory));
649   - DRM_PROC_PRINT("%d pinned\n", atomic_read(&dev->pin_count));
650   - DRM_PROC_PRINT("%d pin bytes\n", atomic_read(&dev->pin_memory));
651   - DRM_PROC_PRINT("%d gtt bytes\n", atomic_read(&dev->gtt_memory));
652   - DRM_PROC_PRINT("%d gtt total\n", dev->gtt_total);
653   - if (len > request + offset)
654   - return request;
655   - *eof = 1;
656   - return len - offset;
657   -}
658   -
659   -#if DRM_DEBUG_CODE
660   -
661   -static int drm__vma_info(char *buf, char **start, off_t offset, int request,
662   - int *eof, void *data)
663   -{
664   - struct drm_minor *minor = (struct drm_minor *) data;
665   - struct drm_device *dev = minor->dev;
666   - int len = 0;
667   - struct drm_vma_entry *pt;
668   - struct vm_area_struct *vma;
669   -#if defined(__i386__)
670   - unsigned int pgprot;
671   -#endif
672   -
673   - if (offset > DRM_PROC_LIMIT) {
674   - *eof = 1;
675   - return 0;
676   - }
677   -
678   - *start = &buf[offset];
679   - *eof = 0;
680   -
681   - DRM_PROC_PRINT("vma use count: %d, high_memory = %p, 0x%08lx\n",
682   - atomic_read(&dev->vma_count),
683   - high_memory, virt_to_phys(high_memory));
684   - list_for_each_entry(pt, &dev->vmalist, head) {
685   - if (!(vma = pt->vma))
686   - continue;
687   - DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx000",
688   - pt->pid,
689   - vma->vm_start,
690   - vma->vm_end,
691   - vma->vm_flags & VM_READ ? 'r' : '-',
692   - vma->vm_flags & VM_WRITE ? 'w' : '-',
693   - vma->vm_flags & VM_EXEC ? 'x' : '-',
694   - vma->vm_flags & VM_MAYSHARE ? 's' : 'p',
695   - vma->vm_flags & VM_LOCKED ? 'l' : '-',
696   - vma->vm_flags & VM_IO ? 'i' : '-',
697   - vma->vm_pgoff);
698   -
699   -#if defined(__i386__)
700   - pgprot = pgprot_val(vma->vm_page_prot);
701   - DRM_PROC_PRINT(" %c%c%c%c%c%c%c%c%c",
702   - pgprot & _PAGE_PRESENT ? 'p' : '-',
703   - pgprot & _PAGE_RW ? 'w' : 'r',
704   - pgprot & _PAGE_USER ? 'u' : 's',
705   - pgprot & _PAGE_PWT ? 't' : 'b',
706   - pgprot & _PAGE_PCD ? 'u' : 'c',
707   - pgprot & _PAGE_ACCESSED ? 'a' : '-',
708   - pgprot & _PAGE_DIRTY ? 'd' : '-',
709   - pgprot & _PAGE_PSE ? 'm' : 'k',
710   - pgprot & _PAGE_GLOBAL ? 'g' : 'l');
711   -#endif
712   - DRM_PROC_PRINT("\n");
713   - }
714   -
715   - if (len > request + offset)
716   - return request;
717   - *eof = 1;
718   - return len - offset;
719   -}
720   -
721   -static int drm_vma_info(char *buf, char **start, off_t offset, int request,
722   - int *eof, void *data)
723   -{
724   - struct drm_minor *minor = (struct drm_minor *) data;
725   - struct drm_device *dev = minor->dev;
726   - int ret;
727   -
728   - mutex_lock(&dev->struct_mutex);
729   - ret = drm__vma_info(buf, start, offset, request, eof, data);
730   - mutex_unlock(&dev->struct_mutex);
731   - return ret;
732   -}
733   -#endif
drivers/gpu/drm/drm_stub.c
... ... @@ -50,6 +50,7 @@
50 50  
51 51 struct class *drm_class;
52 52 struct proc_dir_entry *drm_proc_root;
  53 +struct dentry *drm_debugfs_root;
53 54  
54 55 static int drm_minor_get_id(struct drm_device *dev, int type)
55 56 {
56 57  
... ... @@ -313,8 +314,16 @@
313 314 goto err_mem;
314 315 }
315 316 } else
316   - new_minor->dev_root = NULL;
  317 + new_minor->proc_root = NULL;
317 318  
  319 +#if defined(CONFIG_DEBUG_FS)
  320 + ret = drm_debugfs_init(new_minor, minor_id, drm_debugfs_root);
  321 + if (ret) {
  322 + DRM_ERROR("DRM: Failed to initialize /debugfs/dri.\n");
  323 + goto err_g2;
  324 + }
  325 +#endif
  326 +
318 327 ret = drm_sysfs_device_add(new_minor);
319 328 if (ret) {
320 329 printk(KERN_ERR
... ... @@ -451,6 +460,10 @@
451 460  
452 461 if (minor->type == DRM_MINOR_LEGACY)
453 462 drm_proc_cleanup(minor, drm_proc_root);
  463 +#if defined(CONFIG_DEBUG_FS)
  464 + drm_debugfs_cleanup(minor);
  465 +#endif
  466 +
454 467 drm_sysfs_device_remove(minor);
455 468  
456 469 idr_remove(&drm_minors_idr, minor->index);
... ... @@ -758,6 +758,8 @@
758 758  
759 759 int (*proc_init)(struct drm_minor *minor);
760 760 void (*proc_cleanup)(struct drm_minor *minor);
  761 + int (*debugfs_init)(struct drm_minor *minor);
  762 + void (*debugfs_cleanup)(struct drm_minor *minor);
761 763  
762 764 /**
763 765 * Driver-specific constructor for drm_gem_objects, to set up
764 766  
... ... @@ -793,7 +795,49 @@
793 795 #define DRM_MINOR_CONTROL 2
794 796 #define DRM_MINOR_RENDER 3
795 797  
  798 +
796 799 /**
  800 + * debugfs node list. This structure represents a debugfs file to
  801 + * be created by the drm core
  802 + */
  803 +struct drm_debugfs_list {
  804 + const char *name; /** file name */
  805 + int (*show)(struct seq_file*, void*); /** show callback */
  806 + u32 driver_features; /**< Required driver features for this entry */
  807 +};
  808 +
  809 +/**
  810 + * debugfs node structure. This structure represents a debugfs file.
  811 + */
  812 +struct drm_debugfs_node {
  813 + struct list_head list;
  814 + struct drm_minor *minor;
  815 + struct drm_debugfs_list *debugfs_ent;
  816 + struct dentry *dent;
  817 +};
  818 +
  819 +/**
  820 + * Info file list entry. This structure represents a debugfs or proc file to
  821 + * be created by the drm core
  822 + */
  823 +struct drm_info_list {
  824 + const char *name; /** file name */
  825 + int (*show)(struct seq_file*, void*); /** show callback */
  826 + u32 driver_features; /**< Required driver features for this entry */
  827 + void *data;
  828 +};
  829 +
  830 +/**
  831 + * debugfs node structure. This structure represents a debugfs file.
  832 + */
  833 +struct drm_info_node {
  834 + struct list_head list;
  835 + struct drm_minor *minor;
  836 + struct drm_info_list *info_ent;
  837 + struct dentry *dent;
  838 +};
  839 +
  840 +/**
797 841 * DRM minor structure. This structure represents a drm minor number.
798 842 */
799 843 struct drm_minor {
... ... @@ -802,7 +846,12 @@
802 846 dev_t device; /**< Device number for mknod */
803 847 struct device kdev; /**< Linux device */
804 848 struct drm_device *dev;
805   - struct proc_dir_entry *dev_root; /**< proc directory entry */
  849 +
  850 + struct proc_dir_entry *proc_root; /**< proc directory entry */
  851 + struct drm_info_node proc_nodes;
  852 + struct dentry *debugfs_root;
  853 + struct drm_info_node debugfs_nodes;
  854 +
806 855 struct drm_master *master; /* currently active master for this node */
807 856 struct list_head master_list;
808 857 struct drm_mode_group mode_group;
... ... @@ -1258,6 +1307,7 @@
1258 1307  
1259 1308 extern struct class *drm_class;
1260 1309 extern struct proc_dir_entry *drm_proc_root;
  1310 +extern struct dentry *drm_debugfs_root;
1261 1311  
1262 1312 extern struct idr drm_minors_idr;
1263 1313  
... ... @@ -1267,6 +1317,31 @@
1267 1317 extern int drm_proc_init(struct drm_minor *minor, int minor_id,
1268 1318 struct proc_dir_entry *root);
1269 1319 extern int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root);
  1320 +
  1321 + /* Debugfs support */
  1322 +#if defined(CONFIG_DEBUG_FS)
  1323 +extern int drm_debugfs_init(struct drm_minor *minor, int minor_id,
  1324 + struct dentry *root);
  1325 +extern int drm_debugfs_create_files(struct drm_info_list *files, int count,
  1326 + struct dentry *root, struct drm_minor *minor);
  1327 +extern int drm_debugfs_remove_files(struct drm_info_list *files, int count,
  1328 + struct drm_minor *minor);
  1329 +extern int drm_debugfs_cleanup(struct drm_minor *minor);
  1330 +#endif
  1331 +
  1332 + /* Info file support */
  1333 +extern int drm_name_info(struct seq_file *m, void *data);
  1334 +extern int drm_vm_info(struct seq_file *m, void *data);
  1335 +extern int drm_queues_info(struct seq_file *m, void *data);
  1336 +extern int drm_bufs_info(struct seq_file *m, void *data);
  1337 +extern int drm_vblank_info(struct seq_file *m, void *data);
  1338 +extern int drm_clients_info(struct seq_file *m, void* data);
  1339 +extern int drm_gem_name_info(struct seq_file *m, void *data);
  1340 +extern int drm_gem_object_info(struct seq_file *m, void* data);
  1341 +
  1342 +#if DRM_DEBUG_CODE
  1343 +extern int drm_vma_info(struct seq_file *m, void *data);
  1344 +#endif
1270 1345  
1271 1346 /* Scatter Gather Support (drm_scatter.h) */
1272 1347 extern void drm_sg_cleanup(struct drm_sg_mem * entry);