diff options
author | yongari <yongari@FreeBSD.org> | 2007-05-01 03:35:48 +0000 |
---|---|---|
committer | yongari <yongari@FreeBSD.org> | 2007-05-01 03:35:48 +0000 |
commit | ee96b9879aeecfaf263c527ec77f13f7742a3e07 (patch) | |
tree | b42babbea8ce9a52665275a02472a4b5733b43e0 | |
parent | 5f685fc1dc9b6bbebc958f733b9d99cdf82e0111 (diff) | |
download | FreeBSD-src-ee96b9879aeecfaf263c527ec77f13f7742a3e07.zip FreeBSD-src-ee96b9879aeecfaf263c527ec77f13f7742a3e07.tar.gz |
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.
-rw-r--r-- | sys/dev/stge/if_stge.c | 43 | ||||
-rw-r--r-- | sys/dev/stge/if_stgereg.h | 1 |
2 files changed, 20 insertions, 24 deletions
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 */ |