diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2019-03-01 10:02:45 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2019-03-01 10:02:45 +0000 |
commit | b9da46258ed19c240e791f8696ff97a5ec4bb94a (patch) | |
tree | 80720db41a937ab0a7650f2c3ad12ae4e5d26e90 | |
parent | 8b18066adb684e14a24bbf162082713266c76e62 (diff) |
use a timeout to refill the rx ring when it's empty.
em had rxr, but didn't use a timeout cos it claimed to generate an
RX overflow interrupt when packets fell off slots in the ring. turns
out that's a lie on at least one chip, so add the timeout like other
drivers.
this was hit by mlarkin@, who had nfs and bufs steal all the packets
and memory for packets from em, which didn't recover after the
memory had been released back to the system.
-rw-r--r-- | sys/dev/pci/if_em.c | 25 | ||||
-rw-r--r-- | sys/dev/pci/if_em.h | 3 |
2 files changed, 19 insertions, 9 deletions
diff --git a/sys/dev/pci/if_em.c b/sys/dev/pci/if_em.c index eed5efe3fde..14a90e70ca1 100644 --- a/sys/dev/pci/if_em.c +++ b/sys/dev/pci/if_em.c @@ -31,7 +31,7 @@ POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ -/* $OpenBSD: if_em.c,v 1.341 2018/04/07 11:56:40 sf Exp $ */ +/* $OpenBSD: if_em.c,v 1.342 2019/03/01 10:02:44 dlg Exp $ */ /* $FreeBSD: if_em.c,v 1.46 2004/09/29 18:28:28 mlaier Exp $ */ #include <dev/pci/if_em.h> @@ -250,6 +250,7 @@ void em_txeof(struct em_softc *); int em_allocate_receive_structures(struct em_softc *); int em_allocate_transmit_structures(struct em_softc *); int em_rxfill(struct em_softc *); +void em_rxrefill(void *); int em_rxeof(struct em_softc *); void em_receive_checksum(struct em_softc *, struct em_rx_desc *, struct mbuf *); @@ -375,6 +376,7 @@ em_attach(struct device *parent, struct device *self, void *aux) timeout_set(&sc->timer_handle, em_local_timer, sc); timeout_set(&sc->tx_fifo_timer_handle, em_82547_move_tail, sc); + timeout_set(&sc->rx_refill, em_rxrefill, sc); /* Determine hardware revision */ em_identify_hardware(sc); @@ -959,13 +961,8 @@ em_intr(void *arg) if (ifp->if_flags & IFF_RUNNING) { em_txeof(sc); - - if (em_rxeof(sc) || ISSET(reg_icr, E1000_ICR_RXO)) { - if (em_rxfill(sc)) { - E1000_WRITE_REG(&sc->hw, RDT, - sc->sc_rx_desc_head); - } - } + if (em_rxeof(sc)) + em_rxrefill(sc); } /* Link status change */ @@ -1534,6 +1531,7 @@ em_stop(void *arg, int softonly) INIT_DEBUGOUT("em_stop: begin"); + timeout_del(&sc->rx_refill); timeout_del(&sc->timer_handle); timeout_del(&sc->tx_fifo_timer_handle); @@ -2755,6 +2753,17 @@ em_rxfill(struct em_softc *sc) return (post); } +void +em_rxrefill(void *arg) +{ + struct em_softc *sc = arg; + + if (em_rxfill(sc)) + E1000_WRITE_REG(&sc->hw, RDT, sc->sc_rx_desc_head); + else if (if_rxr_inuse(&sc->sc_rx_ring) == 0) + timeout_add(&sc->rx_refill, 1); +} + /********************************************************************* * * This routine executes in interrupt context. It replenishes diff --git a/sys/dev/pci/if_em.h b/sys/dev/pci/if_em.h index 156a2ca1b7f..4294a133746 100644 --- a/sys/dev/pci/if_em.h +++ b/sys/dev/pci/if_em.h @@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ /* $FreeBSD: if_em.h,v 1.26 2004/09/01 23:22:41 pdeuskar Exp $ */ -/* $OpenBSD: if_em.h,v 1.73 2016/10/27 03:06:53 dlg Exp $ */ +/* $OpenBSD: if_em.h,v 1.74 2019/03/01 10:02:44 dlg Exp $ */ #ifndef _EM_H_DEFINED_ #define _EM_H_DEFINED_ @@ -324,6 +324,7 @@ struct em_softc { struct timeout em_intr_enable; struct timeout timer_handle; struct timeout tx_fifo_timer_handle; + struct timeout rx_refill; /* Info about the board itself */ u_int32_t part_num; |