diff options
author | yongari <yongari@FreeBSD.org> | 2011-02-18 02:58:09 +0000 |
---|---|---|
committer | yongari <yongari@FreeBSD.org> | 2011-02-18 02:58:09 +0000 |
commit | ddc627825d19d98365c3d2b76482818116b2167a (patch) | |
tree | aaa3c545a4513410955d77fb3781c9d9e9927be8 /sys/dev | |
parent | dc543f1c565aff6c848614be2c8831e4d6711e28 (diff) | |
download | FreeBSD-src-ddc627825d19d98365c3d2b76482818116b2167a.zip FreeBSD-src-ddc627825d19d98365c3d2b76482818116b2167a.tar.gz |
Apply special PHY initialization code for 21143 controllers before
any other media configuration. Otherwise some 21143 controller
cannot establish a link. While I'm here remove the PHY
initialization code in dc_setcfg(). Since dc_setcfg() is called
whenever link state is changed, having the PHY initialization code
in dc_setcfg() resulted in continuous link flips.
After driver resets SIA, use default SIA transmit/receive
configuration instead of disabling autosense/autonegotiation.
Otherwise, controller fails to establish a link as well as losing
auto-negotiation capability. For manual media configuration, always
configure 21143 controller with specified media to ensure media
change. This change makes ANA-6922 establish link with/without
auto-negotiation.
While I'm here be more strict on link UP/DOWN detection logic.
Many thanks to marius who fixed several bugs in initial patch and
even tested the patch on a couple of dc(4) controllers.
PR: kern/79262
Reviewed by: marius
Tested by: marius
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/dc/if_dc.c | 73 |
1 files changed, 42 insertions, 31 deletions
diff --git a/sys/dev/dc/if_dc.c b/sys/dev/dc/if_dc.c index 14e68e1..842cd88 100644 --- a/sys/dev/dc/if_dc.c +++ b/sys/dev/dc/if_dc.c @@ -944,23 +944,45 @@ static void dc_miibus_statchg(device_t dev) { struct dc_softc *sc; + struct ifnet *ifp; struct mii_data *mii; struct ifmedia *ifm; sc = device_get_softc(dev); - if (DC_IS_ADMTEK(sc)) - return; mii = device_get_softc(sc->dc_miibus); + ifp = sc->dc_ifp; + if (mii == NULL || ifp == NULL || + (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) + return; + ifm = &mii->mii_media; if (DC_IS_DAVICOM(sc) && IFM_SUBTYPE(ifm->ifm_media) == IFM_HPNA_1) { dc_setcfg(sc, ifm->ifm_media); sc->dc_if_media = ifm->ifm_media; - } else { - dc_setcfg(sc, mii->mii_media_active); - sc->dc_if_media = mii->mii_media_active; + return; + } + + sc->dc_link = 0; + 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->dc_link = 1; + break; + default: + break; + } } + if (sc->dc_link == 0) + return; + + sc->dc_if_media = mii->mii_media_active; + if (DC_IS_ADMTEK(sc)) + return; + dc_setcfg(sc, mii->mii_media_active); } /* @@ -1404,8 +1426,6 @@ dc_setcfg(struct dc_softc *sc, int media) if (!DC_IS_DAVICOM(sc)) DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL); DC_CLRBIT(sc, DC_10BTCTRL, 0xFFFF); - if (DC_IS_INTEL(sc)) - dc_apply_fixup(sc, IFM_AUTO); } else { if (DC_IS_PNIC(sc)) { DC_PN_GPIO_SETBIT(sc, DC_PN_GPIO_SPEEDSEL); @@ -1415,10 +1435,6 @@ dc_setcfg(struct dc_softc *sc, int media) DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL); DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PCS); DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_SCRAMBLER); - if (DC_IS_INTEL(sc)) - dc_apply_fixup(sc, - (media & IFM_GMASK) == IFM_FDX ? - IFM_100_TX | IFM_FDX : IFM_100_TX); } } @@ -1442,8 +1458,6 @@ dc_setcfg(struct dc_softc *sc, int media) if (!DC_IS_DAVICOM(sc)) DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL); DC_CLRBIT(sc, DC_10BTCTRL, 0xFFFF); - if (DC_IS_INTEL(sc)) - dc_apply_fixup(sc, IFM_AUTO); } else { if (DC_IS_PNIC(sc)) { DC_PN_GPIO_CLRBIT(sc, DC_PN_GPIO_SPEEDSEL); @@ -1463,9 +1477,6 @@ dc_setcfg(struct dc_softc *sc, int media) DC_SETBIT(sc, DC_SIARESET, DC_SIA_RESET); DC_CLRBIT(sc, DC_10BTCTRL, DC_TCTL_AUTONEGENBL); - dc_apply_fixup(sc, - (media & IFM_GMASK) == IFM_FDX ? - IFM_10_T | IFM_FDX : IFM_10_T); DELAY(20000); } } @@ -1537,7 +1548,7 @@ dc_reset(struct dc_softc *sc) */ if (DC_IS_INTEL(sc)) { DC_SETBIT(sc, DC_SIARESET, DC_SIA_RESET); - CSR_WRITE_4(sc, DC_10BTCTRL, 0); + CSR_WRITE_4(sc, DC_10BTCTRL, 0xFFFFFFFF); CSR_WRITE_4(sc, DC_WATCHDOG, 0); } } @@ -2963,11 +2974,8 @@ dc_tick(void *xsc) */ if ((DC_HAS_BROKEN_RXSTATE(sc) || (CSR_READ_4(sc, DC_ISR) & DC_ISR_RX_STATE) == DC_RXSTATE_WAIT) && - sc->dc_cdata.dc_tx_cnt == 0) { + sc->dc_cdata.dc_tx_cnt == 0) mii_tick(mii); - if (!(mii->mii_media_status & IFM_ACTIVE)) - sc->dc_link = 0; - } } } else mii_tick(mii); @@ -2991,12 +2999,8 @@ dc_tick(void *xsc) * that time, packets will stay in the send queue, and once the * link comes up, they will be flushed out to the wire. */ - if (!sc->dc_link && mii->mii_media_status & IFM_ACTIVE && - IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { - sc->dc_link++; - if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - dc_start_locked(ifp); - } + if (sc->dc_link != 0 && !IFQ_DRV_IS_EMPTY(&ifp->if_snd)) + dc_start_locked(ifp); if (sc->dc_flags & DC_21143_NWAY && !sc->dc_link) callout_reset(&sc->dc_stat_ch, hz/10, dc_tick, sc); @@ -3421,6 +3425,7 @@ dc_init_locked(struct dc_softc *sc) { struct ifnet *ifp = sc->dc_ifp; struct mii_data *mii; + struct ifmedia *ifm; DC_LOCK_ASSERT(sc); @@ -3431,6 +3436,10 @@ dc_init_locked(struct dc_softc *sc) */ dc_stop(sc); dc_reset(sc); + if (DC_IS_INTEL(sc)) { + ifm = &mii->mii_media; + dc_apply_fixup(sc, ifm->ifm_media); + } /* * Set cache alignment and burst length. @@ -3574,12 +3583,12 @@ dc_init_locked(struct dc_softc *sc) DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ON); CSR_WRITE_4(sc, DC_RXSTART, 0xFFFFFFFF); - mii_mediachg(mii); - dc_setcfg(sc, sc->dc_if_media); - ifp->if_drv_flags |= IFF_DRV_RUNNING; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + mii_mediachg(mii); + dc_setcfg(sc, sc->dc_if_media); + /* Don't start the ticker if this is a homePNA link. */ if (IFM_SUBTYPE(mii->mii_media.ifm_media) == IFM_HPNA_1) sc->dc_link = 1; @@ -3610,7 +3619,9 @@ dc_ifmedia_upd(struct ifnet *ifp) mii_mediachg(mii); ifm = &mii->mii_media; - if (DC_IS_DAVICOM(sc) && + if (DC_IS_INTEL(sc)) + dc_setcfg(sc, ifm->ifm_media); + else if (DC_IS_DAVICOM(sc) && IFM_SUBTYPE(ifm->ifm_media) == IFM_HPNA_1) dc_setcfg(sc, ifm->ifm_media); else |