aq: support detaching

joshua stein <[email protected]>
Newsgroups gmane.os.openbsd.tech
Message-ID <20260818094708.309f118432@94331bf8154cb2e>
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.