As previously threatened, give each device its own sysctl context and
subtree (under the new dev top-level node). This should greatly simplify drivers which need per-device sysctl variables (such as ndis).
This commit is contained in:
parent
15f1cbdd6a
commit
5c1921b779
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=129711
@ -56,6 +56,7 @@ __FBSDID("$FreeBSD$");
|
||||
#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 @@ struct device {
|
||||
u_char pad;
|
||||
void *ivars;
|
||||
void *softc;
|
||||
|
||||
struct sysctl_ctx_list sysctl_ctx;
|
||||
struct sysctl_oid *sysctl_tree;
|
||||
};
|
||||
|
||||
struct device_op_desc {
|
||||
@ -184,6 +188,106 @@ void print_devclass_list(void);
|
||||
#define print_devclass_list() /* nop */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* dev sysctl tree
|
||||
*/
|
||||
|
||||
enum {
|
||||
DEVICE_SYSCTL_CLASS,
|
||||
DEVICE_SYSCTL_DESC,
|
||||
DEVICE_SYSCTL_DRIVER,
|
||||
DEVICE_SYSCTL_LOCATION,
|
||||
DEVICE_SYSCTL_PNPINFO,
|
||||
};
|
||||
|
||||
static int
|
||||
device_sysctl_handler(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
device_t dev = (device_t)arg1;
|
||||
const char *value;
|
||||
char *buf;
|
||||
int error;
|
||||
|
||||
buf = NULL;
|
||||
switch (arg2) {
|
||||
case DEVICE_SYSCTL_CLASS:
|
||||
value = dev->devclass ? dev->devclass->name : NULL;
|
||||
break;
|
||||
case DEVICE_SYSCTL_DESC:
|
||||
value = dev->desc;
|
||||
break;
|
||||
case DEVICE_SYSCTL_DRIVER:
|
||||
value = dev->driver ? dev->driver->name : NULL;
|
||||
break;
|
||||
case DEVICE_SYSCTL_LOCATION:
|
||||
value = buf = malloc(1024, M_BUS, M_WAITOK | M_ZERO);
|
||||
bus_child_location_str(dev, buf, 1024);
|
||||
break;
|
||||
case DEVICE_SYSCTL_PNPINFO:
|
||||
value = buf = malloc(1024, M_BUS, M_WAITOK | M_ZERO);
|
||||
bus_child_pnpinfo_str(dev, buf, 1024);
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
if (value == NULL)
|
||||
value = "?";
|
||||
error = SYSCTL_OUT(req, value, strlen(value));
|
||||
if (buf != NULL)
|
||||
free(buf, M_BUS);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static void
|
||||
device_sysctl_init(device_t dev)
|
||||
{
|
||||
struct sysctl_oid_list *parent_node;
|
||||
|
||||
if (dev->parent) {
|
||||
if (dev->parent->sysctl_tree == NULL)
|
||||
device_sysctl_init(dev->parent);
|
||||
parent_node = SYSCTL_CHILDREN(dev->parent->sysctl_tree);
|
||||
} else {
|
||||
parent_node = SYSCTL_STATIC_CHILDREN(_dev);
|
||||
}
|
||||
if (dev->sysctl_tree != NULL) {
|
||||
sysctl_move_oid(dev->sysctl_tree, parent_node);
|
||||
return;
|
||||
}
|
||||
sysctl_ctx_init(&dev->sysctl_ctx);
|
||||
dev->sysctl_tree = SYSCTL_ADD_NODE(&dev->sysctl_ctx, parent_node,
|
||||
OID_AUTO, dev->nameunit, CTLFLAG_RD, 0, "");
|
||||
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");
|
||||
SYSCTL_ADD_PROC(&dev->sysctl_ctx, SYSCTL_CHILDREN(dev->sysctl_tree),
|
||||
OID_AUTO, "%location", CTLFLAG_RD,
|
||||
dev, DEVICE_SYSCTL_LOCATION, device_sysctl_handler, "A",
|
||||
"device location relative to parent");
|
||||
SYSCTL_ADD_PROC(&dev->sysctl_ctx, SYSCTL_CHILDREN(dev->sysctl_tree),
|
||||
OID_AUTO, "%pnpinfo", CTLFLAG_RD,
|
||||
dev, DEVICE_SYSCTL_PNPINFO, device_sysctl_handler, "A",
|
||||
"device identification");
|
||||
}
|
||||
|
||||
static void
|
||||
device_sysctl_fini(device_t dev)
|
||||
{
|
||||
if (dev->sysctl_tree == NULL)
|
||||
return;
|
||||
sysctl_ctx_free(&dev->sysctl_ctx);
|
||||
dev->sysctl_tree = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* /dev/devctl implementation
|
||||
*/
|
||||
@ -1256,6 +1360,18 @@ device_get_flags(device_t dev)
|
||||
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)
|
||||
{
|
||||
@ -1497,48 +1613,55 @@ device_set_driver(device_t dev, driver_t *driver)
|
||||
int
|
||||
device_probe_and_attach(device_t dev)
|
||||
{
|
||||
device_t bus = dev->parent;
|
||||
int error = 0;
|
||||
int hasclass = (dev->devclass != 0);
|
||||
int error;
|
||||
|
||||
if (dev->state >= DS_ALIVE)
|
||||
return (0);
|
||||
|
||||
if (dev->flags & DF_ENABLED) {
|
||||
error = device_probe_child(bus, dev);
|
||||
if (!error) {
|
||||
if (!device_is_quiet(dev))
|
||||
device_print_child(bus, dev);
|
||||
error = DEVICE_ATTACH(dev);
|
||||
if (!error) {
|
||||
dev->state = DS_ATTACHED;
|
||||
devadded(dev);
|
||||
} else {
|
||||
printf("device_probe_and_attach: %s%d attach returned %d\n",
|
||||
dev->driver->name, dev->unit, error);
|
||||
/* Unset the class; set in device_probe_child */
|
||||
if (!hasclass)
|
||||
device_set_devclass(dev, 0);
|
||||
device_set_driver(dev, NULL);
|
||||
dev->state = DS_NOTPRESENT;
|
||||
}
|
||||
} else {
|
||||
if (!(dev->flags & DF_DONENOMATCH)) {
|
||||
BUS_PROBE_NOMATCH(bus, dev);
|
||||
devnomatch(dev);
|
||||
dev->flags |= DF_DONENOMATCH;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!(dev->flags & DF_ENABLED)) {
|
||||
if (bootverbose) {
|
||||
device_print_prettyname(dev);
|
||||
printf("not probed (disabled)\n");
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
if ((error = device_probe_child(dev->parent, dev)) != 0) {
|
||||
if (!(dev->flags & DF_DONENOMATCH)) {
|
||||
BUS_PROBE_NOMATCH(dev->parent, dev);
|
||||
devnomatch(dev);
|
||||
dev->flags |= DF_DONENOMATCH;
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
error = device_attach(dev);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
device_attach(device_t dev)
|
||||
{
|
||||
int error;
|
||||
|
||||
device_sysctl_init(dev);
|
||||
if (!device_is_quiet(dev))
|
||||
device_print_child(dev->parent, dev);
|
||||
if ((error = DEVICE_ATTACH(dev)) != 0) {
|
||||
printf("device_attach: %s%d attach returned %d\n",
|
||||
dev->driver->name, dev->unit, error);
|
||||
/* Unset the class; set in device_probe_child */
|
||||
if (dev->devclass == 0)
|
||||
device_set_devclass(dev, 0);
|
||||
device_set_driver(dev, NULL);
|
||||
device_sysctl_fini(dev);
|
||||
dev->state = DS_NOTPRESENT;
|
||||
return (error);
|
||||
}
|
||||
dev->state = DS_ATTACHED;
|
||||
devadded(dev);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
device_detach(device_t dev)
|
||||
{
|
||||
@ -1562,6 +1685,7 @@ device_detach(device_t dev)
|
||||
|
||||
dev->state = DS_NOTPRESENT;
|
||||
device_set_driver(dev, NULL);
|
||||
device_sysctl_fini(dev);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -323,6 +323,7 @@ device_t device_add_child_ordered(device_t dev, int order,
|
||||
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);
|
||||
@ -341,6 +342,8 @@ const char *device_get_nameunit(device_t dev);
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user