diff options
author | Markus Friedl <markus@cvs.openbsd.org> | 2011-12-08 20:19:25 +0000 |
---|---|---|
committer | Markus Friedl <markus@cvs.openbsd.org> | 2011-12-08 20:19:25 +0000 |
commit | 05be5b6d202ccbed0134679760fe60cdef459112 (patch) | |
tree | 11fe750f84055ac95ca3e31df137aa29b7887621 /sys/dev | |
parent | 1035792ec3fb8628de6edda50575ee2bb5686641 (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.c | 24 | ||||
-rw-r--r-- | sys/dev/pci/if_vrreg.h | 3 |
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; |