git: 11a9117871e6 - main - Use bus_generic_detach to detach and delete child devices during detach

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

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

commit 11a9117871e6037ae7b8011b243939322efce569
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2025-01-02 18:25:12 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2025-01-02 18:25:12 +0000

    Use bus_generic_detach to detach and delete child devices during detach
    
    This is simpler and more robust than individual calls to
    device_delete_child.
    
    Differential Revision:  https://reviews.freebsd.org/D47972
---
 sys/arm/ti/twl/twl.c              |  8 ++++----
 sys/dev/aac/aac.c                 | 10 ++++------
 sys/dev/aacraid/aacraid.c         |  7 ++++---
 sys/dev/alpm/alpm.c               |  9 +++++----
 sys/dev/amdpm/amdpm.c             |  8 ++++----
 sys/dev/amdsmb/amdsmb.c           |  8 ++++----
 sys/dev/cas/if_cas.c              |  2 +-
 sys/dev/enetc/if_enetc.c          |  3 +--
 sys/dev/gem/if_gem.c              |  2 +-
 sys/dev/mgb/if_mgb.c              |  3 +--
 sys/dev/mlx/mlx.c                 | 14 ++++----------
 sys/dev/nfsmb/nfsmb.c             | 21 ++++++++-------------
 sys/dev/puc/puc.c                 | 18 ++++++++----------
 sys/dev/sound/pci/hda/hdac.c      | 15 +++------------
 sys/dev/usb/net/usb_ethernet.c    |  8 +++-----
 sys/dev/virtio/mmio/virtio_mmio.c | 10 +++-------
 sys/dev/virtio/pci/virtio_pci.c   | 12 ++++--------
 sys/dev/xilinx/if_xae.c           |  3 +--
 18 files changed, 63 insertions(+), 98 deletions(-)

