Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 26 Feb 2004 19:06:24 +0100
From:      des@des.no (Dag-Erling =?iso-8859-1?q?Sm=F8rgrav?=)
To:        arch@freebsd.org
Subject:   per-device sysctls
Message-ID:  <xzpk729lnq7.fsf@dwp.des.no>

next in thread | raw e-mail | index | archive | help
--=-=-=
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: quoted-printable

The first of the attached patches creates a sysctl context and node
for every device in the system named for its nameunit.  Each device's
sysctl node is a child of the parent device's sysctl node, so the
resulting sysctl tree resembles the "show devices by attachment" mode
of Windows's device manager.  Standard entries in each device's tree
include %class, %desc and %driver (device class, device description
and driver name).  I also plan to add entries for device IDs, irq /
drq lines etc., but this will require additional bus-specific code and
is not yet implemented.

Note that root0 is not created through the usual means and therefore
does not get its own sysctl node; its children (nexus0 on i386) are
placed directly in dev.  I haven't yet decided whether this is a
feature or a bug.

The second patch modifies the NDISulator to use the per-device context
and tree rather than create its own.  There are several other drivers
that do this; I chose the NDISulator because I can actually test it.

DES
--=20
Dag-Erling Sm=F8rgrav - des@des.no


--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment; filename=dev.diff

Index: sys/kern/subr_bus.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/subr_bus.c,v
retrieving revision 1.140
diff -u -r1.140 subr_bus.c
--- sys/kern/subr_bus.c	24 Feb 2004 19:31:30 -0000	1.140
+++ sys/kern/subr_bus.c	26 Feb 2004 16:11:13 -0000
@@ -56,6 +56,7 @@
 #include <vm/uma.h>
 
 SYSCTL_NODE(_hw, OID_AUTO, bus, CTLFLAG_RW, NULL, NULL);
