From ee96b9879aeecfaf263c527ec77f13f7742a3e07 Mon Sep 17 00:00:00 2001 From: yongari Date: Tue, 1 May 2007 03:35:48 +0000 Subject: Honor link up/down state in stge_start(). While I'm here move MAC control settings to stge_link_task, a task queue which handles link state and duplex/flow controls. --- sys/dev/stge/if_stge.c | 43 +++++++++++++++++++------------------------ sys/dev/stge/if_stgereg.h | 1 + 2 files changed, 20 insertions(+), 24 deletions(-) (limited to 'sys/dev/stge') diff --git a/sys/dev/stge/if_stge.c b/sys/dev/stge/if_stge.c index 10ca8d5..d648cde 100644 --- a/sys/dev/stge/if_stge.c +++ b/sys/dev/stge/if_stge.c @@ -479,32 +479,9 @@ static void stge_miibus_statchg(device_t dev) { struct stge_softc *sc; - struct mii_data *mii; sc = device_get_softc(dev); - mii = device_get_softc(sc->sc_miibus); - - STGE_MII_LOCK(sc); - if (IFM_SUBTYPE(mii->mii_media_active) == IFM_NONE) { - STGE_MII_UNLOCK(sc); - return; - } - - sc->sc_MACCtrl = 0; - if (((mii->mii_media_active & IFM_GMASK) & IFM_FDX) != 0) - sc->sc_MACCtrl |= MC_DuplexSelect; - if (((mii->mii_media_active & IFM_GMASK) & IFM_FLAG0) != 0) - sc->sc_MACCtrl |= MC_RxFlowControlEnable; - if (((mii->mii_media_active & IFM_GMASK) & IFM_FLAG1) != 0) - sc->sc_MACCtrl |= MC_TxFlowControlEnable; - /* - * We can't access STGE_MACCtrl register in this context due to - * the races between MII layer and driver which accesses this - * register to program MAC. In order to solve the race, we defer - * STGE_MACCtrl programming until we know we are out of MII. - */ taskqueue_enqueue(taskqueue_swi, &sc->sc_link_task); - STGE_MII_UNLOCK(sc); } /* @@ -1317,7 +1294,7 @@ stge_start_locked(struct ifnet *ifp) STGE_LOCK_ASSERT(sc); if ((ifp->if_drv_flags & (IFF_DRV_RUNNING|IFF_DRV_OACTIVE)) != - IFF_DRV_RUNNING) + IFF_DRV_RUNNING || sc->sc_link == 0) return; for (enq = 0; !IFQ_DRV_IS_EMPTY(&ifp->if_snd); ) { @@ -1491,11 +1468,27 @@ static void stge_link_task(void *arg, int pending) { struct stge_softc *sc; + struct mii_data *mii; uint32_t v, ac; int i; sc = (struct stge_softc *)arg; STGE_LOCK(sc); + + mii = device_get_softc(sc->sc_miibus); + if (mii->mii_media_status & IFM_ACTIVE) { + if (IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) + sc->sc_link = 1; + } else + sc->sc_link = 0; + + sc->sc_MACCtrl = 0; + if (((mii->mii_media_active & IFM_GMASK) & IFM_FDX) != 0) + sc->sc_MACCtrl |= MC_DuplexSelect; + if (((mii->mii_media_active & IFM_GMASK) & IFM_FLAG0) != 0) + sc->sc_MACCtrl |= MC_RxFlowControlEnable; + if (((mii->mii_media_active & IFM_GMASK) & IFM_FLAG1) != 0) + sc->sc_MACCtrl |= MC_TxFlowControlEnable; /* * Update STGE_MACCtrl register depending on link status. * (duplex, flow control etc) @@ -2247,6 +2240,7 @@ stge_init_locked(struct stge_softc *sc) stge_start_tx(sc); stge_start_rx(sc); + sc->sc_link = 0; /* * Set the current media. */ @@ -2369,6 +2363,7 @@ stge_stop(struct stge_softc *sc) */ ifp = sc->sc_ifp; ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); + sc->sc_link = 0; } static void diff --git a/sys/dev/stge/if_stgereg.h b/sys/dev/stge/if_stgereg.h index 55ab927..4a62f4f 100644 --- a/sys/dev/stge/if_stgereg.h +++ b/sys/dev/stge/if_stgereg.h @@ -652,6 +652,7 @@ struct stge_softc { int sc_rxint_dmawait; int sc_nerr; int sc_watchdog_timer; + int sc_link; struct task sc_link_task; struct mtx sc_mii_mtx; /* MII mutex */ -- cgit v1.1