svn commit: r215298 - head/sys/dev/mii

Marius Strobl marius at FreeBSD.org
Sun Nov 14 13:31:01 UTC 2010


Author: marius
Date: Sun Nov 14 13:31:01 2010
New Revision: 215298
URL: http://svn.freebsd.org/changeset/base/215298

Log:
  - Change these drivers to take advantage and use the generic IEEE 802.3
    annex 31B full duplex flow control as well as the IFM_1000_T master
    support committed in r215297. For atphy(4) and jmphy(4) this includes
    changing these PHY drivers to no longer unconditionally advertise
    support for flow control but only if the selected media has IFM_FLOW
    set (or MIIF_FORCEPAUSE is set).
  - Rename {atphy,jmphy}_auto() to {atphy,jmphy}_setmedia() as these handle
    other media types as well.
  
  Reviewed by:	yongari (plus additional testing)
  Obtained from:	NetBSD (partially), OpenBSD (partially)
  MFC after:	2 weeks

Modified:
  head/sys/dev/mii/atphy.c
  head/sys/dev/mii/gentbi.c
  head/sys/dev/mii/jmphy.c
  head/sys/dev/mii/nsgphy.c
  head/sys/dev/mii/rgephy.c

Modified: head/sys/dev/mii/atphy.c
==============================================================================
--- head/sys/dev/mii/atphy.c	Sun Nov 14 13:26:10 2010	(r215297)
+++ head/sys/dev/mii/atphy.c	Sun Nov 14 13:31:01 2010	(r215298)
@@ -82,7 +82,7 @@ static int	atphy_service(struct mii_soft
 static void	atphy_status(struct mii_softc *);
 static void	atphy_reset(struct mii_softc *);
 static uint16_t	atphy_anar(struct ifmedia_entry *);
-static int	atphy_auto(struct mii_softc *);
+static int	atphy_setmedia(struct mii_softc *, int);
 
 static const struct mii_phydesc atphys[] = {
 	MII_PHY_DESC(ATHEROS, F1),
@@ -158,7 +158,7 @@ atphy_service(struct mii_softc *sc, stru
 
 		if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO ||
 		    IFM_SUBTYPE(ife->ifm_media) == IFM_1000_T) {
-			atphy_auto(sc);
+			atphy_setmedia(sc, ife->ifm_media);
 			break;
 		}
 
@@ -175,7 +175,7 @@ atphy_service(struct mii_softc *sc, stru
 			/*
 			 * XXX
 			 * Due to an unknown reason powering down PHY resulted
-			 * in unexpected results such as inaccessbility of
+			 * in unexpected results such as inaccessibility of
 			 * hardware of freshly rebooted system. Disable
 			 * powering down PHY until I got more information for
 			 * Attansic/Atheros PHY hardwares.
@@ -189,8 +189,9 @@ atphy_service(struct mii_softc *sc, stru
 		anar = atphy_anar(ife);
 		if (((ife->ifm_media & IFM_GMASK) & IFM_FDX) != 0) {
 			bmcr |= BMCR_FDX;
-			/* Enable pause. */
-			anar |= (3 << 10);
+			if (((ife->ifm_media & IFM_GMASK) & IFM_FLOW) != 0 ||
+			    (sc->mii_flags & MIIF_FORCEPAUSE) != 0)
+				anar |= ANAR_PAUSE_TOWARDS;
 		}
 
 		if ((sc->mii_extcapabilities & (EXTSR_1000TFDX |
@@ -222,7 +223,7 @@ done:
 		}
 
 		/*
-		 * check for link.
+		 * Check for link.
 		 * Read the status register twice; BMSR_LINK is latch-low.
 		 */
 		bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
@@ -238,7 +239,7 @@ done:
 			return (0);
 
 		sc->mii_ticks = 0;
-		atphy_auto(sc);
+		atphy_setmedia(sc, ife->ifm_media);
 		break;
 	}
 
@@ -284,7 +285,7 @@ atphy_status(struct mii_softc *sc)
 	case ATPHY_SSR_1000MBS:
 		mii->mii_media_active |= IFM_1000_T;
 		/*
-		 * atphy(4) got a valid link so reset mii_ticks.
+		 * atphy(4) has a valid link so reset mii_ticks.
 		 * Resetting mii_ticks is needed in order to
 		 * detect link loss after auto-negotiation.
 		 */
@@ -304,11 +305,13 @@ atphy_status(struct mii_softc *sc)
 	}
 
 	if ((ssr & ATPHY_SSR_DUPLEX) != 0)
-		mii->mii_media_active |= IFM_FDX;
+		mii->mii_media_active |= IFM_FDX | mii_phy_flowstatus(sc);
 	else
 		mii->mii_media_active |= IFM_HDX;
 		
-	/* XXX Master/Slave, Flow-control */
+	if ((IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) &&
+	    (PHY_READ(sc, MII_100T2SR) & GTSR_MS_RES) != 0)
+		mii->mii_media_active |= IFM_ETH_MASTER;
 }
 
 static void
@@ -336,7 +339,7 @@ atphy_reset(struct mii_softc *sc)
 	PHY_WRITE(sc, ATPHY_SCR, reg);
 
 	/* Workaround F1 bug to reset phy. */
-	atphy_auto(sc);
+	atphy_setmedia(sc, sc->mii_pdata->mii_media.ifm_cur->ifm_media);
 
 	for (i = 0; i < 1000; i++) {
 		DELAY(1);
@@ -378,12 +381,17 @@ atphy_anar(struct ifmedia_entry *ife)
 }
 
 static int
-atphy_auto(struct mii_softc *sc)
+atphy_setmedia(struct mii_softc *sc, int media)
 {
 	uint16_t anar;
 
-	anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities);
-	PHY_WRITE(sc, MII_ANAR, anar | (3 << 10) | ANAR_CSMA);
+	anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA;
+	if (((IFM_SUBTYPE(media) == IFM_AUTO ||
+	    ((media & IFM_GMASK) & IFM_FDX) != 0) &&
+	    ((media & IFM_GMASK) & IFM_FLOW) != 0) ||
+	    (sc->mii_flags & MIIF_FORCEPAUSE) != 0)
+		anar |= ANAR_PAUSE_TOWARDS;
+	PHY_WRITE(sc, MII_ANAR, anar);
 	if ((sc->mii_extcapabilities & (EXTSR_1000TFDX | EXTSR_1000THDX)) != 0)
 		PHY_WRITE(sc, MII_100T2CR, GTCR_ADV_1000TFDX |
 		    GTCR_ADV_1000THDX);

Modified: head/sys/dev/mii/gentbi.c
==============================================================================
--- head/sys/dev/mii/gentbi.c	Sun Nov 14 13:26:10 2010	(r215297)
+++ head/sys/dev/mii/gentbi.c	Sun Nov 14 13:31:01 2010	(r215298)
@@ -267,7 +267,8 @@ gentbi_status(struct mii_softc *sc)
 		anlpar = PHY_READ(sc, MII_ANLPAR);
 		if ((sc->mii_extcapabilities & EXTSR_1000XFDX) != 0 &&
 		    (anlpar & ANLPAR_X_FD) != 0)
-			mii->mii_media_active |= IFM_FDX;
+			mii->mii_media_active |=
+			    IFM_FDX | mii_phy_flowstatus(sc);
 		else
 			mii->mii_media_active |= IFM_HDX;
 	} else

