summaryrefslogtreecommitdiffstats
path: root/sys/pci/if_rl.c
diff options
context:
space:
mode:
authoryongari <yongari@FreeBSD.org>2008-10-25 03:41:36 +0000
committeryongari <yongari@FreeBSD.org>2008-10-25 03:41:36 +0000
commitfed9d3366599ef48993a855a0826d8c5d8dfc593 (patch)
treef1dfe71f1bcfe6fc2bbc49bb0b39193c65cc817f /sys/pci/if_rl.c
parentc854de7273991a8ebafd7fd9971e0012013035c6 (diff)
downloadFreeBSD-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/if_rl.c')
-rw-r--r--sys/pci/if_rl.c34
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);
OpenPOWER on IntegriCloud