inet6: require RTF_ANNOUNCE to proxy NS
[dragonfly.git] / sys / dev / drm / drm_sysctl.c
blob4778522e39e088bab40e76b1ef4487d4287f33b2
1 /*-
2 * Copyright 2003 Eric Anholt
3 * All Rights Reserved.
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:
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.
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.
23 * $FreeBSD: src/sys/dev/drm2/drm_sysctl.c,v 1.1 2012/05/22 11:07:44 kib Exp $
26 /** @file drm_sysctl.c
27 * Implementation of various sysctls for controlling DRM behavior and reporting
28 * debug information.
31 #include <sys/conf.h>
32 #include <sys/sysctl.h>
33 #include <sys/types.h>
35 #include <drm/drmP.h>
36 #include "drm_legacy.h"
38 SYSCTL_NODE(_hw, OID_AUTO, dri, CTLFLAG_RD, 0, "DRI Graphics");
39 SYSCTL_INT(_hw_dri, OID_AUTO, debug, CTLFLAG_RW, &drm_debug, 0,
40 "Enable debugging output");
41 SYSCTL_INT(_hw_dri, OID_AUTO, vblank_offdelay, CTLFLAG_RW,
42 &drm_vblank_offdelay, 0, "Delay until vblank irq auto-disable");
43 SYSCTL_INT(_hw_dri, OID_AUTO, timestamp_precision, CTLFLAG_RW,
44 &drm_timestamp_precision, 0, "Max. error on timestamps");
46 static int drm_name_info DRM_SYSCTL_HANDLER_ARGS;
47 static int drm_vm_info DRM_SYSCTL_HANDLER_ARGS;
48 static int drm_clients_info DRM_SYSCTL_HANDLER_ARGS;
49 static int drm_bufs_info DRM_SYSCTL_HANDLER_ARGS;
51 struct drm_sysctl_list {
52 const char *name;
53 int (*f) DRM_SYSCTL_HANDLER_ARGS;
54 } drm_sysctl_list[] = {
55 {"name", drm_name_info},
56 {"vm", drm_vm_info},
57 {"clients", drm_clients_info},
58 {"bufs", drm_bufs_info},
60 #define DRM_SYSCTL_ENTRIES NELEM(drm_sysctl_list)
62 int drm_sysctl_init(struct drm_device *dev)
64 struct drm_sysctl_info *info;
65 struct sysctl_oid *oid;
66 struct sysctl_oid *top;
67 int i, unit;
69 info = kzalloc(sizeof *info, GFP_KERNEL);
70 if ( !info )
71 return 1;
72 dev->sysctl = info;
74 unit = device_get_unit(dev->dev->bsddev);
75 if (unit > 9)
76 return 1;
78 /* Add the hw.dri.x for our device */
79 info->name[0] = '0' + unit;
80 info->name[1] = 0;
81 top = SYSCTL_ADD_NODE(&info->ctx, &SYSCTL_NODE_CHILDREN(_hw, dri),
82 OID_AUTO, info->name, CTLFLAG_RW, NULL, NULL);
83 if (!top)
84 return 1;
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_STRING | CTLFLAG_RD,
92 dev,
94 drm_sysctl_list[i].f,
95 "A",
96 NULL);
97 if (!oid)
98 return 1;
100 if (dev->driver->sysctl_init != NULL)
101 dev->driver->sysctl_init(dev, &info->ctx, top);
103 return (0);
106 int drm_sysctl_cleanup(struct drm_device *dev)
108 int error;
110 error = sysctl_ctx_free(&dev->sysctl->ctx);
111 kfree(dev->sysctl);
112 dev->sysctl = NULL;
113 if (dev->driver->sysctl_cleanup != NULL)
114 dev->driver->sysctl_cleanup(dev);
116 return (error);
119 #define DRM_SYSCTL_PRINT(fmt, arg...) \
120 do { \
121 ksnprintf(buf, sizeof(buf), fmt, ##arg); \
122 retcode = SYSCTL_OUT(req, buf, strlen(buf)); \
123 if (retcode) \
124 goto done; \
125 } while (0)
127 static int drm_name_info DRM_SYSCTL_HANDLER_ARGS
129 struct drm_device *dev = arg1;
130 char buf[128];
131 int retcode;
132 int hasunique = 0;
134 DRM_SYSCTL_PRINT("%s", dev->driver->name);
136 DRM_LOCK(dev);
137 if (dev->unique) {
138 ksnprintf(buf, sizeof(buf), " %s", dev->unique);
139 hasunique = 1;
141 DRM_UNLOCK(dev);
143 if (hasunique)
144 SYSCTL_OUT(req, buf, strlen(buf));
146 SYSCTL_OUT(req, "", 1);
148 done:
149 return retcode;
153 * Called when "/proc/dri/.../vm" is read.
155 * Prints information about all mappings in drm_device::maplist.
157 static int drm_vm_info DRM_SYSCTL_HANDLER_ARGS
159 char buf[128];
160 int retcode;
161 struct drm_device *dev = arg1;
162 struct drm_local_map *map;
163 struct drm_map_list *r_list;
165 /* Hardcoded from _DRM_FRAME_BUFFER,
166 _DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and
167 _DRM_SCATTER_GATHER and _DRM_CONSISTENT */
168 const char *types[] = { "FB", "REG", "SHM", "AGP", "SG", "PCI" };
169 const char *type;
170 int i;
172 DRM_LOCK(dev);
173 DRM_SYSCTL_PRINT("\nslot offset size "
174 "type flags address handle mtrr\n");
175 i = 0;
176 list_for_each_entry(r_list, &dev->maplist, head) {
177 map = r_list->map;
178 if (!map)
179 continue;
180 if (map->type < 0 || map->type > 5)
181 type = "??";
182 else
183 type = types[map->type];
185 DRM_SYSCTL_PRINT("%4d 0x%016llx 0x%08lx %4.4s 0x%02x 0x%08lx ",
187 (unsigned long long)map->offset,
188 map->size, type, map->flags,
189 (unsigned long) r_list->user_token);
190 if (map->mtrr < 0)
191 DRM_SYSCTL_PRINT("none\n");
192 else
193 DRM_SYSCTL_PRINT("%4d\n", map->mtrr);
194 i++;
197 SYSCTL_OUT(req, "", 1);
198 DRM_UNLOCK(dev);
200 done:
201 return 0;
204 static int drm_bufs_info DRM_SYSCTL_HANDLER_ARGS
206 struct drm_device *dev = arg1;
207 struct drm_device_dma *dma = dev->dma;
208 struct drm_device_dma tempdma;
209 int *templists;
210 int i;
211 char buf[128];
212 int retcode;
214 /* We can't hold the locks around DRM_SYSCTL_PRINT, so make a temporary
215 * copy of the whole structure and the relevant data from buflist.
217 DRM_LOCK(dev);
218 if (dma == NULL) {
219 DRM_UNLOCK(dev);
220 return 0;
222 tempdma = *dma;
223 templists = kmalloc(sizeof(int) * dma->buf_count, M_DRM,
224 M_WAITOK | M_NULLOK);
225 for (i = 0; i < dma->buf_count; i++)
226 templists[i] = dma->buflist[i]->list;
227 dma = &tempdma;
228 DRM_UNLOCK(dev);
230 DRM_SYSCTL_PRINT("\n o size count free segs pages kB\n");
231 for (i = 0; i <= DRM_MAX_ORDER; i++) {
232 if (dma->bufs[i].buf_count)
233 DRM_SYSCTL_PRINT("%2d %8d %5d %5d %5d %5d\n",
235 dma->bufs[i].buf_size,
236 dma->bufs[i].buf_count,
237 dma->bufs[i].seg_count,
238 dma->bufs[i].seg_count
239 *(1 << dma->bufs[i].page_order),
240 (dma->bufs[i].seg_count
241 * (1 << dma->bufs[i].page_order))
242 * (int)PAGE_SIZE / 1024);
244 DRM_SYSCTL_PRINT("\n");
245 for (i = 0; i < dma->buf_count; i++) {
246 if (i && !(i%32)) DRM_SYSCTL_PRINT("\n");
247 DRM_SYSCTL_PRINT(" %d", templists[i]);
249 DRM_SYSCTL_PRINT("\n");
251 SYSCTL_OUT(req, "", 1);
252 done:
253 kfree(templists);
254 return retcode;
257 static int drm_clients_info DRM_SYSCTL_HANDLER_ARGS
259 struct drm_device *dev = arg1;
260 struct drm_file *priv, *tempprivs;
261 char buf[128];
262 int retcode;
263 int privcount, i;
265 DRM_LOCK(dev);
267 privcount = 0;
268 list_for_each_entry(priv, &dev->filelist, lhead)
269 privcount++;
271 tempprivs = kmalloc(sizeof(struct drm_file) * privcount, M_DRM,
272 M_WAITOK | M_NULLOK);
273 if (tempprivs == NULL) {
274 DRM_UNLOCK(dev);
275 return ENOMEM;
277 i = 0;
278 list_for_each_entry(priv, &dev->filelist, lhead)
279 tempprivs[i++] = *priv;
281 DRM_UNLOCK(dev);
283 DRM_SYSCTL_PRINT(
284 "\na pid magic ioctls\n");
285 for (i = 0; i < privcount; i++) {
286 priv = &tempprivs[i];
287 DRM_SYSCTL_PRINT("%c %5d %10u %10lu\n",
288 priv->authenticated ? 'y' : 'n',
289 priv->pid,
290 priv->magic,
291 0UL);
294 SYSCTL_OUT(req, "", 1);
295 done:
296 kfree(tempprivs);
297 return retcode;