Index: if_vtnet.c =================================================================== --- if_vtnet.c (revision 248477) +++ if_vtnet.c (working copy) @@ -167,6 +167,7 @@ static int vtnet_enable_tx_intr(struct vtnet_softc *); static void vtnet_disable_rx_intr(struct vtnet_softc *); static void vtnet_disable_tx_intr(struct vtnet_softc *); +static int vtnet_tx_blocked(struct vtnet_softc *); /* Tunables. */ static int vtnet_csum_disable = 0; @@ -584,6 +585,25 @@ } static int +vtnet_tx_blocked(struct vtnet_softc *sc) +{ + struct ifnet *ifp; + + VTNET_LOCK_ASSERT(sc); + + ifp = sc->vtnet_ifp; + + if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || + (sc->vtnet_flags & VTNET_FLAG_LINK) == 0) + return (0); + + if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) != 0) + return (1); + + return (0); +} + +static int vtnet_config_change(device_t dev) { struct vtnet_softc *sc; @@ -791,13 +811,20 @@ static void vtnet_config_change_task(void *arg, int pending) { + int txblocked; struct vtnet_softc *sc; sc = arg; VTNET_LOCK(sc); vtnet_update_link_status(sc); + txblocked = vtnet_tx_blocked(sc); VTNET_UNLOCK(sc); + +#ifdef VTNET_TX_INTR_MODERATION + if (txblocked) + taskqueue_enqueue_fast(sc->vtnet_tq, &sc->vtnet_tx_intr_task); +#endif } static int @@ -1999,13 +2026,20 @@ static void vtnet_start(struct ifnet *ifp) { + int txblocked; struct vtnet_softc *sc; sc = ifp->if_softc; VTNET_LOCK(sc); vtnet_start_locked(ifp); + txblocked = vtnet_tx_blocked(sc); VTNET_UNLOCK(sc); + +#ifdef VTNET_TX_INTR_MODERATION + if (txblocked) + taskqueue_enqueue_fast(sc->vtnet_tq, &sc->vtnet_tx_intr_task); +#endif } static void @@ -2732,10 +2766,11 @@ { #ifdef VTNET_TX_INTR_MODERATION - return (0); -#else + if (!vtnet_tx_blocked(sc) || + (sc->vtnet_features & VIRTIO_F_NOTIFY_ON_EMPTY) != 0) + return (0); +#endif return (virtqueue_enable_intr(sc->vtnet_tx_vq)); -#endif } static void