Date: Mon, 8 Dec 2008 02:34:13 +0000 (UTC) From: Pyun YongHyeon <yongari@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r185753 - in head/sys: dev/re pci Message-ID: <200812080234.mB82YDD7042788@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: yongari Date: Mon Dec 8 02:34:13 2008 New Revision: 185753 URL: http://svn.freebsd.org/changeset/base/185753 Log: o Implemented miibus_statchg handler. It detects whether re(4) established a valid link or not. In miibus_statchg handler add a check for established link is valid one for the controller(e.g. 1000baseT is not a valid link for fastethernet controllers.) o Added a flag RE_FLAG_FASTETHER to mark fastethernet controllers. o Added additional check to know whether we've really encountered watchdog timeouts or missed Tx completion interrupts. This change may help to track down the cause of watchdog timeouts. o In interrupt handler, removed a check for link state change interrupt. Not all controllers have the bit and re(4) did not rely on the event for a long time. In addition, re(4) didn't request the interrupt in RL_IMR register. Tested by: rpaulo Modified: head/sys/dev/re/if_re.c head/sys/pci/if_rlreg.h Modified: head/sys/dev/re/if_re.c ============================================================================== --- head/sys/dev/re/if_re.c Mon Dec 8 01:44:18 2008 (r185752) +++ head/sys/dev/re/if_re.c Mon Dec 8 02:34:13 2008 (r185753) @@ -573,7 +573,39 @@ re_miibus_writereg(device_t dev, int phy static void re_miibus_statchg(device_t dev) { + struct rl_softc *sc; + struct ifnet *ifp; + struct mii_data *mii; + sc = device_get_softc(dev); + mii = device_get_softc(sc->rl_miibus); + ifp = sc->rl_ifp; + if (mii == NULL || ifp == NULL || + (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) + return; + + sc->rl_flags &= ~RL_FLAG_LINK; + if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) == + (IFM_ACTIVE | IFM_AVALID)) { + switch (IFM_SUBTYPE(mii->mii_media_active)) { + case IFM_10_T: + case IFM_100_TX: + sc->rl_flags |= RL_FLAG_LINK; + break; + case IFM_1000_T: + if ((sc->rl_flags & RL_FLAG_FASTETHER) != 0) + break; + sc->rl_flags |= RL_FLAG_LINK; + break; + default: + break; + } + } + /* + * RealTek controllers does not provide any interface to + * Tx/Rx MACs for resolved speed, duplex and flow-control + * parameters. + */ } /* @@ -1204,18 +1236,18 @@ re_attach(device_t dev) switch (hw_rev->rl_rev) { case RL_HWREV_8139CPLUS: - sc->rl_flags |= RL_FLAG_NOJUMBO; + sc->rl_flags |= RL_FLAG_NOJUMBO | RL_FLAG_FASTETHER; break; case RL_HWREV_8100E: case RL_HWREV_8101E: sc->rl_flags |= RL_FLAG_NOJUMBO | RL_FLAG_INVMAR | - RL_FLAG_PHYWAKE; + RL_FLAG_PHYWAKE | RL_FLAG_FASTETHER; break; case RL_HWREV_8102E: case RL_HWREV_8102EL: sc->rl_flags |= RL_FLAG_NOJUMBO | RL_FLAG_INVMAR | RL_FLAG_PHYWAKE | RL_FLAG_PAR | RL_FLAG_DESCV2 | - RL_FLAG_MACSTAT; + RL_FLAG_MACSTAT | RL_FLAG_FASTETHER; break; case RL_HWREV_8168_SPIN1: case RL_HWREV_8168_SPIN2: @@ -2011,30 +2043,14 @@ re_tick(void *xsc) { struct rl_softc *sc; struct mii_data *mii; - struct ifnet *ifp; sc = xsc; - ifp = sc->rl_ifp; RL_LOCK_ASSERT(sc); - re_watchdog(sc); - mii = device_get_softc(sc->rl_miibus); mii_tick(mii); - if ((sc->rl_flags & RL_FLAG_LINK) != 0) { - if (!(mii->mii_media_status & IFM_ACTIVE)) - sc->rl_flags &= ~RL_FLAG_LINK; - } else { - if (mii->mii_media_status & IFM_ACTIVE && - IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { - sc->rl_flags |= RL_FLAG_LINK; - if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - taskqueue_enqueue_fast(taskqueue_fast, - &sc->rl_txtask); - } - } - + re_watchdog(sc); callout_reset(&sc->rl_stat_callout, hz, re_tick, sc); } @@ -2149,11 +2165,6 @@ re_int_task(void *arg, int npending) re_init_locked(sc); } - if (status & RL_ISR_LINKCHG) { - callout_stop(&sc->rl_stat_callout); - re_tick(sc); - } - if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) taskqueue_enqueue_fast(taskqueue_fast, &sc->rl_txtask); @@ -2815,18 +2826,30 @@ re_ioctl(struct ifnet *ifp, u_long comma static void re_watchdog(struct rl_softc *sc) { + struct ifnet *ifp; RL_LOCK_ASSERT(sc); if (sc->rl_watchdog_timer == 0 || --sc->rl_watchdog_timer != 0) return; - device_printf(sc->rl_dev, "watchdog timeout\n"); - sc->rl_ifp->if_oerrors++; - + ifp = sc->rl_ifp; re_txeof(sc); + if (sc->rl_ldata.rl_tx_free == sc->rl_ldata.rl_tx_desc_cnt) { + if_printf(ifp, "watchdog timeout (missed Tx interrupts) " + "-- recovering\n"); + if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) + taskqueue_enqueue_fast(taskqueue_fast, &sc->rl_txtask); + return; + } + + if_printf(ifp, "watchdog timeout\n"); + ifp->if_oerrors++; + re_rxeof(sc); re_init_locked(sc); + if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) + taskqueue_enqueue_fast(taskqueue_fast, &sc->rl_txtask); } /* Modified: head/sys/pci/if_rlreg.h ============================================================================== --- head/sys/pci/if_rlreg.h Mon Dec 8 01:44:18 2008 (r185752) +++ head/sys/pci/if_rlreg.h Mon Dec 8 02:34:13 2008 (r185753) @@ -882,6 +882,7 @@ struct rl_softc { #define RL_FLAG_PAR 0x0020 #define RL_FLAG_DESCV2 0x0040 #define RL_FLAG_MACSTAT 0x0080 +#define RL_FLAG_FASTETHER 0x0100 #define RL_FLAG_LINK 0x8000 };
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200812080234.mB82YDD7042788>