git: 3ddaf8200bc9 - main - Use bus_generic_detach instead of device_delete_children in detach

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Thu, 02 Jan 2025 18:28:30 UTC
The branch main has been updated by jhb:

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

commit 3ddaf8200bc90b1410755ebac7b5c979ea90a2f6
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2025-01-02 18:24:28 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2025-01-02 18:24:28 +0000

    Use bus_generic_detach instead of device_delete_children in detach
    
    While here, check for errors from bus_generic_detach and move it to
    the start of detach if necessary.
    
    Differential Revision:  https://reviews.freebsd.org/D47969
---
 sys/arm/freescale/vybrid/vf_ehci.c          |  2 +-
 sys/arm/mv/a37x0_spi.c                      |  2 +-
 sys/arm/nvidia/tegra_ehci.c                 | 10 +++++-----
 sys/arm/nvidia/tegra_xhci.c                 |  6 +++++-
 sys/arm/ti/am335x/am335x_musb.c             |  5 ++++-
 sys/arm/ti/usb/omap_ehci.c                  |  4 +++-
 sys/arm/ti/usb/omap_host.c                  |  5 ++++-
 sys/arm/xilinx/zy7_ehci.c                   |  5 ++++-
 sys/dev/ahci/ahci.c                         |  6 ++++--
 sys/dev/ata/ata-pci.c                       |  5 ++++-
 sys/dev/atopcase/atopcase.c                 |  2 +-
 sys/dev/etherswitch/e6000sw/e6000sw.c       |  8 +++++---
 sys/dev/hyperv/input/hv_hid.c               |  2 +-
 sys/dev/iicbus/iicbus.c                     |  2 +-
 sys/dev/iicbus/iichid.c                     |  2 +-
 sys/dev/intel/spi.c                         |  7 ++++++-
 sys/dev/mmc/host/dwmmc.c                    |  2 +-
 sys/dev/mvs/mvs_pci.c                       |  5 ++++-
 sys/dev/mvs/mvs_soc.c                       |  5 ++++-
 sys/dev/neta/if_mvneta.c                    |  2 +-
 sys/dev/ow/owc_gpiobus.c                    |  2 +-
 sys/dev/p2sb/p2sb.c                         |  6 +++++-
 sys/dev/ppc/ppc.c                           |  5 ++++-
 sys/dev/rtsx/rtsx.c                         |  4 ++--
 sys/dev/siis/siis.c                         |  5 ++++-
 sys/dev/sound/pci/hda/hdaa.c                |  2 +-
 sys/dev/sound/pci/hda/hdacc.c               |  2 +-
 sys/dev/sound/pci/hdsp.c                    |  2 +-
 sys/dev/sound/pci/hdspe.c                   |  2 +-
 sys/dev/spibus/spibus.c                     |  2 +-
 sys/dev/usb/controller/dwc_otg_acpi.c       |  5 ++++-
 sys/dev/usb/controller/dwc_otg_fdt.c        |  5 ++++-
 sys/dev/usb/controller/ehci_fsl.c           | 14 +++++---------
 sys/dev/usb/controller/ehci_imx.c           |  2 +-
 sys/dev/usb/controller/ehci_msm.c           | 10 +++-------
 sys/dev/usb/controller/ehci_mv.c            |  4 +++-
 sys/dev/usb/controller/ehci_pci.c           |  5 ++++-
 sys/dev/usb/controller/generic_ehci.c       |  4 +++-
 sys/dev/usb/controller/generic_ohci.c       |  4 +++-
 sys/dev/usb/controller/generic_xhci.c       |  4 +++-
 sys/dev/usb/controller/musb_otg_allwinner.c | 13 ++++---------
 sys/dev/usb/controller/ohci_pci.c           |  5 ++++-
 sys/dev/usb/controller/uhci_pci.c           |  5 ++++-
 sys/dev/usb/controller/xhci_pci.c           |  5 ++++-
 sys/dev/usb/input/usbhid.c                  |  6 +++++-
 sys/dev/usb/video/udl.c                     |  5 ++++-
 46 files changed, 139 insertions(+), 76 deletions(-)

diff --git a/sys/arm/freescale/vybrid/vf_ehci.c b/sys/arm/freescale/vybrid/vf_ehci.c
index a3477c743997..3a8b48008449 100644
--- a/sys/arm/freescale/vybrid/vf_ehci.c
+++ b/sys/arm/freescale/vybrid/vf_ehci.c
@@ -386,7 +386,7 @@ vybrid_ehci_detach(device_t dev)
 	sc = &esc->base;
 
 	/* First detach all children; we can't detach if that fails. */
