Index: head/sys/dev/acpica/acpi_pci.c =================================================================== --- head/sys/dev/acpica/acpi_pci.c +++ head/sys/dev/acpica/acpi_pci.c @@ -70,6 +70,7 @@ CTASSERT(ACPI_STATE_D3 == PCI_POWERSTATE_D3); static int acpi_pci_attach(device_t dev); +static void acpi_pci_child_deleted(device_t dev, device_t child); static int acpi_pci_child_location_str_method(device_t cbdev, device_t child, char *buf, size_t buflen); static int acpi_pci_probe(device_t dev); @@ -97,6 +98,7 @@ /* Bus interface */ DEVMETHOD(bus_read_ivar, acpi_pci_read_ivar), DEVMETHOD(bus_write_ivar, acpi_pci_write_ivar), + DEVMETHOD(bus_child_deleted, acpi_pci_child_deleted), DEVMETHOD(bus_child_location_str, acpi_pci_child_location_str_method), DEVMETHOD(bus_get_dma_tag, acpi_pci_get_dma_tag), DEVMETHOD(bus_get_domain, acpi_get_domain), @@ -153,6 +155,16 @@ return (pci_write_ivar(dev, child, which, value)); } +static void +acpi_pci_child_deleted(device_t dev, device_t child) +{ + struct acpi_pci_devinfo *dinfo = device_get_ivars(child); + + if (acpi_get_device(dinfo->ap_handle) == child) + AcpiDetachData(dinfo->ap_handle, acpi_fake_objhandler); + pci_child_deleted(dev, child); +} + static int acpi_pci_child_location_str_method(device_t cbdev, device_t child, char *buf, size_t buflen) Index: head/sys/dev/cardbus/cardbus.c =================================================================== --- head/sys/dev/cardbus/cardbus.c +++ head/sys/dev/cardbus/cardbus.c @@ -226,31 +226,30 @@ return (ENOENT); } +static void +cardbus_child_deleted(device_t cbdev, device_t child) +{ + struct cardbus_devinfo *dinfo = device_get_ivars(child); + + if (dinfo->pci.cfg.dev != child) + device_printf(cbdev, "devinfo dev mismatch\n"); + cardbus_device_destroy(dinfo); + pci_child_deleted(cbdev, child); +} + static int cardbus_detach_card(device_t cbdev) { - int numdevs; - device_t *devlist; - int tmp; int err = 0; - if (device_get_children(cbdev, &devlist, &numdevs) != 0) - return (ENOENT); - if (numdevs == 0) { - free(devlist, M_TEMP); - return (ENOENT); - } - - for (tmp = 0; tmp < numdevs; tmp++) { - struct cardbus_devinfo *dinfo = device_get_ivars(devlist[tmp]); + err = bus_generic_detach(cbdev); + if (err) + return (err); + err = device_delete_children(cbdev); + if (err) + return (err); - if (dinfo->pci.cfg.dev != devlist[tmp]) - device_printf(cbdev, "devinfo dev mismatch\n"); - cardbus_device_destroy(dinfo); - pci_delete_child(cbdev, devlist[tmp]); - } POWER_DISABLE_SOCKET(device_get_parent(cbdev), cbdev); - free(devlist, M_TEMP); return (err); } @@ -335,6 +334,7 @@ DEVMETHOD(device_resume, cardbus_resume), /* Bus interface */ + DEVMETHOD(bus_child_deleted, cardbus_child_deleted), DEVMETHOD(bus_get_dma_tag, bus_generic_get_dma_tag), DEVMETHOD(bus_read_ivar, cardbus_read_ivar), DEVMETHOD(bus_driver_added, cardbus_driver_added), Index: head/sys/dev/pci/pci.c =================================================================== --- head/sys/dev/pci/pci.c +++ head/sys/dev/pci/pci.c @@ -161,6 +161,7 @@ DEVMETHOD(bus_release_resource, pci_release_resource), DEVMETHOD(bus_activate_resource, pci_activate_resource), DEVMETHOD(bus_deactivate_resource, pci_deactivate_resource), + DEVMETHOD(bus_child_deleted, pci_child_deleted), DEVMETHOD(bus_child_detached, pci_child_detached), DEVMETHOD(bus_child_pnpinfo_str, pci_child_pnpinfo_str_method), DEVMETHOD(bus_child_location_str, pci_child_location_str_method), @@ -5194,7 +5195,7 @@ } void -pci_delete_child(device_t dev, device_t child) +pci_child_deleted(device_t dev, device_t child) { struct resource_list_entry *rle; struct resource_list *rl; @@ -5203,12 +5204,13 @@ dinfo = device_get_ivars(child); rl = &dinfo->resources; - if (device_is_attached(child)) - device_detach(child); - /* Turn off access to resources we're about to free */ - pci_write_config(child, PCIR_COMMAND, pci_read_config(child, - PCIR_COMMAND, 2) & ~(PCIM_CMD_MEMEN | PCIM_CMD_PORTEN), 2); + if (bus_child_present(child) != 0) { + pci_write_config(child, PCIR_COMMAND, pci_read_config(child, + PCIR_COMMAND, 2) & ~(PCIM_CMD_MEMEN | PCIM_CMD_PORTEN), 2); + + pci_disable_busmaster(child); + } /* Free all allocated resources */ STAILQ_FOREACH(rle, rl, link) { @@ -5229,7 +5231,6 @@ } resource_list_free(rl); - device_delete_child(dev, child); pci_freecfg(dinfo); } Index: head/sys/dev/pci/pci_iov.c =================================================================== --- head/sys/dev/pci/pci_iov.c +++ head/sys/dev/pci/pci_iov.c @@ -640,7 +640,7 @@ error = PCI_IOV_ADD_VF(dev, i, driver_config); if (error != 0) { device_printf(dev, "Failed to add VF %d\n", i); - pci_delete_child(bus, vf); + device_delete_child(bus, vf); } } @@ -833,7 +833,7 @@ vf = devlist[i]; if (pci_iov_is_child_vf(iov, vf)) - pci_delete_child(bus, vf); + device_delete_child(bus, vf); } PCI_IOV_UNINIT(dev); Index: head/sys/dev/pci/pci_private.h =================================================================== --- head/sys/dev/pci/pci_private.h +++ head/sys/dev/pci/pci_private.h @@ -57,7 +57,6 @@ uint32_t prefetchmask); void pci_add_resources_ea(device_t bus, device_t dev, int alloc_iov); int pci_attach_common(device_t dev); -void pci_delete_child(device_t dev, device_t child); void pci_driver_added(device_t dev, driver_t *driver); int pci_ea_is_enabled(device_t dev, int rid); int pci_print_child(device_t dev, device_t child); @@ -122,6 +121,7 @@ size_t size); void pci_print_verbose(struct pci_devinfo *dinfo); int pci_freecfg(struct pci_devinfo *dinfo); +void pci_child_deleted(device_t dev, device_t child); void pci_child_detached(device_t dev, device_t child); int pci_child_location_str_method(device_t cbdev, device_t child, char *buf, size_t buflen); Index: head/sys/powerpc/ofw/ofw_pcibus.c =================================================================== --- head/sys/powerpc/ofw/ofw_pcibus.c +++ head/sys/powerpc/ofw/ofw_pcibus.c @@ -61,6 +61,7 @@ static device_attach_t ofw_pcibus_attach; static pci_assign_interrupt_t ofw_pcibus_assign_interrupt; static ofw_bus_get_devinfo_t ofw_pcibus_get_devinfo; +static bus_child_deleted_t ofw_pcibus_child_deleted; static int ofw_pcibus_child_pnpinfo_str_method(device_t cbdev, device_t child, char *buf, size_t buflen); @@ -73,6 +74,7 @@ DEVMETHOD(device_attach, ofw_pcibus_attach), /* Bus interface */ + DEVMETHOD(bus_child_deleted, ofw_pcibus_child_deleted), DEVMETHOD(bus_child_pnpinfo_str, ofw_pcibus_child_pnpinfo_str_method), /* PCI interface */ @@ -269,6 +271,16 @@ } } +static void +ofw_pcibus_child_deleted(device_t dev, device_t child) +{ + struct ofw_pcibus_devinfo *dinfo; + + dinfo = device_get_ivars(dev); + ofw_bus_gen_destroy_devinfo(&dinfo->opd_obdinfo); + pci_child_deleted(dev, child); +} + static int ofw_pcibus_child_pnpinfo_str_method(device_t cbdev, device_t child, char *buf, size_t buflen) Index: head/sys/sparc64/pci/ofw_pcibus.c =================================================================== --- head/sys/sparc64/pci/ofw_pcibus.c +++ head/sys/sparc64/pci/ofw_pcibus.c @@ -65,6 +65,7 @@ u_int busno, u_int slot, u_int func); /* Methods */ +static bus_child_deleted_t ofw_pcibus_child_deleted; static bus_child_pnpinfo_str_t ofw_pcibus_pnpinfo_str; static device_attach_t ofw_pcibus_attach; static device_probe_t ofw_pcibus_probe; @@ -77,6 +78,7 @@ DEVMETHOD(device_attach, ofw_pcibus_attach), /* Bus interface */ + DEVMETHOD(bus_child_deleted, ofw_pcibus_child_deleted), DEVMETHOD(bus_child_pnpinfo_str, ofw_pcibus_pnpinfo_str), /* PCI interface */ @@ -327,6 +329,16 @@ return (&dinfo->opd_obdinfo); } +static void +ofw_pcibus_child_deleted(device_t dev, device_t child) +{ + struct ofw_pcibus_devinfo *dinfo; + + dinfo = device_get_ivars(dev); + ofw_bus_gen_destroy_devinfo(&dinfo->opd_obdinfo); + pci_child_deleted(dev, child); +} + static int ofw_pcibus_pnpinfo_str(device_t dev, device_t child, char *buf, size_t buflen)