summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorjdc <jdc@NetBSD.org>2021-01-30 07:53:01 +0000
committerjdc <jdc@NetBSD.org>2021-01-30 07:53:01 +0000
commit67f56ea98e1c07754b4e760ccf3385cd253b2d18 (patch)
treefec1f44ca8b19671d0f0887b5f557c07243285d0 /sys/dev
parent32b543ae3d5f0e3aa0a6471357d42a54128c8f28 (diff)
Improve handling of receive overflows. When we get an overflow, don't
reset the chip if we are still receiving packets. Real overflows can happen when network and CPU(s) are loaded, so the reset is not needed in this case. Add a counter to track receive overflows (when GEM_COUNTERS is defined). This reverts some changes (always reset on overflow) from PR port-sparc64/46260.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ic/gem.c42
-rw-r--r--sys/dev/ic/gemvar.h3
2 files changed, 30 insertions, 15 deletions
diff --git a/sys/dev/ic/gem.c b/sys/dev/ic/gem.c
index a61fa73fd01..31a9d25ca69 100644
--- a/sys/dev/ic/gem.c
+++ b/sys/dev/ic/gem.c
@@ -1,4 +1,4 @@
-/* $NetBSD: gem.c,v 1.132 2020/09/15 08:33:40 mrg Exp $ */
+/* $NetBSD: gem.c,v 1.133 2021/01/30 07:53:01 jdc Exp $ */
/*
*
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: gem.c,v 1.132 2020/09/15 08:33:40 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: gem.c,v 1.133 2021/01/30 07:53:01 jdc Exp $");
#include "opt_inet.h"
@@ -169,6 +169,7 @@ gem_detach(struct gem_softc *sc, int flags)
evcnt_detach(&sc->sc_ev_rxfull);
evcnt_detach(&sc->sc_ev_rxint);
evcnt_detach(&sc->sc_ev_txint);
+ evcnt_detach(&sc->sc_ev_rxoverflow);
#endif
evcnt_detach(&sc->sc_ev_intr);
@@ -596,6 +597,8 @@ gem_attach(struct gem_softc *sc, const uint8_t *enaddr)
&sc->sc_ev_rxint, device_xname(sc->sc_dev), "rx ring full");
evcnt_attach_dynamic(&sc->sc_ev_rxnobuf, EVCNT_TYPE_INTR,
&sc->sc_ev_rxint, device_xname(sc->sc_dev), "rx malloc failure");
+ evcnt_attach_dynamic(&sc->sc_ev_rxoverflow, EVCNT_TYPE_INTR,
+ &sc->sc_ev_rxint, device_xname(sc->sc_dev), "rx overflow");
evcnt_attach_dynamic(&sc->sc_ev_rxhist[0], EVCNT_TYPE_INTR,
&sc->sc_ev_rxint, device_xname(sc->sc_dev), "rx 0desc");
evcnt_attach_dynamic(&sc->sc_ev_rxhist[1], EVCNT_TYPE_INTR,
@@ -1803,8 +1806,8 @@ gem_rint(struct gem_softc *sc)
if (rxstat & GEM_RD_BAD_CRC) {
if_statinc(ifp, if_ierrors);
- aprint_error_dev(sc->sc_dev,
- "receive error: CRC error\n");
+ DPRINTF(sc, ("%s: receive error: CRC error\n",
+ device_xname(sc->sc_dev)));
GEM_INIT_RXDESC(sc, i);
continue;
}
@@ -2215,8 +2218,11 @@ gem_intr(void *v)
*/
if (rxstat & GEM_MAC_RX_OVERFLOW) {
if_statinc(ifp, if_ierrors);
+ GEM_COUNTER_INCR(sc, sc_ev_rxoverflow);
+#ifdef GEM_DEBUG
aprint_error_dev(sc->sc_dev,
"receive error: RX overflow sc->rxptr %d, complete %d\n", sc->sc_rxptr, bus_space_read_4(t, h, GEM_RX_COMPLETION));
+#endif
sc->sc_rx_fifo_wr_ptr =
bus_space_read_4(t, h, GEM_RX_FIFO_WR_PTR);
sc->sc_rx_fifo_rd_ptr =
@@ -2282,25 +2288,33 @@ gem_rx_watchdog(void *arg)
"receiver stuck in overflow, resetting\n");
gem_init(ifp);
} else {
+ int needreset = 1;
if ((state & GEM_MAC_STATE_OVERFLOW) != GEM_MAC_STATE_OVERFLOW) {
- aprint_error_dev(sc->sc_dev,
- "rx_watchdog: not in overflow state: 0x%x\n",
- state);
+ DPRINTF(sc,
+ ("%s: rx_watchdog: not in overflow state: 0x%x\n",
+ device_xname(sc->sc_dev), state));
}
if (rx_fifo_wr_ptr != rx_fifo_rd_ptr) {
- aprint_error_dev(sc->sc_dev,
- "rx_watchdog: wr & rd ptr different\n");
+ DPRINTF(sc,
+ ("%s: rx_watchdog: wr & rd ptr different\n",
+ device_xname(sc->sc_dev), state));
+ needreset = 0;
}
if (sc->sc_rx_fifo_wr_ptr != rx_fifo_wr_ptr) {
- aprint_error_dev(sc->sc_dev,
- "rx_watchdog: wr pointer != saved\n");
+ DPRINTF(sc, ("%s: rx_watchdog: wr pointer != saved\n",
+ device_xname(sc->sc_dev), state));
+ needreset = 0;
}
if (sc->sc_rx_fifo_rd_ptr != rx_fifo_rd_ptr) {
+ DPRINTF(sc, ("%s: rx_watchdog: rd pointer != saved\n",
+ device_xname(sc->sc_dev), state));
+ needreset = 0;
+ }
+ if (needreset) {
aprint_error_dev(sc->sc_dev,
- "rx_watchdog: rd pointer != saved\n");
+ "rx_watchdog: resetting anyway\n");
+ gem_init(ifp);
}
- aprint_error_dev(sc->sc_dev, "resetting anyway\n");
- gem_init(ifp);
}
}
diff --git a/sys/dev/ic/gemvar.h b/sys/dev/ic/gemvar.h
index 999adc4917a..f26b69b62cd 100644
--- a/sys/dev/ic/gemvar.h
+++ b/sys/dev/ic/gemvar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: gemvar.h,v 1.27 2020/03/01 05:50:56 thorpej Exp $ */
+/* $NetBSD: gemvar.h,v 1.28 2021/01/30 07:53:01 jdc Exp $ */
/*
*
@@ -219,6 +219,7 @@ struct gem_softc {
#ifdef GEM_COUNTERS
struct evcnt sc_ev_txint;
struct evcnt sc_ev_rxint;
+ struct evcnt sc_ev_rxoverflow;
struct evcnt sc_ev_rxnobuf;
struct evcnt sc_ev_rxfull;
struct evcnt sc_ev_rxhist[9];