-	if ((err = device_delete_children(dev)) != 0)
+	if ((err = bus_generic_detach(dev)) != 0)
 		return (err);
 
 	/*
diff --git a/sys/arm/mv/a37x0_spi.c b/sys/arm/mv/a37x0_spi.c
index bc47da2f3e6e..027dd57677a3 100644
--- a/sys/arm/mv/a37x0_spi.c
+++ b/sys/arm/mv/a37x0_spi.c
@@ -227,7 +227,7 @@ a37x0_spi_detach(device_t dev)
 	int err;
 	struct a37x0_spi_softc *sc;
 
-	if ((err = device_delete_children(dev)) != 0)
+	if ((err = bus_generic_detach(dev)) != 0)
 		return (err);
 	sc = device_get_softc(dev);
 	mtx_destroy(&sc->sc_mtx);
diff --git a/sys/arm/nvidia/tegra_ehci.c b/sys/arm/nvidia/tegra_ehci.c
index 15f086a6c3c0..59bf8646385a 100644
--- a/sys/arm/nvidia/tegra_ehci.c
+++ b/sys/arm/nvidia/tegra_ehci.c
@@ -113,14 +113,17 @@ tegra_ehci_detach(device_t dev)
 {
 	struct tegra_ehci_softc *sc;
 	ehci_softc_t *esc;
+	int error;
+
+	error = bus_generic_detach(dev);
+	if (error != 0)
+		return (error);
 
 	sc = device_get_softc(dev);
 
 	esc = &sc->ehci_softc;
 	if (sc->clk != NULL)
 		clk_release(sc->clk);
-	if (esc->sc_bus.bdev != NULL)
-		device_delete_child(dev, esc->sc_bus.bdev);
 	if (esc->sc_flags & EHCI_SCFLG_DONEINIT)
 		ehci_detach(esc);
 	if (esc->sc_intr_hdl != NULL)
@@ -135,9 +138,6 @@ tegra_ehci_detach(device_t dev)
 	if (sc->usb_alloc_called)
 		usb_bus_mem_free_all(&esc->sc_bus, &ehci_iterate_hw_softc);
 
-	/* During module unload there are lots of children leftover. */
-	device_delete_children(dev);
-
 	return (0);
 }
 
