From d49decefc4b2c877d2492f227e3df371a6786065 Mon Sep 17 00:00:00 2001 From: hselasky Date: Sat, 19 Nov 2011 10:11:50 +0000 Subject: [PATCH 50/65] Move the device_delete_all_children() function from usb_util.c to kern/subr_bus.c. Simplify this function so that it no longer depends on malloc() to execute. Identify a few other places where it makes sense to use device_delete_all_children(). MFC after: 1 week git-svn-id: http://svn.freebsd.org/base/head@227701 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f (cherry picked from commit 87a03069e4672f03c4595b2d62338a14d4f59697) Signed-off-by: Xin Li --- sys/arm/xscale/ixp425/avila_ata.c | 8 +------- sys/dev/ahci/ahci.c | 10 +++------- sys/dev/ata/ata-disk.c | 9 +-------- sys/dev/ata/ata-pci.c | 9 ++------- sys/dev/gpio/gpiobus.c | 11 ++++------- sys/dev/mvs/mvs_pci.c | 9 ++------- sys/dev/mvs/mvs_soc.c | 9 ++------- sys/dev/ppbus/ppbconf.c | 10 ++-------- sys/dev/ppc/ppc.c | 9 +-------- sys/dev/siba/siba_core.c | 12 ++---------- sys/dev/siis/siis.c | 9 ++------- sys/dev/usb/usb_util.c | 25 ------------------------- sys/dev/usb/usb_util.h | 1 - sys/kern/subr_bus.c | 33 +++++++++++++++++++++++++++++++++ sys/sys/bus.h | 1 + 15 files changed, 56 insertions(+), 109 deletions(-) diff --git a/sys/arm/xscale/ixp425/avila_ata.c b/sys/arm/xscale/ixp425/avila_ata.c index 03a534f..7194d03 100644 --- a/sys/arm/xscale/ixp425/avila_ata.c +++ b/sys/arm/xscale/ixp425/avila_ata.c @@ -259,17 +259,11 @@ static int ata_avila_detach(device_t dev) { struct ata_avila_softc *sc = device_get_softc(dev); - device_t *children; - int nc; /* XXX quiesce gpio? */ /* detach & delete all children */ - if (device_get_children(dev, &children, &nc) == 0) { - if (nc > 0) - device_delete_child(dev, children[0]); - free(children, M_TEMP); - } + device_delete_all_children(dev); bus_teardown_intr(dev, sc->sc_irq, sc->sc_ih); bus_release_resource(dev, SYS_RES_IRQ, sc->sc_rid, sc->sc_irq); diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c index 0a20f2c..ec0749d 100644 --- a/sys/dev/ahci/ahci.c +++ b/sys/dev/ahci/ahci.c @@ -514,15 +514,11 @@ static int ahci_detach(device_t dev) { struct ahci_controller *ctlr = device_get_softc(dev); - device_t *children; - int nchildren, i; + int i; /* Detach & delete all children */ - if (!device_get_children(dev, &children, &nchildren)) { - for (i = 0; i < nchildren; i++) - device_delete_child(dev, children[i]); - free(children, M_TEMP); - } + device_delete_all_children(dev); + /* Free interrupts. */ for (i = 0; i < ctlr->numirqs; i++) { if (ctlr->irqs[i].r_irq) { diff --git a/sys/dev/ata/ata-disk.c b/sys/dev/ata/ata-disk.c index bcaf6c4..c872f62 100644 --- a/sys/dev/ata/ata-disk.c +++ b/sys/dev/ata/ata-disk.c @@ -172,8 +172,6 @@ ad_detach(device_t dev) { struct ad_softc *adp = device_get_ivars(dev); struct ata_device *atadev = device_get_softc(dev); - device_t *children; - int nchildren, i; /* check that we have a valid disk to detach */ if (!device_get_ivars(dev)) @@ -183,12 +181,7 @@ ad_detach(device_t dev) callout_drain(&atadev->spindown_timer); /* detach & delete all children */ - if (!device_get_children(dev, &children, &nchildren)) { - for (i = 0; i < nchildren; i++) - if (children[i]) - device_delete_child(dev, children[i]); - free(children, M_TEMP); - } + device_delete_all_children(dev); /* destroy disk from the system so we don't get any further requests */ disk_destroy(adp->disk); diff --git a/sys/dev/ata/ata-pci.c b/sys/dev/ata/ata-pci.c index 374612e..be0ddfb 100644 --- a/sys/dev/ata/ata-pci.c +++ b/sys/dev/ata/ata-pci.c @@ -136,15 +136,10 @@ int ata_pci_detach(device_t dev) { struct ata_pci_controller *ctlr = device_get_softc(dev); - device_t *children; - int nchildren, i; /* detach & delete all children */ - if (!device_get_children(dev, &children, &nchildren)) { - for (i = 0; i < nchildren; i++) - device_delete_child(dev, children[i]); - free(children, M_TEMP); - } + device_delete_all_children(dev); + if (ctlr->r_irq) { bus_teardown_intr(dev, ctlr->r_irq, ctlr->handle); bus_release_resource(dev, SYS_RES_IRQ, ctlr->r_irq_rid, ctlr->r_irq); diff --git a/sys/dev/gpio/gpiobus.c b/sys/dev/gpio/gpiobus.c index d973694..54644a2 100644 --- a/sys/dev/gpio/gpiobus.c +++ b/sys/dev/gpio/gpiobus.c @@ -219,8 +219,7 @@ static int gpiobus_detach(device_t dev) { struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev); - int err, ndevs, i; - device_t *devlist; + int err; KASSERT(mtx_initialized(&sc->sc_mtx), ("gpiobus mutex not initialized")); @@ -228,16 +227,14 @@ gpiobus_detach(device_t dev) if ((err = bus_generic_detach(dev)) != 0) return (err); - if ((err = device_get_children(dev, &devlist, &ndevs)) != 0) - return (err); - for (i = 0; i < ndevs; i++) - device_delete_child(dev, devlist[i]); + + /* detach and delete all children */ + device_delete_all_children(dev); if (sc->sc_pins_mapped) { free(sc->sc_pins_mapped, M_DEVBUF); sc->sc_pins_mapped = NULL; } - free(devlist, M_TEMP); return (0); } diff --git a/sys/dev/mvs/mvs_pci.c b/sys/dev/mvs/mvs_pci.c index e2e37da..36dd93d 100644 --- a/sys/dev/mvs/mvs_pci.c +++ b/sys/dev/mvs/mvs_pci.c @@ -177,15 +177,10 @@ static int mvs_detach(device_t dev) { struct mvs_controller *ctlr = device_get_softc(dev); - device_t *children; - int nchildren, i; /* Detach & delete all children */ - if (!device_get_children(dev, &children, &nchildren)) { - for (i = 0; i < nchildren; i++) - device_delete_child(dev, children[i]); - free(children, M_TEMP); - } + device_delete_all_children(dev); + /* Free interrupt. */ if (ctlr->irq.r_irq) { bus_teardown_intr(dev, ctlr->irq.r_irq, diff --git a/sys/dev/mvs/mvs_soc.c b/sys/dev/mvs/mvs_soc.c index 5c1116c..670bfec 100644 --- a/sys/dev/mvs/mvs_soc.c +++ b/sys/dev/mvs/mvs_soc.c @@ -173,15 +173,10 @@ static int mvs_detach(device_t dev) { struct mvs_controller *ctlr = device_get_softc(dev); - device_t *children; - int nchildren, i; /* Detach & delete all children */ - if (!device_get_children(dev, &children, &nchildren)) { - for (i = 0; i < nchildren; i++) - device_delete_child(dev, children[i]); - free(children, M_TEMP); - } + device_delete_all_children(dev); + /* Free interrupt. */ if (ctlr->irq.r_irq) { bus_teardown_intr(dev, ctlr->irq.r_irq, diff --git a/sys/dev/ppbus/ppbconf.c b/sys/dev/ppbus/ppbconf.c index 9e21c67..858e5b2 100644 --- a/sys/dev/ppbus/ppbconf.c +++ b/sys/dev/ppbus/ppbconf.c @@ -422,20 +422,14 @@ ppbus_attach(device_t dev) static int ppbus_detach(device_t dev) { - device_t *children; - int error, nchildren, i; + int error; error = bus_generic_detach(dev); if (error) return (error); /* detach & delete all children */ - if (!device_get_children(dev, &children, &nchildren)) { - for (i = 0; i < nchildren; i++) - if (children[i]) - device_delete_child(dev, children[i]); - free(children, M_TEMP); - } + device_delete_all_children(dev); return (0); } diff --git a/sys/dev/ppc/ppc.c b/sys/dev/ppc/ppc.c index 1322a33..ef505d8 100644 --- a/sys/dev/ppc/ppc.c +++ b/sys/dev/ppc/ppc.c @@ -1851,20 +1851,13 @@ int ppc_detach(device_t dev) { struct ppc_data *ppc = DEVTOSOFTC(dev); - device_t *children; - int nchildren, i; if (ppc->res_irq == 0) { return (ENXIO); } /* detach & delete all children */ - if (!device_get_children(dev, &children, &nchildren)) { - for (i = 0; i < nchildren; i++) - if (children[i]) - device_delete_child(dev, children[i]); - free(children, M_TEMP); - } + device_delete_all_children(dev); if (ppc->res_irq != 0) { bus_teardown_intr(dev, ppc->res_irq, ppc->intr_cookie); diff --git a/sys/dev/siba/siba_core.c b/sys/dev/siba/siba_core.c index 2b1a84f..61652ad 100644 --- a/sys/dev/siba/siba_core.c +++ b/sys/dev/siba/siba_core.c @@ -214,16 +214,8 @@ siba_core_attach(struct siba_softc *siba) int siba_core_detach(struct siba_softc *siba) { - device_t *devlistp; - int devcnt, error = 0, i; - - error = device_get_children(siba->siba_dev, &devlistp, &devcnt); - if (error != 0) - return (0); - - for ( i = 0 ; i < devcnt ; i++) - device_delete_child(siba->siba_dev, devlistp[i]); - free(devlistp, M_TEMP); + /* detach & delete all children */ + device_delete_all_children(siba->siba_dev); return (0); } diff --git a/sys/dev/siis/siis.c b/sys/dev/siis/siis.c index a7b018a..1512064 100644 --- a/sys/dev/siis/siis.c +++ b/sys/dev/siis/siis.c @@ -205,15 +205,10 @@ static int siis_detach(device_t dev) { struct siis_controller *ctlr = device_get_softc(dev); - device_t *children; - int nchildren, i; /* Detach & delete all children */ - if (!device_get_children(dev, &children, &nchildren)) { - for (i = 0; i < nchildren; i++) - device_delete_child(dev, children[i]); - free(children, M_TEMP); - } + device_delete_all_children(dev); + /* Free interrupts. */ if (ctlr->irq.r_irq) { bus_teardown_intr(dev, ctlr->irq.r_irq, diff --git a/sys/dev/usb/usb_util.c b/sys/dev/usb/usb_util.c index 1c357a3..a9b1d6f 100644 --- a/sys/dev/usb/usb_util.c +++ b/sys/dev/usb/usb_util.c @@ -58,31 +58,6 @@ #include /*------------------------------------------------------------------------* - * device_delete_all_children - delete all children of a device - *------------------------------------------------------------------------*/ -#ifndef device_delete_all_children -int -device_delete_all_children(device_t dev) -{ - device_t *devlist; - int devcount; - int error; - - error = device_get_children(dev, &devlist, &devcount); - if (error == 0) { - while (devcount-- > 0) { - error = device_delete_child(dev, devlist[devcount]); - if (error) { - break; - } - } - free(devlist, M_TEMP); - } - return (error); -} -#endif - -/*------------------------------------------------------------------------* * device_set_usb_desc * * This function can be called at probe or attach to set the USB diff --git a/sys/dev/usb/usb_util.h b/sys/dev/usb/usb_util.h index 35abedd..7e52404 100644 --- a/sys/dev/usb/usb_util.h +++ b/sys/dev/usb/usb_util.h @@ -27,7 +27,6 @@ #ifndef _USB_UTIL_H_ #define _USB_UTIL_H_ -int device_delete_all_children(device_t dev); uint8_t usb_make_str_desc(void *ptr, uint16_t max_len, const char *s); void usb_printbcd(char *p, uint16_t p_len, uint16_t bcd); void usb_trim_spaces(char *p); diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c index e688ca0..fda2c5d 100644 --- a/sys/kern/subr_bus.c +++ b/sys/kern/subr_bus.c @@ -1881,6 +1881,39 @@ device_delete_child(device_t dev, device_t child) } /** + * @brief Delete all children devices of the given device, if any. + * + * This function deletes all children devices of the given device, if + * any, using the device_delete_child() function for each device it + * finds. If a child device cannot be deleted, this function will + * return an error code. + * + * @param dev the parent device + * + * @retval 0 success + * @retval non-zero a device would not detach + */ +int +device_delete_all_children(device_t dev) +{ + device_t child; + int error; + + PDEBUG(("Deleting all children of %s", DEVICENAME(dev))); + + error = 0; + + while ( (child = TAILQ_FIRST(&dev->children)) ) { + error = device_delete_child(dev, child); + if (error) { + PDEBUG(("Failed deleting %s", DEVICENAME(child))); + break; + } + } + return (error); +} + +/** * @brief Find a device given a unit number * * This is similar to devclass_get_devices() but only searches for diff --git a/sys/sys/bus.h b/sys/sys/bus.h index e561042..6636843 100644 --- a/sys/sys/bus.h +++ b/sys/sys/bus.h @@ -424,6 +424,7 @@ device_t device_add_child_ordered(device_t dev, u_int order, const char *name, int unit); void device_busy(device_t dev); int device_delete_child(device_t dev, device_t child); +int device_delete_all_children(device_t dev); int device_attach(device_t dev); int device_detach(device_t dev); void device_disable(device_t dev); -- 1.7.8.3