diff options
| author | jdc <jdc@NetBSD.org> | 2021-01-30 07:53:01 +0000 |
|---|---|---|
| committer | jdc <jdc@NetBSD.org> | 2021-01-30 07:53:01 +0000 |
| commit | 67f56ea98e1c07754b4e760ccf3385cd253b2d18 (patch) | |
| tree | fec1f44ca8b19671d0f0887b5f557c07243285d0 /sys/dev | |
| parent | 32b543ae3d5f0e3aa0a6471357d42a54128c8f28 (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.c | 42 | ||||
| -rw-r--r-- | sys/dev/ic/gemvar.h | 3 |
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]; |
