summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorMarkus Friedl <markus@cvs.openbsd.org>2011-12-08 20:19:25 +0000
committerMarkus Friedl <markus@cvs.openbsd.org>2011-12-08 20:19:25 +0000
commit05be5b6d202ccbed0134679760fe60cdef459112 (patch)
tree11fe750f84055ac95ca3e31df137aa29b7887621 /sys/dev
parent1035792ec3fb8628de6edda50575ee2bb5686641 (diff)
add timeout to fill rx-ring in case of mbuf shortage while in vr_intr();
fixes hanging interfaces similar to in myx(4); ok dlg@, claudio@, henning@
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/pci/if_vr.c24
-rw-r--r--sys/dev/pci/if_vrreg.h3
2 files changed, 24 insertions, 3 deletions
diff --git a/sys/dev/pci/if_vr.c b/sys/dev/pci/if_vr.c
index 3360199e774..a5e260bc97e 100644
--- a/sys/dev/pci/if_vr.c
+++ b/sys/dev/pci/if_vr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_vr.c,v 1.111 2011/06/22 16:44:27 tedu Exp $ */
+/* $OpenBSD: if_vr.c,v 1.112 2011/12/08 20:19:23 markus Exp $ */
/*
* Copyright (c) 1997, 1998
@@ -116,6 +116,7 @@ void vr_rxeof(struct vr_softc *);
void vr_rxeoc(struct vr_softc *);
void vr_txeof(struct vr_softc *);
void vr_tick(void *);
+void vr_rxtick(void *);
int vr_intr(void *);
void vr_start(struct ifnet *);
int vr_ioctl(struct ifnet *, u_long, caddr_t);
@@ -670,6 +671,7 @@ vr_attach(struct device *parent, struct device *self, void *aux)
} else
ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
timeout_set(&sc->sc_to, vr_tick, sc);
+ timeout_set(&sc->sc_rxto, vr_rxtick, sc);
/*
* Call MI attach routines.
@@ -787,8 +789,11 @@ vr_fill_rx_ring(struct vr_softc *sc)
ld = sc->vr_ldata;
while (cd->vr_rx_cnt < VR_RX_LIST_CNT) {
- if (vr_alloc_mbuf(sc, cd->vr_rx_prod))
+ if (vr_alloc_mbuf(sc, cd->vr_rx_prod)) {
+ if (cd->vr_rx_cnt == 0)
+ timeout_add(&sc->sc_rxto, 0);
break;
+ }
cd->vr_rx_prod = cd->vr_rx_prod->vr_nextdesc;
cd->vr_rx_cnt++;
}
@@ -1038,6 +1043,21 @@ vr_tick(void *xsc)
splx(s);
}
+void
+vr_rxtick(void *xsc)
+{
+ struct vr_softc *sc = xsc;
+ int s;
+
+ s = splnet();
+ if (sc->vr_cdata.vr_rx_cnt == 0) {
+ vr_fill_rx_ring(sc);
+ if (sc->vr_cdata.vr_rx_cnt == 0)
+ timeout_add(&sc->sc_rxto, 1);
+ }
+ splx(s);
+}
+
int
vr_intr(void *arg)
{
diff --git a/sys/dev/pci/if_vrreg.h b/sys/dev/pci/if_vrreg.h
index f4b620f8f38..76f196d2cd8 100644
--- a/sys/dev/pci/if_vrreg.h
+++ b/sys/dev/pci/if_vrreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_vrreg.h,v 1.28 2011/03/13 15:38:50 stsp Exp $ */
+/* $OpenBSD: if_vrreg.h,v 1.29 2011/12/08 20:19:24 markus Exp $ */
/*
* Copyright (c) 1997, 1998
@@ -493,6 +493,7 @@ struct vr_softc {
struct vr_chain_data vr_cdata;
struct mii_data sc_mii;
struct timeout sc_to;
+ struct timeout sc_rxto;
bus_dmamap_t sc_listmap; /* descriptor list map */
bus_dma_segment_t sc_listseg;
int sc_rxbufs;