Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 7 Dec 2011 21:29:51 +0000 (UTC)
From:      Pyun YongHyeon <yongari@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r228331 - head/sys/dev/et
Message-ID:  <201112072129.pB7LTpLB056549@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: yongari
Date: Wed Dec  7 21:29:51 2011
New Revision: 228331
URL: http://svn.freebsd.org/changeset/base/228331

Log:
  Rework link state tracking and TX/RX MAC configuration.
   o Do not report link status if driver is not running.
   o TX/RX MAC configuration should be done with resolved speed,
     duplex and flow control after establishing a link so it can't
     be done in driver initialization routine.
     Move the configuration to miibus_statchg callback which will be
     called whenever any link state change is detected.
     At this moment, flow-control is not enabled yet mainly because
     I was not able to set correct flow control parameters to
     generate TX pause frames.
   o Now TX/RX MAC is enabled only when a valid link is detected.
     Rearragnge hardware initialization routine a bit to leave
     enabling MAC to miibus_statchg callback.  In order to that,
     TX/RX DMA engine is enabled in et_init_locked().
   o Introduce ET_FLAG_LINK flag to track current link state.
   o Introduce ET_FLAG_FASTETHER flag to mark whether controller is
     fast ethernet.  This flag is checked in miibus_statchg callback
     to know whether PHY established a valid link.
   o In et_stop(), TX/RX MAC is explicitly disabled instead of
     relying on et_reset().  And move et_reset() from et_stop() to
     controller initialization.  Controler reset is not required here
     and it would also clear critial registers(i.e station address,
     RX filter configuration, WOL etc) that are required to make WOL
     work.
   o Switching to current media is done in et_init_locked() after
     setting IFF_DRV_RUNNING flag.  This should ensure reliable
     auto-negotiation/manual link establishment.
   o In et_start_locked(), check whether driver got a valid link
     before trying to send frames.
   o Remove checking a link in et_tick() as this is done by
     miibus_statchg callback.

Modified:
  head/sys/dev/et/if_et.c
  head/sys/dev/et/if_etvar.h

