--- a/sys/bus/smbus/smbus.c +++ b/sys/bus/smbus/smbus.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -89,11 +90,24 @@ static int smbus_attach(device_t dev) { + device_t *devlist; + int nchildren; unsigned char addr; - device_add_child(dev, NULL, device_get_unit(dev)); - for (addr = 16; addr < 112; ++addr) { - smbus_probe_device(dev, addr); + /* + * Children survive driver teardown (devclass_delete_driver only + * detaches them, never deletes; subr_bus.c:888-897), so the bus + * must only be populated on FIRST attach. Re-creating the child + * set on every attach leaks struct bsd_device per cycle and mints + * duplicate remapped /dev/smbN[-XX] nodes on one physical bus. + */ + if (device_get_children(dev, &devlist, &nchildren) == 0) { + kfree(devlist, M_TEMP); + if (nchildren == 0) { + device_add_child(dev, NULL, device_get_unit(dev)); + for (addr = 16; addr < 112; ++addr) + smbus_probe_device(dev, addr); + } } /*bus_generic_probe(dev);*/ @@ -105,8 +119,17 @@ static int smbus_detach(device_t dev) { + struct smbus_softc *sc = (struct smbus_softc *)device_get_softc(dev); int error; + /* + * A client that owns the bus (or is parked waiting for it) still + * holds the softc in-flight; a successful detach would free the + * softc underneath it (device_set_driver, subr_bus.c:1941-1946). + */ + if (sc->owner != NULL) + return (EBUSY); + error = bus_generic_detach(dev); if (error) return (error);