Modified: head/sys/dev/mii/jmphy.c
==============================================================================
--- head/sys/dev/mii/jmphy.c	Sun Nov 14 13:26:10 2010	(r215297)
+++ head/sys/dev/mii/jmphy.c	Sun Nov 14 13:31:01 2010	(r215298)
@@ -50,11 +50,11 @@ __FBSDID("$FreeBSD$");
 
 #include "miibus_if.h"
 
-static int 	jmphy_probe(device_t);
-static int 	jmphy_attach(device_t);
+static int	jmphy_probe(device_t);
+static int	jmphy_attach(device_t);
 static void	jmphy_reset(struct mii_softc *);
 static uint16_t	jmphy_anar(struct ifmedia_entry *);
-static int	jmphy_auto(struct mii_softc *, struct ifmedia_entry *);
+static int	jmphy_setmedia(struct mii_softc *, struct ifmedia_entry *);
 
 struct jmphy_softc {
 	struct mii_softc mii_sc;
@@ -154,7 +154,7 @@ jmphy_service(struct mii_softc *sc, stru
 		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
 			break;
 
-		if (jmphy_auto(sc, ife) != EJUSTRETURN)
+		if (jmphy_setmedia(sc, ife) != EJUSTRETURN)
 			return (EINVAL);
 		break;
 
@@ -186,7 +186,7 @@ jmphy_service(struct mii_softc *sc, stru
 			return (0);
 
 		sc->mii_ticks = 0;
-		jmphy_auto(sc, ife);
+		(void)jmphy_setmedia(sc, ife);
 		break;
 	}
 
@@ -251,16 +251,14 @@ jmphy_status(struct mii_softc *sc)
 	}
 
 	if ((ssr & JMPHY_SSR_DUPLEX) != 0)
-		mii->mii_media_active |= IFM_FDX;
+		mii->mii_media_active |= IFM_FDX | mii_phy_flowstatus(sc);
 	else
 		mii->mii_media_active |= IFM_HDX;
-	/* XXX Flow-control. */
-#ifdef notyet
+
 	if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) {
 		if ((PHY_READ(sc, MII_100T2SR) & GTSR_MS_RES) != 0)
 			mii->mii_media_active |= IFM_ETH_MASTER;
 	}
