diff options
author | yongari <yongari@FreeBSD.org> | 2008-10-25 03:41:36 +0000 |
---|---|---|
committer | yongari <yongari@FreeBSD.org> | 2008-10-25 03:41:36 +0000 |
commit | fed9d3366599ef48993a855a0826d8c5d8dfc593 (patch) | |
tree | f1dfe71f1bcfe6fc2bbc49bb0b39193c65cc817f /sys/pci | |
parent | c854de7273991a8ebafd7fd9971e0012013035c6 (diff) | |
download | FreeBSD-src-fed9d3366599ef48993a855a0826d8c5d8dfc593.zip FreeBSD-src-fed9d3366599ef48993a855a0826d8c5d8dfc593.tar.gz |
Implement miibus_statchg handler. It detects whether rl(4)
established a valid link or not.
In rl_start_locked, don't try to send packets unless we have valid
link. While I'm here add a check that verifies whether driver can
accept Tx requests by inspecting IFF_DRV_OACTIVE/IFF_DRV_RUNNING
flag.
Diffstat (limited to 'sys/pci')
-rw-r--r-- | sys/pci/if_rl.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/sys/pci/if_rl.c b/sys/pci/if_rl.c index 0026798..4eee1ad 100644 --- a/sys/pci/if_rl.c +++ b/sys/pci/if_rl.c @@ -636,6 +636,34 @@ rl_miibus_writereg(device_t dev, int phy, int reg, int data) static void rl_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; + default: + break; + } + } + /* + * RealTek controllers do not provide any interface to + * Tx/Rx MACs for resolved speed, duplex and flow-control + * parameters. + */ } /* @@ -1545,6 +1573,10 @@ rl_start_locked(struct ifnet *ifp) RL_LOCK_ASSERT(sc); + if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != + IFF_DRV_RUNNING || (sc->rl_flags & RL_FLAG_LINK) == 0) + return; + while (RL_CUR_TXMBUF(sc) == NULL) { IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head); @@ -1686,6 +1718,7 @@ rl_init_locked(struct rl_softc *sc) /* Enable receiver and transmitter. */ CSR_WRITE_1(sc, RL_COMMAND, RL_CMD_TX_ENB|RL_CMD_RX_ENB); + sc->rl_flags &= ~RL_FLAG_LINK; mii_mediachg(mii); CSR_WRITE_1(sc, RL_CFG1, RL_CFG1_DRVLOAD|RL_CFG1_FULLDUPLEX); @@ -1831,6 +1864,7 @@ rl_stop(struct rl_softc *sc) sc->rl_watchdog_timer = 0; callout_stop(&sc->rl_stat_callout); ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); + sc->rl_flags &= ~RL_FLAG_LINK; CSR_WRITE_1(sc, RL_COMMAND, 0x00); CSR_WRITE_2(sc, RL_IMR, 0x0000); |