summaryrefslogtreecommitdiff
path: root/sys/dev/pv
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 /sys/dev/pv
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.
Diffstat (limited to 'sys/dev/pv')
-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