2 * Copyright 2003 Eric Anholt
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
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
32 #include <sys/sysctl.h>
33 #include <sys/types.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 {
53 int (*f) DRM_SYSCTL_HANDLER_ARGS;
54 } drm_sysctl_list[] = {
55 {"name", drm_name_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;
69 info = kzalloc(sizeof *info, GFP_KERNEL);
74 unit = device_get_unit(dev->dev->bsddev);
78 /* Add the hw.dri.x for our device */
79 info->name[0] = '0' + unit;
81 top = SYSCTL_ADD_NODE(&info->ctx, &SYSCTL_NODE_CHILDREN(_hw, dri),
82 OID_AUTO, info->name, CTLFLAG_RW, NULL, NULL);
86 for (i = 0; i < DRM_SYSCTL_ENTRIES; i++) {
87 oid = SYSCTL_ADD_OID(&info->ctx,
90 drm_sysctl_list[i].name,
91 CTLTYPE_STRING | CTLFLAG_RD,
100 if (dev->driver->sysctl_init != NULL)
101 dev->driver->sysctl_init(dev, &info->ctx, top);
106 int drm_sysctl_cleanup(struct drm_device *dev)
110 error = sysctl_ctx_free(&dev->sysctl->ctx);
113 if (dev->driver->sysctl_cleanup != NULL)
114 dev->driver->sysctl_cleanup(dev);
119 #define DRM_SYSCTL_PRINT(fmt, arg...) \
121 ksnprintf(buf, sizeof(buf), fmt, ##arg); \
122 retcode = SYSCTL_OUT(req, buf, strlen(buf)); \
127 static int drm_name_info DRM_SYSCTL_HANDLER_ARGS
129 struct drm_device *dev = arg1;
134 DRM_SYSCTL_PRINT("%s 0x%x", dev->driver->name,
135 devid_from_dev(dev->devnode));
139 ksnprintf(buf, sizeof(buf), " %s", dev->unique);
145 SYSCTL_OUT(req, buf, strlen(buf));
147 SYSCTL_OUT(req, "", 1);
154 * Called when "/proc/dri/.../vm" is read.
156 * Prints information about all mappings in drm_device::maplist.
158 static int drm_vm_info DRM_SYSCTL_HANDLER_ARGS
162 struct drm_device *dev = arg1;
163 struct drm_local_map *map;
164 struct drm_map_list *r_list;
166 /* Hardcoded from _DRM_FRAME_BUFFER,
167 _DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and
168 _DRM_SCATTER_GATHER and _DRM_CONSISTENT */
169 const char *types[] = { "FB", "REG", "SHM", "AGP", "SG", "PCI" };
174 DRM_SYSCTL_PRINT("\nslot offset size "
175 "type flags address handle mtrr\n");
177 list_for_each_entry(r_list, &dev->maplist, head) {
181 if (map->type < 0 || map->type > 5)
184 type = types[map->type];
186 DRM_SYSCTL_PRINT("%4d 0x%016llx 0x%08lx %4.4s 0x%02x 0x%08lx ",
188 (unsigned long long)map->offset,
189 map->size, type, map->flags,
190 (unsigned long) r_list->user_token);
192 DRM_SYSCTL_PRINT("none\n");
194 DRM_SYSCTL_PRINT("%4d\n", map->mtrr);
198 SYSCTL_OUT(req, "", 1);
205 static int drm_bufs_info DRM_SYSCTL_HANDLER_ARGS
207 struct drm_device *dev = arg1;
208 struct drm_device_dma *dma = dev->dma;
209 struct drm_device_dma tempdma;
215 /* We can't hold the locks around DRM_SYSCTL_PRINT, so make a temporary
216 * copy of the whole structure and the relevant data from buflist.
224 templists = kmalloc(sizeof(int) * dma->buf_count, M_DRM,
225 M_WAITOK | M_NULLOK);
226 for (i = 0; i < dma->buf_count; i++)
227 templists[i] = dma->buflist[i]->list;
231 DRM_SYSCTL_PRINT("\n o size count free segs pages kB\n");
232 for (i = 0; i <= DRM_MAX_ORDER; i++) {
233 if (dma->bufs[i].buf_count)
234 DRM_SYSCTL_PRINT("%2d %8d %5d %5d %5d %5d\n",
236 dma->bufs[i].buf_size,
237 dma->bufs[i].buf_count,
238 dma->bufs[i].seg_count,
239 dma->bufs[i].seg_count
240 *(1 << dma->bufs[i].page_order),
241 (dma->bufs[i].seg_count
242 * (1 << dma->bufs[i].page_order))
243 * (int)PAGE_SIZE / 1024);
245 DRM_SYSCTL_PRINT("\n");
246 for (i = 0; i < dma->buf_count; i++) {
247 if (i && !(i%32)) DRM_SYSCTL_PRINT("\n");
248 DRM_SYSCTL_PRINT(" %d", templists[i]);
250 DRM_SYSCTL_PRINT("\n");
252 SYSCTL_OUT(req, "", 1);
258 static int drm_clients_info DRM_SYSCTL_HANDLER_ARGS
260 struct drm_device *dev = arg1;
261 struct drm_file *priv, *tempprivs;
269 list_for_each_entry(priv, &dev->filelist, lhead)
272 tempprivs = kmalloc(sizeof(struct drm_file) * privcount, M_DRM,
273 M_WAITOK | M_NULLOK);
274 if (tempprivs == NULL) {
279 list_for_each_entry(priv, &dev->filelist, lhead)
280 tempprivs[i++] = *priv;
285 "\na dev pid magic ioctls\n");
286 for (i = 0; i < privcount; i++) {
287 priv = &tempprivs[i];
288 DRM_SYSCTL_PRINT("%c %-12s %5d %10u %10lu\n",
289 priv->authenticated ? 'y' : 'n',
290 devtoname(priv->dev->devnode),
296 SYSCTL_OUT(req, "", 1);