re(4) link goes down when manually setting media type

Pyun YongHyeon pyunyh at gmail.com
Thu Aug 10 09:29:41 UTC 2006


On Tue, Aug 08, 2006 at 10:06:56AM +0200, Jelte Jansen wrote:
 > -----BEGIN PGP SIGNED MESSAGE-----
 > Hash: SHA1
 > 
 > 
 > Hi,
 > 
 > i have a problem with the if_re driver for my gigabit network card
 > (RTL8196). When i set it to autoselect, it works fine,
 > although with apparently random performance problems. When i try to set
 > it to a fixed media type (both 100baseTX and 1000baseTX) the link goes
 > down, and stays down until i set it to autoselect again. It does seem to
 > work when setting it to 10baset/utp.
 > 
 > This happens with the driver in -CURRENT (__FBSDID("$FreeBSD:
 > src/sys/dev/re/if_re.c,v 1.72 2006/08/03 00:15:19 yongari Ex)
 > 
 > I have seen in the issue tracker and on the -current and -stable that
 > there were other problems with the re(4) driver, but did not see this
 > one. Any ideas?
 > 

Due to the poor PHY documentation from RealTek I can't sure but
I guess the RealTek PHY needs to set RGEPHY_BMCR_AUTOEN bit of
RGEPHY_MII_BMCR register and proper ANAR register setting for
manual media type selection.
How about attached patch?

-- 
Regards,
Pyun YongHyeon
-------------- next part --------------
Index: rgephy.c
===================================================================
RCS file: /pool/ncvs/src/sys/dev/mii/rgephy.c,v
retrieving revision 1.10
diff -u -r1.10 rgephy.c
--- rgephy.c	3 Jul 2006 02:53:39 -0000	1.10
+++ rgephy.c	10 Aug 2006 09:28:26 -0000
@@ -166,7 +166,7 @@
 rgephy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
 {
 	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
-	int reg, speed, gig;
+	int reg, speed, gig, anar;
 
 	switch (cmd) {
 	case MII_POLLSTAT:
@@ -196,6 +196,10 @@
 
 		rgephy_reset(sc);	/* XXX hardware bug work-around */
 
+		anar = PHY_READ(sc, RGEPHY_MII_ANAR);
+		anar &= ~(RGEPHY_ANAR_TX_FD | RGEPHY_ANAR_TX |
+		    RGEPHY_ANAR_10_FD | RGEPHY_ANAR_10);
+
 		switch (IFM_SUBTYPE(ife->ifm_media)) {
 		case IFM_AUTO:
 #ifdef foo
@@ -212,28 +216,30 @@
 			goto setit;
 		case IFM_100_TX:
 			speed = RGEPHY_S100;
+			anar |= RGEPHY_ANAR_TX_FD | RGEPHY_ANAR_TX;
 			goto setit;
 		case IFM_10_T:
 			speed = RGEPHY_S10;
+			anar |= RGEPHY_ANAR_10_FD | RGEPHY_ANAR_10;
 setit:
 			rgephy_loop(sc);
 			if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) {
 				speed |= RGEPHY_BMCR_FDX;
 				gig = RGEPHY_1000CTL_AFD;
+				anar &= ~(RGEPHY_ANAR_TX | RGEPHY_ANAR_10);
 			} else {
 				gig = RGEPHY_1000CTL_AHD;
+				anar &=
+				    ~(RGEPHY_ANAR_TX_FD | RGEPHY_ANAR_10_FD);
 			}
 
-			PHY_WRITE(sc, RGEPHY_MII_1000CTL, 0);
-			PHY_WRITE(sc, RGEPHY_MII_BMCR, speed);
-			PHY_WRITE(sc, RGEPHY_MII_ANAR, RGEPHY_SEL_TYPE);
-
-			if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T) 
+			if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T) {
+				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);
 				break;
-
-			PHY_WRITE(sc, RGEPHY_MII_1000CTL, gig);
-			PHY_WRITE(sc, RGEPHY_MII_BMCR,
-			    speed|RGEPHY_BMCR_AUTOEN|RGEPHY_BMCR_STARTNEG);
+			}
 
 			/*
 			 * When settning the link manually, one side must
@@ -250,6 +256,8 @@
 				PHY_WRITE(sc, RGEPHY_MII_1000CTL,
 				    gig|RGEPHY_1000CTL_MSE);
 			}
+			PHY_WRITE(sc, RGEPHY_MII_BMCR, speed |
+			    RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG);
 			break;
 #ifdef foo
 		case IFM_NONE:


More information about the freebsd-current mailing list