Modified: head/sys/dev/et/if_et.c
==============================================================================
--- head/sys/dev/et/if_et.c	Wed Dec  7 21:17:50 2011	(r228330)
+++ head/sys/dev/et/if_et.c	Wed Dec  7 21:29:51 2011	(r228331)
@@ -141,13 +141,11 @@ static int	et_start_rxdma(struct et_soft
 static int	et_start_txdma(struct et_softc *);
 static int	et_stop_rxdma(struct et_softc *);
 static int	et_stop_txdma(struct et_softc *);
-static int	et_enable_txrx(struct et_softc *, int);
 static void	et_reset(struct et_softc *);
 static int	et_bus_config(struct et_softc *);
 static void	et_get_eaddr(device_t, uint8_t[]);
 static void	et_setmulti(struct et_softc *);
 static void	et_tick(void *);
-static void	et_setmedia(struct et_softc *);
 
 static const struct et_dev {
 	uint16_t	vid;
@@ -296,6 +294,9 @@ et_attach(device_t dev)
 		goto fail;
 	}
 
+	if (pci_get_device(dev) == PCI_PRODUCT_LUCENT_ET1310_FAST)
+		sc->sc_flags |= ET_FLAG_FASTETHER;
+
 	error = et_bus_config(sc);
 	if (error)
 		goto fail;
@@ -487,7 +488,89 @@ et_miibus_writereg(device_t dev, int phy
 static void
 et_miibus_statchg(device_t dev)
 {
-	et_setmedia(device_get_softc(dev));
+	struct et_softc *sc;
+	struct mii_data *mii;
+	struct ifnet *ifp;
+	uint32_t cfg1, cfg2, ctrl;
+	int i;
+
+	sc = device_get_softc(dev);
+
+	mii = device_get_softc(sc->sc_miibus);
+	ifp = sc->ifp;
+	if (mii == NULL || ifp == NULL ||
+	    (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+		return;
+
+	sc->sc_flags &= ~ET_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->sc_flags |= ET_FLAG_LINK;
+			break;
+		case IFM_1000_T:
+			if ((sc->sc_flags & ET_FLAG_FASTETHER) == 0)
+				sc->sc_flags |= ET_FLAG_LINK;
+			break;
+		}
+	}
+
+	/* XXX Stop TX/RX MAC? */
+	if ((sc->sc_flags & ET_FLAG_LINK) == 0)
+		return;
+
+	/* Program MACs with resolved speed/duplex/flow-control. */
+	ctrl = CSR_READ_4(sc, ET_MAC_CTRL);
+	ctrl &= ~(ET_MAC_CTRL_GHDX | ET_MAC_CTRL_MODE_MII);
+	cfg1 = CSR_READ_4(sc, ET_MAC_CFG1);
+	cfg1 &= ~(ET_MAC_CFG1_TXFLOW | ET_MAC_CFG1_RXFLOW |
+	    ET_MAC_CFG1_LOOPBACK);
+	cfg2 = CSR_READ_4(sc, ET_MAC_CFG2);
+	cfg2 &= ~(ET_MAC_CFG2_MODE_MII | ET_MAC_CFG2_MODE_GMII |
+	    ET_MAC_CFG2_FDX | ET_MAC_CFG2_BIGFRM);
+	cfg2 |= ET_MAC_CFG2_LENCHK | ET_MAC_CFG2_CRC | ET_MAC_CFG2_PADCRC |
+	    ((7 << ET_MAC_CFG2_PREAMBLE_LEN_SHIFT) &
+	    ET_MAC_CFG2_PREAMBLE_LEN_MASK);
+
+	if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T)
+		cfg2 |= ET_MAC_CFG2_MODE_GMII;
+	else {
+		cfg2 |= ET_MAC_CFG2_MODE_MII;
+		ctrl |= ET_MAC_CTRL_MODE_MII;
+	}
+
+	if (IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) {
+		cfg2 |= ET_MAC_CFG2_FDX;
+#ifdef notyet
+		if (IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_TXPAUSE)
+			cfg1 |= ET_MAC_CFG1_TXFLOW;
+		if (IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_RXPAUSE)
+			cfg1 |= ET_MAC_CFG1_RXFLOW;
+#endif
+	} else
+		ctrl |= ET_MAC_CTRL_GHDX;
+
+	CSR_WRITE_4(sc, ET_MAC_CTRL, ctrl);
+	CSR_WRITE_4(sc, ET_MAC_CFG2, cfg2);
+	cfg1 |= ET_MAC_CFG1_TXEN | ET_MAC_CFG1_RXEN;
+	CSR_WRITE_4(sc, ET_MAC_CFG1, cfg1);
+
+#define NRETRY	50
+
+	for (i = 0; i < NRETRY; ++i) {
+		cfg1 = CSR_READ_4(sc, ET_MAC_CFG1);
+		if ((cfg1 & (ET_MAC_CFG1_SYNC_TXEN | ET_MAC_CFG1_SYNC_RXEN)) ==
+		    (ET_MAC_CFG1_SYNC_TXEN | ET_MAC_CFG1_SYNC_RXEN))
+			break;
+		DELAY(100);
+	}
+	if (i == NRETRY)
+		if_printf(ifp, "can't enable RX/TX\n");
+	sc->sc_flags |= ET_FLAG_TXRX_ENABLED;
+
+#undef NRETRY
 }
 
 static int
@@ -518,10 +601,17 @@ et_ifmedia_upd(struct ifnet *ifp)
 static void
 et_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
 {
-	struct et_softc *sc = ifp->if_softc;
-	struct mii_data *mii = device_get_softc(sc->sc_miibus);
+	struct et_softc *sc;
+	struct mii_data *mii;
 
+	sc = ifp->if_softc;
 	ET_LOCK(sc);
+	if ((ifp->if_flags & IFF_UP) == 0) {
+		ET_UNLOCK(sc);
+		return;
+	}
+
+	mii = device_get_softc(sc->sc_miibus);
 	mii_pollstat(mii);
 	ifmr->ifm_active = mii->mii_media_active;
 	ifmr->ifm_status = mii->mii_media_status;
@@ -539,14 +629,16 @@ et_stop(struct et_softc *sc)
 	/* Disable interrupts. */
 	CSR_WRITE_4(sc, ET_INTR_MASK, 0xffffffff);
 
+	CSR_WRITE_4(sc, ET_MAC_CFG1, CSR_READ_4(sc, ET_MAC_CFG1) & ~(
+	    ET_MAC_CFG1_TXEN | ET_MAC_CFG1_RXEN));
+	DELAY(100);
+
 	et_stop_rxdma(sc);
 	et_stop_txdma(sc);
 
 	et_free_tx_ring(sc);
 	et_free_rx_ring(sc);
 
-	et_reset(sc);
-
 	sc->sc_tx = 0;
 	sc->sc_tx_intr = 0;
 	sc->sc_flags &= ~ET_FLAG_TXRX_ENABLED;
@@ -1104,6 +1196,7 @@ et_init_locked(struct et_softc *sc)
 		return;
 
 	et_stop(sc);
+	et_reset(sc);
 
 	et_init_tx_ring(sc);
 	error = et_init_rx_ring(sc);
@@ -1112,22 +1205,33 @@ et_init_locked(struct et_softc *sc)
 
 	error = et_chip_init(sc);
 	if (error)
-		goto back;
+		goto fail;
 
-	error = et_enable_txrx(sc, 1);
+	/*
+	 * Start TX/RX DMA engine
+	 */
+	error = et_start_rxdma(sc);
 	if (error)
-		goto back;
+		return;
+
+	error = et_start_txdma(sc);
+	if (error)
+		return;
 
 	/* Enable interrupts. */
 	CSR_WRITE_4(sc, ET_INTR_MASK, ~ET_INTRS);
 
-	callout_reset(&sc->sc_tick, hz, et_tick, sc);
-
 	CSR_WRITE_4(sc, ET_TIMER, sc->sc_timer);
 
 	ifp->if_drv_flags |= IFF_DRV_RUNNING;
 	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
-back:
+
+	sc->sc_flags &= ~ET_FLAG_LINK;
+	et_ifmedia_upd_locked(ifp);
+
+	callout_reset(&sc->sc_tick, hz, et_tick, sc);
+
+fail:
 	if (error)
 		et_stop(sc);
 }
@@ -1239,10 +1343,10 @@ et_start_locked(struct ifnet *ifp)
 	sc = ifp->if_softc;
 	ET_LOCK_ASSERT(sc);
 
-	if ((sc->sc_flags & ET_FLAG_TXRX_ENABLED) == 0)
-		return;
-
-	if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != IFF_DRV_RUNNING)
+	if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
+	    IFF_DRV_RUNNING ||
+	    (sc->sc_flags & (ET_FLAG_LINK | ET_FLAG_TXRX_ENABLED)) !=
+	    (ET_FLAG_LINK | ET_FLAG_TXRX_ENABLED))
 		return;
 
 	/*
@@ -1870,56 +1974,6 @@ et_start_txdma(struct et_softc *sc)
 	return (0);
 }
 
-static int
-et_enable_txrx(struct et_softc *sc, int media_upd)
-{
-	struct ifnet *ifp = sc->ifp;
-	uint32_t val;
-	int i, error;
-
-	val = CSR_READ_4(sc, ET_MAC_CFG1);
-	val |= ET_MAC_CFG1_TXEN | ET_MAC_CFG1_RXEN;
-	val &= ~(ET_MAC_CFG1_TXFLOW | ET_MAC_CFG1_RXFLOW |
-		 ET_MAC_CFG1_LOOPBACK);
-	CSR_WRITE_4(sc, ET_MAC_CFG1, val);
-
-	if (media_upd)
-		et_ifmedia_upd_locked(ifp);
-	else
-		et_setmedia(sc);
-
-#define NRETRY	50
-
-	for (i = 0; i < NRETRY; ++i) {
-		val = CSR_READ_4(sc, ET_MAC_CFG1);
-		if ((val & (ET_MAC_CFG1_SYNC_TXEN | ET_MAC_CFG1_SYNC_RXEN)) ==
-		    (ET_MAC_CFG1_SYNC_TXEN | ET_MAC_CFG1_SYNC_RXEN))
-			break;
-
-		DELAY(100);
-	}
-	if (i == NRETRY) {
-		if_printf(ifp, "can't enable RX/TX\n");
-		return (0);
-	}
-	sc->sc_flags |= ET_FLAG_TXRX_ENABLED;
-
-#undef NRETRY
-
-	/*
-	 * Start TX/RX DMA engine
-	 */
-	error = et_start_rxdma(sc);
-	if (error)
-		return (error);
-
-	error = et_start_txdma(sc);
-	if (error)
-		return (error);
-
-	return (0);
-}
-
 static void
 et_rxeof(struct et_softc *sc)
 {
@@ -2192,6 +2246,7 @@ et_txeof(struct et_softc *sc)
 	if (tbd->tbd_used + ET_NSEG_SPARE < ET_TX_NDESC)
 		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
 }
