From dc961de0b415d3928821fdeee5a24ae76b969cb0 Mon Sep 17 00:00:00 2001 From: Bill Paul Date: Fri, 17 Sep 2004 04:58:17 +0000 Subject: Commit patch to supress spurious link change events. Apparently, with copper NICs, a link change event is posted whenever MII autopolling is toggled off and on, which happens whenever someone calls bge_miibus_readreg() or bge_miibus_writereg() to access the PHY registers. This means anytime someone called the SIOCGIFMEDIA ioctl on a bge interface, the link would reset. Even a simple "ifconfig bge0" would do it, though other apps like dhclient or the PPPoE daemon could trigger it as well. An obvious symptom of this problem is lots of "bgeX: gigabit link up" messages appearing on the console for no apparent reason. Through experimentation, I determined that when a real link change event occurs, the BGE_MIMODE_AUTOPOLL in the BGE_MI_MODE register is always set, so now if we have a copper NIC and an link change event occurs and the BGE_MIMODE_AUTOPOLL bit is clear, we ignore the event. Note that this does not apply to the original BCM5700 chip since we use a different method for sensing link changes with that chip (the status block method was broken), nor to fiber optic NICs since they don't use the GMII PHY access registers. --- sys/dev/bge/if_bge.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'sys/dev/bge') diff --git a/sys/dev/bge/if_bge.c b/sys/dev/bge/if_bge.c index 5468423d7593..71ad6ab36938 100644 --- a/sys/dev/bge/if_bge.c +++ b/sys/dev/bge/if_bge.c @@ -2802,7 +2802,7 @@ bge_intr(xsc) struct bge_softc *sc; struct ifnet *ifp; u_int32_t statusword; - u_int32_t status; + u_int32_t status, mimode; sc = xsc; ifp = &sc->arpcom.ac_if; @@ -2863,10 +2863,19 @@ bge_intr(xsc) * that sometimes appear on fiber NICs during * periods of heavy traffic. (There should be no * effect on copper NICs.) + * + * If we do have a copper NIC (bge_tbi == 0) then + * check that the AUTOPOLL bit is set before + * processing the event as a real link change. + * Turning AUTOPOLL on and off in the MII read/write + * functions will often trigger a link status + * interrupt for no reason. */ status = CSR_READ_4(sc, BGE_MAC_STS); + mimode = CSR_READ_4(sc, BGE_MI_MODE); if (!(status & (BGE_MACSTAT_PORT_DECODE_ERROR| - BGE_MACSTAT_MI_COMPLETE))) { + BGE_MACSTAT_MI_COMPLETE)) && (!sc->bge_tbi && + (mimode & BGE_MIMODE_AUTOPOLL))) { sc->bge_link = 0; callout_stop(&sc->bge_stat_ch); bge_tick_locked(sc); -- cgit v1.3