diff --git a/sys/arm/nvidia/tegra_xhci.c b/sys/arm/nvidia/tegra_xhci.c
index e3b4dd483189..474e31981770 100644
--- a/sys/arm/nvidia/tegra_xhci.c
+++ b/sys/arm/nvidia/tegra_xhci.c
@@ -916,12 +916,16 @@ tegra_xhci_detach(device_t dev)
 {
 	struct tegra_xhci_softc *sc;
 	struct xhci_softc *xsc;
+	int error;
 
 	sc = device_get_softc(dev);
 	xsc = &sc->xhci_softc;
 
 	/* during module unload there are lots of children leftover */
-	device_delete_children(dev);
+	error = bus_generic_detach(dev);
+	if (error != 0)
+		return (error);
+
 	if (sc->xhci_inited) {
 		usb_callout_drain(&xsc->sc_callout);
 		xhci_halt_controller(xsc);
diff --git a/sys/arm/ti/am335x/am335x_musb.c b/sys/arm/ti/am335x/am335x_musb.c
index 147602c4dbd3..24a204e42c9c 100644
--- a/sys/arm/ti/am335x/am335x_musb.c
+++ b/sys/arm/ti/am335x/am335x_musb.c
@@ -404,9 +404,12 @@ static int
 musbotg_detach(device_t dev)
 {
 	struct musbotg_super_softc *sc = device_get_softc(dev);
+	int error;
 
 	/* during module unload there are lots of children leftover */
-	device_delete_children(dev);
+	error = bus_generic_detach(dev);
+	if (error != 0)
+		return (error);
 
 	if (sc->sc_otg.sc_irq_res && sc->sc_otg.sc_intr_hdl) {
 		/*
diff --git a/sys/arm/ti/usb/omap_ehci.c b/sys/arm/ti/usb/omap_ehci.c
index fee5f662963b..224c786bf9fa 100644
--- a/sys/arm/ti/usb/omap_ehci.c
+++ b/sys/arm/ti/usb/omap_ehci.c
@@ -406,7 +406,9 @@ omap_ehci_detach(device_t dev)
 	int err;
 
 	/* during module unload there are lots of children leftover */
-	device_delete_children(dev);
+	err = bus_generic_detach(dev);
+	if (err != 0)
+		return (err);
 
 	/*
 	 * disable interrupts that might have been switched on in ehci_init
diff --git a/sys/arm/ti/usb/omap_host.c b/sys/arm/ti/usb/omap_host.c
index b7c387c00601..c336a25eabf3 100644
--- a/sys/arm/ti/usb/omap_host.c
+++ b/sys/arm/ti/usb/omap_host.c
@@ -432,9 +432,12 @@ static int
 omap_uhh_detach(device_t dev)
 {
 	struct omap_uhh_softc *isc = device_get_softc(dev);
+	int error;
 
 	/* during module unload there are lots of children leftover */
-	device_delete_children(dev);
+	error = bus_generic_detach(dev);
+	if (error != 0)
+		return (error);
 
 	if (isc->uhh_mem_res) {
 		bus_release_resource(dev, SYS_RES_MEMORY, 0, isc->uhh_mem_res);
diff --git a/sys/arm/xilinx/zy7_ehci.c b/sys/arm/xilinx/zy7_ehci.c
index f2e1d8a9ec2b..545e2a9bce16 100644
--- a/sys/arm/xilinx/zy7_ehci.c
+++ b/sys/arm/xilinx/zy7_ehci.c
@@ -315,9 +315,12 @@ static int
 zy7_ehci_detach(device_t dev)
 {
 	ehci_softc_t *sc = device_get_softc(dev);
+	int error;
 
 	/* during module unload there are lots of children leftover */
-	device_delete_children(dev);
+	error = bus_generic_detach(dev);
+	if (error != 0)
+		return (error);
 
 	if ((sc->sc_flags & EHCI_SCFLG_DONEINIT) != 0) {
 		ehci_detach(sc);
diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c
index d64ec8caa13f..d5ce503f62ee 100644
--- a/sys/dev/ahci/ahci.c
+++ b/sys/dev/ahci/ahci.c
@@ -391,10 +391,12 @@ int
 ahci_detach(device_t dev)
 {
 	struct ahci_controller *ctlr = device_get_softc(dev);
-	int i;
+	int error, i;
 
 	/* Detach & delete all children */
-	device_delete_children(dev);
+	error = bus_generic_detach(dev);
+	if (error != 0)
+		return (error);
 
 	/* Free interrupts. */
 	for (i = 0; i < ctlr->numirqs; i++) {
diff --git a/sys/dev/ata/ata-pci.c b/sys/dev/ata/ata-pci.c
index 8c22bb6ff427..6d8b8fb3aad1 100644
--- a/sys/dev/ata/ata-pci.c
+++ b/sys/dev/ata/ata-pci.c
@@ -134,9 +134,12 @@ int
 ata_pci_detach(device_t dev)
 {
     struct ata_pci_controller *ctlr = device_get_softc(dev);
+    int error;
 
     /* detach & delete all children */
-    device_delete_children(dev);
+    error = bus_generic_detach(dev);
+    if (error != 0)
+	return (error);
 
     if (ctlr->r_irq) {
 	bus_teardown_intr(dev, ctlr->r_irq, ctlr->handle);
diff --git a/sys/dev/atopcase/atopcase.c b/sys/dev/atopcase/atopcase.c
index e4e248f7ce0a..9e64b389c9e3 100644
--- a/sys/dev/atopcase/atopcase.c
+++ b/sys/dev/atopcase/atopcase.c
@@ -545,7 +545,7 @@ atopcase_destroy(struct atopcase_softc *sc)
 {
 	int err;
 
-	err = device_delete_children(sc->sc_dev);
+	err = bus_generic_detach(sc->sc_dev);
 	if (err)
 		return (err);
 
diff --git a/sys/dev/etherswitch/e6000sw/e6000sw.c b/sys/dev/etherswitch/e6000sw/e6000sw.c
index e79082759593..cb71fa5b0e88 100644
--- a/sys/dev/etherswitch/e6000sw/e6000sw.c
+++ b/sys/dev/etherswitch/e6000sw/e6000sw.c
@@ -845,19 +845,21 @@ e6000sw_writephy_locked(device_t dev, int phy, int reg, int data)
 static int
 e6000sw_detach(device_t dev)
 {
-	int phy;
+	int error, phy;
 	e6000sw_softc_t *sc;
 
 	sc = device_get_softc(dev);
 
+	error = bus_generic_detach(dev);
+	if (error != 0)
+		return (error);
+
 	if (device_is_attached(dev))
 		taskqueue_drain_timeout(sc->sc_tq, &sc->sc_tt);
 
 	if (sc->sc_tq != NULL)
 		taskqueue_free(sc->sc_tq);
 
-	device_delete_children(dev);
-
 	sx_destroy(&sc->sx);
 	for (phy = 0; phy < sc->num_ports; phy++) {
 		if (sc->ifp[phy] != NULL)
diff --git a/sys/dev/hyperv/input/hv_hid.c b/sys/dev/hyperv/input/hv_hid.c
index c54bc43c0f24..a26c46184442 100644
--- a/sys/dev/hyperv/input/hv_hid.c
+++ b/sys/dev/hyperv/input/hv_hid.c
@@ -457,7 +457,7 @@ hv_hid_detach(device_t dev)
 	int		ret;
 
 	sc = device_get_softc(dev);
-	ret = device_delete_children(dev);
+	ret = bus_generic_detach(dev);
 	if (ret != 0)
 		return (ret);
 	if (sc->hs_xact_ctx != NULL)
diff --git a/sys/dev/iicbus/iicbus.c b/sys/dev/iicbus/iicbus.c
index 97dc9c437866..0894ddddb8e8 100644
--- a/sys/dev/iicbus/iicbus.c
+++ b/sys/dev/iicbus/iicbus.c
@@ -144,7 +144,7 @@ iicbus_detach(device_t dev)
 	struct iicbus_softc *sc = IICBUS_SOFTC(dev);
 	int err;
 
-	if ((err = device_delete_children(dev)) != 0)
+	if ((err = bus_generic_detach(dev)) != 0)
 		return (err);
 	iicbus_reset(dev, IIC_FASTEST, 0, NULL);
 	mtx_destroy(&sc->lock);
diff --git a/sys/dev/iicbus/iichid.c b/sys/dev/iicbus/iichid.c
index ed016fa0e0cc..346d432a74b5 100644
--- a/sys/dev/iicbus/iichid.c
+++ b/sys/dev/iicbus/iichid.c
@@ -1218,7 +1218,7 @@ iichid_detach(device_t dev)
 	int error;
 
 	sc = device_get_softc(dev);
-	error = device_delete_children(dev);
+	error = bus_generic_detach(dev);
 	if (error)
 		return (error);
 	iichid_teardown_interrupt(sc);
diff --git a/sys/dev/intel/spi.c b/sys/dev/intel/spi.c
index 4c45ef7863a7..9a0d4305227d 100644
--- a/sys/dev/intel/spi.c
+++ b/sys/dev/intel/spi.c
@@ -550,9 +550,14 @@ int
 intelspi_detach(device_t dev)
 {
 	struct intelspi_softc	*sc;
+	int error;
 
 	sc = device_get_softc(dev);
 
+	error = bus_generic_detach(dev);
+	if (error != 0)
+		return (error);
+
 	INTELSPI_LOCK_DESTROY(sc);
 
 	if (sc->sc_irq_ih)
@@ -566,7 +571,7 @@ intelspi_detach(device_t dev)
 		bus_release_resource(dev, SYS_RES_IRQ,
 		    sc->sc_irq_rid, sc->sc_irq_res);
 
-	return (device_delete_children(dev));
+	return (0);
 }
 
 int
diff --git a/sys/dev/mmc/host/dwmmc.c b/sys/dev/mmc/host/dwmmc.c
index f39a2033f64c..51709bcbb7e9 100644
--- a/sys/dev/mmc/host/dwmmc.c
+++ b/sys/dev/mmc/host/dwmmc.c
@@ -778,7 +778,7 @@ dwmmc_detach(device_t dev)
 
 	sc = device_get_softc(dev);
 
-	ret = device_delete_children(dev);
+	ret = bus_generic_detach(dev);
 	if (ret != 0)
 		return (ret);
 
diff --git a/sys/dev/mvs/mvs_pci.c b/sys/dev/mvs/mvs_pci.c
index 9743328d9593..9dfb5e3bbedd 100644
--- a/sys/dev/mvs/mvs_pci.c
+++ b/sys/dev/mvs/mvs_pci.c
@@ -176,9 +176,12 @@ static int
 mvs_detach(device_t dev)
 {
 	struct mvs_controller *ctlr = device_get_softc(dev);
+	int error;
 
 	/* Detach & delete all children */
-	device_delete_children(dev);
+	error = bus_generic_detach(dev);
+	if (error != 0)
+		return (error);
 
 	/* Free interrupt. */
 	if (ctlr->irq.r_irq) {
diff --git a/sys/dev/mvs/mvs_soc.c b/sys/dev/mvs/mvs_soc.c
index 41f2bf648c9d..8712dc0123e8 100644
--- a/sys/dev/mvs/mvs_soc.c
+++ b/sys/dev/mvs/mvs_soc.c
@@ -180,9 +180,12 @@ static int
 mvs_detach(device_t dev)
 {
 	struct mvs_controller *ctlr = device_get_softc(dev);
+	int error;
 
 	/* Detach & delete all children */
-	device_delete_children(dev);
+	error = bus_generic_detach(dev);
+	if (error != 0)
+		return (error);
 
 	/* Free interrupt. */
 	if (ctlr->irq.r_irq) {
diff --git a/sys/dev/neta/if_mvneta.c b/sys/dev/neta/if_mvneta.c
index 84cbc1e43462..1c6247adb56b 100644
--- a/sys/dev/neta/if_mvneta.c
+++ b/sys/dev/neta/if_mvneta.c
@@ -843,7 +843,7 @@ mvneta_detach(device_t dev)
 	for (q = 0; q < MVNETA_TX_QNUM_MAX; q++)
 		mvneta_ring_dealloc_tx_queue(sc, q);
 
-	device_delete_children(dev);
+	bus_generic_detach(dev);
 
 	if (sc->ih_cookie[0] != NULL)
 		bus_teardown_intr(dev, sc->res[1], sc->ih_cookie[0]);
diff --git a/sys/dev/ow/owc_gpiobus.c b/sys/dev/ow/owc_gpiobus.c
index 231902e02536..f010a4dc75f1 100644
--- a/sys/dev/ow/owc_gpiobus.c
+++ b/sys/dev/ow/owc_gpiobus.c
@@ -146,7 +146,7 @@ owc_gpiobus_detach(device_t dev)
 
 	sc = device_get_softc(dev);
 
-	if ((err = device_delete_children(dev)) != 0)
+	if ((err = bus_generic_detach(dev)) != 0)
 		return (err);
 
 	gpio_pin_release(sc->sc_pin);
diff --git a/sys/dev/p2sb/p2sb.c b/sys/dev/p2sb/p2sb.c
index 941e35469c69..950ee4e86866 100644
--- a/sys/dev/p2sb/p2sb.c
+++ b/sys/dev/p2sb/p2sb.c
@@ -159,9 +159,13 @@ static int
 p2sb_detach(device_t dev)
 {
 	struct p2sb_softc *sc;
+	int error;
 
 	/* Teardown the state in our softc created in our attach routine. */
-	device_delete_children(dev);
+	error = bus_generic_detach(dev);
+	if (error != 0)
+		return (error);
+
 	sc = device_get_softc(dev);
 	mtx_destroy(&sc->mutex);
 	if (sc->res != NULL)
diff --git a/sys/dev/ppc/ppc.c b/sys/dev/ppc/ppc.c
index 020043732222..9870379e2eba 100644
--- a/sys/dev/ppc/ppc.c
+++ b/sys/dev/ppc/ppc.c
@@ -1815,13 +1815,16 @@ int
 ppc_detach(device_t dev)
 {
 	struct ppc_data *ppc = DEVTOSOFTC(dev);
+	int error;
 
 	if (ppc->res_irq == 0) {
 		return (ENXIO);
 	}
 
 	/* detach & delete all children */
-	device_delete_children(dev);
+	error = bus_generic_detach(dev);
+	if (error != 0)
+		return (error);
 
 	if (ppc->res_irq != 0) {
 		bus_teardown_intr(dev, ppc->res_irq, ppc->intr_cookie);
diff --git a/sys/dev/rtsx/rtsx.c b/sys/dev/rtsx/rtsx.c
index a293d5e12e5e..f06b493e0c15 100644
--- a/sys/dev/rtsx/rtsx.c
+++ b/sys/dev/rtsx/rtsx.c
@@ -3784,10 +3784,10 @@ rtsx_detach(device_t dev)
 	WRITE4(sc, RTSX_BIER, sc->rtsx_intr_enabled);
 
 	/* Stop device. */
-	error = device_delete_children(sc->rtsx_dev);
-	sc->rtsx_mmc_dev = NULL;
+	error = bus_generic_detach(sc->rtsx_dev);
 	if (error)
 		return (error);
+	sc->rtsx_mmc_dev = NULL;
 
 	taskqueue_drain_timeout(taskqueue_swi_giant, &sc->rtsx_card_insert_task);
 	taskqueue_drain(taskqueue_swi_giant, &sc->rtsx_card_remove_task);
diff --git a/sys/dev/siis/siis.c b/sys/dev/siis/siis.c
index 4cc78ed57323..df11b36ec844 100644
--- a/sys/dev/siis/siis.c
+++ b/sys/dev/siis/siis.c
@@ -203,9 +203,12 @@ static int
 siis_detach(device_t dev)
 {
 	struct siis_controller *ctlr = device_get_softc(dev);
+	int error;
 
 	/* Detach & delete all children */
-	device_delete_children(dev);
+	error = bus_generic_detach(dev);
+	if (error != 0)
+		return (error);
 
 	/* Free interrupts. */
 	if (ctlr->irq.r_irq) {
diff --git a/sys/dev/sound/pci/hda/hdaa.c b/sys/dev/sound/pci/hda/hdaa.c
index 2fab3ae014d1..51d6e024225f 100644
--- a/sys/dev/sound/pci/hda/hdaa.c
+++ b/sys/dev/sound/pci/hda/hdaa.c
@@ -6684,7 +6684,7 @@ hdaa_detach(device_t dev)
 	struct hdaa_devinfo *devinfo = device_get_softc(dev);
 	int error;
 
-	if ((error = device_delete_children(dev)) != 0)
+	if ((error = bus_generic_detach(dev)) != 0)
 		return (error);
 
 	hdaa_lock(devinfo);
diff --git a/sys/dev/sound/pci/hda/hdacc.c b/sys/dev/sound/pci/hda/hdacc.c
index c79e9297025c..76aeaec757a5 100644
--- a/sys/dev/sound/pci/hda/hdacc.c
+++ b/sys/dev/sound/pci/hda/hdacc.c
@@ -541,7 +541,7 @@ hdacc_detach(device_t dev)
 	struct hdacc_softc *codec = device_get_softc(dev);
 	int error;
 
-	if ((error = device_delete_children(dev)) != 0)
+	if ((error = bus_generic_detach(dev)) != 0)
 		return (error);
 	free(codec->fgs, M_HDACC);
 	return (0);
diff --git a/sys/dev/sound/pci/hdsp.c b/sys/dev/sound/pci/hdsp.c
index ac343928b26b..4712d78ea88b 100644
--- a/sys/dev/sound/pci/hdsp.c
+++ b/sys/dev/sound/pci/hdsp.c
@@ -985,7 +985,7 @@ hdsp_detach(device_t dev)
 		return (0);
 	}
 
-	err = device_delete_children(dev);
+	err = bus_generic_detach(dev);
 	if (err)
 		return (err);
 
diff --git a/sys/dev/sound/pci/hdspe.c b/sys/dev/sound/pci/hdspe.c
index 4b5c31801d55..c292b2ddef56 100644
--- a/sys/dev/sound/pci/hdspe.c
+++ b/sys/dev/sound/pci/hdspe.c
@@ -877,7 +877,7 @@ hdspe_detach(device_t dev)
 		return (0);
 	}
 
-	err = device_delete_children(dev);
+	err = bus_generic_detach(dev);
 	if (err)
 		return (err);
 
diff --git a/sys/dev/spibus/spibus.c b/sys/dev/spibus/spibus.c
index 9251bd0c2962..f082b9ec171a 100644
--- a/sys/dev/spibus/spibus.c
+++ b/sys/dev/spibus/spibus.c
@@ -68,7 +68,7 @@ spibus_attach(device_t dev)
 int
 spibus_detach(device_t dev)
 {
-	return (device_delete_children(dev));
+	return (bus_generic_detach(dev));
 }
 
 static int
diff --git a/sys/dev/usb/controller/dwc_otg_acpi.c b/sys/dev/usb/controller/dwc_otg_acpi.c
index 9b982dfd6e41..5d509911a54a 100644
--- a/sys/dev/usb/controller/dwc_otg_acpi.c
+++ b/sys/dev/usb/controller/dwc_otg_acpi.c
@@ -127,9 +127,12 @@ static int
 dwc_otg_detach(device_t dev)
 {
 	struct dwc_otg_softc *sc = device_get_softc(dev);
+	int error;
 
 	/* during module unload there are lots of children leftover */
-	device_delete_children(dev);
+	error = bus_generic_detach(dev);
+	if (error != 0)
+		return (error);
 
 	if (sc->sc_irq_res && sc->sc_intr_hdl) {
 		/*
diff --git a/sys/dev/usb/controller/dwc_otg_fdt.c b/sys/dev/usb/controller/dwc_otg_fdt.c
index d692638857c5..3d5dcb9e9a7b 100644
--- a/sys/dev/usb/controller/dwc_otg_fdt.c
+++ b/sys/dev/usb/controller/dwc_otg_fdt.c
@@ -162,9 +162,12 @@ int
 dwc_otg_detach(device_t dev)
 {
 	struct dwc_otg_fdt_softc *sc = device_get_softc(dev);
+	int error;
 
 	/* during module unload there are lots of children leftover */
-	device_delete_children(dev);
+	error = bus_generic_detach(dev);
+	if (error != 0)
+		return (error);
 
 	if (sc->sc_otg.sc_irq_res && sc->sc_otg.sc_intr_hdl) {
 		/*
diff --git a/sys/dev/usb/controller/ehci_fsl.c b/sys/dev/usb/controller/ehci_fsl.c
index 49d23996b696..ed3d4c64f4f8 100644
--- a/sys/dev/usb/controller/ehci_fsl.c
+++ b/sys/dev/usb/controller/ehci_fsl.c
@@ -372,10 +372,14 @@ fsl_ehci_attach(device_t self)
 static int
 fsl_ehci_detach(device_t self)
 {
-
 	int err;
 	ehci_softc_t *sc;
 
+	/* During module unload there are lots of children leftover */
+	err = bus_generic_detach(self);
+	if (err != 0)
+		return (err);
+
 	sc = device_get_softc(self);
 	/*
 	 * only call ehci_detach() after ehci_init()
@@ -399,14 +403,6 @@ fsl_ehci_detach(device_t self)
 		sc->sc_intr_hdl = NULL;
 	}
 
-	if (sc->sc_bus.bdev) {
-		device_delete_child(self, sc->sc_bus.bdev);
-		sc->sc_bus.bdev = NULL;
-	}
-
-	/* During module unload there are lots of children leftover */
-	device_delete_children(self);
-
 	if (sc->sc_irq_res) {
 		bus_release_resource(self, SYS_RES_IRQ, 0, sc->sc_irq_res);
 		sc->sc_irq_res = NULL;
diff --git a/sys/dev/usb/controller/ehci_imx.c b/sys/dev/usb/controller/ehci_imx.c
index 0ab9bf0ed6f2..caba6b7da85a 100644
--- a/sys/dev/usb/controller/ehci_imx.c
+++ b/sys/dev/usb/controller/ehci_imx.c
@@ -314,7 +314,7 @@ imx_ehci_detach(device_t dev)
 	esc = &sc->ehci_softc;
 
 	/* First detach all children; we can't detach if that fails. */
-	if ((err = device_delete_children(dev)) != 0)
+	if ((err = bus_generic_detach(dev)) != 0)
 		return (err);
 
 	if (esc->sc_flags & EHCI_SCFLG_DONEINIT)
diff --git a/sys/dev/usb/controller/ehci_msm.c b/sys/dev/usb/controller/ehci_msm.c
index c628d5bf8fde..7f06ad6a1600 100644
--- a/sys/dev/usb/controller/ehci_msm.c
+++ b/sys/dev/usb/controller/ehci_msm.c
@@ -171,13 +171,9 @@ ehci_msm_detach(device_t dev)
 
 	sc = device_get_softc(dev);
 
-	if (sc->sc_bus.bdev) {
-		bdev = sc->sc_bus.bdev;
-		device_detach(bdev);
-		device_delete_child(dev, bdev);
-	}
-
-	device_delete_children(dev);
+	err = bus_generic_detach(dev);
+	if (err != 0)
+		return (err);
 
 	if (sc->sc_irq_res && sc->sc_intr_hdl) {
 		/* only call ehci_detach() after ehci_init() */
diff --git a/sys/dev/usb/controller/ehci_mv.c b/sys/dev/usb/controller/ehci_mv.c
index 5535cb061949..817cd68257c8 100644
--- a/sys/dev/usb/controller/ehci_mv.c
+++ b/sys/dev/usb/controller/ehci_mv.c
@@ -283,7 +283,9 @@ mv_ehci_detach(device_t self)
 	int err;
 
 	/* during module unload there are lots of children leftover */
-	device_delete_children(self);
+	err = bus_generic_detach(self);
+	if (err != 0)
+		return (err);
 
 	/*
 	 * disable interrupts that might have been switched on in mv_ehci_attach
diff --git a/sys/dev/usb/controller/ehci_pci.c b/sys/dev/usb/controller/ehci_pci.c
index 5141548bf793..bc75669a8d20 100644
--- a/sys/dev/usb/controller/ehci_pci.c
+++ b/sys/dev/usb/controller/ehci_pci.c
@@ -505,9 +505,12 @@ static int
 ehci_pci_detach(device_t self)
 {
 	ehci_softc_t *sc = device_get_softc(self);
+	int error;
 
 	/* during module unload there are lots of children leftover */
-	device_delete_children(self);
+	error = bus_generic_detach(self);
+	if (error != 0)
+		return (error);
 
 	pci_disable_busmaster(self);
 
diff --git a/sys/dev/usb/controller/generic_ehci.c b/sys/dev/usb/controller/generic_ehci.c
index e660a338df64..35a9564631e0 100644
--- a/sys/dev/usb/controller/generic_ehci.c
+++ b/sys/dev/usb/controller/generic_ehci.c
@@ -139,7 +139,9 @@ generic_ehci_detach(device_t self)
 	int err;
 
 	/* during module unload there are lots of children leftover */
-	device_delete_children(self);
+	err = bus_generic_detach(self);
+	if (err != 0)
+		return (err);
 
 	if (sc->sc_irq_res && sc->sc_intr_hdl) {
 		/*
diff --git a/sys/dev/usb/controller/generic_ohci.c b/sys/dev/usb/controller/generic_ohci.c
index fe4493fda977..5c0de59074d2 100644
--- a/sys/dev/usb/controller/generic_ohci.c
+++ b/sys/dev/usb/controller/generic_ohci.c
@@ -231,7 +231,9 @@ generic_ohci_detach(device_t dev)
 	struct hwrst_list *rst, *rst_tmp;
 
 	/* during module unload there are lots of children leftover */
-	device_delete_children(dev);
+	err = bus_generic_detach(dev);
+	if (err != 0)
+		return (err);
 
 	/*
 	 * Put the controller into reset, then disable clocks and do
diff --git a/sys/dev/usb/controller/generic_xhci.c b/sys/dev/usb/controller/generic_xhci.c
index 95551aafa519..f64e1fd01ba0 100644
--- a/sys/dev/usb/controller/generic_xhci.c
+++ b/sys/dev/usb/controller/generic_xhci.c
@@ -152,7 +152,9 @@ generic_xhci_detach(device_t dev)
 	int err;
 
 	/* during module unload there are lots of children leftover */
-	device_delete_children(dev);
+	err = bus_generic_detach(dev);
+	if (err != 0)
+		return (err);
 
 	if (sc->sc_irq_res != NULL && sc->sc_intr_hdl != NULL) {
 		err = bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_intr_hdl);
diff --git a/sys/dev/usb/controller/musb_otg_allwinner.c b/sys/dev/usb/controller/musb_otg_allwinner.c
index c52b381fd16a..574e8e712713 100644
--- a/sys/dev/usb/controller/musb_otg_allwinner.c
+++ b/sys/dev/usb/controller/musb_otg_allwinner.c
@@ -561,16 +561,13 @@ static int
 awusbdrd_detach(device_t dev)
 {
 	struct awusbdrd_softc *sc;
-	device_t bdev;
 	int error;
 
-	sc = device_get_softc(dev);
+	error = bus_generic_detach(dev);
+	if (error != 0)
+		return (error);
 
-	if (sc->sc.sc_bus.bdev != NULL) {
-		bdev = sc->sc.sc_bus.bdev;
-		device_detach(bdev);
-		device_delete_child(dev, bdev);
-	}
+	sc = device_get_softc(dev);
 
 	musbotg_uninit(&sc->sc);
 	error = bus_teardown_intr(dev, sc->res[1], sc->sc.sc_intr_hdl);
@@ -594,8 +591,6 @@ awusbdrd_detach(device_t dev)
 
 	bus_release_resources(dev, awusbdrd_spec, sc->res);
 
-	device_delete_children(dev);
-
 	return (0);
 }
 
diff --git a/sys/dev/usb/controller/ohci_pci.c b/sys/dev/usb/controller/ohci_pci.c
index 03291ff34a6f..027be4ce9588 100644
--- a/sys/dev/usb/controller/ohci_pci.c
+++ b/sys/dev/usb/controller/ohci_pci.c
@@ -320,9 +320,12 @@ static int
 ohci_pci_detach(device_t self)
 {
 	ohci_softc_t *sc = device_get_softc(self);
+	int error;
 
 	/* during module unload there are lots of children leftover */
-	device_delete_children(self);
+	error = bus_generic_detach(self);
+	if (error != 0)
+		return (error);
 
 	pci_disable_busmaster(self);
 
diff --git a/sys/dev/usb/controller/uhci_pci.c b/sys/dev/usb/controller/uhci_pci.c
index 90f3dca8f830..0dc2763aed8d 100644
--- a/sys/dev/usb/controller/uhci_pci.c
+++ b/sys/dev/usb/controller/uhci_pci.c
@@ -414,9 +414,12 @@ int
 uhci_pci_detach(device_t self)
 {
 	uhci_softc_t *sc = device_get_softc(self);
+	int error;
 
 	/* during module unload there are lots of children leftover */
-	device_delete_children(self);
+	error = bus_generic_detach(self);
+	if (error != 0)
+		return (error);
 
 	/*
 	 * disable interrupts that might have been switched on in
diff --git a/sys/dev/usb/controller/xhci_pci.c b/sys/dev/usb/controller/xhci_pci.c
index 6f128f1d2fa7..c436f60aefcf 100644
--- a/sys/dev/usb/controller/xhci_pci.c
+++ b/sys/dev/usb/controller/xhci_pci.c
@@ -465,9 +465,12 @@ static int
 xhci_pci_detach(device_t self)
 {
 	struct xhci_softc *sc = device_get_softc(self);
+	int error;
 
 	/* during module unload there are lots of children leftover */
-	device_delete_children(self);
+	error = bus_generic_detach(self);
+	if (error != 0)
+		return (error);
 
 	usb_callout_drain(&sc->sc_callout);
 	xhci_halt_controller(sc);
diff --git a/sys/dev/usb/input/usbhid.c b/sys/dev/usb/input/usbhid.c
index d357a699b527..e88588182ae5 100644
--- a/sys/dev/usb/input/usbhid.c
+++ b/sys/dev/usb/input/usbhid.c
@@ -851,8 +851,12 @@ static int
 usbhid_detach(device_t dev)
 {
 	struct usbhid_softc *sc = device_get_softc(dev);
+	int error;
+
+	error = bus_generic_detach(dev);
+	if (error != 0)
+		return (error);
 
-	device_delete_children(dev);
 	mtx_destroy(&sc->sc_mtx);
 
 	return (0);
diff --git a/sys/dev/usb/video/udl.c b/sys/dev/usb/video/udl.c
index b5af3be8bc50..213f1f5bb957 100644
--- a/sys/dev/usb/video/udl.c
+++ b/sys/dev/usb/video/udl.c
@@ -441,9 +441,12 @@ static int
 udl_detach(device_t dev)
 {
 	struct udl_softc *sc = device_get_softc(dev);
+	int error;
 
 	/* delete all child devices */
-	device_delete_children(dev);
+	error = bus_generic_detach(dev);
+	if (error != 0)
+		return (error);
 
 	UDL_LOCK(sc);
 	sc->sc_gone = 1;