-#endif
 }
 
 static void
@@ -309,7 +307,7 @@ jmphy_anar(struct ifmedia_entry *ife)
 }
 
 static int
-jmphy_auto(struct mii_softc *sc, struct ifmedia_entry *ife)
+jmphy_setmedia(struct mii_softc *sc, struct ifmedia_entry *ife)
 {
 	uint16_t anar, bmcr, gig;
 
@@ -336,17 +334,18 @@ jmphy_auto(struct mii_softc *sc, struct 
 		bmcr |= BMCR_LOOP;
 
 	anar = jmphy_anar(ife);
-	/* XXX Always advertise pause capability. */
-	anar |= (3 << 10);
+	if (((IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO ||
+	    (ife->ifm_media & IFM_FDX) != 0) &&
+	    (ife->ifm_media & IFM_FLOW) != 0) ||
+	    (sc->mii_flags & MIIF_FORCEPAUSE) != 0)
+		anar |= ANAR_PAUSE_TOWARDS;
 
 	if ((sc->mii_flags & MIIF_HAVE_GTCR) != 0) {
-#ifdef notyet
-		struct mii_data *mii;
-
-		mii = sc->mii_pdata;
-		if ((mii->mii_media.ifm_media & IFM_ETH_MASTER) != 0)
-			gig |= GTCR_MAN_MS | GTCR_MAN_ADV;
-#endif
+		if (IFM_SUBTYPE(ife->ifm_media) == IFM_1000_T) {
+			gig |= GTCR_MAN_MS;
+			if ((ife->ifm_media & IFM_ETH_MASTER) != 0)
+				gig |= GTCR_ADV_MS;
+		}
 		PHY_WRITE(sc, MII_100T2CR, gig);
 	}
 	PHY_WRITE(sc, MII_ANAR, anar | ANAR_CSMA);

Modified: head/sys/dev/mii/nsgphy.c
==============================================================================
--- head/sys/dev/mii/nsgphy.c	Sun Nov 14 13:26:10 2010	(r215297)
+++ head/sys/dev/mii/nsgphy.c	Sun Nov 14 13:31:01 2010	(r215298)
@@ -246,7 +246,8 @@ nsgphy_status(struct mii_softc *sc)
 		}
 
 		if (physup & PHY_SUP_DUPLEX)
-			mii->mii_media_active |= IFM_FDX;
+			mii->mii_media_active |=
+			    IFM_FDX | mii_phy_flowstatus(sc);
 		else
 			mii->mii_media_active |= IFM_HDX;
 	} else

