xref: /dflybsd-src/sys/dev/drm/drm_sysctl.c (revision 3f2dd94a569761201b5b0a18b2f697f97fe1b9dc)
17f3c3d6fSHasso Tepper /*-
27f3c3d6fSHasso Tepper  * Copyright 2003 Eric Anholt
37f3c3d6fSHasso Tepper  * All Rights Reserved.
47f3c3d6fSHasso Tepper  *
57f3c3d6fSHasso Tepper  * Permission is hereby granted, free of charge, to any person obtaining a
67f3c3d6fSHasso Tepper  * copy of this software and associated documentation files (the "Software"),
77f3c3d6fSHasso Tepper  * to deal in the Software without restriction, including without limitation
87f3c3d6fSHasso Tepper  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
97f3c3d6fSHasso Tepper  * and/or sell copies of the Software, and to permit persons to whom the
107f3c3d6fSHasso Tepper  * Software is furnished to do so, subject to the following conditions:
117f3c3d6fSHasso Tepper  *
127f3c3d6fSHasso Tepper  * The above copyright notice and this permission notice (including the next
137f3c3d6fSHasso Tepper  * paragraph) shall be included in all copies or substantial portions of the
147f3c3d6fSHasso Tepper  * Software.
157f3c3d6fSHasso Tepper  *
167f3c3d6fSHasso Tepper  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
177f3c3d6fSHasso Tepper  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
187f3c3d6fSHasso Tepper  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
197f3c3d6fSHasso Tepper  * ERIC ANHOLT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
207f3c3d6fSHasso Tepper  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
217f3c3d6fSHasso Tepper  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
225718399fSFrançois Tigeot  *
235718399fSFrançois Tigeot  * $FreeBSD: src/sys/dev/drm2/drm_sysctl.c,v 1.1 2012/05/22 11:07:44 kib Exp $
247f3c3d6fSHasso Tepper  */
257f3c3d6fSHasso Tepper 
267f3c3d6fSHasso Tepper /** @file drm_sysctl.c
277f3c3d6fSHasso Tepper  * Implementation of various sysctls for controlling DRM behavior and reporting
287f3c3d6fSHasso Tepper  * debug information.
297f3c3d6fSHasso Tepper  */
307f3c3d6fSHasso Tepper 
315718399fSFrançois Tigeot #include <sys/conf.h>
325718399fSFrançois Tigeot #include <sys/sysctl.h>
335718399fSFrançois Tigeot #include <sys/types.h>
345718399fSFrançois Tigeot 
3518e26a6dSFrançois Tigeot #include <drm/drmP.h>
364250aa95Szrj #include "drm_legacy.h"
377f3c3d6fSHasso Tepper 
3883dc5405SImre Vadász SYSCTL_NODE(_hw, OID_AUTO, dri, CTLFLAG_RD, 0, "DRI Graphics");
3983dc5405SImre Vadász SYSCTL_INT(_hw_dri, OID_AUTO, debug, CTLFLAG_RW, &drm_debug, 0,
4083dc5405SImre Vadász 	    "Enable debugging output");
4183dc5405SImre Vadász SYSCTL_INT(_hw_dri, OID_AUTO, vblank_offdelay, CTLFLAG_RW,
4283dc5405SImre Vadász 	    &drm_vblank_offdelay, 0, "Delay until vblank irq auto-disable");
4383dc5405SImre Vadász SYSCTL_INT(_hw_dri, OID_AUTO, timestamp_precision, CTLFLAG_RW,
4483dc5405SImre Vadász 	    &drm_timestamp_precision, 0, "Max. error on timestamps");
4583dc5405SImre Vadász 
467f3c3d6fSHasso Tepper static int	   drm_name_info DRM_SYSCTL_HANDLER_ARGS;
477f3c3d6fSHasso Tepper static int	   drm_vm_info DRM_SYSCTL_HANDLER_ARGS;
487f3c3d6fSHasso Tepper static int	   drm_clients_info DRM_SYSCTL_HANDLER_ARGS;
497f3c3d6fSHasso Tepper static int	   drm_bufs_info DRM_SYSCTL_HANDLER_ARGS;
507f3c3d6fSHasso Tepper 
517f3c3d6fSHasso Tepper struct drm_sysctl_list {
527f3c3d6fSHasso Tepper 	const char *name;
537f3c3d6fSHasso Tepper 	int	   (*f) DRM_SYSCTL_HANDLER_ARGS;
547f3c3d6fSHasso Tepper } drm_sysctl_list[] = {
557f3c3d6fSHasso Tepper 	{"name",    drm_name_info},
567f3c3d6fSHasso Tepper 	{"vm",	    drm_vm_info},
577f3c3d6fSHasso Tepper 	{"clients", drm_clients_info},
587f3c3d6fSHasso Tepper 	{"bufs",    drm_bufs_info},
597f3c3d6fSHasso Tepper };
60c157ff7aSSascha Wildner #define DRM_SYSCTL_ENTRIES NELEM(drm_sysctl_list)
617f3c3d6fSHasso Tepper 
drm_sysctl_init(struct drm_device * dev)62b3705d71SHasso Tepper int drm_sysctl_init(struct drm_device *dev)
637f3c3d6fSHasso Tepper {
647f3c3d6fSHasso Tepper 	struct drm_sysctl_info *info;
657f3c3d6fSHasso Tepper 	struct sysctl_oid *oid;
6683dc5405SImre Vadász 	struct sysctl_oid *top;
67ad8fda21SImre Vadász 	int i, unit;
687f3c3d6fSHasso Tepper 
69175896dfSzrj 	info = kzalloc(sizeof *info, GFP_KERNEL);
707f3c3d6fSHasso Tepper 	if ( !info )
717f3c3d6fSHasso Tepper 		return 1;
727f3c3d6fSHasso Tepper 	dev->sysctl = info;
737f3c3d6fSHasso Tepper 
74fb572d17SFrançois Tigeot 	unit = device_get_unit(dev->dev->bsddev);
75ad8fda21SImre Vadász 	if (unit > 9)
767f3c3d6fSHasso Tepper 		return 1;
777f3c3d6fSHasso Tepper 
787f3c3d6fSHasso Tepper 	/* Add the hw.dri.x for our device */
79ad8fda21SImre Vadász 	info->name[0] = '0' + unit;
807f3c3d6fSHasso Tepper 	info->name[1] = 0;
8183dc5405SImre Vadász 	top = SYSCTL_ADD_NODE(&info->ctx, &SYSCTL_NODE_CHILDREN(_hw, dri),
825718399fSFrançois Tigeot 	    OID_AUTO, info->name, CTLFLAG_RW, NULL, NULL);
837f3c3d6fSHasso Tepper 	if (!top)
847f3c3d6fSHasso Tepper 		return 1;
857f3c3d6fSHasso Tepper 
867f3c3d6fSHasso Tepper 	for (i = 0; i < DRM_SYSCTL_ENTRIES; i++) {
877f3c3d6fSHasso Tepper 		oid = SYSCTL_ADD_OID(&info->ctx,
887f3c3d6fSHasso Tepper 			SYSCTL_CHILDREN(top),
897f3c3d6fSHasso Tepper 			OID_AUTO,
907f3c3d6fSHasso Tepper 			drm_sysctl_list[i].name,
9199f70504SFrançois Tigeot 			CTLTYPE_STRING | CTLFLAG_RD,
927f3c3d6fSHasso Tepper 			dev,
937f3c3d6fSHasso Tepper 			0,
947f3c3d6fSHasso Tepper 			drm_sysctl_list[i].f,
957f3c3d6fSHasso Tepper 			"A",
967f3c3d6fSHasso Tepper 			NULL);
977f3c3d6fSHasso Tepper 		if (!oid)
987f3c3d6fSHasso Tepper 			return 1;
997f3c3d6fSHasso Tepper 	}
1005718399fSFrançois Tigeot 	if (dev->driver->sysctl_init != NULL)
1015718399fSFrançois Tigeot 		dev->driver->sysctl_init(dev, &info->ctx, top);
1025718399fSFrançois Tigeot 
1035718399fSFrançois Tigeot 	return (0);
1047f3c3d6fSHasso Tepper }
1057f3c3d6fSHasso Tepper 
drm_sysctl_cleanup(struct drm_device * dev)106b3705d71SHasso Tepper int drm_sysctl_cleanup(struct drm_device *dev)
1077f3c3d6fSHasso Tepper {
1087f3c3d6fSHasso Tepper 	int error;
1095718399fSFrançois Tigeot 
1107f3c3d6fSHasso Tepper 	error = sysctl_ctx_free(&dev->sysctl->ctx);
111175896dfSzrj 	kfree(dev->sysctl);
1127f3c3d6fSHasso Tepper 	dev->sysctl = NULL;
1135718399fSFrançois Tigeot 	if (dev->driver->sysctl_cleanup != NULL)
1145718399fSFrançois Tigeot 		dev->driver->sysctl_cleanup(dev);
1157f3c3d6fSHasso Tepper 
1165718399fSFrançois Tigeot 	return (error);
1177f3c3d6fSHasso Tepper }
1187f3c3d6fSHasso Tepper 
1197f3c3d6fSHasso Tepper #define DRM_SYSCTL_PRINT(fmt, arg...)				\
1207f3c3d6fSHasso Tepper do {								\
1215718399fSFrançois Tigeot 	ksnprintf(buf, sizeof(buf), fmt, ##arg);			\
1227f3c3d6fSHasso Tepper 	retcode = SYSCTL_OUT(req, buf, strlen(buf));		\
1237f3c3d6fSHasso Tepper 	if (retcode)						\
1247f3c3d6fSHasso Tepper 		goto done;					\
1257f3c3d6fSHasso Tepper } while (0)
1267f3c3d6fSHasso Tepper 
1277f3c3d6fSHasso Tepper static int drm_name_info DRM_SYSCTL_HANDLER_ARGS
1287f3c3d6fSHasso Tepper {
129b3705d71SHasso Tepper 	struct drm_device *dev = arg1;
1307f3c3d6fSHasso Tepper 	char buf[128];
1317f3c3d6fSHasso Tepper 	int retcode;
1327f3c3d6fSHasso Tepper 	int hasunique = 0;
1337f3c3d6fSHasso Tepper 
134*3f2dd94aSFrançois Tigeot 	DRM_SYSCTL_PRINT("%s", dev->driver->name);
1357f3c3d6fSHasso Tepper 
1365718399fSFrançois Tigeot 	DRM_LOCK(dev);
1377f3c3d6fSHasso Tepper 	if (dev->unique) {
1385718399fSFrançois Tigeot 		ksnprintf(buf, sizeof(buf), " %s", dev->unique);
1397f3c3d6fSHasso Tepper 		hasunique = 1;
1407f3c3d6fSHasso Tepper 	}
1415718399fSFrançois Tigeot 	DRM_UNLOCK(dev);
1427f3c3d6fSHasso Tepper 
1437f3c3d6fSHasso Tepper 	if (hasunique)
1447f3c3d6fSHasso Tepper 		SYSCTL_OUT(req, buf, strlen(buf));
1457f3c3d6fSHasso Tepper 
1467f3c3d6fSHasso Tepper 	SYSCTL_OUT(req, "", 1);
1477f3c3d6fSHasso Tepper 
1487f3c3d6fSHasso Tepper done:
1497f3c3d6fSHasso Tepper 	return retcode;
1507f3c3d6fSHasso Tepper }
1517f3c3d6fSHasso Tepper 
152f599cd46SFrançois Tigeot /**
153f599cd46SFrançois Tigeot  * Called when "/proc/dri/.../vm" is read.
154f599cd46SFrançois Tigeot  *
155f599cd46SFrançois Tigeot  * Prints information about all mappings in drm_device::maplist.
156f599cd46SFrançois Tigeot  */
1577f3c3d6fSHasso Tepper static int drm_vm_info DRM_SYSCTL_HANDLER_ARGS
1587f3c3d6fSHasso Tepper {
1597f3c3d6fSHasso Tepper 	char buf[128];
1607f3c3d6fSHasso Tepper 	int retcode;
161f599cd46SFrançois Tigeot 	struct drm_device *dev = arg1;
162f599cd46SFrançois Tigeot 	struct drm_local_map *map;
163f599cd46SFrançois Tigeot 	struct drm_map_list *r_list;
1647f3c3d6fSHasso Tepper 
165f599cd46SFrançois Tigeot 	/* Hardcoded from _DRM_FRAME_BUFFER,
166f599cd46SFrançois Tigeot 	   _DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and
167f599cd46SFrançois Tigeot 	   _DRM_SCATTER_GATHER and _DRM_CONSISTENT */
168f599cd46SFrançois Tigeot 	const char *types[] = { "FB", "REG", "SHM", "AGP", "SG", "PCI" };
169f599cd46SFrançois Tigeot 	const char *type;
170f599cd46SFrançois Tigeot 	int i;
171f599cd46SFrançois Tigeot 
1725718399fSFrançois Tigeot 	DRM_LOCK(dev);
173b3705d71SHasso Tepper 	DRM_SYSCTL_PRINT("\nslot offset	        size       "
17499f70504SFrançois Tigeot 	    "type flags address            handle mtrr\n");
175f599cd46SFrançois Tigeot 	i = 0;
176f599cd46SFrançois Tigeot 	list_for_each_entry(r_list, &dev->maplist, head) {
177f599cd46SFrançois Tigeot 		map = r_list->map;
178f599cd46SFrançois Tigeot 		if (!map)
179f599cd46SFrançois Tigeot 			continue;
180f599cd46SFrançois Tigeot 		if (map->type < 0 || map->type > 5)
1817f3c3d6fSHasso Tepper 			type = "??";
1827f3c3d6fSHasso Tepper 		else
183f599cd46SFrançois Tigeot 			type = types[map->type];
1847f3c3d6fSHasso Tepper 
185f599cd46SFrançois Tigeot 		DRM_SYSCTL_PRINT("%4d 0x%016llx 0x%08lx %4.4s  0x%02x 0x%08lx ",
186f599cd46SFrançois Tigeot 			   i,
187f599cd46SFrançois Tigeot 			   (unsigned long long)map->offset,
188f599cd46SFrançois Tigeot 			   map->size, type, map->flags,
189f599cd46SFrançois Tigeot 			   (unsigned long) r_list->user_token);
190f599cd46SFrançois Tigeot 		if (map->mtrr < 0)
191f599cd46SFrançois Tigeot 			DRM_SYSCTL_PRINT("none\n");
192f599cd46SFrançois Tigeot 		else
193f599cd46SFrançois Tigeot 			DRM_SYSCTL_PRINT("%4d\n", map->mtrr);
194f599cd46SFrançois Tigeot 		i++;
195f599cd46SFrançois Tigeot 
1967f3c3d6fSHasso Tepper 	}
1977f3c3d6fSHasso Tepper 	SYSCTL_OUT(req, "", 1);
198f599cd46SFrançois Tigeot 	DRM_UNLOCK(dev);
1997f3c3d6fSHasso Tepper 
2007f3c3d6fSHasso Tepper done:
201f599cd46SFrançois Tigeot 	return 0;
2027f3c3d6fSHasso Tepper }
2037f3c3d6fSHasso Tepper 
2047f3c3d6fSHasso Tepper static int drm_bufs_info DRM_SYSCTL_HANDLER_ARGS
2057f3c3d6fSHasso Tepper {
206b3705d71SHasso Tepper 	struct drm_device	 *dev = arg1;
2074250aa95Szrj 	struct drm_device_dma *dma = dev->dma;
2084250aa95Szrj 	struct drm_device_dma tempdma;
2097f3c3d6fSHasso Tepper 	int *templists;
2107f3c3d6fSHasso Tepper 	int i;
2117f3c3d6fSHasso Tepper 	char buf[128];
2127f3c3d6fSHasso Tepper 	int retcode;
2137f3c3d6fSHasso Tepper 
2147f3c3d6fSHasso Tepper 	/* We can't hold the locks around DRM_SYSCTL_PRINT, so make a temporary
2157f3c3d6fSHasso Tepper 	 * copy of the whole structure and the relevant data from buflist.
2167f3c3d6fSHasso Tepper 	 */
2175718399fSFrançois Tigeot 	DRM_LOCK(dev);
2187f3c3d6fSHasso Tepper 	if (dma == NULL) {
2195718399fSFrançois Tigeot 		DRM_UNLOCK(dev);
2207f3c3d6fSHasso Tepper 		return 0;
2217f3c3d6fSHasso Tepper 	}
2227f3c3d6fSHasso Tepper 	tempdma = *dma;
2235a3b77d5SFrançois Tigeot 	templists = kmalloc(sizeof(int) * dma->buf_count, M_DRM,
224f8677ba6SMatthew Dillon 			    M_WAITOK | M_NULLOK);
2257f3c3d6fSHasso Tepper 	for (i = 0; i < dma->buf_count; i++)
2267f3c3d6fSHasso Tepper 		templists[i] = dma->buflist[i]->list;
2277f3c3d6fSHasso Tepper 	dma = &tempdma;
2285718399fSFrançois Tigeot 	DRM_UNLOCK(dev);
2297f3c3d6fSHasso Tepper 
2307f3c3d6fSHasso Tepper 	DRM_SYSCTL_PRINT("\n o     size count  free	 segs pages    kB\n");
2317f3c3d6fSHasso Tepper 	for (i = 0; i <= DRM_MAX_ORDER; i++) {
2327f3c3d6fSHasso Tepper 		if (dma->bufs[i].buf_count)
23324edb884SFrançois Tigeot 			DRM_SYSCTL_PRINT("%2d %8d %5d %5d %5d %5d\n",
2347f3c3d6fSHasso Tepper 				       i,
2357f3c3d6fSHasso Tepper 				       dma->bufs[i].buf_size,
2367f3c3d6fSHasso Tepper 				       dma->bufs[i].buf_count,
2377f3c3d6fSHasso Tepper 				       dma->bufs[i].seg_count,
2387f3c3d6fSHasso Tepper 				       dma->bufs[i].seg_count
2397f3c3d6fSHasso Tepper 				       *(1 << dma->bufs[i].page_order),
2407f3c3d6fSHasso Tepper 				       (dma->bufs[i].seg_count
2417f3c3d6fSHasso Tepper 					* (1 << dma->bufs[i].page_order))
2425718399fSFrançois Tigeot 				       * (int)PAGE_SIZE / 1024);
2437f3c3d6fSHasso Tepper 	}
2447f3c3d6fSHasso Tepper 	DRM_SYSCTL_PRINT("\n");
2457f3c3d6fSHasso Tepper 	for (i = 0; i < dma->buf_count; i++) {
2467f3c3d6fSHasso Tepper 		if (i && !(i%32)) DRM_SYSCTL_PRINT("\n");
2477f3c3d6fSHasso Tepper 		DRM_SYSCTL_PRINT(" %d", templists[i]);
2487f3c3d6fSHasso Tepper 	}
2497f3c3d6fSHasso Tepper 	DRM_SYSCTL_PRINT("\n");
2507f3c3d6fSHasso Tepper 
2517f3c3d6fSHasso Tepper 	SYSCTL_OUT(req, "", 1);
2527f3c3d6fSHasso Tepper done:
253175896dfSzrj 	kfree(templists);
2547f3c3d6fSHasso Tepper 	return retcode;
2557f3c3d6fSHasso Tepper }
2567f3c3d6fSHasso Tepper 
2577f3c3d6fSHasso Tepper static int drm_clients_info DRM_SYSCTL_HANDLER_ARGS
2587f3c3d6fSHasso Tepper {
259b3705d71SHasso Tepper 	struct drm_device *dev = arg1;
260b3705d71SHasso Tepper 	struct drm_file *priv, *tempprivs;
2617f3c3d6fSHasso Tepper 	char buf[128];
2627f3c3d6fSHasso Tepper 	int retcode;
2637f3c3d6fSHasso Tepper 	int privcount, i;
2647f3c3d6fSHasso Tepper 
2655718399fSFrançois Tigeot 	DRM_LOCK(dev);
2667f3c3d6fSHasso Tepper 
2677f3c3d6fSHasso Tepper 	privcount = 0;
2681610a1a0SFrançois Tigeot 	list_for_each_entry(priv, &dev->filelist, lhead)
2697f3c3d6fSHasso Tepper 		privcount++;
2707f3c3d6fSHasso Tepper 
2715a3b77d5SFrançois Tigeot 	tempprivs = kmalloc(sizeof(struct drm_file) * privcount, M_DRM,
272f8677ba6SMatthew Dillon 			    M_WAITOK | M_NULLOK);
2737f3c3d6fSHasso Tepper 	if (tempprivs == NULL) {
2745718399fSFrançois Tigeot 		DRM_UNLOCK(dev);
2757f3c3d6fSHasso Tepper 		return ENOMEM;
2767f3c3d6fSHasso Tepper 	}
2777f3c3d6fSHasso Tepper 	i = 0;
2781610a1a0SFrançois Tigeot 	list_for_each_entry(priv, &dev->filelist, lhead)
2797f3c3d6fSHasso Tepper 		tempprivs[i++] = *priv;
2807f3c3d6fSHasso Tepper 
2815718399fSFrançois Tigeot 	DRM_UNLOCK(dev);
2827f3c3d6fSHasso Tepper 
2835718399fSFrançois Tigeot 	DRM_SYSCTL_PRINT(
284*3f2dd94aSFrançois Tigeot 	    "\na pid      magic     ioctls\n");
2857f3c3d6fSHasso Tepper 	for (i = 0; i < privcount; i++) {
2867f3c3d6fSHasso Tepper 		priv = &tempprivs[i];
287*3f2dd94aSFrançois Tigeot 		DRM_SYSCTL_PRINT("%c %5d %10u %10lu\n",
2887f3c3d6fSHasso Tepper 			       priv->authenticated ? 'y' : 'n',
2897f3c3d6fSHasso Tepper 			       priv->pid,
2907f3c3d6fSHasso Tepper 			       priv->magic,
291a85cb24fSFrançois Tigeot 			       0UL);
2927f3c3d6fSHasso Tepper 	}
2937f3c3d6fSHasso Tepper 
2947f3c3d6fSHasso Tepper 	SYSCTL_OUT(req, "", 1);
2957f3c3d6fSHasso Tepper done:
296175896dfSzrj 	kfree(tempprivs);
2977f3c3d6fSHasso Tepper 	return retcode;
2987f3c3d6fSHasso Tepper }
299