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.
24 /** @file drm_sysctl.c
25 * Implementation of various sysctls for controlling DRM behavior and reporting
32 #include <sys/sysctl.h>
34 static int drm_name_info DRM_SYSCTL_HANDLER_ARGS
;
35 static int drm_vm_info DRM_SYSCTL_HANDLER_ARGS
;
36 static int drm_clients_info DRM_SYSCTL_HANDLER_ARGS
;
37 static int drm_bufs_info DRM_SYSCTL_HANDLER_ARGS
;
39 struct drm_sysctl_list
{
41 int (*f
) DRM_SYSCTL_HANDLER_ARGS
;
42 } drm_sysctl_list
[] = {
43 {"name", drm_name_info
},
45 {"clients", drm_clients_info
},
46 {"bufs", drm_bufs_info
},
48 #define DRM_SYSCTL_ENTRIES (sizeof(drm_sysctl_list)/sizeof(drm_sysctl_list[0]))
50 struct drm_sysctl_info
{
51 #if defined(__FreeBSD__)
52 struct sysctl_ctx_list ctx
;
54 #elif defined(__NetBSD__)
55 const struct sysctlnode
*dri
, *dri_card
, *dri_debug
;
56 const struct sysctlnode
*dri_rest
[DRM_SYSCTL_ENTRIES
];
61 int drm_sysctl_init(struct drm_device
*dev
)
63 struct drm_sysctl_info
*info
;
64 #if defined(__FreeBSD__)
65 struct sysctl_oid
*oid
;
66 struct sysctl_oid
*top
, *drioid
;
70 info
= malloc(sizeof *info
, DRM_MEM_DRIVER
, M_WAITOK
| M_ZERO
);
75 #if defined(__FreeBSD__)
76 /* Add the sysctl node for DRI if it doesn't already exist */
77 drioid
= SYSCTL_ADD_NODE( &info
->ctx
, &sysctl__hw_children
, OID_AUTO
, "dri", CTLFLAG_RW
, NULL
, "DRI Graphics");
81 /* Find the next free slot under hw.dri */
83 SLIST_FOREACH(oid
, SYSCTL_CHILDREN(drioid
), oid_link
) {
84 if (i
<= oid
->oid_arg2
)
85 i
= oid
->oid_arg2
+ 1;
90 /* Add the hw.dri.x for our device */
91 info
->name
[0] = '0' + i
;
93 top
= SYSCTL_ADD_NODE( &info
->ctx
, SYSCTL_CHILDREN(drioid
), OID_AUTO
, info
->name
, CTLFLAG_RW
, NULL
, NULL
);
97 for (i
= 0; i
< DRM_SYSCTL_ENTRIES
; i
++) {
98 oid
= SYSCTL_ADD_OID(&info
->ctx
,
101 drm_sysctl_list
[i
].name
,
102 CTLTYPE_INT
| CTLFLAG_RD
,
105 drm_sysctl_list
[i
].f
,
111 SYSCTL_ADD_INT(&info
->ctx
, SYSCTL_CHILDREN(top
), OID_AUTO
, "debug",
112 CTLFLAG_RW
, &drm_debug_flag
, sizeof(drm_debug_flag
),
113 "Enable debugging output");
114 #elif defined(__NetBSD__)
115 sysctl_createv(NULL
, 0, NULL
, &info
->dri
,
116 CTLFLAG_READWRITE
, CTLTYPE_NODE
,
117 "dri", SYSCTL_DESCR("DRI Graphics"), NULL
, 0, NULL
, 0,
119 snprintf(info
->name
, 7, "card%d", minor(dev
->kdev
));
120 sysctl_createv(NULL
, 0, NULL
, &info
->dri_card
,
121 CTLFLAG_READWRITE
, CTLTYPE_NODE
,
122 info
->name
, NULL
, NULL
, 0, NULL
, 0,
123 CTL_HW
, info
->dri
->sysctl_num
, CTL_CREATE
);
124 for (i
= 0; i
< DRM_SYSCTL_ENTRIES
; i
++)
125 sysctl_createv(NULL
, 0, NULL
, &(info
->dri_rest
[i
]),
126 CTLFLAG_READONLY
, CTLTYPE_STRING
,
127 drm_sysctl_list
[i
].name
, NULL
,
128 drm_sysctl_list
[i
].f
, 0, dev
,
129 sizeof(struct drm_device
*),
131 info
->dri
->sysctl_num
,
132 info
->dri_card
->sysctl_num
, CTL_CREATE
);
133 sysctl_createv(NULL
, 0, NULL
, &info
->dri_debug
,
134 CTLFLAG_READWRITE
, CTLTYPE_INT
,
135 "debug", SYSCTL_DESCR("Enable debugging output"),
137 &drm_debug_flag
, sizeof(drm_debug_flag
),
138 CTL_HW
, info
->dri
->sysctl_num
, CTL_CREATE
);
144 int drm_sysctl_cleanup(struct drm_device
*dev
)
146 #if defined(__FreeBSD__)
148 error
= sysctl_ctx_free( &dev
->sysctl
->ctx
);
150 free(dev
->sysctl
, DRM_MEM_DRIVER
);
154 #elif defined(__NetBSD__)
157 sysctl_destroyv(NULL
, CTL_HW
, dev
->sysctl
->dri
->sysctl_num
,
158 dev
->sysctl
->dri_debug
->sysctl_num
,
160 for (i
= 0; i
< DRM_SYSCTL_ENTRIES
; i
++)
161 sysctl_destroyv(NULL
, CTL_HW
, dev
->sysctl
->dri
->sysctl_num
,
162 dev
->sysctl
->dri_card
->sysctl_num
,
163 dev
->sysctl
->dri_rest
[i
]->sysctl_num
,
165 sysctl_destroyv(NULL
, CTL_HW
, dev
->sysctl
->dri
->sysctl_num
,
166 dev
->sysctl
->dri_card
->sysctl_num
,
168 sysctl_destroyv(NULL
, CTL_HW
, dev
->sysctl
->dri
->sysctl_num
, CTL_DESTROY
);
170 free(dev
->sysctl
, DRM_MEM_DRIVER
);
178 #define SYSCTL_OUT(x, y, z) \
179 (len+=z,(len<*oldlenp)?(strcat((char*)oldp, y),0):EOVERFLOW)
182 #define DRM_SYSCTL_PRINT(fmt, arg...) \
184 snprintf(buf, sizeof(buf), fmt, ##arg); \
185 retcode = SYSCTL_OUT(req, buf, strlen(buf)); \
190 static int drm_name_info DRM_SYSCTL_HANDLER_ARGS
192 #if defined(__FreeBSD__)
193 struct drm_device
*dev
= arg1
;
194 #elif defined(__NetBSD__)
195 struct drm_device
*dev
= rnode
->sysctl_data
;
202 #if defined(__FreeBSD__)
203 DRM_SYSCTL_PRINT("%s 0x%x", dev
->driver
->name
, dev2udev(dev
->devnode
));
204 #elif defined(__NetBSD__)
207 *((char*)oldp
) = '\0';
209 DRM_SYSCTL_PRINT("%s", dev
->driver
->name
);
214 snprintf(buf
, sizeof(buf
), " %s", dev
->unique
);
220 SYSCTL_OUT(req
, buf
, strlen(buf
));
222 SYSCTL_OUT(req
, "", 1);
228 static int drm_vm_info DRM_SYSCTL_HANDLER_ARGS
230 #if defined(__FreeBSD__)
231 struct drm_device
*dev
= arg1
;
232 #elif defined(__NetBSD__)
233 struct drm_device
*dev
= rnode
->sysctl_data
;
236 drm_local_map_t
*map
, *tempmaps
;
237 const char *types
[] = { "FB", "REG", "SHM", "AGP", "SG" };
238 const char *type
, *yesno
;
243 /* We can't hold the lock while doing SYSCTL_OUTs, so allocate a
244 * temporary copy of all the map entries and then SYSCTL_OUT that.
249 TAILQ_FOREACH(map
, &dev
->maplist
, link
)
252 tempmaps
= malloc(sizeof(drm_local_map_t
) * mapcount
, DRM_MEM_DRIVER
,
254 if (tempmaps
== NULL
) {
260 TAILQ_FOREACH(map
, &dev
->maplist
, link
)
261 tempmaps
[i
++] = *map
;
265 DRM_SYSCTL_PRINT("\nslot offset size "
266 "type flags address mtrr\n");
268 for (i
= 0; i
< mapcount
; i
++) {
274 type
= types
[map
->type
];
282 "%4d 0x%016lx 0x%08lx %4.4s 0x%02x 0x%016lx %s\n", i
,
283 map
->offset
, map
->size
, type
, map
->flags
,
284 (unsigned long)map
->handle
, yesno
);
286 SYSCTL_OUT(req
, "", 1);
289 free(tempmaps
, DRM_MEM_DRIVER
);
293 static int drm_bufs_info DRM_SYSCTL_HANDLER_ARGS
295 #if defined(__FreeBSD__)
296 struct drm_device
*dev
= arg1
;
297 #elif defined(__NetBSD__)
298 struct drm_device
*dev
= rnode
->sysctl_data
;
301 drm_device_dma_t
*dma
= dev
->dma
;
302 drm_device_dma_t tempdma
;
308 /* We can't hold the locks around DRM_SYSCTL_PRINT, so make a temporary
309 * copy of the whole structure and the relevant data from buflist.
316 DRM_SPINLOCK(&dev
->dma_lock
);
318 templists
= malloc(sizeof(int) * dma
->buf_count
, DRM_MEM_DRIVER
,
320 for (i
= 0; i
< dma
->buf_count
; i
++)
321 templists
[i
] = dma
->buflist
[i
]->list
;
323 DRM_SPINUNLOCK(&dev
->dma_lock
);
326 DRM_SYSCTL_PRINT("\n o size count free segs pages kB\n");
327 for (i
= 0; i
<= DRM_MAX_ORDER
; i
++) {
328 if (dma
->bufs
[i
].buf_count
)
329 DRM_SYSCTL_PRINT("%2d %8d %5d %5d %5d %5d %5d\n",
331 dma
->bufs
[i
].buf_size
,
332 dma
->bufs
[i
].buf_count
,
333 atomic_read(&dma
->bufs
[i
]
335 dma
->bufs
[i
].seg_count
,
336 dma
->bufs
[i
].seg_count
337 *(1 << dma
->bufs
[i
].page_order
),
338 (dma
->bufs
[i
].seg_count
339 * (1 << dma
->bufs
[i
].page_order
))
342 DRM_SYSCTL_PRINT("\n");
343 for (i
= 0; i
< dma
->buf_count
; i
++) {
344 if (i
&& !(i
%32)) DRM_SYSCTL_PRINT("\n");
345 DRM_SYSCTL_PRINT(" %d", templists
[i
]);
347 DRM_SYSCTL_PRINT("\n");
349 SYSCTL_OUT(req
, "", 1);
351 free(templists
, DRM_MEM_DRIVER
);
355 static int drm_clients_info DRM_SYSCTL_HANDLER_ARGS
357 #if defined(__FreeBSD__)
358 struct drm_device
*dev
= arg1
;
359 #elif defined(__NetBSD__)
360 struct drm_device
*dev
= rnode
->sysctl_data
;
363 struct drm_file
*priv
, *tempprivs
;
371 TAILQ_FOREACH(priv
, &dev
->files
, link
)
374 tempprivs
= malloc(sizeof(struct drm_file
) * privcount
, DRM_MEM_DRIVER
,
376 if (tempprivs
== NULL
) {
381 TAILQ_FOREACH(priv
, &dev
->files
, link
)
382 tempprivs
[i
++] = *priv
;
386 DRM_SYSCTL_PRINT("\na dev pid uid magic ioctls\n");
387 for (i
= 0; i
< privcount
; i
++) {
388 priv
= &tempprivs
[i
];
389 DRM_SYSCTL_PRINT("%c %3d %5d %5d %10u %10lu\n",
390 priv
->authenticated
? 'y' : 'n',
398 SYSCTL_OUT(req
, "", 1);
400 free(tempprivs
, DRM_MEM_DRIVER
);