From: "Theo de Raadt" Subject: Re: aq: support detaching To: tech@openbsd.org Date: Tue, 18 Aug 2026 09:11:15 -0600 Your diff looks pretty good. > I bought an OWC 10gbit Thunderbolt adapter and it showed up as > aq(4). I unplugged it and the kernel panicked with "config_detach: > forced detach of aq0 failed (45)". This implements a detach routine > that works for me. > > aq0 at pci5 dev 0 function 0 "Aquantia AQC107S" rev 0x02: msix, 4 queues, Atlantic B1, F/W version 3.0.33, address 00:30:93:17:07:dc > > > Index: sys/dev/pci/if_aq_pci.c > =================================================================== > RCS file: /cvs/src/sys/dev/pci/if_aq_pci.c,v > diff -u -p -u -p -r1.37 if_aq_pci.c > --- sys/dev/pci/if_aq_pci.c 24 Jul 2026 02:31:43 -0000 1.37 > +++ sys/dev/pci/if_aq_pci.c 18 Aug 2026 14:46:41 -0000 > @@ -1001,6 +1001,7 @@ struct aq_softc { > void *sc_ih; > bus_space_handle_t sc_ioh; > bus_space_tag_t sc_iot; > + bus_size_t sc_iosize; > > uint32_t sc_mbox_addr; > int sc_rbl_enabled; > @@ -1130,6 +1131,7 @@ const struct aq_product { > > int aq_match(struct device *, void *, void *); > void aq_attach(struct device *, struct device *, void *); > +int aq_detach(struct device *, int); > int aq_activate(struct device *, int); > int aq_intr(void *); > int aq_intr_link(void *); > @@ -1230,7 +1232,7 @@ const struct aq_firmware_ops aq2_fw_ops > }; > > const struct cfattach aq_ca = { > - sizeof(struct aq_softc), aq_match, aq_attach, NULL, > + sizeof(struct aq_softc), aq_match, aq_attach, aq_detach, > aq_activate > }; > > @@ -1296,7 +1298,7 @@ aq_attach(struct device *parent, struct > > memtype = pci_mapreg_type(pc, tag, AQ_BAR0); > if (pci_mapreg_map(pa, AQ_BAR0, memtype, 0, &sc->sc_iot, &sc->sc_ioh, > - NULL, NULL, 0)) { > + NULL, &sc->sc_iosize, 0)) { > printf(": failed to map BAR0\n"); > return; > } > @@ -1528,6 +1530,53 @@ aq_attach(struct device *parent, struct > > aq_enable_intr(sc, 1, 0); > printf("\n"); > +} > + > +int > +aq_detach(struct device *self, int flags) > +{ > + struct aq_softc *sc = (struct aq_softc *)self; > + struct ifnet *ifp = &sc->sc_arpcom.ac_if; > + struct aq_queues *aq; > + int i; > + > + if (ifp->if_flags & IFF_RUNNING) > + aq_down(sc); > + > + aq_enable_intr(sc, 0, 0); > + > + for (i = 0; i < sc->sc_nqueues; i++) { > + aq = &sc->sc_queues[i]; > + > + if (aq->q_ihc != NULL) { > + pci_intr_disestablish(sc->sc_pc, aq->q_ihc); > + aq->q_ihc = NULL; > + } > + timeout_del(&aq->q_rx.rx_refill); > + } > + > + if (sc->sc_ih != NULL) { > + pci_intr_disestablish(sc->sc_pc, sc->sc_ih); > + sc->sc_ih = NULL; > + } > + > + if (sc->sc_intrmap != NULL) { > + intrmap_destroy(sc->sc_intrmap); > + sc->sc_intrmap = NULL; > + } > + > + if (ifp->if_softc != NULL) { > + ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY); > + ether_ifdetach(ifp); > + if_detach(ifp); > + } > + > + if (sc->sc_iosize != 0) { > + bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_iosize); > + sc->sc_iosize = 0; > + } > + > + return 0; > } > > int >