diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2011-06-23 04:09:09 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2011-06-23 04:09:09 +0000 |
commit | 16501fbc736ecd54e420c0c45ad7c21f0be256a9 (patch) | |
tree | 16c9d757fcd7c90257398d82d60c86fe6d4c4a63 /sys/dev | |
parent | c5d1441dbda35ddef2ef3e727db2b37c30a58f69 (diff) |
cope with empty rx rings by scheduling a timeout to keep trying until it
gets some packets onto the rings.
also annoying, but the hardware doesnt report empty rings, we have to
handle it ourselves.
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/pci/if_myx.c | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/sys/dev/pci/if_myx.c b/sys/dev/pci/if_myx.c index e0bc692db86..8a1186d4221 100644 --- a/sys/dev/pci/if_myx.c +++ b/sys/dev/pci/if_myx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_myx.c,v 1.27 2011/06/23 03:36:06 dlg Exp $ */ +/* $OpenBSD: if_myx.c,v 1.28 2011/06/23 04:09:08 dlg Exp $ */ /* * Copyright (c) 2007 Reyk Floeter <reyk@openbsd.org> @@ -129,6 +129,7 @@ struct myx_softc { u_int sc_rx_ring_idx[2]; #define MYX_RXSMALL 0 #define MYX_RXBIG 1 + struct timeout sc_refill; bus_size_t sc_tx_boundary; u_int sc_tx_ring_count; @@ -191,6 +192,7 @@ struct myx_buf * myx_buf_fill(struct myx_softc *, int); void myx_rx_zero(struct myx_softc *, int); int myx_rx_fill(struct myx_softc *, int); +void myx_refill(void *); struct cfdriver myx_cd = { NULL, "myx", DV_IFNET @@ -231,6 +233,8 @@ myx_attach(struct device *parent, struct device *self, void *aux) SIMPLEQ_INIT(&sc->sc_tx_buf_free); SIMPLEQ_INIT(&sc->sc_tx_buf_list); + timeout_set(&sc->sc_refill, myx_refill, sc); + /* Map the PCI memory space */ memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, MYXBAR0); if (pci_mapreg_map(pa, MYXBAR0, memtype, 0, &sc->sc_memt, @@ -1298,6 +1302,8 @@ myx_down(struct myx_softc *sc) BUS_DMASYNC_POSTREAD); } + timeout_del(&sc->sc_refill); + CLR(ifp->if_flags, IFF_RUNNING); if (ifp->if_link_state != LINK_STATE_UNKNOWN) { @@ -1562,14 +1568,33 @@ myx_intr(void *arg) } for (i = 0; i < 2; i++) { - if (ISSET(refill, 1 << i)) + if (ISSET(refill, 1 << i)) { myx_rx_fill(sc, i); + if (SIMPLEQ_EMPTY(&sc->sc_rx_buf_list[i])) + timeout_add(&sc->sc_refill, 0); + } } return (1); } void +myx_refill(void *xsc) +{ + struct myx_softc *sc = xsc; + int i; + int s; + + s = splnet(); + for (i = 0; i < 2; i++) { + myx_rx_fill(sc, i); + if (SIMPLEQ_EMPTY(&sc->sc_rx_buf_list[i])) + timeout_add(&sc->sc_refill, 1); + } + splx(s); +} + +void myx_txeof(struct myx_softc *sc, u_int32_t done_count) { struct ifnet *ifp = &sc->sc_ac.ac_if; |