git: ee15875c0159 - main - stand/kshim: Update for devclass being removed from DRIVER_MODULE

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Sat, 11 Jan 2025 04:03:50 UTC
The branch main has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=ee15875c01593b287e55147c482b914e3ab01152

commit ee15875c01593b287e55147c482b914e3ab01152
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2025-01-11 04:01:48 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2025-01-11 04:03:32 +0000

    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
---
 stand/kshim/bsd_kernel.c         | 140 ++++++++++++++++++---------------------
 stand/kshim/bsd_kernel.h         |  11 +--
 stand/usb/storage/umass_common.c |   4 +-
 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)