Index: sys/kern/subr_gtaskqueue.c =================================================================== --- sys/kern/subr_gtaskqueue.c +++ sys/kern/subr_gtaskqueue.c @@ -812,6 +812,7 @@ qgroup->tqg_queue[i].tgc_cnt--; LIST_REMOVE(gtask, gt_list); mtx_unlock(&qgroup->tqg_lock); + gtaskqueue_drain(gtask->gt_taskqueue, >ask->gt_task); gtask->gt_taskqueue = NULL; } Index: sys/net/iflib.h =================================================================== --- sys/net/iflib.h +++ sys/net/iflib.h @@ -246,7 +246,7 @@ /* fields necessary for probe */ pci_vendor_info_t *isc_vendor_info; char *isc_driver_version; -/* optional function to transform the read values to match the table*/ + /* optional function to transform the read values to match the table*/ void (*isc_parse_devinfo) (uint16_t *device_id, uint16_t *subvendor_id, uint16_t *subdevice_id, uint16_t *rev_id); int isc_nrxd_min[8]; @@ -375,6 +375,8 @@ if_shared_ctx_t iflib_get_sctx(if_ctx_t ctx); void iflib_set_mac(if_ctx_t ctx, uint8_t mac[ETHER_ADDR_LEN]); +void iflib_request_reset(if_ctx_t ctx); +uint8_t iflib_in_detach(if_ctx_t ctx); /* * If the driver can plug cleanly in to newbus use these Index: sys/net/iflib.c =================================================================== --- sys/net/iflib.c +++ sys/net/iflib.c @@ -101,6 +101,10 @@ #include #endif +#ifdef PCI_IOV +#include +#endif + #include /* * enable accounting of every mbuf as it comes in to and goes out of @@ -157,9 +161,9 @@ struct iflib_ctx { KOBJ_FIELDS; - /* - * Pointer to hardware driver's softc - */ + /* + * Pointer to hardware driver's softc + */ void *ifc_softc; device_t ifc_dev; if_t ifc_ifp; @@ -178,7 +182,6 @@ uint32_t ifc_if_flags; uint32_t ifc_flags; uint32_t ifc_max_fl_buf_size; - int ifc_in_detach; int ifc_link_state; int ifc_link_irq; @@ -253,12 +256,6 @@ return (ctx->ifc_flags); } -void -iflib_set_detach(if_ctx_t ctx) -{ - ctx->ifc_in_detach = 1; -} - void iflib_set_mac(if_ctx_t ctx, uint8_t mac[ETHER_ADDR_LEN]) { @@ -571,6 +568,13 @@ #define CALLOUT_LOCK(txq) mtx_lock(&txq->ift_mtx) #define CALLOUT_UNLOCK(txq) mtx_unlock(&txq->ift_mtx) +void +iflib_set_detach(if_ctx_t ctx) +{ + STATE_LOCK(ctx); + ctx->ifc_flags |= IFC_IN_DETACH; + STATE_UNLOCK(ctx); +} /* Our boot-time initialization hook */ static int iflib_module_event_handler(module_t, int, void *); @@ -738,6 +742,7 @@ static void iflib_ifmp_purge(iflib_txq_t txq); static void _iflib_pre_assert(if_softc_ctx_t scctx); static void iflib_if_init_locked(if_ctx_t ctx); +static void iflib_free_intr_mem(if_ctx_t ctx); #ifndef __NO_STRICT_ALIGNMENT static struct mbuf * iflib_fixup_rx(struct mbuf *m); #endif @@ -2072,6 +2077,16 @@ _iflib_fl_refill(ctx, fl, min(max, reclaimable)); } +uint8_t +iflib_in_detach(if_ctx_t ctx) +{ + bool in_detach; + STATE_LOCK(ctx); + in_detach = !!(ctx->ifc_flags & IFC_IN_DETACH); + STATE_UNLOCK(ctx); + return (in_detach); +} + static void iflib_fl_bufs_free(iflib_fl_t fl) { @@ -2087,7 +2102,8 @@ if (fl->ifl_sds.ifsd_map != NULL) { bus_dmamap_t sd_map = fl->ifl_sds.ifsd_map[i]; bus_dmamap_unload(fl->ifl_desc_tag, sd_map); - if (fl->ifl_rxq->ifr_ctx->ifc_in_detach) + // XXX: Should this get moved out? + if (iflib_in_detach(fl->ifl_rxq->ifr_ctx)) bus_dmamap_destroy(fl->ifl_desc_tag, sd_map); } if (*sd_m != NULL) { @@ -3842,7 +3858,7 @@ if_softc_ctx_t sctx = &ctx->ifc_softc_ctx; iflib_txq_t txq; int i; - bool oactive, running, do_reset, do_watchdog; + bool oactive, running, do_reset, do_watchdog, in_detach; uint32_t reset_on = hz / 2; STATE_LOCK(ctx); @@ -3850,11 +3866,13 @@ oactive = (if_getdrvflags(ctx->ifc_ifp) & IFF_DRV_OACTIVE); do_reset = (ctx->ifc_flags & IFC_DO_RESET); do_watchdog = (ctx->ifc_flags & IFC_DO_WATCHDOG); + in_detach = (ctx->ifc_flags & IFC_IN_DETACH); ctx->ifc_flags &= ~(IFC_DO_RESET|IFC_DO_WATCHDOG); STATE_UNLOCK(ctx); - if ((!running & !oactive) && - !(ctx->ifc_sctx->isc_flags & IFLIB_ADMIN_ALWAYS_RUN)) + if ((!running && !oactive) && !(ctx->ifc_sctx->isc_flags & IFLIB_ADMIN_ALWAYS_RUN)) + return; + if (in_detach) return; CTX_LOCK(ctx); @@ -3893,7 +3911,8 @@ { if_ctx_t ctx = context; - if (!(if_getdrvflags(ctx->ifc_ifp) & IFF_DRV_RUNNING)) + if (!(if_getdrvflags(ctx->ifc_ifp) & IFF_DRV_RUNNING) && + !(ctx->ifc_sctx->isc_flags & IFLIB_ADMIN_ALWAYS_RUN)) return; CTX_LOCK(ctx); @@ -4689,6 +4708,7 @@ iflib_tx_structures_free(ctx); iflib_rx_structures_free(ctx); fail: + iflib_free_intr_mem(ctx); IFDI_DETACH(ctx); CTX_UNLOCK(ctx); return (err); @@ -4978,9 +4998,18 @@ device_printf(dev,"Vlan in use, detach first\n"); return (EBUSY); } +#ifdef PCI_IOV + if (pci_iov_detach(dev)) { + device_printf(dev, "SR-IOV in use; detach first.\n"); + return (EBUSY); + } +#endif + + STATE_LOCK(ctx); + ctx->ifc_flags |= IFC_IN_DETACH; + STATE_UNLOCK(ctx); CTX_LOCK(ctx); - ctx->ifc_in_detach = 1; iflib_stop(ctx); CTX_UNLOCK(ctx); @@ -5021,17 +5050,7 @@ /* ether_ifdetach calls if_qflush - lock must be destroy afterwards*/ CTX_LOCK_DESTROY(ctx); device_set_softc(ctx->ifc_dev, NULL); - if (ctx->ifc_softc_ctx.isc_intr != IFLIB_INTR_LEGACY) { - pci_release_msi(dev); - } - if (ctx->ifc_softc_ctx.isc_intr != IFLIB_INTR_MSIX) { - iflib_irq_free(ctx, &ctx->ifc_legacy_irq); - } - if (ctx->ifc_msix_mem != NULL) { - bus_release_resource(ctx->ifc_dev, SYS_RES_MEMORY, - ctx->ifc_softc_ctx.isc_msix_bar, ctx->ifc_msix_mem); - ctx->ifc_msix_mem = NULL; - } + iflib_free_intr_mem(ctx); bus_generic_detach(dev); if_free(ifp); @@ -5040,10 +5059,27 @@ iflib_rx_structures_free(ctx); if (ctx->ifc_flags & IFC_SC_ALLOCATED) free(ctx->ifc_softc, M_IFLIB); + STATE_LOCK_DESTROY(ctx); free(ctx, M_IFLIB); return (0); } +static void +iflib_free_intr_mem(if_ctx_t ctx) +{ + + if (ctx->ifc_softc_ctx.isc_intr != IFLIB_INTR_LEGACY) { + pci_release_msi(ctx->ifc_dev); + } + if (ctx->ifc_softc_ctx.isc_intr != IFLIB_INTR_MSIX) { + iflib_irq_free(ctx, &ctx->ifc_legacy_irq); + } + if (ctx->ifc_msix_mem != NULL) { + bus_release_resource(ctx->ifc_dev, SYS_RES_MEMORY, + ctx->ifc_softc_ctx.isc_msix_bar, ctx->ifc_msix_mem); + ctx->ifc_msix_mem = NULL; + } +} int iflib_device_detach(device_t dev) @@ -5399,7 +5435,7 @@ fl[j].ifl_ifdi = &rxq->ifr_ifdi[j + rxq->ifr_fl_offset]; fl[j].ifl_rxd_size = scctx->isc_rxd_size[j]; } - /* Allocate receive buffers for the ring*/ + /* Allocate receive buffers for the ring */ if (iflib_rxsd_alloc(rxq)) { device_printf(dev, "Critical Failure setting up receive buffers\n"); @@ -5935,7 +5971,10 @@ { #ifdef INVARIANTS struct grouptask *gtask; - +#endif + if (iflib_in_detach(ctx)) + return; +#ifdef INVARIANTS gtask = &ctx->ifc_admin_task; MPASS(gtask != NULL && gtask->gt_taskqueue != NULL); #endif @@ -6463,6 +6502,15 @@ } +void +iflib_request_reset(if_ctx_t ctx) +{ + + STATE_LOCK(ctx); + ctx->ifc_flags |= IFC_DO_RESET; + STATE_UNLOCK(ctx); +} + #ifndef __NO_STRICT_ALIGNMENT static struct mbuf * iflib_fixup_rx(struct mbuf *m) Index: sys/net/iflib_private.h =================================================================== --- sys/net/iflib_private.h +++ sys/net/iflib_private.h @@ -42,6 +42,7 @@ #define IFC_DO_WATCHDOG 0x100 #define IFC_CHECK_HUNG 0x200 #define IFC_PSEUDO 0x400 +#define IFC_IN_DETACH 0x800 #define IFC_NETMAP_TX_IRQ 0x80000000