summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordlg <dlg@openbsd.org>2019-08-06 09:36:54 +0000
committerdlg <dlg@openbsd.org>2019-08-06 09:36:54 +0000
commitc1eef7ca61ac0ceb5dc07846cf4300581876cbf4 (patch)
tree8445d7ec20bf2d9ec202b168a1a90db92dc7b602
parentsync (diff)
downloadwireguard-openbsd-c1eef7ca61ac0ceb5dc07846cf4300581876cbf4.tar.xz
wireguard-openbsd-c1eef7ca61ac0ceb5dc07846cf4300581876cbf4.zip
if the rx ring gets empty and can't be filled, retry in the future
there have been several reports that vmx gets stuck sometimes and only comes good after it's taken down and up again. hopefully this fixes that issue.
-rw-r--r--sys/dev/pci/if_vmx.c59
1 files changed, 40 insertions, 19 deletions
diff --git a/sys/dev/pci/if_vmx.c b/sys/dev/pci/if_vmx.c
index 46ce9619aca..0a1447bc74d 100644
--- a/sys/dev/pci/if_vmx.c
+++ b/sys/dev/pci/if_vmx.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_vmx.c,v 1.46 2019/08/06 07:21:29 dlg Exp $ */
+/* $OpenBSD: if_vmx.c,v 1.47 2019/08/06 09:36:54 dlg Exp $ */
/*
* Copyright (c) 2013 Tsubai Masanari
@@ -53,6 +53,8 @@
#define VMXNET3_DRIVER_VERSION 0x00010000
+struct vmxnet3_softc;
+
struct vmxnet3_txring {
struct mbuf *m[NTXDESC];
bus_dmamap_t dmap[NTXDESC];
@@ -64,9 +66,11 @@ struct vmxnet3_txring {
};
struct vmxnet3_rxring {
+ struct vmxnet3_softc *sc;
struct mbuf *m[NRXDESC];
bus_dmamap_t dmap[NRXDESC];
struct if_rxring rxr;
+ struct timeoutgrefill;
struct vmxnet3_rxdesc *rxd;
u_int fill;
u_int8_t gen;
@@ -157,6 +161,7 @@ int vmxnet3_intr(void *);
void vmxnet3_evintr(struct vmxnet3_softc *);
void vmxnet3_txintr(struct vmxnet3_softc *, struct vmxnet3_txqueue *);
void vmxnet3_rxintr(struct vmxnet3_softc *, struct vmxnet3_rxqueue *);
+void vmxnet3_rxfill(void *);
void vmxnet3_iff(struct vmxnet3_softc *);
void vmxnet3_rx_csum(struct vmxnet3_rxcompdesc *, struct mbuf *);
int vmxnet3_getbuf(struct vmxnet3_softc *, struct vmxnet3_rxring *);
@@ -434,7 +439,9 @@ vmxnet3_alloc_rxring(struct vmxnet3_softc *sc, int queue)
for (i = 0; i < 2; i++) {
ring = &rq->cmd_ring[i];
+ ring->sc = sc;
ring->rid = i;
+ timeout_set(&ring->refill, vmxnet3_rxfill, ring);
for (idx = 0; idx < NRXDESC; idx++) {
if (bus_dmamap_create(sc->sc_dmat, JUMBO_LEN, 1,
JUMBO_LEN, 0, BUS_DMA_NOWAIT, &ring->dmap[idx]))
@@ -474,12 +481,28 @@ vmxnet3_txinit(struct vmxnet3_softc *sc, struct vmxnet3_txqueue *tq)
}
void
+vmxnet3_rxfill(void *arg)
+{
+ struct vmxnet3_rxring *ring = arg;
+ struct vmxnet3_softc *sc = ring->sc;
+ u_int slots;
+
+ for (slots = if_rxr_get(&ring->rxr, NRXDESC); slots > 0; slots--) {
+ if (vmxnet3_getbuf(sc, ring))
+ break;
+ }
+ if_rxr_put(&ring->rxr, slots);
+
+ if (if_rxr_inuse(&ring->rxr) == 0)
+ timeout_add(&ring->refill, 1);
+}
+
+void
vmxnet3_rxinit(struct vmxnet3_softc *sc, struct vmxnet3_rxqueue *rq)
{
struct vmxnet3_rxring *ring;
struct vmxnet3_comp_ring *comp_ring;
int i;
- u_int slots;
for (i = 0; i < 2; i++) {
ring = &rq->cmd_ring[i];
@@ -487,13 +510,11 @@ vmxnet3_rxinit(struct vmxnet3_softc *sc, struct vmxnet3_rxqueue *rq)
ring->gen = 1;
bzero(ring->rxd, NRXDESC * sizeof ring->rxd[0]);
if_rxr_init(&ring->rxr, 2, NRXDESC - 1);
- for (slots = if_rxr_get(&ring->rxr, NRXDESC);
- slots > 0; slots--) {
- if (vmxnet3_getbuf(sc, ring))
- break;
- }
- if_rxr_put(&ring->rxr, slots);
}
+
+ /* XXX only fill ring 0 */
+ vmxnet3_rxfill(&rq->cmd_ring[0]);
+
comp_ring = &rq->comp_ring;
comp_ring->next = 0;
comp_ring->gen = 1;
@@ -523,11 +544,15 @@ vmxnet3_rxstop(struct vmxnet3_softc *sc, struct vmxnet3_rxqueue *rq)
for (i = 0; i < 2; i++) {
ring = &rq->cmd_ring[i];
+ timeout_del(&ring->refill);
for (idx = 0; idx < NRXDESC; idx++) {
- if (ring->m[idx]) {
- m_freem(ring->m[idx]);
- ring->m[idx] = NULL;
- }
+ struct mbuf *m = ring->m[idx];
+ if (m == NULL)
+ continue;
+
+ ring->m[idx] = NULL;
+ m_freem(m);
+ bus_dmamap_unload(sc->sc_dmat, ring->dmap[idx]);
}
}
}
@@ -710,7 +735,6 @@ vmxnet3_rxintr(struct vmxnet3_softc *sc, struct vmxnet3_rxqueue *rq)
struct mbuf_list ml = MBUF_LIST_INITIALIZER();
struct mbuf *m;
int idx, len;
- u_int slots;
for (;;) {
rxcd = &comp_ring->rxcd[comp_ring->next];
@@ -785,16 +809,13 @@ skip_buffer:
}
}
+ ring = &rq->cmd_ring[0];
+
if (ifiq_input(&ifp->if_rcv, &ml))
if_rxr_livelocked(&ring->rxr);
/* XXX Should we (try to) allocate buffers for ring 2 too? */
- ring = &rq->cmd_ring[0];
- for (slots = if_rxr_get(&ring->rxr, NRXDESC); slots > 0; slots--) {
- if (vmxnet3_getbuf(sc, ring))
- break;
- }
- if_rxr_put(&ring->rxr, slots);
+ vmxnet3_rxfill(ring);
}
void