1 /*-
2 * Copyright 2003 Eric Anholt
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * ERIC ANHOLT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24 #include <sys/cdefs.h>
25 __FBSDID("$FreeBSD: releng/6.4/sys/dev/drm/drm_sysctl.c 153401 2005-12-14 00:52:59Z anholt $");
26
27 #include "dev/drm/drmP.h"
28 #include "dev/drm/drm.h"
29
30 #include <sys/sysctl.h>
31
32 static int drm_name_info DRM_SYSCTL_HANDLER_ARGS;
33 static int drm_vm_info DRM_SYSCTL_HANDLER_ARGS;
34 static int drm_clients_info DRM_SYSCTL_HANDLER_ARGS;
35 static int drm_bufs_info DRM_SYSCTL_HANDLER_ARGS;
36
37 struct drm_sysctl_list {
38 const char *name;
39 int (*f) DRM_SYSCTL_HANDLER_ARGS;
40 } drm_sysctl_list[] = {
41 {"name", drm_name_info},
42 {"vm", drm_vm_info},
43 {"clients", drm_clients_info},
44 {"bufs", drm_bufs_info},
45 };
46 #define DRM_SYSCTL_ENTRIES (sizeof(drm_sysctl_list)/sizeof(drm_sysctl_list[0]))
47
48 struct drm_sysctl_info {
49 struct sysctl_ctx_list ctx;
50 char name[2];
51 };
52
53 int drm_sysctl_init(drm_device_t *dev)
54 {
55 struct drm_sysctl_info *info;
56 struct sysctl_oid *oid;
57 struct sysctl_oid *top, *drioid;
58 int i;
59
60 info = malloc(sizeof *info, M_DRM, M_WAITOK | M_ZERO);
61 if ( !info )
62 return 1;
63 dev->sysctl = info;
64
65 /* Add the sysctl node for DRI if it doesn't already exist */
66 drioid = SYSCTL_ADD_NODE( &info->ctx, &sysctl__hw_children, OID_AUTO, "dri", CTLFLAG_RW, NULL, "DRI Graphics");
67 if (!drioid)
68 return 1;
69
70 /* Find the next free slot under hw.dri */
71 i = 0;
72 SLIST_FOREACH(oid, SYSCTL_CHILDREN(drioid), oid_link) {
73 if (i <= oid->oid_arg2)
74 i = oid->oid_arg2 + 1;
75 }
76 if (i>9)
77 return 1;
78
79 /* Add the hw.dri.x for our device */
80 info->name[0] = '' + i;
81 info->name[1] = 0;
82 top = SYSCTL_ADD_NODE( &info->ctx, SYSCTL_CHILDREN(drioid), OID_AUTO, info->name, CTLFLAG_RW, NULL, NULL);
83 if (!top)
84 return 1;
85
86 for (i = 0; i < DRM_SYSCTL_ENTRIES; i++) {
87 oid = SYSCTL_ADD_OID(&info->ctx,
88 SYSCTL_CHILDREN(top),
89 OID_AUTO,
90 drm_sysctl_list[i].name,
91 CTLTYPE_INT | CTLFLAG_RD,
92 dev,
93 0,
94 drm_sysctl_list[i].f,
95 "A",
96 NULL);
97 if (!oid)
98 return 1;
99 }
100 SYSCTL_ADD_INT(&info->ctx, SYSCTL_CHILDREN(top), OID_AUTO, "debug",
101 CTLFLAG_RW, &drm_debug_flag, sizeof(drm_debug_flag),
102 "Enable debugging output");
103
104 return 0;
105 }
106
107 int drm_sysctl_cleanup(drm_device_t *dev)
108 {
109 int error;
110 error = sysctl_ctx_free( &dev->sysctl->ctx );
111
112 free(dev->sysctl, M_DRM);
113 dev->sysctl = NULL;
114
115 return error;
116 }
117
118 #define DRM_SYSCTL_PRINT(fmt, arg...) \
119 do { \
120 snprintf(buf, sizeof(buf), fmt, ##arg); \
121 retcode = SYSCTL_OUT(req, buf, strlen(buf)); \
122 if (retcode) \
123 goto done; \
124 } while (0)
125
126 static int drm_name_info DRM_SYSCTL_HANDLER_ARGS
127 {
128 drm_device_t *dev = arg1;
129 char buf[128];
130 int retcode;
131 int hasunique = 0;
132
133 DRM_SYSCTL_PRINT("%s 0x%x", dev->driver.name, dev2udev(dev->devnode));
134
135 DRM_LOCK();
136 if (dev->unique) {
137 snprintf(buf, sizeof(buf), " %s", dev->unique);
138 hasunique = 1;
139 }
140 DRM_UNLOCK();
141
142 if (hasunique)
143 SYSCTL_OUT(req, buf, strlen(buf));
144
145 SYSCTL_OUT(req, "", 1);
146
147 done:
148 return retcode;
149 }
150
151 static int drm_vm_info DRM_SYSCTL_HANDLER_ARGS
152 {
153 drm_device_t *dev = arg1;
154 drm_local_map_t *map, *tempmaps;
155 const char *types[] = { "FB", "REG", "SHM", "AGP", "SG" };
156 const char *type, *yesno;
157 int i, mapcount;
158 char buf[128];
159 int retcode;
160
161 /* We can't hold the lock while doing SYSCTL_OUTs, so allocate a
162 * temporary copy of all the map entries and then SYSCTL_OUT that.
163 */
164 DRM_LOCK();
165
166 mapcount = 0;
167 TAILQ_FOREACH(map, &dev->maplist, link)
168 mapcount++;
169
170 tempmaps = malloc(sizeof(drm_local_map_t) * mapcount, M_DRM, M_NOWAIT);
171 if (tempmaps == NULL) {
172 DRM_UNLOCK();
173 return ENOMEM;
174 }
175
176 i = 0;
177 TAILQ_FOREACH(map, &dev->maplist, link)
178 tempmaps[i++] = *map;
179
180 DRM_UNLOCK();
181
182 DRM_SYSCTL_PRINT("\nslot offset size type flags "
183 "address mtrr\n");
184
185 for (i = 0; i < mapcount; i++) {
186 map = &tempmaps[i];
187
188 if (map->type < 0 || map->type > 4)
189 type = "??";
190 else
191 type = types[map->type];
192
193 if (!map->mtrr)
194 yesno = "no";
195 else
196 yesno = "yes";
197
198 DRM_SYSCTL_PRINT(
199 "%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08lx %s\n", i,
200 map->offset, map->size, type, map->flags,
201 (unsigned long)map->handle, yesno);
202 }
203 SYSCTL_OUT(req, "", 1);
204
205 done:
206 free(tempmaps, M_DRM);
207 return retcode;
208 }
209
210 static int drm_bufs_info DRM_SYSCTL_HANDLER_ARGS
211 {
212 drm_device_t *dev = arg1;
213 drm_device_dma_t *dma = dev->dma;
214 drm_device_dma_t tempdma;
215 int *templists;
216 int i;
217 char buf[128];
218 int retcode;
219
220 /* We can't hold the locks around DRM_SYSCTL_PRINT, so make a temporary
221 * copy of the whole structure and the relevant data from buflist.
222 */
223 DRM_LOCK();
224 if (dma == NULL) {
225 DRM_UNLOCK();
226 return 0;
227 }
228 DRM_SPINLOCK(&dev->dma_lock);
229 tempdma = *dma;
230 templists = malloc(sizeof(int) * dma->buf_count, M_DRM, M_NOWAIT);
231 for (i = 0; i < dma->buf_count; i++)
232 templists[i] = dma->buflist[i]->list;
233 dma = &tempdma;
234 DRM_SPINUNLOCK(&dev->dma_lock);
235 DRM_UNLOCK();
236
237 DRM_SYSCTL_PRINT("\n o size count free segs pages kB\n");
238 for (i = 0; i <= DRM_MAX_ORDER; i++) {
239 if (dma->bufs[i].buf_count)
240 DRM_SYSCTL_PRINT("%2d %8d %5d %5d %5d %5d %5d\n",
241 i,
242 dma->bufs[i].buf_size,
243 dma->bufs[i].buf_count,
244 atomic_read(&dma->bufs[i]
245 .freelist.count),
246 dma->bufs[i].seg_count,
247 dma->bufs[i].seg_count
248 *(1 << dma->bufs[i].page_order),
249 (dma->bufs[i].seg_count
250 * (1 << dma->bufs[i].page_order))
251 * PAGE_SIZE / 1024);
252 }
253 DRM_SYSCTL_PRINT("\n");
254 for (i = 0; i < dma->buf_count; i++) {
255 if (i && !(i%32)) DRM_SYSCTL_PRINT("\n");
256 DRM_SYSCTL_PRINT(" %d", templists[i]);
257 }
258 DRM_SYSCTL_PRINT("\n");
259
260 SYSCTL_OUT(req, "", 1);
261 done:
262 free(templists, M_DRM);
263 return retcode;
264 }
265
266 static int drm_clients_info DRM_SYSCTL_HANDLER_ARGS
267 {
268 drm_device_t *dev = arg1;
269 drm_file_t *priv, *tempprivs;
270 char buf[128];
271 int retcode;
272 int privcount, i;
273
274 DRM_LOCK();
275
276 privcount = 0;
277 TAILQ_FOREACH(priv, &dev->files, link)
278 privcount++;
279
280 tempprivs = malloc(sizeof(drm_file_t) * privcount, M_DRM, M_NOWAIT);
281 if (tempprivs == NULL) {
282 DRM_UNLOCK();
283 return ENOMEM;
284 }
285 i = 0;
286 TAILQ_FOREACH(priv, &dev->files, link)
287 tempprivs[i++] = *priv;
288
289 DRM_UNLOCK();
290
291 DRM_SYSCTL_PRINT("\na dev pid uid magic ioctls\n");
292 for (i = 0; i < privcount; i++) {
293 priv = &tempprivs[i];
294 DRM_SYSCTL_PRINT("%c %3d %5d %5d %10u %10lu\n",
295 priv->authenticated ? 'y' : 'n',
296 priv->minor,
297 priv->pid,
298 priv->uid,
299 priv->magic,
300 priv->ioctl_count);
301 }
302
303 SYSCTL_OUT(req, "", 1);
304 done:
305 free(tempprivs, M_DRM);
306 return retcode;
307 }
Cache object: eea0dc1cebd7cd08bc5beabecdc2b346
|