xref: /freebsd/sys/dev/drm2/drm_sysctl.c (revision 685dc743dc3b5645e34836464128e1c0558b404b)
1592ffb21SWarner Losh /*-
2592ffb21SWarner Losh  * Copyright 2003 Eric Anholt
3592ffb21SWarner Losh  * All Rights Reserved.
4592ffb21SWarner Losh  *
5592ffb21SWarner Losh  * Permission is hereby granted, free of charge, to any person obtaining a
6592ffb21SWarner Losh  * copy of this software and associated documentation files (the "Software"),
7592ffb21SWarner Losh  * to deal in the Software without restriction, including without limitation
8592ffb21SWarner Losh  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9592ffb21SWarner Losh  * and/or sell copies of the Software, and to permit persons to whom the
10592ffb21SWarner Losh  * Software is furnished to do so, subject to the following conditions:
11592ffb21SWarner Losh  *
12592ffb21SWarner Losh  * The above copyright notice and this permission notice (including the next
13592ffb21SWarner Losh  * paragraph) shall be included in all copies or substantial portions of the
14592ffb21SWarner Losh  * Software.
15592ffb21SWarner Losh  *
16592ffb21SWarner Losh  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17592ffb21SWarner Losh  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18592ffb21SWarner Losh  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19592ffb21SWarner Losh  * ERIC ANHOLT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20592ffb21SWarner Losh  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21592ffb21SWarner Losh  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22592ffb21SWarner Losh  */
23592ffb21SWarner Losh 
24592ffb21SWarner Losh #include <sys/cdefs.h>
25592ffb21SWarner Losh /** @file drm_sysctl.c
26592ffb21SWarner Losh  * Implementation of various sysctls for controlling DRM behavior and reporting
27592ffb21SWarner Losh  * debug information.
28592ffb21SWarner Losh  */
29592ffb21SWarner Losh 
30592ffb21SWarner Losh #include <dev/drm2/drmP.h>
31592ffb21SWarner Losh #include <dev/drm2/drm.h>
32592ffb21SWarner Losh 
33592ffb21SWarner Losh #include <sys/sysctl.h>
34592ffb21SWarner Losh 
35592ffb21SWarner Losh static int	   drm_name_info DRM_SYSCTL_HANDLER_ARGS;
36592ffb21SWarner Losh static int	   drm_vm_info DRM_SYSCTL_HANDLER_ARGS;
37592ffb21SWarner Losh static int	   drm_clients_info DRM_SYSCTL_HANDLER_ARGS;
38592ffb21SWarner Losh static int	   drm_bufs_info DRM_SYSCTL_HANDLER_ARGS;
39592ffb21SWarner Losh static int	   drm_vblank_info DRM_SYSCTL_HANDLER_ARGS;
40592ffb21SWarner Losh 
41592ffb21SWarner Losh struct drm_sysctl_list {
42592ffb21SWarner Losh 	const char *name;
43592ffb21SWarner Losh 	int	   (*f) DRM_SYSCTL_HANDLER_ARGS;
44592ffb21SWarner Losh } drm_sysctl_list[] = {
45592ffb21SWarner Losh 	{"name",    drm_name_info},
46592ffb21SWarner Losh 	{"vm",	    drm_vm_info},
47592ffb21SWarner Losh 	{"clients", drm_clients_info},
48592ffb21SWarner Losh 	{"bufs",    drm_bufs_info},
49592ffb21SWarner Losh 	{"vblank",    drm_vblank_info},
50592ffb21SWarner Losh };
51592ffb21SWarner Losh #define DRM_SYSCTL_ENTRIES (sizeof(drm_sysctl_list)/sizeof(drm_sysctl_list[0]))
52592ffb21SWarner Losh 
53592ffb21SWarner Losh struct drm_sysctl_info {
54592ffb21SWarner Losh 	struct sysctl_ctx_list ctx;
55592ffb21SWarner Losh 	char		       name[2];
56592ffb21SWarner Losh };
57592ffb21SWarner Losh 
drm_sysctl_init(struct drm_device * dev)58592ffb21SWarner Losh int drm_sysctl_init(struct drm_device *dev)
59592ffb21SWarner Losh {
60592ffb21SWarner Losh 	struct drm_sysctl_info *info;
61592ffb21SWarner Losh 	struct sysctl_oid *oid;
62592ffb21SWarner Losh 	struct sysctl_oid *top, *drioid;
63592ffb21SWarner Losh 	int		  i;
64592ffb21SWarner Losh 
65592ffb21SWarner Losh 	info = malloc(sizeof *info, DRM_MEM_DRIVER, M_WAITOK | M_ZERO);
66592ffb21SWarner Losh 	dev->sysctl = info;
67592ffb21SWarner Losh 
68592ffb21SWarner Losh 	/* Add the sysctl node for DRI if it doesn't already exist */
69592ffb21SWarner Losh 	drioid = SYSCTL_ADD_NODE(&info->ctx, SYSCTL_CHILDREN(&sysctl___hw), OID_AUTO,
7059e4be22SPawel Biernacki 	    "dri", CTLFLAG_RW | CTLFLAG_MPSAFE, NULL, "DRI Graphics");
71592ffb21SWarner Losh 	if (!drioid) {
72592ffb21SWarner Losh 		free(dev->sysctl, DRM_MEM_DRIVER);
73592ffb21SWarner Losh 		dev->sysctl = NULL;
74592ffb21SWarner Losh 		return (-ENOMEM);
75592ffb21SWarner Losh 	}
76592ffb21SWarner Losh 
77592ffb21SWarner Losh 	/* Find the next free slot under hw.dri */
78592ffb21SWarner Losh 	i = 0;
79*fbc9f1b2SAndrew Turner 	SYSCTL_FOREACH(oid, SYSCTL_CHILDREN(drioid)) {
80592ffb21SWarner Losh 		if (i <= oid->oid_arg2)
81592ffb21SWarner Losh 			i = oid->oid_arg2 + 1;
82592ffb21SWarner Losh 	}
83592ffb21SWarner Losh 	if (i > 9) {
84592ffb21SWarner Losh 		drm_sysctl_cleanup(dev);
85592ffb21SWarner Losh 		return (-ENOSPC);
86592ffb21SWarner Losh 	}
87592ffb21SWarner Losh 
88592ffb21SWarner Losh 	dev->sysctl_node_idx = i;
89592ffb21SWarner Losh 	/* Add the hw.dri.x for our device */
90592ffb21SWarner Losh 	info->name[0] = '0' + i;
91592ffb21SWarner Losh 	info->name[1] = 0;
92592ffb21SWarner Losh 	top = SYSCTL_ADD_NODE(&info->ctx, SYSCTL_CHILDREN(drioid),
9359e4be22SPawel Biernacki 	    OID_AUTO, info->name, CTLFLAG_RW | CTLFLAG_MPSAFE, NULL, NULL);
94592ffb21SWarner Losh 	if (!top) {
95592ffb21SWarner Losh 		drm_sysctl_cleanup(dev);
96592ffb21SWarner Losh 		return (-ENOMEM);
97592ffb21SWarner Losh 	}
98592ffb21SWarner Losh 
99592ffb21SWarner Losh 	for (i = 0; i < DRM_SYSCTL_ENTRIES; i++) {
10059e4be22SPawel Biernacki 		oid = SYSCTL_ADD_OID(&info->ctx, SYSCTL_CHILDREN(top),
10159e4be22SPawel Biernacki 			OID_AUTO, drm_sysctl_list[i].name,
10259e4be22SPawel Biernacki 			CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NEEDGIANT,
10359e4be22SPawel Biernacki 			dev, 0, drm_sysctl_list[i].f, "A", NULL);
104592ffb21SWarner Losh 		if (!oid) {
105592ffb21SWarner Losh 			drm_sysctl_cleanup(dev);
106592ffb21SWarner Losh 			return (-ENOMEM);
107592ffb21SWarner Losh 		}
108592ffb21SWarner Losh 	}
109592ffb21SWarner Losh 	SYSCTL_ADD_INT(&info->ctx, SYSCTL_CHILDREN(drioid), OID_AUTO, "debug",
110592ffb21SWarner Losh 	    CTLFLAG_RW, &drm_debug, sizeof(drm_debug),
111592ffb21SWarner Losh 	    "Enable debugging output");
112592ffb21SWarner Losh 	SYSCTL_ADD_INT(&info->ctx, SYSCTL_CHILDREN(drioid), OID_AUTO, "notyet",
113592ffb21SWarner Losh 	    CTLFLAG_RW, &drm_notyet, sizeof(drm_debug),
114592ffb21SWarner Losh 	    "Enable notyet reminders");
115592ffb21SWarner Losh 
116592ffb21SWarner Losh 	if (dev->driver->sysctl_init != NULL)
117592ffb21SWarner Losh 		dev->driver->sysctl_init(dev, &info->ctx, top);
118592ffb21SWarner Losh 
119592ffb21SWarner Losh 	SYSCTL_ADD_INT(&info->ctx, SYSCTL_CHILDREN(drioid), OID_AUTO,
120592ffb21SWarner Losh 	    "vblank_offdelay", CTLFLAG_RW, &drm_vblank_offdelay,
121592ffb21SWarner Losh 	    sizeof(drm_vblank_offdelay),
122592ffb21SWarner Losh 	    "");
123592ffb21SWarner Losh 	SYSCTL_ADD_INT(&info->ctx, SYSCTL_CHILDREN(drioid), OID_AUTO,
124592ffb21SWarner Losh 	    "timestamp_precision", CTLFLAG_RW, &drm_timestamp_precision,
125592ffb21SWarner Losh 	    sizeof(drm_timestamp_precision),
126592ffb21SWarner Losh 	    "");
127592ffb21SWarner Losh 
128592ffb21SWarner Losh 	return (0);
129592ffb21SWarner Losh }
130592ffb21SWarner Losh 
drm_sysctl_cleanup(struct drm_device * dev)131592ffb21SWarner Losh int drm_sysctl_cleanup(struct drm_device *dev)
132592ffb21SWarner Losh {
133592ffb21SWarner Losh 	int error;
134592ffb21SWarner Losh 
135592ffb21SWarner Losh 	if (dev->sysctl == NULL)
136592ffb21SWarner Losh 		return (0);
137592ffb21SWarner Losh 
138592ffb21SWarner Losh 	error = sysctl_ctx_free(&dev->sysctl->ctx);
139592ffb21SWarner Losh 	free(dev->sysctl, DRM_MEM_DRIVER);
140592ffb21SWarner Losh 	dev->sysctl = NULL;
141592ffb21SWarner Losh 	if (dev->driver->sysctl_cleanup != NULL)
142592ffb21SWarner Losh 		dev->driver->sysctl_cleanup(dev);
143592ffb21SWarner Losh 
144592ffb21SWarner Losh 	return (-error);
145592ffb21SWarner Losh }
146592ffb21SWarner Losh 
147592ffb21SWarner Losh #define DRM_SYSCTL_PRINT(fmt, arg...)				\
148592ffb21SWarner Losh do {								\
149592ffb21SWarner Losh 	snprintf(buf, sizeof(buf), fmt, ##arg);			\
150592ffb21SWarner Losh 	retcode = SYSCTL_OUT(req, buf, strlen(buf));		\
151592ffb21SWarner Losh 	if (retcode)						\
152592ffb21SWarner Losh 		goto done;					\
153592ffb21SWarner Losh } while (0)
154592ffb21SWarner Losh 
155592ffb21SWarner Losh static int drm_name_info DRM_SYSCTL_HANDLER_ARGS
156592ffb21SWarner Losh {
157592ffb21SWarner Losh 	struct drm_device *dev = arg1;
158592ffb21SWarner Losh 	struct drm_minor *minor;
159592ffb21SWarner Losh 	struct drm_master *master;
160592ffb21SWarner Losh 	char buf[128];
161592ffb21SWarner Losh 	int retcode;
162592ffb21SWarner Losh 	int hasunique = 0;
163592ffb21SWarner Losh 
164592ffb21SWarner Losh 	/* FIXME: This still uses primary minor. */
165592ffb21SWarner Losh 	minor = dev->primary;
166592ffb21SWarner Losh 	DRM_SYSCTL_PRINT("%s 0x%jx", dev->driver->name,
167592ffb21SWarner Losh 	    (uintmax_t)dev2udev(minor->device));
168592ffb21SWarner Losh 
169592ffb21SWarner Losh 	DRM_LOCK(dev);
170592ffb21SWarner Losh 	master = minor->master;
171592ffb21SWarner Losh 	if (master != NULL && master->unique) {
172592ffb21SWarner Losh 		snprintf(buf, sizeof(buf), " %s", master->unique);
173592ffb21SWarner Losh 		hasunique = 1;
174592ffb21SWarner Losh 	}
175592ffb21SWarner Losh 	DRM_UNLOCK(dev);
176592ffb21SWarner Losh 
177592ffb21SWarner Losh 	if (hasunique)
178592ffb21SWarner Losh 		SYSCTL_OUT(req, buf, strlen(buf));
179592ffb21SWarner Losh 
180592ffb21SWarner Losh 	SYSCTL_OUT(req, "", 1);
181592ffb21SWarner Losh 
182592ffb21SWarner Losh done:
183592ffb21SWarner Losh 	return retcode;
184592ffb21SWarner Losh }
185592ffb21SWarner Losh 
186592ffb21SWarner Losh static int drm_vm_info DRM_SYSCTL_HANDLER_ARGS
187592ffb21SWarner Losh {
188592ffb21SWarner Losh 	struct drm_device *dev = arg1;
189592ffb21SWarner Losh 	struct drm_map_list *entry;
190592ffb21SWarner Losh 	struct drm_local_map *map, *tempmaps;
191592ffb21SWarner Losh 	const char *types[] = {
192592ffb21SWarner Losh 		[_DRM_FRAME_BUFFER] = "FB",
193592ffb21SWarner Losh 		[_DRM_REGISTERS] = "REG",
194592ffb21SWarner Losh 		[_DRM_SHM] = "SHM",
195592ffb21SWarner Losh 		[_DRM_AGP] = "AGP",
196592ffb21SWarner Losh 		[_DRM_SCATTER_GATHER] = "SG",
197592ffb21SWarner Losh 		[_DRM_CONSISTENT] = "CONS",
198592ffb21SWarner Losh 		[_DRM_GEM] = "GEM"
199592ffb21SWarner Losh 	};
200592ffb21SWarner Losh 	const char *type, *yesno;
201592ffb21SWarner Losh 	int i, mapcount;
202592ffb21SWarner Losh 	char buf[128];
203592ffb21SWarner Losh 	int retcode;
204592ffb21SWarner Losh 
205592ffb21SWarner Losh 	/* We can't hold the lock while doing SYSCTL_OUTs, so allocate a
206592ffb21SWarner Losh 	 * temporary copy of all the map entries and then SYSCTL_OUT that.
207592ffb21SWarner Losh 	 */
208592ffb21SWarner Losh 	DRM_LOCK(dev);
209592ffb21SWarner Losh 
210592ffb21SWarner Losh 	mapcount = 0;
211592ffb21SWarner Losh 	list_for_each_entry(entry, &dev->maplist, head) {
212592ffb21SWarner Losh 		if (entry->map != NULL)
213592ffb21SWarner Losh 			mapcount++;
214592ffb21SWarner Losh 	}
215592ffb21SWarner Losh 
216592ffb21SWarner Losh 	tempmaps = malloc(sizeof(*tempmaps) * mapcount, DRM_MEM_DRIVER,
217592ffb21SWarner Losh 	    M_NOWAIT);
218592ffb21SWarner Losh 	if (tempmaps == NULL) {
219592ffb21SWarner Losh 		DRM_UNLOCK(dev);
220592ffb21SWarner Losh 		return ENOMEM;
221592ffb21SWarner Losh 	}
222592ffb21SWarner Losh 
223592ffb21SWarner Losh 	i = 0;
224592ffb21SWarner Losh 	list_for_each_entry(entry, &dev->maplist, head) {
225592ffb21SWarner Losh 		if (entry->map != NULL)
226592ffb21SWarner Losh 			tempmaps[i++] = *entry->map;
227592ffb21SWarner Losh 	}
228592ffb21SWarner Losh 
229592ffb21SWarner Losh 	DRM_UNLOCK(dev);
230592ffb21SWarner Losh 
231592ffb21SWarner Losh 	DRM_SYSCTL_PRINT("\nslot offset	        size       "
232592ffb21SWarner Losh 	    "type flags address            mtrr\n");
233592ffb21SWarner Losh 
234592ffb21SWarner Losh 	for (i = 0; i < mapcount; i++) {
235592ffb21SWarner Losh 		map = &tempmaps[i];
236592ffb21SWarner Losh 
237592ffb21SWarner Losh 		switch(map->type) {
238592ffb21SWarner Losh 		default:
239592ffb21SWarner Losh 			type = "??";
240592ffb21SWarner Losh 			break;
241592ffb21SWarner Losh 		case _DRM_FRAME_BUFFER:
242592ffb21SWarner Losh 		case _DRM_REGISTERS:
243592ffb21SWarner Losh 		case _DRM_SHM:
244592ffb21SWarner Losh 		case _DRM_AGP:
245592ffb21SWarner Losh 		case _DRM_SCATTER_GATHER:
246592ffb21SWarner Losh 		case _DRM_CONSISTENT:
247592ffb21SWarner Losh 		case _DRM_GEM:
248592ffb21SWarner Losh 			type = types[map->type];
249592ffb21SWarner Losh 			break;
250592ffb21SWarner Losh 		}
251592ffb21SWarner Losh 
252592ffb21SWarner Losh 		if (map->mtrr < 0)
253592ffb21SWarner Losh 			yesno = "no";
254592ffb21SWarner Losh 		else
255592ffb21SWarner Losh 			yesno = "yes";
256592ffb21SWarner Losh 
257592ffb21SWarner Losh 		DRM_SYSCTL_PRINT(
258592ffb21SWarner Losh 		    "%4d 0x%016llx 0x%08lx %4.4s  0x%02x 0x%016lx %s\n",
259592ffb21SWarner Losh 		    i, (unsigned long long)map->offset, map->size, type,
260592ffb21SWarner Losh 		    map->flags, (unsigned long)map->handle, yesno);
261592ffb21SWarner Losh 	}
262592ffb21SWarner Losh 	SYSCTL_OUT(req, "", 1);
263592ffb21SWarner Losh 
264592ffb21SWarner Losh done:
265592ffb21SWarner Losh 	free(tempmaps, DRM_MEM_DRIVER);
266592ffb21SWarner Losh 	return retcode;
267592ffb21SWarner Losh }
268592ffb21SWarner Losh 
269592ffb21SWarner Losh static int drm_bufs_info DRM_SYSCTL_HANDLER_ARGS
270592ffb21SWarner Losh {
271592ffb21SWarner Losh 	struct drm_device	 *dev = arg1;
272592ffb21SWarner Losh 	struct drm_device_dma *dma = dev->dma;
273592ffb21SWarner Losh 	struct drm_device_dma tempdma;
274592ffb21SWarner Losh 	int *templists;
275592ffb21SWarner Losh 	int i;
276592ffb21SWarner Losh 	char buf[128];
277592ffb21SWarner Losh 	int retcode;
278592ffb21SWarner Losh 
279592ffb21SWarner Losh 	/* We can't hold the locks around DRM_SYSCTL_PRINT, so make a temporary
280592ffb21SWarner Losh 	 * copy of the whole structure and the relevant data from buflist.
281592ffb21SWarner Losh 	 */
282592ffb21SWarner Losh 	DRM_LOCK(dev);
283592ffb21SWarner Losh 	if (dma == NULL) {
284592ffb21SWarner Losh 		DRM_UNLOCK(dev);
285592ffb21SWarner Losh 		return 0;
286592ffb21SWarner Losh 	}
287592ffb21SWarner Losh 	DRM_SPINLOCK(&dev->dma_lock);
288592ffb21SWarner Losh 	tempdma = *dma;
289592ffb21SWarner Losh 	templists = malloc(sizeof(int) * dma->buf_count, DRM_MEM_DRIVER,
290592ffb21SWarner Losh 	    M_NOWAIT);
291592ffb21SWarner Losh 	for (i = 0; i < dma->buf_count; i++)
292592ffb21SWarner Losh 		templists[i] = dma->buflist[i]->list;
293592ffb21SWarner Losh 	dma = &tempdma;
294592ffb21SWarner Losh 	DRM_SPINUNLOCK(&dev->dma_lock);
295592ffb21SWarner Losh 	DRM_UNLOCK(dev);
296592ffb21SWarner Losh 
297592ffb21SWarner Losh 	DRM_SYSCTL_PRINT("\n o     size count  free	 segs pages    kB\n");
298592ffb21SWarner Losh 	for (i = 0; i <= DRM_MAX_ORDER; i++) {
299592ffb21SWarner Losh 		if (dma->bufs[i].buf_count)
300592ffb21SWarner Losh 			DRM_SYSCTL_PRINT("%2d %8d %5d %5d %5d %5d %5d\n",
301592ffb21SWarner Losh 				       i,
302592ffb21SWarner Losh 				       dma->bufs[i].buf_size,
303592ffb21SWarner Losh 				       dma->bufs[i].buf_count,
304592ffb21SWarner Losh 				       atomic_read(&dma->bufs[i]
305592ffb21SWarner Losh 						   .freelist.count),
306592ffb21SWarner Losh 				       dma->bufs[i].seg_count,
307592ffb21SWarner Losh 				       dma->bufs[i].seg_count
308592ffb21SWarner Losh 				       *(1 << dma->bufs[i].page_order),
309592ffb21SWarner Losh 				       (dma->bufs[i].seg_count
310592ffb21SWarner Losh 					* (1 << dma->bufs[i].page_order))
311592ffb21SWarner Losh 				       * (int)PAGE_SIZE / 1024);
312592ffb21SWarner Losh 	}
313592ffb21SWarner Losh 	DRM_SYSCTL_PRINT("\n");
314592ffb21SWarner Losh 	for (i = 0; i < dma->buf_count; i++) {
315592ffb21SWarner Losh 		if (i && !(i%32)) DRM_SYSCTL_PRINT("\n");
316592ffb21SWarner Losh 		DRM_SYSCTL_PRINT(" %d", templists[i]);
317592ffb21SWarner Losh 	}
318592ffb21SWarner Losh 	DRM_SYSCTL_PRINT("\n");
319592ffb21SWarner Losh 
320592ffb21SWarner Losh 	SYSCTL_OUT(req, "", 1);
321592ffb21SWarner Losh done:
322592ffb21SWarner Losh 	free(templists, DRM_MEM_DRIVER);
323592ffb21SWarner Losh 	return retcode;
324592ffb21SWarner Losh }
325592ffb21SWarner Losh 
326592ffb21SWarner Losh static int drm_clients_info DRM_SYSCTL_HANDLER_ARGS
327592ffb21SWarner Losh {
328592ffb21SWarner Losh 	struct drm_device *dev = arg1;
329592ffb21SWarner Losh 	struct drm_file *priv, *tempprivs;
330592ffb21SWarner Losh 	char buf[128];
331592ffb21SWarner Losh 	int retcode;
332592ffb21SWarner Losh 	int privcount, i;
333592ffb21SWarner Losh 
334592ffb21SWarner Losh 	DRM_LOCK(dev);
335592ffb21SWarner Losh 
336592ffb21SWarner Losh 	privcount = 0;
337592ffb21SWarner Losh 	list_for_each_entry(priv, &dev->filelist, lhead)
338592ffb21SWarner Losh 		privcount++;
339592ffb21SWarner Losh 
340592ffb21SWarner Losh 	tempprivs = malloc(sizeof(struct drm_file) * privcount, DRM_MEM_DRIVER,
341592ffb21SWarner Losh 	    M_NOWAIT);
342592ffb21SWarner Losh 	if (tempprivs == NULL) {
343592ffb21SWarner Losh 		DRM_UNLOCK(dev);
344592ffb21SWarner Losh 		return ENOMEM;
345592ffb21SWarner Losh 	}
346592ffb21SWarner Losh 	i = 0;
347592ffb21SWarner Losh 	list_for_each_entry(priv, &dev->filelist, lhead)
348592ffb21SWarner Losh 		tempprivs[i++] = *priv;
349592ffb21SWarner Losh 
350592ffb21SWarner Losh 	DRM_UNLOCK(dev);
351592ffb21SWarner Losh 
352592ffb21SWarner Losh 	DRM_SYSCTL_PRINT(
353592ffb21SWarner Losh 	    "\na dev            pid   uid      magic     ioctls\n");
354592ffb21SWarner Losh 	for (i = 0; i < privcount; i++) {
355592ffb21SWarner Losh 		priv = &tempprivs[i];
356592ffb21SWarner Losh 		DRM_SYSCTL_PRINT("%c %-12s %5d %5d %10u %10lu\n",
357592ffb21SWarner Losh 			       priv->authenticated ? 'y' : 'n',
358592ffb21SWarner Losh 			       devtoname(priv->minor->device),
359592ffb21SWarner Losh 			       priv->pid,
360592ffb21SWarner Losh 			       priv->uid,
361592ffb21SWarner Losh 			       priv->magic,
362592ffb21SWarner Losh 			       priv->ioctl_count);
363592ffb21SWarner Losh 	}
364592ffb21SWarner Losh 
365592ffb21SWarner Losh 	SYSCTL_OUT(req, "", 1);
366592ffb21SWarner Losh done:
367592ffb21SWarner Losh 	free(tempprivs, DRM_MEM_DRIVER);
368592ffb21SWarner Losh 	return retcode;
369592ffb21SWarner Losh }
370592ffb21SWarner Losh 
371592ffb21SWarner Losh static int drm_vblank_info DRM_SYSCTL_HANDLER_ARGS
372592ffb21SWarner Losh {
373592ffb21SWarner Losh 	struct drm_device *dev = arg1;
374592ffb21SWarner Losh 	char buf[128];
375592ffb21SWarner Losh 	int retcode;
376592ffb21SWarner Losh 	int i;
377592ffb21SWarner Losh 
378592ffb21SWarner Losh 	DRM_SYSCTL_PRINT("\ncrtc ref count    last     enabled inmodeset\n");
379592ffb21SWarner Losh 	DRM_LOCK(dev);
380592ffb21SWarner Losh 	if (dev->_vblank_count == NULL)
381592ffb21SWarner Losh 		goto done;
382592ffb21SWarner Losh 	for (i = 0 ; i < dev->num_crtcs ; i++) {
383592ffb21SWarner Losh 		DRM_SYSCTL_PRINT("  %02d  %02d %08d %08d %02d      %02d\n",
384592ffb21SWarner Losh 		    i, dev->vblank_refcount[i],
385592ffb21SWarner Losh 		    dev->_vblank_count[i],
386592ffb21SWarner Losh 		    dev->last_vblank[i],
387592ffb21SWarner Losh 		    dev->vblank_enabled[i],
388592ffb21SWarner Losh 		    dev->vblank_inmodeset[i]);
389592ffb21SWarner Losh 	}
390592ffb21SWarner Losh done:
391592ffb21SWarner Losh 	DRM_UNLOCK(dev);
392592ffb21SWarner Losh 
393592ffb21SWarner Losh 	SYSCTL_OUT(req, "", -1);
394592ffb21SWarner Losh 	return retcode;
395592ffb21SWarner Losh }
396