aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2025-01-11 04:01:48 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2025-01-11 04:03:32 +0000
commitee15875c01593b287e55147c482b914e3ab01152 (patch)
treee096fce95690cbe398a9fda6dca656af1d458476
parent4378bd382ea0f5707099273b1fa2393979a22628 (diff)
stand/kshim: Update for devclass being removed from DRIVER_MODULE
The kshim code abused the devclass argument to DRIVER_MODULE in some odd ways. Instead, refactor the devclass handling to more closely mirror what new-bus does in the kernel by having a linked list of devclasses looked up by name and associate devices with a devclass. Devices are now only associated with a module while probing and attaching. Reviewed by: imp, markj Differential Revision: https://reviews.freebsd.org/D48409
-rw-r--r--stand/kshim/bsd_kernel.c140
-rw-r--r--stand/kshim/bsd_kernel.h11
-rw-r--r--stand/usb/storage/umass_common.c4
3 files changed, 71 insertions, 84 deletions
diff --git a/stand/kshim/bsd_kernel.c b/stand/kshim/bsd_kernel.c
index fb1b4239fd03..78b6f9e0b4d4 100644
--- a/stand/kshim/bsd_kernel.c
+++ b/stand/kshim/bsd_kernel.c
@@ -554,6 +554,8 @@ static const char unknown_string[] = { "unknown" };
static TAILQ_HEAD(, module_data) module_head =
TAILQ_HEAD_INITIALIZER(module_head);
+static TAILQ_HEAD(, devclass) devclasses =
+ TAILQ_HEAD_INITIALIZER(devclasses);
static uint8_t
devclass_equal(const char *a, const char *b)
@@ -686,58 +688,50 @@ device_get_nameunit(device_t dev)
return (unknown_string);
}
-static uint8_t
-devclass_create(devclass_t *dc_pp)
+static devclass_t
+devclass_create(const char *classname)
{
- if (dc_pp == NULL) {
- return (1);
- }
- if (dc_pp[0] == NULL) {
- dc_pp[0] = malloc(sizeof(**(dc_pp)),
- M_DEVBUF, M_WAITOK | M_ZERO);
+ devclass_t dc;
- if (dc_pp[0] == NULL) {
- return (1);
- }
+ dc = malloc(sizeof(*dc), M_DEVBUF, M_WAITOK | M_ZERO);
+ if (dc == NULL) {
+ return (NULL);
}
- return (0);
+ dc->name = classname;
+ TAILQ_INSERT_TAIL(&devclasses, dc, link);
+ return (dc);
}
-static const struct module_data *
+static devclass_t
devclass_find_create(const char *classname)
{
- const struct module_data *mod;
+ devclass_t dc;
- TAILQ_FOREACH(mod, &module_head, entry) {
- if (devclass_equal(mod->mod_name, classname)) {
- if (devclass_create(mod->devclass_pp)) {
- continue;
- }
- return (mod);
- }
- }
- return (NULL);
+ dc = devclass_find(classname);
+ if (dc == NULL)
+ dc = devclass_create(classname);
+ return (dc);
}
static uint8_t
-devclass_add_device(const struct module_data *mod, device_t dev)
+devclass_add_device(devclass_t dc, device_t dev)
{
device_t *pp_dev;
device_t *end;
uint8_t unit;
- pp_dev = mod->devclass_pp[0]->dev_list;
+ pp_dev = dc->dev_list;
end = pp_dev + DEVCLASS_MAXUNIT;
unit = 0;
while (pp_dev != end) {
if (*pp_dev == NULL) {
*pp_dev = dev;
+ dev->dev_class = dc;
dev->dev_unit = unit;
- dev->dev_module = mod;
snprintf(dev->dev_nameunit,
sizeof(dev->dev_nameunit),
- "%s%d", device_get_name(dev), unit);
+ "%s%d", dc->name, unit);
return (0);
}
pp_dev++;
@@ -748,26 +742,26 @@ devclass_add_device(const struct module_data *mod, device_t dev)
}
static void
-devclass_delete_device(const struct module_data *mod, device_t dev)
+devclass_delete_device(devclass_t dc, device_t dev)
{
- if (mod == NULL) {
+ if (dc == NULL) {
return;
}
- mod->devclass_pp[0]->dev_list[dev->dev_unit] = NULL;
- dev->dev_module = NULL;
+ dc->dev_list[dev->dev_unit] = NULL;
+ dev->dev_class = NULL;
}
static device_t
make_device(device_t parent, const char *name)
{
device_t dev = NULL;
- const struct module_data *mod = NULL;
+ devclass_t dc = NULL;
if (name) {
- mod = devclass_find_create(name);
+ dc = devclass_find_create(name);
- if (!mod) {
+ if (!dc) {
DPRINTF("%s:%d:%s: can't find device "
"class %s\n", __FILE__, __LINE__,
@@ -787,7 +781,7 @@ make_device(device_t parent, const char *name)
if (name) {
dev->dev_fixed_class = 1;
- if (devclass_add_device(mod, dev)) {
+ if (devclass_add_device(dc, dev)) {
goto error;
}
}
@@ -843,7 +837,8 @@ device_delete_child(device_t dev, device_t child)
}
}
- devclass_delete_device(child->dev_module, child);
+ if (child->dev_class != NULL)
+ devclass_delete_device(child->dev_class, child);
if (dev != NULL) {
/* remove child from parent */
@@ -911,7 +906,7 @@ device_get_method(device_t dev, const char *what)
const char *
device_get_name(device_t dev)
{
- if (dev == NULL)
+ if (dev == NULL || dev->dev_module == NULL)
return (unknown_string);
return (dev->dev_module->driver->name);
@@ -942,16 +937,34 @@ device_probe_and_attach(device_t dev)
{
const struct module_data *mod;
const char *bus_name_parent;
-
- bus_name_parent = device_get_name(device_get_parent(dev));
+ devclass_t dc;
if (dev->dev_attached)
return (0); /* fail-safe */
- if (dev->dev_fixed_class) {
+ /*
+ * Find a module for our device, if any
+ */
+ bus_name_parent = device_get_name(device_get_parent(dev));
+
+ TAILQ_FOREACH(mod, &module_head, entry) {
+ if (!devclass_equal(mod->bus_name, bus_name_parent))
+ continue;
+
+ dc = devclass_find(mod->mod_name);
- mod = dev->dev_module;
+ /* Does this device need assigning to the new devclass? */
+ if (dev->dev_class != dc) {
+ if (dev->dev_fixed_class)
+ continue;
+ if (dev->dev_class != NULL)
+ devclass_delete_device(dev->dev_class, dev);
+ if (devclass_add_device(dc, dev)) {
+ continue;
+ }
+ }
+ dev->dev_module = mod;
if (DEVICE_PROBE(dev) <= 0) {
if (device_allocate_softc(dev) == 0) {
@@ -963,40 +976,11 @@ device_probe_and_attach(device_t dev)
}
}
}
- device_detach(dev);
+ /* else try next driver */
- goto error;
- }
- /*
- * Else find a module for our device, if any
- */
-
- TAILQ_FOREACH(mod, &module_head, entry) {
- if (devclass_equal(mod->bus_name, bus_name_parent)) {
- if (devclass_create(mod->devclass_pp)) {
- continue;
- }
- if (devclass_add_device(mod, dev)) {
- continue;
- }
- if (DEVICE_PROBE(dev) <= 0) {
-
- if (device_allocate_softc(dev) == 0) {
-
- if (DEVICE_ATTACH(dev) == 0) {
- /* success */
- dev->dev_attached = 1;
- return (0);
- }
- }
- }
- /* else try next driver */
-
- device_detach(dev);
- }
+ device_detach(dev);
}
-error:
return (ENODEV);
}
@@ -1015,9 +999,10 @@ device_detach(device_t dev)
dev->dev_attached = 0;
}
device_set_softc(dev, NULL);
+ dev->dev_module = NULL;
if (dev->dev_fixed_class == 0)
- devclass_delete_device(mod, dev);
+ devclass_delete_device(dev->dev_class, dev);
return (0);
}
@@ -1093,11 +1078,11 @@ devclass_get_device(devclass_t dc, int unit)
devclass_t
devclass_find(const char *classname)
{
- const struct module_data *mod;
+ devclass_t dc;
- TAILQ_FOREACH(mod, &module_head, entry) {
- if (devclass_equal(mod->driver->name, classname))
- return (mod->devclass_pp[0]);
+ TAILQ_FOREACH(dc, &devclasses, link) {
+ if (devclass_equal(dc->name, classname))
+ return (dc);
}
return (NULL);
}
@@ -1108,6 +1093,7 @@ module_register(void *data)
struct module_data *mdata = data;
TAILQ_INSERT_TAIL(&module_head, mdata, entry);
+ (void)devclass_find_create(mdata->mod_name);
}
/*------------------------------------------------------------------------*
diff --git a/stand/kshim/bsd_kernel.h b/stand/kshim/bsd_kernel.h
index 0b5d659951a2..8600bd1f31dc 100644
--- a/stand/kshim/bsd_kernel.h
+++ b/stand/kshim/bsd_kernel.h
@@ -87,11 +87,11 @@ struct sysctl_req {
#define MOD_UNLOAD 2
#define DEVMETHOD(what,func) { #what, (void *)&func }
#define DEVMETHOD_END {0,0}
-#define EARLY_DRIVER_MODULE(a, b, c, d, e, f, g) DRIVER_MODULE(a, b, c, d, e, f)
-#define DRIVER_MODULE(name, busname, driver, devclass, evh, arg) \
+#define EARLY_DRIVER_MODULE(a, b, c, d, e, f) DRIVER_MODULE(a, b, c, d, e)
+#define DRIVER_MODULE(name, busname, driver, evh, arg) \
static struct module_data bsd_##name##_##busname##_driver_mod = { \
evh, arg, #busname, #name, #busname "/" #name, \
- &driver, &devclass, { 0, 0 } }; \
+ &driver, { 0, 0 } }; \
SYSINIT(bsd_##name##_##busname##_driver_mod, SI_SUB_DRIVERS, \
SI_ORDER_MIDDLE, module_register, \
&bsd_##name##_##busname##_driver_mod)
@@ -135,6 +135,7 @@ SYSINIT_ENTRY(uniq##_entry, "sysuninit", (subs), \
#define cold 0
#define BUS_PROBE_GENERIC 0
#define BUS_PROBE_DEFAULT (-20)
+#define DEVICE_UNIT_ANY -1
#define CALLOUT_RETURNUNLOCKED 0x1
#undef ffs
#define ffs(x) __builtin_ffs(x)
@@ -406,6 +407,7 @@ struct device {
TAILQ_HEAD(device_list, device) dev_children;
TAILQ_ENTRY(device) dev_link;
+ devclass_t dev_class;
struct device *dev_parent;
const struct module_data *dev_module;
void *dev_sc;
@@ -429,6 +431,8 @@ struct device {
};
struct devclass {
+ TAILQ_ENTRY(devclass) link;
+ const char *name;
device_t dev_list[DEVCLASS_MAXUNIT];
};
@@ -445,7 +449,6 @@ struct module_data {
const char *mod_name;
const char *long_name;
const struct driver *driver;
- struct devclass **devclass_pp;
TAILQ_ENTRY(module_data) entry;
};
diff --git a/stand/usb/storage/umass_common.c b/stand/usb/storage/umass_common.c
index 639d70a7f7e6..b62412b13637 100644
--- a/stand/usb/storage/umass_common.c
+++ b/stand/usb/storage/umass_common.c
@@ -38,8 +38,6 @@ static device_probe_t umass_probe;
static device_attach_t umass_attach;
static device_detach_t umass_detach;
-static devclass_t umass_devclass;
-
static device_method_t umass_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, umass_probe),
@@ -54,7 +52,7 @@ static driver_t umass_driver = {
.methods = umass_methods,
};
-DRIVER_MODULE(umass, uhub, umass_driver, umass_devclass, NULL, 0);
+DRIVER_MODULE(umass, uhub, umass_driver, NULL, 0);
static int
umass_probe(device_t dev)