diff --git a/sys/arm/ti/twl/twl.c b/sys/arm/ti/twl/twl.c
index 3a7a0ddcb0b1..ee54b0ea1f2c 100644
--- a/sys/arm/ti/twl/twl.c
+++ b/sys/arm/ti/twl/twl.c
@@ -425,13 +425,13 @@ static int
 twl_detach(device_t dev)
 {
 	struct twl_softc *sc;
+	int error;
 
 	sc = device_get_softc(dev);
 
-	if (sc->sc_vreg)
-		device_delete_child(dev, sc->sc_vreg);
-	if (sc->sc_clks)
-		device_delete_child(dev, sc->sc_clks);
+	error = bus_generic_detach(dev);
+	if (error != 0)
+		return (error);
 
 	TWL_LOCK_DESTROY(sc);
 
diff --git a/sys/dev/aac/aac.c b/sys/dev/aac/aac.c
index 12f5eb50426b..912b3dc903e3 100644
--- a/sys/dev/aac/aac.c
+++ b/sys/dev/aac/aac.c
@@ -669,6 +669,10 @@ aac_detach(device_t dev)
 	sc = device_get_softc(dev);
 	fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
 
+	error = bus_generic_detach(dev);
+	if (error != 0)
+		return (error);
+
 	callout_drain(&sc->aac_daemontime);
 
 	mtx_lock(&sc->aac_io_lock);
@@ -683,9 +687,6 @@ aac_detach(device_t dev)
 
 	/* Remove the child containers */
 	while ((co = TAILQ_FIRST(&sc->aac_container_tqh)) != NULL) {
-		error = device_delete_child(dev, co->co_disk);
-		if (error)
-			return (error);
 		TAILQ_REMOVE(&sc->aac_container_tqh, co, co_link);
 		free(co, M_AACBUF);
 	}
@@ -693,9 +694,6 @@ aac_detach(device_t dev)
 	/* Remove the CAM SIMs */
 	while ((sim = TAILQ_FIRST(&sc->aac_sim_tqh)) != NULL) {
 		TAILQ_REMOVE(&sc->aac_sim_tqh, sim, sim_link);
-		error = device_delete_child(dev, sim->sim_dev);
-		if (error)
-			return (error);
 		free(sim, M_AACBUF);
 	}
 
diff --git a/sys/dev/aacraid/aacraid.c b/sys/dev/aacraid/aacraid.c
index 9e9b1c602b9d..90a073d10039 100644
--- a/sys/dev/aacraid/aacraid.c
+++ b/sys/dev/aacraid/aacraid.c
@@ -739,6 +739,10 @@ aacraid_detach(device_t dev)
 	sc = device_get_softc(dev);
 	fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
 
+	error = bus_generic_detach(dev);
+	if (error != 0)
+		return (error);
+
 	callout_drain(&sc->aac_daemontime);
 	/* Remove the child containers */
 	while ((co = TAILQ_FIRST(&sc->aac_container_tqh)) != NULL) {
@@ -749,9 +753,6 @@ aacraid_detach(device_t dev)
 	/* Remove the CAM SIMs */
 	while ((sim = TAILQ_FIRST(&sc->aac_sim_tqh)) != NULL) {
 		TAILQ_REMOVE(&sc->aac_sim_tqh, sim, sim_link);
-		error = device_delete_child(dev, sim->sim_dev);
-		if (error)
-			return (error);
 		free(sim, M_AACRAIDBUF);
 	}
 
diff --git a/sys/dev/alpm/alpm.c b/sys/dev/alpm/alpm.c
index 46dc85ebc485..d7c3d3657d3b 100644
--- a/sys/dev/alpm/alpm.c
+++ b/sys/dev/alpm/alpm.c
@@ -232,11 +232,12 @@ static int
 alpm_detach(device_t dev)
 {
 	struct alpm_softc *alpm = device_get_softc(dev);
+	int error;
+
+	error = bus_generic_detach(dev);
+	if (error != 0)
+		return (error);
 
-	if (alpm->smbus) {
-		device_delete_child(dev, alpm->smbus);
-		alpm->smbus = NULL;
-	}
 	mtx_destroy(&alpm->lock);
 
 	if (alpm->res)
diff --git a/sys/dev/amdpm/amdpm.c b/sys/dev/amdpm/amdpm.c
index 22b252f572b0..d744c0aa5d4b 100644
--- a/sys/dev/amdpm/amdpm.c
+++ b/sys/dev/amdpm/amdpm.c
@@ -229,11 +229,11 @@ static int
 amdpm_detach(device_t dev)
 {
 	struct amdpm_softc *amdpm_sc = device_get_softc(dev);
+	int error;
 
-	if (amdpm_sc->smbus) {
-		device_delete_child(dev, amdpm_sc->smbus);
-		amdpm_sc->smbus = NULL;
-	}
+	error = bus_generic_detach(dev);
+	if (error != 0)
+		return (error);
 
 	mtx_destroy(&amdpm_sc->lock);
 	if (amdpm_sc->res)
diff --git a/sys/dev/amdsmb/amdsmb.c b/sys/dev/amdsmb/amdsmb.c
index 00e2f979b6cc..3d2e7a5e0c19 100644
--- a/sys/dev/amdsmb/amdsmb.c
+++ b/sys/dev/amdsmb/amdsmb.c
@@ -174,11 +174,11 @@ static int
 amdsmb_detach(device_t dev)
 {
 	struct amdsmb_softc *amdsmb_sc = device_get_softc(dev);
+	int error;
 
-	if (amdsmb_sc->smbus) {
-		device_delete_child(dev, amdsmb_sc->smbus);
-		amdsmb_sc->smbus = NULL;
-	}
+	error = bus_generic_detach(dev);
+	if (error != 0)
+		return (error);
 
 	mtx_destroy(&amdsmb_sc->lock);
 	if (amdsmb_sc->res)
diff --git a/sys/dev/cas/if_cas.c b/sys/dev/cas/if_cas.c
index 1f684097bd3a..fed2c3a3a051 100644
--- a/sys/dev/cas/if_cas.c
+++ b/sys/dev/cas/if_cas.c
@@ -477,7 +477,7 @@ cas_detach(struct cas_softc *sc)
 	taskqueue_drain(sc->sc_tq, &sc->sc_tx_task);
 	if_free(ifp);
 	taskqueue_free(sc->sc_tq);
-	device_delete_child(sc->sc_dev, sc->sc_miibus);
+	bus_generic_detach(sc->sc_dev);
 
 	for (i = 0; i < CAS_NRXDESC; i++)
 		if (sc->sc_rxdsoft[i].rxds_dmamap != NULL)
diff --git a/sys/dev/enetc/if_enetc.c b/sys/dev/enetc/if_enetc.c
index 3c0bc4723b05..3a5d6ec23282 100644
--- a/sys/dev/enetc/if_enetc.c
+++ b/sys/dev/enetc/if_enetc.c
@@ -459,8 +459,7 @@ enetc_detach(if_ctx_t ctx)
 	for (i = 0; i < sc->rx_num_queues; i++)
 		iflib_irq_free(ctx, &sc->rx_queues[i].irq);
 
-	if (sc->miibus != NULL)
-		device_delete_child(sc->dev, sc->miibus);
+	bus_generic_detach(sc->dev);
 
 	if (sc->regs != NULL)
 		error = bus_release_resource(sc->dev, SYS_RES_MEMORY,
diff --git a/sys/dev/gem/if_gem.c b/sys/dev/gem/if_gem.c
index 434c5309d019..74504a950d31 100644
--- a/sys/dev/gem/if_gem.c
+++ b/sys/dev/gem/if_gem.c
@@ -413,7 +413,7 @@ gem_detach(struct gem_softc *sc)
 	callout_drain(&sc->sc_rx_ch);
 #endif
 	if_free(ifp);
-	device_delete_child(sc->sc_dev, sc->sc_miibus);
+	bus_generic_detach(sc->sc_dev);
 
 	for (i = 0; i < GEM_NRXDESC; i++)
 		if (sc->sc_rxsoft[i].rxs_dmamap != NULL)
diff --git a/sys/dev/mgb/if_mgb.c b/sys/dev/mgb/if_mgb.c
index 05c4c242f739..1240d0f84415 100644
--- a/sys/dev/mgb/if_mgb.c
+++ b/sys/dev/mgb/if_mgb.c
@@ -482,8 +482,7 @@ mgb_detach(if_ctx_t ctx)
 	iflib_irq_free(ctx, &sc->rx_irq);
 	iflib_irq_free(ctx, &sc->admin_irq);
 
-	if (sc->miibus != NULL)
-		device_delete_child(sc->dev, sc->miibus);
+	bus_generic_detach(sc->dev);
 
 	if (sc->pba != NULL)
 		error = bus_release_resource(sc->dev, SYS_RES_MEMORY,
diff --git a/sys/dev/mlx/mlx.c b/sys/dev/mlx/mlx.c
index d9a2a1f5442b..f0c7591803e0 100644
--- a/sys/dev/mlx/mlx.c
+++ b/sys/dev/mlx/mlx.c
@@ -642,7 +642,7 @@ mlx_shutdown(device_t dev)
 static int
 mlx_shutdown_locked(struct mlx_softc *sc)
 {
-    int			i, error;
+    int			error;
 
     debug_called(1);
 
@@ -660,17 +660,11 @@ mlx_shutdown_locked(struct mlx_softc *sc)
 	printf("done\n");
     }
     MLX_IO_UNLOCK(sc);
-    
+
     /* delete all our child devices */
-    for (i = 0; i < MLX_MAXDRIVES; i++) {
-	if (sc->mlx_sysdrive[i].ms_disk != 0) {
-	    if ((error = device_delete_child(sc->mlx_dev, sc->mlx_sysdrive[i].ms_disk)) != 0)
-		return (error);
-	    sc->mlx_sysdrive[i].ms_disk = 0;
-	}
-    }
+    error = bus_generic_detach(sc->mlx_dev);
 
-    return (0);
+    return (error);
 }
 
 /********************************************************************************
diff --git a/sys/dev/nfsmb/nfsmb.c b/sys/dev/nfsmb/nfsmb.c
index 462f90264885..b88b2ca0001f 100644
--- a/sys/dev/nfsmb/nfsmb.c
+++ b/sys/dev/nfsmb/nfsmb.c
@@ -275,13 +275,13 @@ nfsmbsub_detach(device_t dev)
 {
 	device_t parent;
 	struct nfsmb_softc *nfsmbsub_sc = device_get_softc(dev);
+	int error;
 
 	parent = device_get_parent(dev);
 
-	if (nfsmbsub_sc->smbus) {
-		device_delete_child(dev, nfsmbsub_sc->smbus);
-		nfsmbsub_sc->smbus = NULL;
-	}
+	error = bus_generic_detach(dev);
+	if (error != 0)
+		return (error);
 	mtx_destroy(&nfsmbsub_sc->lock);
 	if (nfsmbsub_sc->res) {
 		bus_release_resource(parent, SYS_RES_IOPORT, nfsmbsub_sc->rid,
@@ -295,16 +295,11 @@ static int
 nfsmb_detach(device_t dev)
 {
 	struct nfsmb_softc *nfsmb_sc = device_get_softc(dev);
+	int error;
 
-	if (nfsmb_sc->subdev) {
-		device_delete_child(dev, nfsmb_sc->subdev);
-		nfsmb_sc->subdev = NULL;
-	}
-
-	if (nfsmb_sc->smbus) {
-		device_delete_child(dev, nfsmb_sc->smbus);
-		nfsmb_sc->smbus = NULL;
-	}
+	error = bus_generic_detach(dev);
+	if (error != 0)
+		return (error);
 
 	mtx_destroy(&nfsmb_sc->lock);
 	if (nfsmb_sc->res) {
diff --git a/sys/dev/puc/puc.c b/sys/dev/puc/puc.c
index 01193acf85b4..e10d0374c7de 100644
--- a/sys/dev/puc/puc.c
+++ b/sys/dev/puc/puc.c
@@ -409,21 +409,19 @@ puc_bfe_detach(device_t dev)
 	sc = device_get_softc(dev);
 
 	/* Detach our children. */
-	error = 0;
+	error = bus_generic_detach(dev);
+	if (error != 0)
+		return (error);
+
 	for (idx = 0; idx < sc->sc_nports; idx++) {
 		port = &sc->sc_port[idx];
 		if (port->p_dev == NULL)
 			continue;
-		if (device_delete_child(dev, port->p_dev) == 0) {
-			if (port->p_rres != NULL)
-				rman_release_resource(port->p_rres);
-			if (port->p_ires != NULL)
-				rman_release_resource(port->p_ires);
-		} else
-			error = ENXIO;
+		if (port->p_rres != NULL)
+			rman_release_resource(port->p_rres);
+		if (port->p_ires != NULL)
+			rman_release_resource(port->p_ires);
 	}
-	if (error)
-		return (error);
 
 	if (sc->sc_serdevs != 0UL)
 		bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie);
diff --git a/sys/dev/sound/pci/hda/hdac.c b/sys/dev/sound/pci/hda/hdac.c
index c9b11de01d18..4f9f70d98cb6 100644
--- a/sys/dev/sound/pci/hda/hdac.c
+++ b/sys/dev/sound/pci/hda/hdac.c
@@ -1740,20 +1740,11 @@ static int
 hdac_detach(device_t dev)
 {
 	struct hdac_softc *sc = device_get_softc(dev);
-	device_t *devlist;
-	int cad, i, devcount, error;
+	int i, error;
 
-	if ((error = device_get_children(dev, &devlist, &devcount)) != 0)
+	error = bus_generic_detach(dev);
+	if (error != 0)
 		return (error);
-	for (i = 0; i < devcount; i++) {
-		cad = (intptr_t)device_get_ivars(devlist[i]);
-		if ((error = device_delete_child(dev, devlist[i])) != 0) {
-			free(devlist, M_TEMP);
-			return (error);
-		}
-		sc->codecs[cad].dev = NULL;
-	}
-	free(devlist, M_TEMP);
 
 	hdac_lock(sc);
 	hdac_reset(sc, false);
diff --git a/sys/dev/usb/net/usb_ethernet.c b/sys/dev/usb/net/usb_ethernet.c
index 2f423f557569..977805cefe66 100644
--- a/sys/dev/usb/net/usb_ethernet.c
+++ b/sys/dev/usb/net/usb_ethernet.c
@@ -315,11 +315,9 @@ uether_ifdetach(struct usb_ether *ue)
 		ether_ifdetach(ifp);
 
 		/* detach miibus */
-		if (ue->ue_miibus != NULL) {
-			bus_topo_lock();
-			device_delete_child(ue->ue_dev, ue->ue_miibus);
-			bus_topo_unlock();
-		}
+		bus_topo_lock();
+		bus_generic_detach(ue->ue_dev);
+		bus_topo_unlock();
 
 		/* free interface instance */
 		if_free(ifp);
diff --git a/sys/dev/virtio/mmio/virtio_mmio.c b/sys/dev/virtio/mmio/virtio_mmio.c
index b1a4230f7b46..175b33b42ed8 100644
--- a/sys/dev/virtio/mmio/virtio_mmio.c
+++ b/sys/dev/virtio/mmio/virtio_mmio.c
@@ -292,17 +292,13 @@ static int
 vtmmio_detach(device_t dev)
 {
 	struct vtmmio_softc *sc;
-	device_t child;
 	int error;
 
 	sc = device_get_softc(dev);
 
-	if ((child = sc->vtmmio_child_dev) != NULL) {
-		error = device_delete_child(dev, child);
-		if (error)
-			return (error);
-		sc->vtmmio_child_dev = NULL;
-	}
+	error = bus_generic_detach(dev);
+	if (error)
+		return (error);
 
 	vtmmio_reset(sc);
 
diff --git a/sys/dev/virtio/pci/virtio_pci.c b/sys/dev/virtio/pci/virtio_pci.c
index fc26d62543c1..b7b34b448f6e 100644
--- a/sys/dev/virtio/pci/virtio_pci.c
+++ b/sys/dev/virtio/pci/virtio_pci.c
@@ -182,18 +182,14 @@ vtpci_add_child(struct vtpci_common *cn)
 int
 vtpci_delete_child(struct vtpci_common *cn)
 {
-	device_t dev, child;
+	device_t dev;
 	int error;
 
 	dev = cn->vtpci_dev;
 
-	child = cn->vtpci_child_dev;
-	if (child != NULL) {
-		error = device_delete_child(dev, child);
-		if (error)
-			return (error);
-		cn->vtpci_child_dev = NULL;
-	}
+	error = bus_generic_detach(dev);
+	if (error)
+		return (error);
 
 	return (0);
 }
diff --git a/sys/dev/xilinx/if_xae.c b/sys/dev/xilinx/if_xae.c
index 26f1bf805ffa..080b13606525 100644
--- a/sys/dev/xilinx/if_xae.c
+++ b/sys/dev/xilinx/if_xae.c
@@ -1052,8 +1052,7 @@ xae_detach(device_t dev)
 		ether_ifdetach(ifp);
 	}
 
-	if (sc->miibus != NULL)
-		device_delete_child(dev, sc->miibus);
+	bus_generic_detach(dev);
 
 	if (ifp != NULL)
 		if_free(ifp);