+
 static void
 et_tick(void *xsc)
 {
@@ -2204,13 +2259,6 @@ et_tick(void *xsc)
 	mii = device_get_softc(sc->sc_miibus);
 
 	mii_tick(mii);
-	if ((sc->sc_flags & ET_FLAG_TXRX_ENABLED) == 0 &&
-	    (mii->mii_media_status & IFM_ACTIVE) &&
-	    IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
-		if_printf(ifp, "Link up, enable TX/RX\n");
-		if (et_enable_txrx(sc, 0) == 0)
-			et_start_locked(ifp);
-	}
 	if (et_watchdog(sc) == EJUSTRETURN)
 		return;
 	callout_reset(&sc->sc_tick, hz, et_tick, sc);
@@ -2398,38 +2446,6 @@ back:
 	return (error);
 }
 
-static void
-et_setmedia(struct et_softc *sc)
-{
-	struct mii_data *mii = device_get_softc(sc->sc_miibus);
-	uint32_t cfg2, ctrl;
-
-	cfg2 = CSR_READ_4(sc, ET_MAC_CFG2);
-	cfg2 &= ~(ET_MAC_CFG2_MODE_MII | ET_MAC_CFG2_MODE_GMII |
-		  ET_MAC_CFG2_FDX | ET_MAC_CFG2_BIGFRM);
-	cfg2 |= ET_MAC_CFG2_LENCHK | ET_MAC_CFG2_CRC | ET_MAC_CFG2_PADCRC |
-	    ((7 << ET_MAC_CFG2_PREAMBLE_LEN_SHIFT) &
-	    ET_MAC_CFG2_PREAMBLE_LEN_MASK);
-
-	ctrl = CSR_READ_4(sc, ET_MAC_CTRL);
-	ctrl &= ~(ET_MAC_CTRL_GHDX | ET_MAC_CTRL_MODE_MII);
-
-	if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) {
-		cfg2 |= ET_MAC_CFG2_MODE_GMII;
-	} else {
-		cfg2 |= ET_MAC_CFG2_MODE_MII;
-		ctrl |= ET_MAC_CTRL_MODE_MII;
-	}
-
-	if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX)
-		cfg2 |= ET_MAC_CFG2_FDX;
-	else
-		ctrl |= ET_MAC_CTRL_GHDX;
-
-	CSR_WRITE_4(sc, ET_MAC_CTRL, ctrl);
-	CSR_WRITE_4(sc, ET_MAC_CFG2, cfg2);
-}
-
 static int
 et_suspend(device_t dev)
 {

Modified: head/sys/dev/et/if_etvar.h
==============================================================================
--- head/sys/dev/et/if_etvar.h	Wed Dec  7 21:17:50 2011	(r228330)
+++ head/sys/dev/et/if_etvar.h	Wed Dec  7 21:29:51 2011	(r228331)
@@ -289,7 +289,9 @@ struct et_softc {
 
 #define ET_FLAG_PCIE		0x0001
 #define ET_FLAG_MSI		0x0002
+#define ET_FLAG_FASTETHER	0x0004
 #define ET_FLAG_TXRX_ENABLED	0x0100
 #define ET_FLAG_JUMBO		0x0200
+#define ET_FLAG_LINK		0x8000
 
 #endif	/* !_IF_ETVAR_H */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201112072129.pB7LTpLB056549>