summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2019-03-01 10:02:45 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2019-03-01 10:02:45 +0000
commitb9da46258ed19c240e791f8696ff97a5ec4bb94a (patch)
tree80720db41a937ab0a7650f2c3ad12ae4e5d26e90 /sys/dev/pci
parent8b18066adb684e14a24bbf162082713266c76e62 (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.
Diffstat (limited to 'sys/dev/pci')
-rw-r--r--sys/dev/pci/if_em.c25
-rw-r--r--sys/dev/pci/if_em.h3
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;