+SYSCTL_NODE(, OID_AUTO, dev, CTLFLAG_RW, NULL, NULL);
 
 /*
  * Used to attach drivers to devclasses.
@@ -123,6 +124,9 @@
 	u_char	pad;
 	void	*ivars;
 	void	*softc;
+
+	struct sysctl_ctx_list sysctl_ctx;
+	struct sysctl_oid *sysctl_tree;
 };
 
 struct device_op_desc {
@@ -252,6 +256,8 @@
 
 static dev_t		devctl_dev;
 
+static struct sysctl_ctx_list device_sysctl_ctx;
+
 static void
 devinit(void)
 {
@@ -260,6 +266,7 @@
 	mtx_init(&devsoftc.mtx, "dev mtx", "devd", MTX_DEF);
 	cv_init(&devsoftc.cv, "dev cv");
 	TAILQ_INIT(&devsoftc.devq);
+	sysctl_ctx_init(&device_sysctl_ctx);
 }
 
 static int
@@ -381,6 +388,8 @@
 	struct dev_event_info *n1 = NULL;
 	struct proc *p;
 
+	if (*data != '?')
+		printf("devctl: %s", data);
 	n1 = malloc(sizeof(*n1), M_BUS, M_NOWAIT);
 	if (n1 == NULL)
 		return;
@@ -1256,6 +1265,18 @@
 	return (dev->devflags);
 }
 
+struct sysctl_ctx_list *
+device_get_sysctl_ctx(device_t dev)
+{
+	return (&dev->sysctl_ctx);
+}
+
+struct sysctl_oid *
+device_get_sysctl_tree(device_t dev)
+{
+	return (dev->sysctl_tree);
+}
+
 int
 device_print_prettyname(device_t dev)
 {
@@ -1509,7 +1530,7 @@
 		if (!error) {
 			if (!device_is_quiet(dev))
 				device_print_child(bus, dev);
-			error = DEVICE_ATTACH(dev);
+			error = device_attach(dev);
 			if (!error) {
 				dev->state = DS_ATTACHED;
 				devadded(dev);
@@ -1539,6 +1560,71 @@
 	return (error);
 }
 
+enum {
+	DEVICE_SYSCTL_CLASS,
+	DEVICE_SYSCTL_DESC,
+	DEVICE_SYSCTL_DRIVER,
+};
+
+static int
+device_sysctl_handler(SYSCTL_HANDLER_ARGS)
+{
+	device_t dev = (device_t)arg1;
+	const char *value;
+	size_t len;
+
+	switch (arg2) {
+	case DEVICE_SYSCTL_CLASS:
+		value = dev->devclass->name;
+		break;
+	case DEVICE_SYSCTL_DESC:
+		value = dev->desc;
+		break;
+	case DEVICE_SYSCTL_DRIVER:
+		value = dev->driver->name;
+		break;
+	default:
+		return (EINVAL);
+	}
+	if (value == NULL)
+		return (ENODEV);
+	len = strlen(value);
+	return (SYSCTL_OUT(req, value, strlen(value)));
+}
+
+int
+device_attach(device_t dev)
+{
+	struct sysctl_oid_list *parent_node;
+	int error;
+
+	sysctl_ctx_init(&dev->sysctl_ctx);
+	if (dev->parent && dev->parent->sysctl_tree)
+		parent_node = SYSCTL_CHILDREN(dev->parent->sysctl_tree);
+	else
+		parent_node = SYSCTL_STATIC_CHILDREN(_dev);
+	dev->sysctl_tree = SYSCTL_ADD_NODE(&dev->sysctl_ctx, parent_node,
+	    OID_AUTO, dev->nameunit, CTLFLAG_RD, 0, "");
+	if ((error = DEVICE_ATTACH(dev)) != 0) {
+		sysctl_ctx_free(&dev->sysctl_ctx);
+		dev->sysctl_tree = NULL;
+		return (error);
+	}
+	SYSCTL_ADD_PROC(&dev->sysctl_ctx, SYSCTL_CHILDREN(dev->sysctl_tree),
+	    OID_AUTO, "%class", CTLFLAG_RD,
+	    dev, DEVICE_SYSCTL_CLASS, device_sysctl_handler, "A",
+	    "device class name");
+	SYSCTL_ADD_PROC(&dev->sysctl_ctx, SYSCTL_CHILDREN(dev->sysctl_tree),
+	    OID_AUTO, "%desc", CTLFLAG_RD,
+	    dev, DEVICE_SYSCTL_DESC, device_sysctl_handler, "A",
+	    "device description");
+	SYSCTL_ADD_PROC(&dev->sysctl_ctx, SYSCTL_CHILDREN(dev->sysctl_tree),
+	    OID_AUTO, "%driver", CTLFLAG_RD,
+	    dev, DEVICE_SYSCTL_DRIVER, device_sysctl_handler, "A",
+	    "device driver name");
+	return (0);
+}
+
 int
 device_detach(device_t dev)
 {
@@ -1552,6 +1638,10 @@
 
 	if ((error = DEVICE_DETACH(dev)) != 0)
 		return (error);
+	if (dev->sysctl_tree != NULL) {
+		sysctl_ctx_free(&dev->sysctl_ctx);
+		dev->sysctl_tree = NULL;
+	}
 	devremoved(dev);
 	device_printf(dev, "detached\n");
 	if (dev->parent)
Index: sys/sys/bus.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/bus.h,v
retrieving revision 1.57
diff -u -r1.57 bus.h
--- sys/sys/bus.h	24 Oct 2003 22:41:54 -0000	1.57
+++ sys/sys/bus.h	26 Feb 2004 15:51:43 -0000
@@ -317,6 +317,7 @@
 					 const char *name, int unit);
 void	device_busy(device_t dev);
 int	device_delete_child(device_t dev, device_t child);
+int	device_attach(device_t dev);
 int	device_detach(device_t dev);
 void	device_disable(device_t dev);
 void	device_enable(device_t dev);
@@ -335,6 +336,8 @@
 void	*device_get_softc(device_t dev);
 device_state_t	device_get_state(device_t dev);
 int	device_get_unit(device_t dev);
+struct sysctl_ctx_list *device_get_sysctl_ctx(device_t dev);
+struct sysctl_oid *device_get_sysctl_tree(device_t dev);
 int	device_is_alive(device_t dev);	/* did probe succeed? */
 int	device_is_attached(device_t dev);	/* did attach succeed? */
 int	device_is_enabled(device_t dev);
Index: sys/sys/sysctl.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/sysctl.h,v
retrieving revision 1.124
diff -u -r1.124 sysctl.h
--- sys/sys/sysctl.h	26 Feb 2004 00:27:03 -0000	1.124
+++ sys/sys/sysctl.h	26 Feb 2004 13:30:25 -0000
@@ -52,7 +52,7 @@
  * respective subsystem header files.
  */
 
-#define CTL_MAXNAME	12	/* largest number of components supported */
+#define CTL_MAXNAME	24	/* largest number of components supported */
 
 /*
  * Each subsystem defined by sysctl defines a list of variables

--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment; filename=ndis.diff

Index: sys/compat/ndis/kern_ndis.c
===================================================================
RCS file: /home/ncvs/src/sys/compat/ndis/kern_ndis.c,v
retrieving revision 1.39
diff -u -r1.39 kern_ndis.c
--- sys/compat/ndis/kern_ndis.c	14 Feb 2004 20:57:32 -0000	1.39
+++ sys/compat/ndis/kern_ndis.c	26 Feb 2004 16:05:07 -0000
@@ -585,6 +585,8 @@
 ndis_create_sysctls(arg)
 	void			*arg;
 {
+	struct sysctl_ctx_list	*sysctl_ctx;
+	struct sysctl_oid	*sysctl_tree;
 	struct ndis_softc	*sc;
 	ndis_cfg		*vals;
 	char			buf[256];
@@ -597,12 +599,8 @@
 
 	TAILQ_INIT(&sc->ndis_cfglist_head);
 
-	/* Create the sysctl tree. */
-
-	sc->ndis_tree = SYSCTL_ADD_NODE(&sc->ndis_ctx,
-	    SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO,
-	    device_get_nameunit(sc->ndis_dev), CTLFLAG_RD, 0,
-	    device_get_desc(sc->ndis_dev));
+	sysctl_ctx = device_get_sysctl_ctx(sc->ndis_dev);
+	sysctl_tree = device_get_sysctl_tree(sc->ndis_dev);
 
 	/* Add the driver-specific registry keys. */
 
