Author: neel
Date: Tue Apr 30 00:36:16 2013
New Revision: 250083
URL: http://svnweb.freebsd.org/changeset/base/250083

Log:
  Use a separate mutex for the receive path instead of overloading the softc
  mutex for this purpose.
  
  Reviewed by:  grehan

Modified:
  head/usr.sbin/bhyve/pci_virtio_net.c

Modified: head/usr.sbin/bhyve/pci_virtio_net.c
==============================================================================
--- head/usr.sbin/bhyve/pci_virtio_net.c        Mon Apr 29 23:57:41 2013        
(r250082)
+++ head/usr.sbin/bhyve/pci_virtio_net.c        Tue Apr 30 00:36:16 2013        
(r250083)
@@ -140,7 +140,6 @@ struct pci_vtnet_softc {
        int             vsc_isr;
        int             vsc_tapfd;
        int             vsc_rx_ready;
-       int             tx_in_progress;
        int             resetting;
 
        uint32_t        vsc_features;
@@ -149,9 +148,14 @@ struct pci_vtnet_softc {
        uint64_t        vsc_pfn[VTNET_MAXQ];
        struct  vring_hqueue vsc_hq[VTNET_MAXQ];
        uint16_t        vsc_msix_table_idx[VTNET_MAXQ];
+
+       pthread_mutex_t rx_mtx;
+       int             rx_in_progress;
+
        pthread_t       tx_tid;
        pthread_mutex_t tx_mtx;
        pthread_cond_t  tx_cond;
+       int             tx_in_progress;
 };
 #define        vtnet_ctx(sc)   ((sc)->vsc_pi->pi_vmctx)
 
@@ -220,6 +224,38 @@ pci_vtnet_ring_reset(struct pci_vtnet_so
        hq->hq_cur_aidx = 0;
 }
 
+/*
+ * If the transmit thread is active then stall until it is done.
+ */
+static void
+pci_vtnet_txwait(struct pci_vtnet_softc *sc)
+{
+
+       pthread_mutex_lock(&sc->tx_mtx);
+       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_update_status(struct pci_vtnet_softc *sc, uint32_t value)
 {
@@ -227,21 +263,19 @@ pci_vtnet_update_status(struct pci_vtnet
        if (value == 0) {
                DPRINTF(("vtnet: device reset requested !\n"));
                
-               /* Wait for TX thread to complete pending desc processing */
                sc->resetting = 1;
-               pthread_mutex_lock(&sc->tx_mtx);
 
-               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);
-                               
+               /*
+                * Wait for the transmit and receive threads to finish their
+                * processing.
+                */
+               pci_vtnet_txwait(sc);
+               pci_vtnet_rxwait(sc);
+
+               sc->vsc_rx_ready = 0;
                pci_vtnet_ring_reset(sc, VTNET_RXQ);
                pci_vtnet_ring_reset(sc, VTNET_TXQ);
-               sc->vsc_rx_ready = 0;
+
                sc->resetting = 0;
        }
 
@@ -303,9 +337,9 @@ pci_vtnet_tap_rx(struct pci_vtnet_softc 
 
        /*
         * But, will be called when the rx ring hasn't yet
-        * been set up. 
+        * been set up or the guest is resetting the device.
         */
-       if (sc->vsc_rx_ready == 0) {
+       if (!sc->vsc_rx_ready || sc->resetting) {
                /*
                 * Drop the packet and try later.
                 */
@@ -393,9 +427,11 @@ pci_vtnet_tap_callback(int fd, enum ev_t
 {
        struct pci_vtnet_softc *sc = param;
 
-       pthread_mutex_lock(&sc->vsc_mtx);
+       pthread_mutex_lock(&sc->rx_mtx);
+       sc->rx_in_progress = 1;
        pci_vtnet_tap_rx(sc);
-       pthread_mutex_unlock(&sc->vsc_mtx);
+       sc->rx_in_progress = 0;
+       pthread_mutex_unlock(&sc->rx_mtx);
 
 }
 
@@ -462,7 +498,6 @@ pci_vtnet_proctx(struct pci_vtnet_softc 
        vu->vu_tlen = tlen;
        hq->hq_cur_aidx = aidx + 1;
        *hq->hq_used_idx = uidx + 1;
-
 }
 
 static void
@@ -706,21 +741,24 @@ pci_vtnet_init(struct vmctx *ctx, struct
        }
        
        pci_emul_alloc_bar(pi, 0, PCIBAR_IO, VTNET_REGSZ);
-       
+
+       sc->resetting = 0;
+
+       sc->rx_in_progress = 0;
+       pthread_mutex_init(&sc->rx_mtx, NULL); 
+
        /* 
         * Initialize tx semaphore & spawn TX processing thread
         * As of now, only one thread for TX desc processing is
         * spawned. 
         */
        sc->tx_in_progress = 0;
-       sc->resetting = 0;
        pthread_mutex_init(&sc->tx_mtx, NULL);
        pthread_cond_init(&sc->tx_cond, NULL);
        pthread_create(&sc->tx_tid, NULL, pci_vtnet_tx_thread, (void *)sc);
         snprintf(tname, sizeof(tname), "%s vtnet%d tx", vmname, pi->pi_slot);
         pthread_set_name_np(sc->tx_tid, tname);
 
-       
        return (0);
 }
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to