Index | Thread | Search

From:
"Theo de Raadt" <deraadt@openbsd.org>
Subject:
Re: aq: support detaching
To:
tech@openbsd.org
Date:
Tue, 18 Aug 2026 09:11:15 -0600

Download raw body.

Thread
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
>