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