summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2019-08-06 09:36:55 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2019-08-06 09:36:55 +0000
commitce0c200bacb13528a7d55afad1e0bdb490e578c6 (patch)
tree8590f4c1f3a112f55b562dac84ec86f76c014079 /sys/dev
parent052a5e3e7a74211786d4c1f6e28ba792909e6fa0 (diff)
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.
Diffstat (limited to 'sys/dev')
-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