--- sys/dev/netif/ral/if_ral_pci.c +++ sys/dev/netif/ral/if_ral_pci.c @@ -272,17 +272,31 @@ ral_pci_attach(device_t dev) device_printf(dev, "could not allocate interrupt resource\n"); pci_release_msi(dev); bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(psc->mem), psc->mem); return ENXIO; } error = (*psc->sc_opns->attach)(dev, pci_get_device(dev)); if (error != 0) { - (void)ral_pci_detach(dev); + /* + * The child attach failed and has already unwound all of + * its own state (DMA rings freed, driver lock destroyed); + * in particular ieee80211_ifattach() was never called. + * Only release the PCI-layer resources here: running the + * full ral_pci_detach() would dispatch the child detach a + * SECOND time and ieee80211_ifdetach() would LIST_REMOVE() + * an ieee80211com that was never attached (NULL-pointer + * write in sys/sys/queue.h LIST_REMOVE -> panic), followed + * by double-frees of every DMA ring. + * + * The IRQ resource must be released before pci_release_msi() + * (pci_release_msi_method() returns EBUSY while an MSI + * resource is still allocated). + */ + bus_release_resource(dev, SYS_RES_IRQ, + rman_get_rid(psc->irq), psc->irq); + pci_release_msi(dev); + bus_release_resource(dev, SYS_RES_MEMORY, + rman_get_rid(psc->mem), psc->mem); return error; } /* * Hook our interrupt after all initialization is complete. */