diff options
| author | Pyun YongHyeon <yongari@FreeBSD.org> | 2011-11-22 20:45:09 +0000 |
|---|---|---|
| committer | Pyun YongHyeon <yongari@FreeBSD.org> | 2011-11-22 20:45:09 +0000 |
| commit | 66c6108d5dfe14f8bbed3821103cc4bb5990d7f8 (patch) | |
| tree | c01b7dedb17a8e15c4877548ee24b55a795b89e1 /sys/dev/vge | |
| parent | beb7471b16d9ea8fe169db04cb382d4ea209e844 (diff) | |
Notes
Diffstat (limited to 'sys/dev/vge')
| -rw-r--r-- | sys/dev/vge/if_vge.c | 62 |
1 files changed, 44 insertions, 18 deletions
diff --git a/sys/dev/vge/if_vge.c b/sys/dev/vge/if_vge.c index c75726194ad6..720c32035c20 100644 --- a/sys/dev/vge/if_vge.c +++ b/sys/dev/vge/if_vge.c @@ -173,6 +173,7 @@ static __inline void static void vge_freebufs(struct vge_softc *); static void vge_ifmedia_sts(struct ifnet *, struct ifmediareq *); static int vge_ifmedia_upd(struct ifnet *); +static int vge_ifmedia_upd_locked(struct vge_softc *); static void vge_init(void *); static void vge_init_locked(struct vge_softc *); static void vge_intr(void *); @@ -180,7 +181,6 @@ static void vge_intr_holdoff(struct vge_softc *); static int vge_ioctl(struct ifnet *, u_long, caddr_t); static void vge_link_statchg(void *); static int vge_miibus_readreg(device_t, int, int); -static void vge_miibus_statchg(device_t); static int vge_miibus_writereg(device_t, int, int, int); static void vge_miipoll_start(struct vge_softc *); static void vge_miipoll_stop(struct vge_softc *); @@ -190,6 +190,7 @@ static void vge_reset(struct vge_softc *); static int vge_rx_list_init(struct vge_softc *); static int vge_rxeof(struct vge_softc *, int); static void vge_rxfilter(struct vge_softc *); +static void vge_setmedia(struct vge_softc *); static void vge_setvlan(struct vge_softc *); static void vge_setwol(struct vge_softc *); static void vge_start(struct ifnet *); @@ -218,7 +219,6 @@ static device_method_t vge_methods[] = { /* MII interface */ DEVMETHOD(miibus_readreg, vge_miibus_readreg), DEVMETHOD(miibus_writereg, vge_miibus_writereg), - DEVMETHOD(miibus_statchg, vge_miibus_statchg), { 0, 0 } }; @@ -1661,30 +1661,41 @@ vge_link_statchg(void *xsc) { struct vge_softc *sc; struct ifnet *ifp; - struct mii_data *mii; + uint8_t physts; sc = xsc; ifp = sc->vge_ifp; VGE_LOCK_ASSERT(sc); - mii = device_get_softc(sc->vge_miibus); - mii_pollstat(mii); - if ((sc->vge_flags & VGE_FLAG_LINK) != 0) { - if (!(mii->mii_media_status & IFM_ACTIVE)) { + physts = CSR_READ_1(sc, VGE_PHYSTS0); + if ((physts & VGE_PHYSTS_RESETSTS) == 0) { + if ((physts & VGE_PHYSTS_LINK) == 0) { sc->vge_flags &= ~VGE_FLAG_LINK; if_link_state_change(sc->vge_ifp, LINK_STATE_DOWN); - } - } else { - if (mii->mii_media_status & IFM_ACTIVE && - IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { + } else { sc->vge_flags |= VGE_FLAG_LINK; if_link_state_change(sc->vge_ifp, LINK_STATE_UP); + CSR_WRITE_1(sc, VGE_CRC2, VGE_CR2_FDX_TXFLOWCTL_ENABLE | + VGE_CR2_FDX_RXFLOWCTL_ENABLE); + if ((physts & VGE_PHYSTS_FDX) != 0) { + if ((physts & VGE_PHYSTS_TXFLOWCAP) != 0) + CSR_WRITE_1(sc, VGE_CRS2, + VGE_CR2_FDX_TXFLOWCTL_ENABLE); + if ((physts & VGE_PHYSTS_RXFLOWCAP) != 0) + CSR_WRITE_1(sc, VGE_CRS2, + VGE_CR2_FDX_RXFLOWCTL_ENABLE); + } if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) vge_start_locked(ifp); } } + /* + * Restart MII auto-polling because link state change interrupt + * will disable it. + */ + vge_miipoll_start(sc); } #ifdef DEVICE_POLLING @@ -2131,7 +2142,7 @@ vge_init_locked(struct vge_softc *sc) CSR_WRITE_1(sc, VGE_CRS3, VGE_CR3_INT_GMSK); sc->vge_flags &= ~VGE_FLAG_LINK; - mii_mediachg(mii); + vge_ifmedia_upd_locked(sc); ifp->if_drv_flags |= IFF_DRV_RUNNING; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; @@ -2145,14 +2156,28 @@ static int vge_ifmedia_upd(struct ifnet *ifp) { struct vge_softc *sc; - struct mii_data *mii; int error; sc = ifp->if_softc; VGE_LOCK(sc); + error = vge_ifmedia_upd_locked(sc); + VGE_UNLOCK(sc); + + return (error); +} + +static int +vge_ifmedia_upd_locked(struct vge_softc *sc) +{ + struct mii_data *mii; + struct mii_softc *miisc; + int error; + mii = device_get_softc(sc->vge_miibus); + LIST_FOREACH(miisc, &mii->mii_phys, mii_list) + PHY_RESET(miisc); + vge_setmedia(sc); error = mii_mediachg(mii); - VGE_UNLOCK(sc); return (error); } @@ -2181,13 +2206,11 @@ vge_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) } static void -vge_miibus_statchg(device_t dev) +vge_setmedia(struct vge_softc *sc) { - struct vge_softc *sc; struct mii_data *mii; struct ifmedia_entry *ife; - sc = device_get_softc(dev); mii = device_get_softc(sc->vge_miibus); ife = mii->mii_media.ifm_cur; @@ -2221,7 +2244,7 @@ vge_miibus_statchg(device_t dev) } break; default: - device_printf(dev, "unknown media type: %x\n", + device_printf(sc->vge_dev, "unknown media type: %x\n", IFM_SUBTYPE(ife->ifm_media)); break; } @@ -2774,6 +2797,9 @@ vge_setlinkspeed(struct vge_softc *sc) break; } } + /* Clear forced MAC speed/duplex configuration. */ + CSR_CLRBIT_1(sc, VGE_DIAGCTL, VGE_DIAGCTL_MACFORCE); + CSR_CLRBIT_1(sc, VGE_DIAGCTL, VGE_DIAGCTL_FDXFORCE); vge_miibus_writereg(sc->vge_dev, sc->vge_phyaddr, MII_100T2CR, 0); vge_miibus_writereg(sc->vge_dev, sc->vge_phyaddr, MII_ANAR, ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10 | ANAR_CSMA); |
