Index: head/usr.sbin/bhyve/pci_virtio_net.c =================================================================== --- head/usr.sbin/bhyve/pci_virtio_net.c +++ head/usr.sbin/bhyve/pci_virtio_net.c @@ -150,14 +150,13 @@ struct nm_desc *vsc_nmd; int vsc_rx_ready; - volatile int resetting; /* set and checked outside lock */ + int resetting; /* protected by tx_mtx */ uint64_t vsc_features; /* negotiated features */ struct virtio_net_config vsc_config; pthread_mutex_t rx_mtx; - int rx_in_progress; int rx_vhdrlen; int rx_merge; /* merged rx bufs in use */ @@ -189,62 +188,39 @@ VTNET_S_HOSTCAPS, /* our capabilities */ }; -/* - * If the transmit thread is active then stall until it is done. - */ static void -pci_vtnet_txwait(struct pci_vtnet_softc *sc) +pci_vtnet_reset(void *vsc) { + struct pci_vtnet_softc *sc = vsc; + DPRINTF(("vtnet: device reset requested !\n")); + + /* Acquire the RX lock to block RX processing. */ + pthread_mutex_lock(&sc->rx_mtx); + + /* Set sc->resetting and give a chance to the TX thread to stop. */ pthread_mutex_lock(&sc->tx_mtx); + sc->resetting = 1; while (sc->tx_in_progress) { pthread_mutex_unlock(&sc->tx_mtx); usleep(10000); pthread_mutex_lock(&sc->tx_mtx); } - pthread_mutex_unlock(&sc->tx_mtx); -} -/* - * If the receive thread is active then stall until it is done. - */ -static void -pci_vtnet_rxwait(struct pci_vtnet_softc *sc) -{ - - pthread_mutex_lock(&sc->rx_mtx); - while (sc->rx_in_progress) { - pthread_mutex_unlock(&sc->rx_mtx); - usleep(10000); - pthread_mutex_lock(&sc->rx_mtx); - } - pthread_mutex_unlock(&sc->rx_mtx); -} - -static void -pci_vtnet_reset(void *vsc) -{ - struct pci_vtnet_softc *sc = vsc; - - DPRINTF(("vtnet: device reset requested !\n")); - - sc->resetting = 1; - - /* - * Wait for the transmit and receive threads to finish their - * processing. - */ - pci_vtnet_txwait(sc); - pci_vtnet_rxwait(sc); - sc->vsc_rx_ready = 0; sc->rx_merge = 1; sc->rx_vhdrlen = sizeof(struct virtio_net_rxhdr); - /* now reset rings, MSI-X vectors, and negotiated capabilities */ + /* + * Now reset rings, MSI-X vectors, and negotiated capabilities. + * Do that with the TX lock held, since we need to reset + * sc->resetting. + */ vi_reset_dev(&sc->vsc_vs); sc->resetting = 0; + pthread_mutex_unlock(&sc->tx_mtx); + pthread_mutex_unlock(&sc->rx_mtx); } /* @@ -318,9 +294,9 @@ /* * But, will be called when the rx ring hasn't yet - * been set up or the guest is resetting the device. + * been set up. */ - if (!sc->vsc_rx_ready || sc->resetting) { + if (!sc->vsc_rx_ready) { /* * Drop the packet and try later. */ @@ -515,9 +491,9 @@ /* * But, will be called when the rx ring hasn't yet - * been set up or the guest is resetting the device. + * been set up. */ - if (!sc->vsc_rx_ready || sc->resetting) { + if (!sc->vsc_rx_ready) { /* * Drop the packet and try later. */ @@ -594,9 +570,7 @@ struct pci_vtnet_softc *sc = param; pthread_mutex_lock(&sc->rx_mtx); - sc->rx_in_progress = 1; sc->pci_vtnet_rx(sc); - sc->rx_in_progress = 0; pthread_mutex_unlock(&sc->rx_mtx); } @@ -921,7 +895,6 @@ sc->rx_merge = 1; sc->rx_vhdrlen = sizeof(struct virtio_net_rxhdr); - sc->rx_in_progress = 0; pthread_mutex_init(&sc->rx_mtx, NULL); /*