Modified: head/sys/dev/mii/rgephy.c
==============================================================================
--- head/sys/dev/mii/rgephy.c	Sun Nov 14 13:26:10 2010	(r215297)
+++ head/sys/dev/mii/rgephy.c	Sun Nov 14 13:31:01 2010	(r215298)
@@ -89,7 +89,7 @@ DRIVER_MODULE(rgephy, miibus, rgephy_dri
 
 static int	rgephy_service(struct mii_softc *, struct mii_data *, int);
 static void	rgephy_status(struct mii_softc *);
-static int	rgephy_mii_phy_auto(struct mii_softc *);
+static int	rgephy_mii_phy_auto(struct mii_softc *, int);
 static void	rgephy_reset(struct mii_softc *);
 static void	rgephy_loop(struct mii_softc *);
 static void	rgephy_load_dspcode(struct mii_softc *);
@@ -113,7 +113,6 @@ rgephy_attach(device_t dev)
 	struct mii_softc *sc;
 	struct mii_attach_args *ma;
 	struct mii_data *mii;
-	const char *sep = "";
 
 	rsc = device_get_softc(dev);
 	sc = &rsc->mii_sc;
@@ -132,27 +131,21 @@ rgephy_attach(device_t dev)
 	rsc->mii_revision = MII_REV(ma->mii_id2);
 
 #define	ADD(m, c)	ifmedia_add(&mii->mii_media, (m), (c), NULL)
-#define PRINT(s)	printf("%s%s", sep, s); sep = ", "
 
 #if 0
 	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst),
 	    MII_MEDIA_100_TX);
 #endif
 
-	sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
-	sc->mii_capabilities &= ~BMSR_ANEG;
+	/* RTL8169S do not report auto-sense; add manually. */
+	sc->mii_capabilities = (PHY_READ(sc, MII_BMSR) | BMSR_ANEG) &
+	    ma->mii_capmask;
 	if (sc->mii_capabilities & BMSR_EXTSTAT)
 		sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
-
 	device_printf(dev, " ");
 	mii_phy_add_media(sc);
-	/* RTL8169S do not report auto-sense; add manually. */
-	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), MII_NMEDIA);
-	sep = ", ";
-	PRINT("auto");
 	printf("\n");
 #undef ADD
-#undef PRINT
 
 	rgephy_reset(sc);
 	MIIBUS_MEDIAINIT(sc->mii_dev);