@@ -614,8 +612,8 @@
 			vals++;
 			continue;
 		}
-		SYSCTL_ADD_STRING(&sc->ndis_ctx,
-		    SYSCTL_CHILDREN(sc->ndis_tree),
+		SYSCTL_ADD_STRING(sysctl_ctx,
+		    SYSCTL_CHILDREN(sysctl_tree),
 		    OID_AUTO, vals->nc_cfgkey,
 		    CTLFLAG_RW, vals->nc_val,
 		    sizeof(vals->nc_val),
@@ -684,7 +682,8 @@
 
 	TAILQ_INSERT_TAIL(&sc->ndis_cfglist_head, cfg, link);
 
-	SYSCTL_ADD_STRING(&sc->ndis_ctx, SYSCTL_CHILDREN(sc->ndis_tree),
+	SYSCTL_ADD_STRING(device_get_sysctl_ctx(sc->ndis_dev),
+	    SYSCTL_CHILDREN(device_get_sysctl_tree(sc->ndis_dev)),
 	    OID_AUTO, cfg->ndis_cfg.nc_cfgkey, flag,
 	    cfg->ndis_cfg.nc_val, sizeof(cfg->ndis_cfg.nc_val),
 	    cfg->ndis_cfg.nc_cfgdesc);
Index: sys/compat/ndis/subr_ndis.c
===================================================================
RCS file: /home/ncvs/src/sys/compat/ndis/subr_ndis.c,v
retrieving revision 1.48
diff -u -r1.48 subr_ndis.c
--- sys/compat/ndis/subr_ndis.c	16 Feb 2004 02:50:03 -0000	1.48
+++ sys/compat/ndis/subr_ndis.c	26 Feb 2004 15:49:19 -0000
@@ -582,7 +582,7 @@
 	 * See if registry key is already in a list of known keys
 	 * included with the driver.
 	 */
-	TAILQ_FOREACH(e, &sc->ndis_ctx, link) {
+	TAILQ_FOREACH(e, device_get_sysctl_ctx(sc->ndis_dev), link) {
 		oidp = e->entry;
 		if (strcmp(oidp->oid_name, keystr) == 0) {
 			if (strcmp((char *)oidp->oid_arg1, "UNSET") == 0) {
@@ -678,7 +678,7 @@
 
 	/* See if the key already exists. */
 
-	TAILQ_FOREACH(e, &sc->ndis_ctx, link) {
+	TAILQ_FOREACH(e, device_get_sysctl_ctx(sc->ndis_dev), link) {
 		oidp = e->entry;
 		if (strcmp(oidp->oid_name, keystr) == 0) {
 			/* Found it, set the value. */
Index: sys/dev/if_ndis/if_ndis.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/if_ndis/if_ndis.c,v
retrieving revision 1.42
diff -u -r1.42 if_ndis.c
--- sys/dev/if_ndis/if_ndis.c	11 Feb 2004 21:53:40 -0000	1.42
+++ sys/dev/if_ndis/if_ndis.c	26 Feb 2004 15:44:52 -0000
@@ -43,7 +43,6 @@
 #include <sys/kernel.h>
 #include <sys/socket.h>
 #include <sys/queue.h>
-#include <sys/sysctl.h>
 
 #include <net/if.h>
 #include <net/if_arp.h>
@@ -586,8 +585,6 @@
 	else
 		sc->ndis_devidx = devidx;
 
-	sysctl_ctx_init(&sc->ndis_ctx);
-
 	/* Create sysctl registry nodes */
 	ndis_create_sysctls(sc);
 
@@ -948,8 +945,6 @@
 	ndis_unload_driver((void *)ifp);
 
 	bus_dma_tag_destroy(sc->ndis_parent_tag);
-
-	sysctl_ctx_free(&sc->ndis_ctx);
 
 	return(0);
 }
Index: sys/dev/if_ndis/if_ndisvar.h
===================================================================
RCS file: /home/ncvs/src/sys/dev/if_ndis/if_ndisvar.h,v
retrieving revision 1.10
diff -u -r1.10 if_ndisvar.h
--- sys/dev/if_ndis/if_ndisvar.h	27 Jan 2004 09:08:12 -0000	1.10
+++ sys/dev/if_ndis/if_ndisvar.h	26 Feb 2004 15:44:46 -0000
@@ -104,8 +104,6 @@
 	int			ndis_if_flags;
 	int			ndis_skip;
 
-	struct sysctl_ctx_list	ndis_ctx;
-	struct sysctl_oid	*ndis_tree;
 	int			ndis_devidx;
 	interface_type		ndis_iftype;
 

--=-=-=--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?xzpk729lnq7.fsf>