summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Belopuhov <mikeb@cvs.openbsd.org>2016-11-11 18:45:25 +0000
committerMike Belopuhov <mikeb@cvs.openbsd.org>2016-11-11 18:45:25 +0000
commitddbc0cbc4f750587926b35b597bd3c1a0233d951 (patch)
tree7bc22035824572151d781ee55524d8b173e203e7
parentdf57cc472526807f446d178b1e134d54232f2907 (diff)
Reorder atomic operations dealing with sc_tx_avail
The atomic decrement of the number of available descriptors must be performed before sending the RNDIS message to the hypervisor so that packet transmit completion that may execute in parallel won't increase the value past the maximum.
-rw-r--r--sys/dev/pv/if_hvn.c18
1 files changed, 9 insertions, 9 deletions
diff --git a/sys/dev/pv/if_hvn.c b/sys/dev/pv/if_hvn.c
index 42e70180b80..14cb3421037 100644
--- a/sys/dev/pv/if_hvn.c
+++ b/sys/dev/pv/if_hvn.c
@@ -120,7 +120,7 @@ TAILQ_HEAD(rndis_queue, rndis_cmd);
struct hvn_tx_desc {
uint32_t txd_id;
- int txd_ready;
+ volatile int txd_ready;
struct vmbus_gpa txd_sgl[HVN_TX_FRAGS + 1];
int txd_nsge;
struct mbuf *txd_buf;
@@ -485,9 +485,6 @@ hvn_start(struct ifnet *ifp)
}
sc->sc_tx_next++;
- sc->sc_tx_next %= HVN_TX_DESC;
-
- atomic_dec_int(&sc->sc_tx_avail);
ifp->if_opackets++;
}
@@ -524,12 +521,11 @@ hvn_encap(struct hvn_softc *sc, struct mbuf *m, struct hvn_tx_desc **txd0)
size_t pktlen;
int i, rv;
- txd = &sc->sc_tx_desc[sc->sc_tx_next];
- while (!txd->txd_ready) {
+ do {
+ txd = &sc->sc_tx_desc[sc->sc_tx_next % HVN_TX_DESC];
sc->sc_tx_next++;
- sc->sc_tx_next %= HVN_TX_DESC;
- txd = &sc->sc_tx_desc[sc->sc_tx_next];
- }
+ } while (!txd->txd_ready);
+ txd->txd_ready = 0;
pkt = txd->txd_req;
memset(pkt, 0, sizeof(*pkt));
@@ -602,6 +598,9 @@ hvn_encap(struct hvn_softc *sc, struct mbuf *m, struct hvn_tx_desc **txd0)
}
*txd0 = txd;
+
+ atomic_dec_int(&sc->sc_tx_avail);
+
return (0);
}
@@ -614,6 +613,7 @@ hvn_decap(struct hvn_softc *sc, struct hvn_tx_desc *txd)
txd->txd_buf = NULL;
txd->txd_nsge = 0;
txd->txd_ready = 1;
+ atomic_inc_int(&sc->sc_tx_avail);
}
int