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
, dev2udev(dev
->devnode
));
138 ksnprintf(buf
, sizeof(buf
), " %s", dev
->unique
);
144 SYSCTL_OUT(req
, buf
, strlen(buf
));
146 SYSCTL_OUT(req
, "", 1);
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
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" };
173 DRM_SYSCTL_PRINT("\nslot offset size "
174 "type flags address handle mtrr\n");
176 list_for_each_entry(r_list
, &dev
->maplist
, head
) {
180 if (map
->type
< 0 || map
->type
> 5)
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
);
191 DRM_SYSCTL_PRINT("none\n");
193 DRM_SYSCTL_PRINT("%4d\n", map
->mtrr
);
197 SYSCTL_OUT(req
, "", 1);
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
;
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.
222 spin_lock(&dev
->dma_lock
);
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
;
229 spin_unlock(&dev
->dma_lock
);
232 DRM_SYSCTL_PRINT("\n o size count free segs pages kB\n");
233 for (i
= 0; i
<= DRM_MAX_ORDER
; i
++) {
234 if (dma
->bufs
[i
].buf_count
)
235 DRM_SYSCTL_PRINT("%2d %8d %5d %5d %5d %5d\n",
237 dma
->bufs
[i
].buf_size
,
238 dma
->bufs
[i
].buf_count
,
239 dma
->bufs
[i
].seg_count
,
240 dma
->bufs
[i
].seg_count
241 *(1 << dma
->bufs
[i
].page_order
),
242 (dma
->bufs
[i
].seg_count
243 * (1 << dma
->bufs
[i
].page_order
))
244 * (int)PAGE_SIZE
/ 1024);
246 DRM_SYSCTL_PRINT("\n");
247 for (i
= 0; i
< dma
->buf_count
; i
++) {
248 if (i
&& !(i
%32)) DRM_SYSCTL_PRINT("\n");
249 DRM_SYSCTL_PRINT(" %d", templists
[i
]);
251 DRM_SYSCTL_PRINT("\n");
253 SYSCTL_OUT(req
, "", 1);
259 static int drm_clients_info DRM_SYSCTL_HANDLER_ARGS
261 struct drm_device
*dev
= arg1
;
262 struct drm_file
*priv
, *tempprivs
;
270 list_for_each_entry(priv
, &dev
->filelist
, lhead
)
273 tempprivs
= kmalloc(sizeof(struct drm_file
) * privcount
, M_DRM
,
274 M_WAITOK
| M_NULLOK
);
275 if (tempprivs
== NULL
) {
280 list_for_each_entry(priv
, &dev
->filelist
, lhead
)
281 tempprivs
[i
++] = *priv
;
286 "\na dev pid uid magic ioctls\n");
287 for (i
= 0; i
< privcount
; i
++) {
288 priv
= &tempprivs
[i
];
289 DRM_SYSCTL_PRINT("%c %-12s %5d %5d %10u %10lu\n",
290 priv
->authenticated
? 'y' : 'n',
291 devtoname(priv
->dev
->devnode
),
298 SYSCTL_OUT(req
, "", 1);