aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBen Gamari <bgamari@gmail.com>2009-02-17 20:08:49 -0500
committerDave Airlie <airlied@redhat.com>2009-03-13 00:24:07 -0400
commit955b12def42e83287c1bdb1411d99451753c1391 (patch)
tree5dc5025f500b7a0a86c70ea79f2294e94902e3b2 /drivers
parentdd8d7cb49e6e61da96ca44174b063081892c4dc6 (diff)
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. This contains the i915 hooks rewrite as well, to make bisectability better. Signed-off-by: Ben Gamari <bgamari@gmail.com> Signed-off-by: Eric Anholt <eric@anholt.net> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/Makefile3
-rw-r--r--drivers/gpu/drm/drm_debugfs.c235
-rw-r--r--drivers/gpu/drm/drm_drv.c12
-rw-r--r--drivers/gpu/drm/drm_info.c328
-rw-r--r--drivers/gpu/drm/drm_proc.c720
-rw-r--r--drivers/gpu/drm/drm_stub.c15
-rw-r--r--drivers/gpu/drm/i915/Makefile2
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c6
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h6
-rw-r--r--drivers/gpu/drm/i915/i915_gem_debugfs.c230
-rw-r--r--drivers/gpu/drm/i915/i915_gem_proc.c334
11 files changed, 938 insertions, 953 deletions
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 30022c4a5c12..4ec5061fa584 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -10,7 +10,8 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \
10 drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \ 10 drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \
11 drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \ 11 drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \
12 drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o \ 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
15drm-$(CONFIG_COMPAT) += drm_ioc32.o 16drm-$(CONFIG_COMPAT) += drm_ioc32.o
16 17
diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c
new file mode 100644
index 000000000000..c77c6c6d9d2c
--- /dev/null
+++ b/drivers/gpu/drm/drm_debugfs.c
@@ -0,0 +1,235 @@
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
43static 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
58static 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
66static 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 */
87int 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
123fail:
124 drm_debugfs_remove_files(files, count, minor);
125 return ret;
126}
127EXPORT_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 */
140int 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 */
186int 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}
206EXPORT_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 */
216int 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 */
235
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 1441655388ab..c26ee0822a05 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -46,9 +46,11 @@
46 * OTHER DEALINGS IN THE SOFTWARE. 46 * OTHER DEALINGS IN THE SOFTWARE.
47 */ 47 */
48 48
49#include <linux/debugfs.h>
49#include "drmP.h" 50#include "drmP.h"
50#include "drm_core.h" 51#include "drm_core.h"
51 52
53
52static int drm_version(struct drm_device *dev, void *data, 54static int drm_version(struct drm_device *dev, void *data,
53 struct drm_file *file_priv); 55 struct drm_file *file_priv);
54 56
@@ -178,7 +180,7 @@ int drm_lastclose(struct drm_device * dev)
178 180
179 /* Clear AGP information */ 181 /* Clear AGP information */
180 if (drm_core_has_AGP(dev) && dev->agp && 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 struct drm_agp_mem *entry, *tempe; 184 struct drm_agp_mem *entry, *tempe;
183 185
184 /* Remove AGP resources, but leave dev->agp 186 /* Remove AGP resources, but leave dev->agp
@@ -335,6 +337,13 @@ static int __init drm_core_init(void)
335 goto err_p3; 337 goto err_p3;
336 } 338 }
337 339
340 drm_debugfs_root = debugfs_create_dir("dri", NULL);
341 if (!drm_debugfs_root) {
342 DRM_ERROR("Cannot create /debugfs/dri\n");
343 ret = -1;
344 goto err_p3;
345 }
346
338 drm_mem_init(); 347 drm_mem_init();
339 348
340 DRM_INFO("Initialized %s %d.%d.%d %s\n", 349 DRM_INFO("Initialized %s %d.%d.%d %s\n",
@@ -353,6 +362,7 @@ err_p1:
353static void __exit drm_core_exit(void) 362static void __exit drm_core_exit(void)
354{ 363{
355 remove_proc_entry("dri", NULL); 364 remove_proc_entry("dri", NULL);
365 debugfs_remove(drm_debugfs_root);
356 drm_sysfs_destroy(); 366 drm_sysfs_destroy();
357 367
358 unregister_chrdev(DRM_MAJOR, "drm"); 368 unregister_chrdev(DRM_MAJOR, "drm");
diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c
new file mode 100644
index 000000000000..fc98952b9033
--- /dev/null
+++ b/drivers/gpu/drm/drm_info.c
@@ -0,0 +1,328 @@
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 (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 */
71int 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 */
115int 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 */
151int 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 */
193int 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 */
218int 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
238int 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
252int 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
262int 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
278int 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
328
diff --git a/drivers/gpu/drm/drm_proc.c b/drivers/gpu/drm/drm_proc.c
index 2e3f907a203a..bae5391165ac 100644
--- a/drivers/gpu/drm/drm_proc.c
+++ b/drivers/gpu/drm/drm_proc.c
@@ -37,697 +37,195 @@
37 * OTHER DEALINGS IN THE SOFTWARE. 37 * OTHER DEALINGS IN THE SOFTWARE.
38 */ 38 */
39 39
40#include <linux/seq_file.h>
40#include "drmP.h" 41#include "drmP.h"
41 42
42static int drm_name_info(char *buf, char **start, off_t offset, 43/***************************************************
43 int request, int *eof, void *data); 44 * Initialization, etc.
44static int drm_vm_info(char *buf, char **start, off_t offset, 45 **************************************************/
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);
52static int drm_vblank_info(char *buf, char **start, off_t offset,
53 int request, int *eof, void *data);
54static int drm_gem_name_info(char *buf, char **start, off_t offset,
55 int request, int *eof, void *data);
56static int drm_gem_object_info(char *buf, char **start, off_t offset,
57 int request, int *eof, void *data);
58#if DRM_DEBUG_CODE
59static int drm_vma_info(char *buf, char **start, off_t offset,
60 int request, int *eof, void *data);
61#endif
62 46
63/** 47/**
64 * Proc file list. 48 * Proc file list.
65 */ 49 */
66static struct drm_proc_list { 50static struct drm_info_list 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[] = {
71 {"name", drm_name_info, 0}, 51 {"name", drm_name_info, 0},
72 {"mem", drm_mem_info, 0},
73 {"vm", drm_vm_info, 0}, 52 {"vm", drm_vm_info, 0},
74 {"clients", drm_clients_info, 0}, 53 {"clients", drm_clients_info, 0},
75 {"queues", drm_queues_info, 0}, 54 {"queues", drm_queues_info, 0},
76 {"bufs", drm_bufs_info, 0}, 55 {"bufs", drm_bufs_info, 0},
77 {"vblank", drm_vblank_info, 0},
78 {"gem_names", drm_gem_name_info, DRIVER_GEM}, 56 {"gem_names", drm_gem_name_info, DRIVER_GEM},
79 {"gem_objects", drm_gem_object_info, DRIVER_GEM}, 57 {"gem_objects", drm_gem_object_info, DRIVER_GEM},
80#if DRM_DEBUG_CODE 58#if DRM_DEBUG_CODE
81 {"vma", drm_vma_info}, 59 {"vma", drm_vma_info, 0},
82#endif 60#endif
83}; 61};
84
85#define DRM_PROC_ENTRIES ARRAY_SIZE(drm_proc_list) 62#define DRM_PROC_ENTRIES ARRAY_SIZE(drm_proc_list)
86 63
64static int drm_proc_open(struct inode *inode, struct file *file)
65{
66 struct drm_info_node* node = PDE(inode)->data;
67
68 return single_open(file, node->info_ent->show, node);
69}
70
71static const struct file_operations drm_proc_fops = {
72 .owner = THIS_MODULE,
73 .open = drm_proc_open,
74 .read = seq_read,
75 .llseek = seq_lseek,
76 .release = single_release,
77};
78
79
87/** 80/**
88 * Initialize the DRI proc filesystem for a device. 81 * Initialize a given set of proc files for a device
89 * 82 *
90 * \param dev DRM device. 83 * \param files The array of files to create
91 * \param minor device minor number. 84 * \param count The number of files given
92 * \param root DRI proc dir entry. 85 * \param root DRI proc dir entry.
93 * \param dev_root resulting DRI device proc dir entry. 86 * \param minor device minor number
94 * \return root entry pointer on success, or NULL on failure. 87 * \return Zero on success, non-zero on failure
95 * 88 *
96 * Create the DRI proc root entry "/proc/dri", the device proc root entry 89 * Create a given set of proc files represented by an array of
97 * "/proc/dri/%minor%/", and each entry in proc_list as 90 * gdm_proc_lists in the given root directory.
98 * "/proc/dri/%minor%/%name%".
99 */ 91 */
100int drm_proc_init(struct drm_minor *minor, int minor_id, 92int drm_proc_create_files(struct drm_info_list *files, int count,
101 struct proc_dir_entry *root) 93 struct proc_dir_entry *root, struct drm_minor *minor)
102{ 94{
103 struct drm_device *dev = minor->dev; 95 struct drm_device *dev = minor->dev;
104 struct proc_dir_entry *ent; 96 struct proc_dir_entry *ent;
105 int i, j, ret; 97 struct drm_info_node *tmp;
106 char name[64]; 98 char name[64];
99 int i, ret;
107 100
108 sprintf(name, "%d", minor_id); 101 for (i = 0; i < count; i++) {
109 minor->dev_root = proc_mkdir(name, root); 102 u32 features = files[i].driver_features;
110 if (!minor->dev_root) {
111 DRM_ERROR("Cannot create /proc/dri/%s\n", name);
112 return -1;
113 }
114
115 for (i = 0; i < DRM_PROC_ENTRIES; i++) {
116 u32 features = drm_proc_list[i].driver_features;
117 103
118 if (features != 0 && 104 if (features != 0 &&
119 (dev->driver->driver_features & features) != features) 105 (dev->driver->driver_features & features) != features)
120 continue; 106 continue;
121 107
122 ent = create_proc_entry(drm_proc_list[i].name, 108 tmp = drm_alloc(sizeof(struct drm_info_node), _DRM_DRIVER);
123 S_IFREG | S_IRUGO, minor->dev_root); 109 ent = create_proc_entry(files[i].name, S_IFREG | S_IRUGO, root);
124 if (!ent) { 110 if (!ent) {
125 DRM_ERROR("Cannot create /proc/dri/%s/%s\n", 111 DRM_ERROR("Cannot create /proc/dri/%s/%s\n",
126 name, drm_proc_list[i].name); 112 name, files[i].name);
113 drm_free(tmp, sizeof(struct drm_info_node),
114 _DRM_DRIVER);
127 ret = -1; 115 ret = -1;
128 goto fail; 116 goto fail;
129 } 117 }
130 ent->read_proc = drm_proc_list[i].f;
131 ent->data = minor;
132 }
133 118
134 if (dev->driver->proc_init) { 119 ent->proc_fops = &drm_proc_fops;
135 ret = dev->driver->proc_init(minor); 120 ent->data = tmp;
136 if (ret) { 121 tmp->minor = minor;
137 DRM_ERROR("DRM: Driver failed to initialize " 122 tmp->info_ent = &files[i];
138 "/proc/dri.\n"); 123 list_add(&(tmp->list), &(minor->proc_nodes.list));
139 goto fail;
140 }
141 } 124 }
142
143 return 0; 125 return 0;
144 fail:
145 126
146 for (j = 0; j < i; j++) 127fail:
147 remove_proc_entry(drm_proc_list[i].name, 128 for (i = 0; i < count; i++)
148 minor->dev_root); 129 remove_proc_entry(drm_proc_list[i].name, minor->proc_root);
149 remove_proc_entry(name, root);
150 minor->dev_root = NULL;
151 return ret; 130 return ret;
152} 131}
153 132
154/** 133/**
155 * Cleanup the proc filesystem resources. 134 * Initialize the DRI proc filesystem for a device
156 * 135 *
157 * \param minor device minor number. 136 * \param dev DRM device
137 * \param minor device minor number
158 * \param root DRI proc dir entry. 138 * \param root DRI proc dir entry.
159 * \param dev_root DRI device proc dir entry. 139 * \param dev_root resulting DRI device proc dir entry.
160 * \return always zero. 140 * \return root entry pointer on success, or NULL on failure.
161 * 141 *
162 * Remove all proc entries created by proc_init(). 142 * Create the DRI proc root entry "/proc/dri", the device proc root entry
143 * "/proc/dri/%minor%/", and each entry in proc_list as
144 * "/proc/dri/%minor%/%name%".
163 */ 145 */
164int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root) 146int drm_proc_init(struct drm_minor *minor, int minor_id,
147 struct proc_dir_entry *root)
165{ 148{
166 struct drm_device *dev = minor->dev; 149 struct drm_device *dev = minor->dev;
167 int i;
168 char name[64]; 150 char name[64];
151 int ret;
169 152
170 if (!root || !minor->dev_root) 153 INIT_LIST_HEAD(&minor->proc_nodes.list);
171 return 0; 154 sprintf(name, "%d", minor_id);
172 155 minor->proc_root = proc_mkdir(name, root);
173 if (dev->driver->proc_cleanup) 156 if (!minor->proc_root) {
174 dev->driver->proc_cleanup(minor); 157 DRM_ERROR("Cannot create /proc/dri/%s\n", name);
175 158 return -1;
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 */
197static 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;
208 } 159 }
209 160
210 if (!master) 161 ret = drm_proc_create_files(drm_proc_list, DRM_PROC_ENTRIES,
211 return 0; 162 minor->proc_root, minor);
212 163 if (ret) {
213 *start = &buf[offset]; 164 remove_proc_entry(name, root);
214 *eof = 0; 165 minor->proc_root = NULL;
215 166 DRM_ERROR("Failed to create core drm proc files\n");
216 if (master->unique) { 167 return ret;
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));
223 } 168 }
224 169
225 if (len > request + offset) 170 if (dev->driver->proc_init) {
226 return request; 171 ret = dev->driver->proc_init(minor);
227 *eof = 1; 172 if (ret) {
228 return len - offset; 173 DRM_ERROR("DRM: Driver failed to initialize "
229} 174 "/proc/dri.\n");
230 175 return ret;
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 */
244static 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_local_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%08llx 0x%08lx %4.4s 0x%02x 0x%08lx ",
280 i,
281 (unsigned long long)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);
288 } 176 }
289 i++;
290 }
291
292 if (len > request + offset)
293 return request;
294 *eof = 1;
295 return len - offset;
296}
297
298/**
299 * Simply calls _vm_info() while holding the drm_device::struct_mutex lock.
300 */
301static int drm_vm_info(char *buf, char **start, off_t offset, int request,
302 int *eof, void *data)
303{
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 */
325static 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;
331 int i;
332 struct drm_queue *q;
333
334 if (offset > DRM_PROC_LIMIT) {
335 *eof = 1;
336 return 0;
337 } 177 }
338 178 return 0;
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;
371}
372
373/**
374 * Simply calls _queues_info() while holding the drm_device::struct_mutex lock.
375 */
376static 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} 179}
388 180
389/** 181int drm_proc_remove_files(struct drm_info_list *files, int count,
390 * Called when "/proc/dri/.../bufs" is read. 182 struct drm_minor *minor)
391 *
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 */
400static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
401 int *eof, void *data)
402{ 183{
403 struct drm_minor *minor = (struct drm_minor *) data; 184 struct list_head *pos, *q;
404 struct drm_device *dev = minor->dev; 185 struct drm_info_node *tmp;
405 int len = 0;
406 struct drm_device_dma *dma = dev->dma;
407 int i; 186 int i;
408 187
409 if (!dma || offset > DRM_PROC_LIMIT) { 188 for (i = 0; i < count; i++) {
410 *eof = 1; 189 list_for_each_safe(pos, q, &minor->proc_nodes.list) {
411 return 0; 190 tmp = list_entry(pos, struct drm_info_node, list);
412 } 191 if (tmp->info_ent == &files[i]) {
413 192 remove_proc_entry(files[i].name,
414 *start = &buf[offset]; 193 minor->proc_root);
415 *eof = 0; 194 list_del(pos);
416 195 drm_free(tmp, sizeof(struct drm_info_node),
417 DRM_PROC_PRINT(" o size count free segs pages kB\n\n"); 196 _DRM_DRIVER);
418 for (i = 0; i <= DRM_MAX_ORDER; i++) { 197 }
419 if (dma->bufs[i].buf_count) 198 }
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 } 199 }
439 DRM_PROC_PRINT("\n"); 200 return 0;
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 */
450static 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} 201}
462 202
463/** 203/**
464 * Called when "/proc/dri/.../vblank" is read. 204 * Cleanup the proc filesystem resources.
465 * 205 *
466 * \param buf output buffer. 206 * \param minor device minor number.
467 * \param start start of output data. 207 * \param root DRI proc dir entry.
468 * \param offset requested start offset. 208 * \param dev_root DRI device proc dir entry.
469 * \param request requested number of bytes. 209 * \return always zero.
470 * \param eof whether there is no more data to return.
471 * \param data private data.
472 * \return number of written bytes.
473 */
474static int drm__vblank_info(char *buf, char **start, off_t offset, int request,
475 int *eof, void *data)
476{
477 struct drm_minor *minor = (struct drm_minor *) data;
478 struct drm_device *dev = minor->dev;
479 int len = 0;
480 int crtc;
481
482 if (offset > DRM_PROC_LIMIT) {
483 *eof = 1;
484 return 0;
485 }
486
487 *start = &buf[offset];
488 *eof = 0;
489
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 }
500
501 if (len > request + offset)
502 return request;
503 *eof = 1;
504 return len - offset;
505}
506
507/**
508 * Simply calls _vblank_info() while holding the drm_device::struct_mutex lock.
509 */
510static 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 * 210 *
526 * \param buf output buffer. 211 * Remove all proc entries created by proc_init().
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 */ 212 */
534static int drm__clients_info(char *buf, char **start, off_t offset, 213int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root)
535 int request, int *eof, void *data)
536{ 214{
537 struct drm_minor *minor = (struct drm_minor *) data;
538 struct drm_device *dev = minor->dev; 215 struct drm_device *dev = minor->dev;
539 int len = 0; 216 char name[64];
540 struct drm_file *priv;
541 217
542 if (offset > DRM_PROC_LIMIT) { 218 if (!root || !minor->proc_root)
543 *eof = 1;
544 return 0; 219 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 220
559 if (len > request + offset) 221 if (dev->driver->proc_cleanup)
560 return request; 222 dev->driver->proc_cleanup(minor);
561 *eof = 1;
562 return len - offset;
563}
564
565/**
566 * Simply calls _clients_info() while holding the drm_device::struct_mutex lock.
567 */
568static 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
581struct drm_gem_name_info_data {
582 int len;
583 char *buf;
584 int eof;
585};
586 223
587static int drm_gem_one_name_info(int id, void *ptr, void *data) 224 drm_proc_remove_files(drm_proc_list, DRM_PROC_ENTRIES, minor);
588{
589 struct drm_gem_object *obj = ptr;
590 struct drm_gem_name_info_data *nid = data;
591 225
592 DRM_INFO("name %d size %zd\n", obj->name, obj->size); 226 sprintf(name, "%d", minor->index);
593 if (nid->eof) 227 remove_proc_entry(name, root);
594 return 0;
595 228
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 return 0; 229 return 0;
606} 230}
607 231
608static 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
633static 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
661static 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
721static 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
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index 45a536b9d7f5..d009661781bc 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -50,6 +50,7 @@ struct idr drm_minors_idr;
50 50
51struct class *drm_class; 51struct class *drm_class;
52struct proc_dir_entry *drm_proc_root; 52struct proc_dir_entry *drm_proc_root;
53struct dentry *drm_debugfs_root;
53 54
54static int drm_minor_get_id(struct drm_device *dev, int type) 55static int drm_minor_get_id(struct drm_device *dev, int type)
55{ 56{
@@ -313,7 +314,15 @@ static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int t
313 goto err_mem; 314 goto err_mem;
314 } 315 }
315 } else 316 } else
316 new_minor->dev_root = NULL; 317 new_minor->proc_root = NULL;
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
317 326
318 ret = drm_sysfs_device_add(new_minor); 327 ret = drm_sysfs_device_add(new_minor);
319 if (ret) { 328 if (ret) {
@@ -430,6 +439,10 @@ int drm_put_minor(struct drm_minor **minor_p)
430 439
431 if (minor->type == DRM_MINOR_LEGACY) 440 if (minor->type == DRM_MINOR_LEGACY)
432 drm_proc_cleanup(minor, drm_proc_root); 441 drm_proc_cleanup(minor, drm_proc_root);
442#if defined(CONFIG_DEBUG_FS)
443 drm_debugfs_cleanup(minor);
444#endif
445
433 drm_sysfs_device_remove(minor); 446 drm_sysfs_device_remove(minor);
434 447
435 idr_remove(&drm_minors_idr, minor->index); 448 idr_remove(&drm_minors_idr, minor->index);
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 793cba39d832..51c5a050aa73 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -7,7 +7,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \
7 i915_suspend.o \ 7 i915_suspend.o \
8 i915_gem.o \ 8 i915_gem.o \
9 i915_gem_debug.o \ 9 i915_gem_debug.o \
10 i915_gem_proc.o \ 10 i915_gem_debugfs.o \
11 i915_gem_tiling.o \ 11 i915_gem_tiling.o \
12 intel_display.o \ 12 intel_display.o \
13 intel_crt.o \ 13 intel_crt.o \
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index d10ec9e5033c..2c0167693450 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -182,8 +182,10 @@ static struct drm_driver driver = {
182 .get_reg_ofs = drm_core_get_reg_ofs, 182 .get_reg_ofs = drm_core_get_reg_ofs,
183 .master_create = i915_master_create, 183 .master_create = i915_master_create,
184 .master_destroy = i915_master_destroy, 184 .master_destroy = i915_master_destroy,
185 .proc_init = i915_gem_proc_init, 185#if defined(CONFIG_DEBUG_FS)
186 .proc_cleanup = i915_gem_proc_cleanup, 186 .debugfs_init = i915_gem_debugfs_init,
187 .debugfs_cleanup = i915_gem_debugfs_cleanup,
188#endif
187 .gem_init_object = i915_gem_init_object, 189 .gem_init_object = i915_gem_init_object,
188 .gem_free_object = i915_gem_free_object, 190 .gem_free_object = i915_gem_free_object,
189 .gem_vm_ops = &i915_gem_vm_ops, 191 .gem_vm_ops = &i915_gem_vm_ops,
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index d6cc9861e0a1..1bc45a78ffcd 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -604,8 +604,6 @@ int i915_gem_get_tiling(struct drm_device *dev, void *data,
604int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, 604int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
605 struct drm_file *file_priv); 605 struct drm_file *file_priv);
606void i915_gem_load(struct drm_device *dev); 606void i915_gem_load(struct drm_device *dev);
607int i915_gem_proc_init(struct drm_minor *minor);
608void i915_gem_proc_cleanup(struct drm_minor *minor);
609int i915_gem_init_object(struct drm_gem_object *obj); 607int i915_gem_init_object(struct drm_gem_object *obj);
610void i915_gem_free_object(struct drm_gem_object *obj); 608void i915_gem_free_object(struct drm_gem_object *obj);
611int i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment); 609int i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment);
@@ -649,6 +647,10 @@ void i915_gem_dump_object(struct drm_gem_object *obj, int len,
649 const char *where, uint32_t mark); 647 const char *where, uint32_t mark);
650void i915_dump_lru(struct drm_device *dev, const char *where); 648void i915_dump_lru(struct drm_device *dev, const char *where);
651 649
650/* i915_debugfs.c */
651int i915_gem_debugfs_init(struct drm_minor *minor);
652void i915_gem_debugfs_cleanup(struct drm_minor *minor);
653
652/* i915_suspend.c */ 654/* i915_suspend.c */
653extern int i915_save_state(struct drm_device *dev); 655extern int i915_save_state(struct drm_device *dev);
654extern int i915_restore_state(struct drm_device *dev); 656extern int i915_restore_state(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/i915_gem_debugfs.c b/drivers/gpu/drm/i915/i915_gem_debugfs.c
new file mode 100644
index 000000000000..dd2b0edb9963
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_gem_debugfs.c
@@ -0,0 +1,230 @@
1/*
2 * Copyright © 2008 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 *
23 * Authors:
24 * Eric Anholt <eric@anholt.net>
25 * Keith Packard <keithp@keithp.com>
26 *
27 */
28
29#include <linux/seq_file.h>
30#include "drmP.h"
31#include "drm.h"
32#include "i915_drm.h"
33#include "i915_drv.h"
34
35#define DRM_I915_RING_DEBUG 1
36
37
38#if defined(CONFIG_DEBUG_FS)
39
40static int i915_gem_active_info(struct seq_file *m, void *data)
41{
42 struct drm_info_node *node = (struct drm_info_node *) m->private;
43 struct drm_device *dev = node->minor->dev;
44 drm_i915_private_t *dev_priv = dev->dev_private;
45 struct drm_i915_gem_object *obj_priv;
46
47 seq_printf(m, "Active:\n");
48 list_for_each_entry(obj_priv, &dev_priv->mm.active_list,
49 list)
50 {
51 struct drm_gem_object *obj = obj_priv->obj;
52 if (obj->name) {
53 seq_printf(m, " %p(%d): %08x %08x %d\n",
54 obj, obj->name,
55 obj->read_domains, obj->write_domain,
56 obj_priv->last_rendering_seqno);
57 } else {
58 seq_printf(m, " %p: %08x %08x %d\n",
59 obj,
60 obj->read_domains, obj->write_domain,
61 obj_priv->last_rendering_seqno);
62 }
63 }
64 return 0;
65}
66
67static int i915_gem_flushing_info(struct seq_file *m, void *data)
68{
69 struct drm_info_node *node = (struct drm_info_node *) m->private;
70 struct drm_device *dev = node->minor->dev;
71 drm_i915_private_t *dev_priv = dev->dev_private;
72 struct drm_i915_gem_object *obj_priv;
73
74 seq_printf(m, "Flushing:\n");
75 list_for_each_entry(obj_priv, &dev_priv->mm.flushing_list,
76 list)
77 {
78 struct drm_gem_object *obj = obj_priv->obj;
79 if (obj->name) {
80 seq_printf(m, " %p(%d): %08x %08x %d\n",
81 obj, obj->name,
82 obj->read_domains, obj->write_domain,
83 obj_priv->last_rendering_seqno);
84 } else {
85 seq_printf(m, " %p: %08x %08x %d\n", obj,
86 obj->read_domains, obj->write_domain,
87 obj_priv->last_rendering_seqno);
88 }
89 }
90 return 0;
91}
92
93static int i915_gem_inactive_info(struct seq_file *m, void *data)
94{
95 struct drm_info_node *node = (struct drm_info_node *) m->private;
96 struct drm_device *dev = node->minor->dev;
97 drm_i915_private_t *dev_priv = dev->dev_private;
98 struct drm_i915_gem_object *obj_priv;
99
100 seq_printf(m, "Inactive:\n");
101 list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list,
102 list)
103 {
104 struct drm_gem_object *obj = obj_priv->obj;
105 if (obj->name) {
106 seq_printf(m, " %p(%d): %08x %08x %d\n",
107 obj, obj->name,
108 obj->read_domains, obj->write_domain,
109 obj_priv->last_rendering_seqno);
110 } else {
111 seq_printf(m, " %p: %08x %08x %d\n", obj,
112 obj->read_domains, obj->write_domain,
113 obj_priv->last_rendering_seqno);
114 }
115 }
116 return 0;
117}
118
119static int i915_gem_request_info(struct seq_file *m, void *data)
120{
121 struct drm_info_node *node = (struct drm_info_node *) m->private;
122 struct drm_device *dev = node->minor->dev;
123 drm_i915_private_t *dev_priv = dev->dev_private;
124 struct drm_i915_gem_request *gem_request;
125
126 seq_printf(m, "Request:\n");
127 list_for_each_entry(gem_request, &dev_priv->mm.request_list, list) {
128 seq_printf(m, " %d @ %d\n",
129 gem_request->seqno,
130 (int) (jiffies - gem_request->emitted_jiffies));
131 }
132 return 0;
133}
134
135static int i915_gem_seqno_info(struct seq_file *m, void *data)
136{
137 struct drm_info_node *node = (struct drm_info_node *) m->private;
138 struct drm_device *dev = node->minor->dev;
139 drm_i915_private_t *dev_priv = dev->dev_private;
140
141 if (dev_priv->hw_status_page != NULL) {
142 seq_printf(m, "Current sequence: %d\n",
143 i915_get_gem_seqno(dev));
144 } else {
145 seq_printf(m, "Current sequence: hws uninitialized\n");
146 }
147 seq_printf(m, "Waiter sequence: %d\n",
148 dev_priv->mm.waiting_gem_seqno);
149 seq_printf(m, "IRQ sequence: %d\n", dev_priv->mm.irq_gem_seqno);
150 return 0;
151}
152
153
154static int i915_interrupt_info(struct seq_file *m, void *data)
155{
156 struct drm_info_node *node = (struct drm_info_node *) m->private;
157 struct drm_device *dev = node->minor->dev;
158 drm_i915_private_t *dev_priv = dev->dev_private;
159
160 seq_printf(m, "Interrupt enable: %08x\n",
161 I915_READ(IER));
162 seq_printf(m, "Interrupt identity: %08x\n",
163 I915_READ(IIR));
164 seq_printf(m, "Interrupt mask: %08x\n",
165 I915_READ(IMR));
166 seq_printf(m, "Pipe A stat: %08x\n",
167 I915_READ(PIPEASTAT));
168 seq_printf(m, "Pipe B stat: %08x\n",
169 I915_READ(PIPEBSTAT));
170 seq_printf(m, "Interrupts received: %d\n",
171 atomic_read(&dev_priv->irq_received));
172 if (dev_priv->hw_status_page != NULL) {
173 seq_printf(m, "Current sequence: %d\n",
174 i915_get_gem_seqno(dev));
175 } else {
176 seq_printf(m, "Current sequence: hws uninitialized\n");
177 }
178 seq_printf(m, "Waiter sequence: %d\n",
179 dev_priv->mm.waiting_gem_seqno);
180 seq_printf(m, "IRQ sequence: %d\n",
181 dev_priv->mm.irq_gem_seqno);
182 return 0;
183}
184
185static int i915_hws_info(struct seq_file *m, void *data)
186{
187 struct drm_info_node *node = (struct drm_info_node *) m->private;
188 struct drm_device *dev = node->minor->dev;
189 drm_i915_private_t *dev_priv = dev->dev_private;
190 int i;
191 volatile u32 *hws;
192
193 hws = (volatile u32 *)dev_priv->hw_status_page;
194 if (hws == NULL)
195 return 0;
196
197 for (i = 0; i < 4096 / sizeof(u32) / 4; i += 4) {
198 seq_printf(m, "0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
199 i * 4,
200 hws[i], hws[i + 1], hws[i + 2], hws[i + 3]);
201 }
202 return 0;
203}
204
205static struct drm_info_list i915_gem_debugfs_list[] = {
206 {"i915_gem_active", i915_gem_active_info, 0},
207 {"i915_gem_flushing", i915_gem_flushing_info, 0},
208 {"i915_gem_inactive", i915_gem_inactive_info, 0},
209 {"i915_gem_request", i915_gem_request_info, 0},
210 {"i915_gem_seqno", i915_gem_seqno_info, 0},
211 {"i915_gem_interrupt", i915_interrupt_info, 0},
212 {"i915_gem_hws", i915_hws_info, 0},
213};
214#define I915_GEM_DEBUGFS_ENTRIES ARRAY_SIZE(i915_gem_debugfs_list)
215
216int i915_gem_debugfs_init(struct drm_minor *minor)
217{
218 return drm_debugfs_create_files(i915_gem_debugfs_list,
219 I915_GEM_DEBUGFS_ENTRIES,
220 minor->debugfs_root, minor);
221}
222
223void i915_gem_debugfs_cleanup(struct drm_minor *minor)
224{
225 drm_debugfs_remove_files(i915_gem_debugfs_list,
226 I915_GEM_DEBUGFS_ENTRIES, minor);
227}
228
229#endif /* CONFIG_DEBUG_FS */
230
diff --git a/drivers/gpu/drm/i915/i915_gem_proc.c b/drivers/gpu/drm/i915/i915_gem_proc.c
deleted file mode 100644
index 4d1b9de0cd8b..000000000000
--- a/drivers/gpu/drm/i915/i915_gem_proc.c
+++ /dev/null
@@ -1,334 +0,0 @@
1/*
2 * Copyright © 2008 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 *
23 * Authors:
24 * Eric Anholt <eric@anholt.net>
25 * Keith Packard <keithp@keithp.com>
26 *
27 */
28
29#include "drmP.h"
30#include "drm.h"
31#include "i915_drm.h"
32#include "i915_drv.h"
33
34static int i915_gem_active_info(char *buf, char **start, off_t offset,
35 int request, int *eof, void *data)
36{
37 struct drm_minor *minor = (struct drm_minor *) data;
38 struct drm_device *dev = minor->dev;
39 drm_i915_private_t *dev_priv = dev->dev_private;
40 struct drm_i915_gem_object *obj_priv;
41 int len = 0;
42
43 if (offset > DRM_PROC_LIMIT) {
44 *eof = 1;
45 return 0;
46 }
47
48 *start = &buf[offset];
49 *eof = 0;
50 DRM_PROC_PRINT("Active:\n");
51 list_for_each_entry(obj_priv, &dev_priv->mm.active_list,
52 list)
53 {
54 struct drm_gem_object *obj = obj_priv->obj;
55 if (obj->name) {
56 DRM_PROC_PRINT(" %p(%d): %08x %08x %d\n",
57 obj, obj->name,
58 obj->read_domains, obj->write_domain,
59 obj_priv->last_rendering_seqno);
60 } else {
61 DRM_PROC_PRINT(" %p: %08x %08x %d\n",
62 obj,
63 obj->read_domains, obj->write_domain,
64 obj_priv->last_rendering_seqno);
65 }
66 }
67 if (len > request + offset)
68 return request;
69 *eof = 1;
70 return len - offset;
71}
72
73static int i915_gem_flushing_info(char *buf, char **start, off_t offset,
74 int request, int *eof, void *data)
75{
76 struct drm_minor *minor = (struct drm_minor *) data;
77 struct drm_device *dev = minor->dev;
78 drm_i915_private_t *dev_priv = dev->dev_private;
79 struct drm_i915_gem_object *obj_priv;
80 int len = 0;
81
82 if (offset > DRM_PROC_LIMIT) {
83 *eof = 1;
84 return 0;
85 }
86
87 *start = &buf[offset];
88 *eof = 0;
89 DRM_PROC_PRINT("Flushing:\n");
90 list_for_each_entry(obj_priv, &dev_priv->mm.flushing_list,
91 list)
92 {
93 struct drm_gem_object *obj = obj_priv->obj;
94 if (obj->name) {
95 DRM_PROC_PRINT(" %p(%d): %08x %08x %d\n",
96 obj, obj->name,
97 obj->read_domains, obj->write_domain,
98 obj_priv->last_rendering_seqno);
99 } else {
100 DRM_PROC_PRINT(" %p: %08x %08x %d\n", obj,
101 obj->read_domains, obj->write_domain,
102 obj_priv->last_rendering_seqno);
103 }
104 }
105 if (len > request + offset)
106 return request;
107 *eof = 1;
108 return len - offset;
109}
110
111static int i915_gem_inactive_info(char *buf, char **start, off_t offset,
112 int request, int *eof, void *data)
113{
114 struct drm_minor *minor = (struct drm_minor *) data;
115 struct drm_device *dev = minor->dev;
116 drm_i915_private_t *dev_priv = dev->dev_private;
117 struct drm_i915_gem_object *obj_priv;
118 int len = 0;
119
120 if (offset > DRM_PROC_LIMIT) {
121 *eof = 1;
122 return 0;
123 }
124
125 *start = &buf[offset];
126 *eof = 0;
127 DRM_PROC_PRINT("Inactive:\n");
128 list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list,
129 list)
130 {
131 struct drm_gem_object *obj = obj_priv->obj;
132 if (obj->name) {
133 DRM_PROC_PRINT(" %p(%d): %08x %08x %d\n",
134 obj, obj->name,
135 obj->read_domains, obj->write_domain,
136 obj_priv->last_rendering_seqno);
137 } else {
138 DRM_PROC_PRINT(" %p: %08x %08x %d\n", obj,
139 obj->read_domains, obj->write_domain,
140 obj_priv->last_rendering_seqno);
141 }
142 }
143 if (len > request + offset)
144 return request;
145 *eof = 1;
146 return len - offset;
147}
148
149static int i915_gem_request_info(char *buf, char **start, off_t offset,
150 int request, int *eof, void *data)
151{
152 struct drm_minor *minor = (struct drm_minor *) data;
153 struct drm_device *dev = minor->dev;
154 drm_i915_private_t *dev_priv = dev->dev_private;
155 struct drm_i915_gem_request *gem_request;
156 int len = 0;
157
158 if (offset > DRM_PROC_LIMIT) {
159 *eof = 1;
160 return 0;
161 }
162
163 *start = &buf[offset];
164 *eof = 0;
165 DRM_PROC_PRINT("Request:\n");
166 list_for_each_entry(gem_request, &dev_priv->mm.request_list,
167 list)
168 {
169 DRM_PROC_PRINT(" %d @ %d\n",
170 gem_request->seqno,
171 (int) (jiffies - gem_request->emitted_jiffies));
172 }
173 if (len > request + offset)
174 return request;
175 *eof = 1;
176 return len - offset;
177}
178
179static int i915_gem_seqno_info(char *buf, char **start, off_t offset,
180 int request, int *eof, void *data)
181{
182 struct drm_minor *minor = (struct drm_minor *) data;
183 struct drm_device *dev = minor->dev;
184 drm_i915_private_t *dev_priv = dev->dev_private;
185 int len = 0;
186
187 if (offset > DRM_PROC_LIMIT) {
188 *eof = 1;
189 return 0;
190 }
191
192 *start = &buf[offset];
193 *eof = 0;
194 if (dev_priv->hw_status_page != NULL) {
195 DRM_PROC_PRINT("Current sequence: %d\n",
196 i915_get_gem_seqno(dev));
197 } else {
198 DRM_PROC_PRINT("Current sequence: hws uninitialized\n");
199 }
200 DRM_PROC_PRINT("Waiter sequence: %d\n",
201 dev_priv->mm.waiting_gem_seqno);
202 DRM_PROC_PRINT("IRQ sequence: %d\n", dev_priv->mm.irq_gem_seqno);
203 if (len > request + offset)
204 return request;
205 *eof = 1;
206 return len - offset;
207}
208
209
210static int i915_interrupt_info(char *buf, char **start, off_t offset,
211 int request, int *eof, void *data)
212{
213 struct drm_minor *minor = (struct drm_minor *) data;
214 struct drm_device *dev = minor->dev;
215 drm_i915_private_t *dev_priv = dev->dev_private;
216 int len = 0;
217
218 if (offset > DRM_PROC_LIMIT) {
219 *eof = 1;
220 return 0;
221 }
222
223 *start = &buf[offset];
224 *eof = 0;
225 DRM_PROC_PRINT("Interrupt enable: %08x\n",
226 I915_READ(IER));
227 DRM_PROC_PRINT("Interrupt identity: %08x\n",
228 I915_READ(IIR));
229 DRM_PROC_PRINT("Interrupt mask: %08x\n",
230 I915_READ(IMR));
231 DRM_PROC_PRINT("Pipe A stat: %08x\n",
232 I915_READ(PIPEASTAT));
233 DRM_PROC_PRINT("Pipe B stat: %08x\n",
234 I915_READ(PIPEBSTAT));
235 DRM_PROC_PRINT("Interrupts received: %d\n",
236 atomic_read(&dev_priv->irq_received));
237 if (dev_priv->hw_status_page != NULL) {
238 DRM_PROC_PRINT("Current sequence: %d\n",
239 i915_get_gem_seqno(dev));
240 } else {
241 DRM_PROC_PRINT("Current sequence: hws uninitialized\n");
242 }
243 DRM_PROC_PRINT("Waiter sequence: %d\n",
244 dev_priv->mm.waiting_gem_seqno);
245 DRM_PROC_PRINT("IRQ sequence: %d\n",
246 dev_priv->mm.irq_gem_seqno);
247 if (len > request + offset)
248 return request;
249 *eof = 1;
250 return len - offset;
251}
252
253static int i915_hws_info(char *buf, char **start, off_t offset,
254 int request, int *eof, void *data)
255{
256 struct drm_minor *minor = (struct drm_minor *) data;
257 struct drm_device *dev = minor->dev;
258 drm_i915_private_t *dev_priv = dev->dev_private;
259 int len = 0, i;
260 volatile u32 *hws;
261
262 if (offset > DRM_PROC_LIMIT) {
263 *eof = 1;
264 return 0;
265 }
266
267 hws = (volatile u32 *)dev_priv->hw_status_page;
268 if (hws == NULL) {
269 *eof = 1;
270 return 0;
271 }
272
273 *start = &buf[offset];
274 *eof = 0;
275 for (i = 0; i < 4096 / sizeof(u32) / 4; i += 4) {
276 DRM_PROC_PRINT("0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
277 i * 4,
278 hws[i], hws[i + 1], hws[i + 2], hws[i + 3]);
279 }
280 if (len > request + offset)
281 return request;
282 *eof = 1;
283 return len - offset;
284}
285
286static struct drm_proc_list {
287 /** file name */
288 const char *name;
289 /** proc callback*/
290 int (*f) (char *, char **, off_t, int, int *, void *);
291} i915_gem_proc_list[] = {
292 {"i915_gem_active", i915_gem_active_info},
293 {"i915_gem_flushing", i915_gem_flushing_info},
294 {"i915_gem_inactive", i915_gem_inactive_info},
295 {"i915_gem_request", i915_gem_request_info},
296 {"i915_gem_seqno", i915_gem_seqno_info},
297 {"i915_gem_interrupt", i915_interrupt_info},
298 {"i915_gem_hws", i915_hws_info},
299};
300
301#define I915_GEM_PROC_ENTRIES ARRAY_SIZE(i915_gem_proc_list)
302
303int i915_gem_proc_init(struct drm_minor *minor)
304{
305 struct proc_dir_entry *ent;
306 int i, j;
307
308 for (i = 0; i < I915_GEM_PROC_ENTRIES; i++) {
309 ent = create_proc_entry(i915_gem_proc_list[i].name,
310 S_IFREG | S_IRUGO, minor->dev_root);
311 if (!ent) {
312 DRM_ERROR("Cannot create /proc/dri/.../%s\n",
313 i915_gem_proc_list[i].name);
314 for (j = 0; j < i; j++)
315 remove_proc_entry(i915_gem_proc_list[i].name,
316 minor->dev_root);
317 return -1;
318 }
319 ent->read_proc = i915_gem_proc_list[i].f;
320 ent->data = minor;
321 }
322 return 0;
323}
324
325void i915_gem_proc_cleanup(struct drm_minor *minor)
326{
327 int i;
328
329 if (!minor->dev_root)
330 return;
331
332 for (i = 0; i < I915_GEM_PROC_ENTRIES; i++)
333 remove_proc_entry(i915_gem_proc_list[i].name, minor->dev_root);
334}