@@ -182,7 +175,8 @@ rgephy_service(struct mii_softc *sc, str
 		rgephy_reset(sc);	/* XXX hardware bug work-around */
 
 		anar = PHY_READ(sc, RGEPHY_MII_ANAR);
-		anar &= ~(RGEPHY_ANAR_TX_FD | RGEPHY_ANAR_TX |
+		anar &= ~(RGEPHY_ANAR_PC | RGEPHY_ANAR_ASP |
+		    RGEPHY_ANAR_TX_FD | RGEPHY_ANAR_TX |
 		    RGEPHY_ANAR_10_FD | RGEPHY_ANAR_10);
 
 		switch (IFM_SUBTYPE(ife->ifm_media)) {
@@ -194,7 +188,7 @@ rgephy_service(struct mii_softc *sc, str
 			if (PHY_READ(sc, RGEPHY_MII_BMCR) & RGEPHY_BMCR_AUTOEN)
 				return (0);
 #endif
-			(void) rgephy_mii_phy_auto(sc);
+			(void)rgephy_mii_phy_auto(sc, ife->ifm_media);
 			break;
 		case IFM_1000_T:
 			speed = RGEPHY_S1000;
@@ -222,32 +216,26 @@ setit:
 				PHY_WRITE(sc, RGEPHY_MII_1000CTL, 0);
 				PHY_WRITE(sc, RGEPHY_MII_ANAR, anar);
 				PHY_WRITE(sc, RGEPHY_MII_BMCR, speed |
-				    RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG);
+				    RGEPHY_BMCR_AUTOEN |
+				    RGEPHY_BMCR_STARTNEG);
 				break;
 			}
 
-			/*
-			 * When setting the link manually, one side must
-			 * be the master and the other the slave. However
-			 * ifmedia doesn't give us a good way to specify
-			 * this, so we fake it by using one of the LINK
-			 * flags. If LINK0 is set, we program the PHY to
-			 * be a master, otherwise it's a slave.
-			 */
-			if ((mii->mii_ifp->if_flags & IFF_LINK0)) {
-				PHY_WRITE(sc, RGEPHY_MII_1000CTL,
-				    gig|RGEPHY_1000CTL_MSE|RGEPHY_1000CTL_MSC);
-			} else {
-				PHY_WRITE(sc, RGEPHY_MII_1000CTL,
-				    gig|RGEPHY_1000CTL_MSE);
-			}
+			if ((ife->ifm_media & IFM_FLOW) != 0 ||
+			    (sc->mii_flags & MIIF_FORCEPAUSE) != 0)
+				anar |= RGEPHY_ANAR_PC | RGEPHY_ANAR_ASP;
+
+			gig |= RGEPHY_1000CTL_MSE;
+			if ((ife->ifm_media & IFM_ETH_MASTER) != 0)
+			    gig |= RGEPHY_1000CTL_MSC;
+			PHY_WRITE(sc, RGEPHY_MII_1000CTL, gig);
+			PHY_WRITE(sc, RGEPHY_MII_ANAR, anar);
 			PHY_WRITE(sc, RGEPHY_MII_BMCR, speed |
 			    RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG);
 			break;
 		case IFM_NONE:
-			PHY_WRITE(sc, MII_BMCR, BMCR_ISO|BMCR_PDOWN);
+			PHY_WRITE(sc, MII_BMCR, BMCR_ISO | BMCR_PDOWN);
 			break;
-		case IFM_100_T4:
 		default:
 			return (EINVAL);
 		}
@@ -297,7 +285,7 @@ setit:
 			return (0);
 
 		sc->mii_ticks = 0;
-		rgephy_mii_phy_auto(sc);
+		rgephy_mii_phy_auto(sc, ife->ifm_media);
 		break;
 	}
 
@@ -395,22 +383,32 @@ rgephy_status(struct mii_softc *sc)
 		else
 			mii->mii_media_active |= IFM_HDX;
 	}
+
+	if ((mii->mii_media_active & IFM_FDX) != 0)
+		mii->mii_media_active |= mii_phy_flowstatus(sc);
+
+	if ((IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) &&
+	    (PHY_READ(sc, RGEPHY_MII_1000STS) & RGEPHY_1000STS_MSR) != 0)
+		mii->mii_media_active |= IFM_ETH_MASTER;
 }
 
 static int
-rgephy_mii_phy_auto(struct mii_softc *mii)
+rgephy_mii_phy_auto(struct mii_softc *sc, int media)
 {
+	int anar;
 
-	rgephy_loop(mii);
-	rgephy_reset(mii);
+	rgephy_loop(sc);
+	rgephy_reset(sc);
 
-	PHY_WRITE(mii, RGEPHY_MII_ANAR,
-	    BMSR_MEDIA_TO_ANAR(mii->mii_capabilities) | ANAR_CSMA);
+	anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA;
+	if ((media & IFM_FLOW) != 0 || (sc->mii_flags & MIIF_FORCEPAUSE) != 0)
+		anar |= RGEPHY_ANAR_PC | RGEPHY_ANAR_ASP;
+	PHY_WRITE(sc, RGEPHY_MII_ANAR, anar);
 	DELAY(1000);
-	PHY_WRITE(mii, RGEPHY_MII_1000CTL,
-            RGEPHY_1000CTL_AHD|RGEPHY_1000CTL_AFD);
+	PHY_WRITE(sc, RGEPHY_MII_1000CTL,
+	    RGEPHY_1000CTL_AHD | RGEPHY_1000CTL_AFD);
 	DELAY(1000);
-	PHY_WRITE(mii, RGEPHY_MII_BMCR,
+	PHY_WRITE(sc, RGEPHY_MII_BMCR,
 	    RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG);
 	DELAY(100);
 


More information about the svn-src-all mailing list