Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 8 Dec 2008 02:34:13 +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: r185753 - in head/sys: dev/re pci
Message-ID:  <200812080234.mB82YDD7042788@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: yongari
Date: Mon Dec  8 02:34:13 2008
New Revision: 185753
URL: http://svn.freebsd.org/changeset/base/185753

Log:
  o Implemented miibus_statchg handler. It detects whether re(4)
    established a valid link or not. In miibus_statchg handler add a
    check for established link is valid one for the controller(e.g.
    1000baseT is not a valid link for fastethernet controllers.)
  o Added a flag RE_FLAG_FASTETHER to mark fastethernet controllers.
  o Added additional check to know whether we've really encountered
    watchdog timeouts or missed Tx completion interrupts. This change
    may help to track down the cause of watchdog timeouts.
  o In interrupt handler, removed a check for link state change
    interrupt. Not all controllers have the bit and re(4) did not
    rely on the event for a long time. In addition, re(4) didn't
    request the interrupt in RL_IMR register.
  
  Tested by:	rpaulo

Modified:
  head/sys/dev/re/if_re.c
  head/sys/pci/if_rlreg.h

Modified: head/sys/dev/re/if_re.c
==============================================================================
--- head/sys/dev/re/if_re.c	Mon Dec  8 01:44:18 2008	(r185752)
+++ head/sys/dev/re/if_re.c	Mon Dec  8 02:34:13 2008	(r185753)
@@ -573,7 +573,39 @@ re_miibus_writereg(device_t dev, int phy
 static void
 re_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;
+		case IFM_1000_T:
+			if ((sc->rl_flags & RL_FLAG_FASTETHER) != 0)
+				break;
+			sc->rl_flags |= RL_FLAG_LINK;
+			break;
+		default:
+			break;
+		}
+	}
+	/*
+	 * RealTek controllers does not provide any interface to
+	 * Tx/Rx MACs for resolved speed, duplex and flow-control
+	 * parameters.
+	 */
 }
 
 /*
@@ -1204,18 +1236,18 @@ re_attach(device_t dev)
 
 	switch (hw_rev->rl_rev) {
 	case RL_HWREV_8139CPLUS:
-		sc->rl_flags |= RL_FLAG_NOJUMBO;
+		sc->rl_flags |= RL_FLAG_NOJUMBO | RL_FLAG_FASTETHER;
 		break;
 	case RL_HWREV_8100E:
 	case RL_HWREV_8101E:
 		sc->rl_flags |= RL_FLAG_NOJUMBO | RL_FLAG_INVMAR |
-		    RL_FLAG_PHYWAKE;
+		    RL_FLAG_PHYWAKE | RL_FLAG_FASTETHER;
 		break;
 	case RL_HWREV_8102E:
 	case RL_HWREV_8102EL:
 		sc->rl_flags |= RL_FLAG_NOJUMBO | RL_FLAG_INVMAR |
 		    RL_FLAG_PHYWAKE | RL_FLAG_PAR | RL_FLAG_DESCV2 |
-		    RL_FLAG_MACSTAT;
+		    RL_FLAG_MACSTAT | RL_FLAG_FASTETHER;
 		break;
 	case RL_HWREV_8168_SPIN1:
 	case RL_HWREV_8168_SPIN2:
@@ -2011,30 +2043,14 @@ re_tick(void *xsc)
 {
 	struct rl_softc		*sc;
 	struct mii_data		*mii;
-	struct ifnet		*ifp;
 
 	sc = xsc;
-	ifp = sc->rl_ifp;
 
 	RL_LOCK_ASSERT(sc);
 
-	re_watchdog(sc);
-
 	mii = device_get_softc(sc->rl_miibus);
 	mii_tick(mii);
-	if ((sc->rl_flags & RL_FLAG_LINK) != 0) {
-		if (!(mii->mii_media_status & IFM_ACTIVE))
-			sc->rl_flags &= ~RL_FLAG_LINK;
-	} else {
-		if (mii->mii_media_status & IFM_ACTIVE &&
-		    IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
-			sc->rl_flags |= RL_FLAG_LINK;
-			if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
-				taskqueue_enqueue_fast(taskqueue_fast,
-				    &sc->rl_txtask);
-		}
-	}
-
+	re_watchdog(sc);
 	callout_reset(&sc->rl_stat_callout, hz, re_tick, sc);
 }
 
@@ -2149,11 +2165,6 @@ re_int_task(void *arg, int npending)
 		re_init_locked(sc);
 	}
 
-	if (status & RL_ISR_LINKCHG) {
-		callout_stop(&sc->rl_stat_callout);
-		re_tick(sc);
-	}
-
 	if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
 		taskqueue_enqueue_fast(taskqueue_fast, &sc->rl_txtask);
 
@@ -2815,18 +2826,30 @@ re_ioctl(struct ifnet *ifp, u_long comma
 static void
 re_watchdog(struct rl_softc *sc)
 {
+	struct ifnet		*ifp;
 
 	RL_LOCK_ASSERT(sc);
 
 	if (sc->rl_watchdog_timer == 0 || --sc->rl_watchdog_timer != 0)
 		return;
 
-	device_printf(sc->rl_dev, "watchdog timeout\n");
-	sc->rl_ifp->if_oerrors++;
-
+	ifp = sc->rl_ifp;
 	re_txeof(sc);
+	if (sc->rl_ldata.rl_tx_free == sc->rl_ldata.rl_tx_desc_cnt) {
+		if_printf(ifp, "watchdog timeout (missed Tx interrupts) "
+		    "-- recovering\n");
+		if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+			taskqueue_enqueue_fast(taskqueue_fast, &sc->rl_txtask);
+		return;
+	}
+
+	if_printf(ifp, "watchdog timeout\n");
+	ifp->if_oerrors++;
+
 	re_rxeof(sc);
 	re_init_locked(sc);
+	if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+		taskqueue_enqueue_fast(taskqueue_fast, &sc->rl_txtask);
 }
 
 /*

Modified: head/sys/pci/if_rlreg.h
==============================================================================
--- head/sys/pci/if_rlreg.h	Mon Dec  8 01:44:18 2008	(r185752)
+++ head/sys/pci/if_rlreg.h	Mon Dec  8 02:34:13 2008	(r185753)
@@ -882,6 +882,7 @@ struct rl_softc {
 #define	RL_FLAG_PAR		0x0020
 #define	RL_FLAG_DESCV2		0x0040
 #define	RL_FLAG_MACSTAT		0x0080
+#define	RL_FLAG_FASTETHER	0x0100
 #define	RL_FLAG_LINK		0x8000
 };
 



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