summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>1998-09-08 23:42:10 +0000
committerwpaul <wpaul@FreeBSD.org>1998-09-08 23:42:10 +0000
commit166efce87664bcc58f164d78dd7f0710ea66a474 (patch)
treeb5c872fd9db2698215f5bbe7b4445c7c4981ed0f /sys
parent347d8d653af3d3e6592aa5cf28282feb71ba8efe (diff)
downloadFreeBSD-src-166efce87664bcc58f164d78dd7f0710ea66a474.zip
FreeBSD-src-166efce87664bcc58f164d78dd7f0710ea66a474.tar.gz
- If the OACTIVE flag is set on entry to xl_start(), check to see if the
transmitter is wedged. If so, try to unwedge it, process any descriptors that might need to be free()d, then proceed. - Disable the 'background' autonegotiation performed during bootstrap. What happens currently is that the driver starts an autoneg session, the sets a timeout in the ifnet structure and returns. Later, when the timer expires, the watchdog routine calls the autoneg handler to check the results of the session. The problem with this is that the session may not complete until some point after we have started to mount NFS filesystems, which can cause the mounts to fail. This is especially troublesome if booting with an NFS rootfs: we need the interface up and running before reaching the mountroot() code. The default behavior now is to do the autoneg synchronously, i.e. wait 5 seconds for the autoneg to complete before exiting the driver attach routine. People who want the old behavior can compile the driver with XL_BACKGROUND_AUTONEG #defined. This has no effect on autoneg sessions initiated by 'ifconfig xl0 media autoselect.' This slows the probe down a little, but it's either that or botching NFS mounts at bootup. - If xl_setmode_mii() is called and there's an autoneg session in progress, cancel it, _then_ set the modes.
Diffstat (limited to 'sys')
-rw-r--r--sys/pci/if_xl.c72
1 files changed, 68 insertions, 4 deletions
diff --git a/sys/pci/if_xl.c b/sys/pci/if_xl.c
index e818b82..7b24cad 100644
--- a/sys/pci/if_xl.c
+++ b/sys/pci/if_xl.c
@@ -29,7 +29,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: if_xl.c,v 1.9 1998/09/04 16:22:15 wpaul Exp $
+ * $Id: if_xl.c,v 1.53 1998/09/08 16:05:04 wpaul Exp $
*/
/*
@@ -123,11 +123,31 @@
*/
#define XL_USEIOSPACE
+/*
+ * This #define controls the behavior of autonegotiation during the
+ * bootstrap phase. It's possible to have the driver initiate an
+ * autonegotiation session and then set a timeout which will cause the
+ * autoneg results to be polled later, usually once the kernel has
+ * finished booting. This is clever and all, but it can have bad side
+ * effects in some cases, particularly where NFS is involved. For
+ * example, if we're booting diskless with an NFS rootfs, the network
+ * interface has to be up and running before we hit the mountroot()
+ * code, otherwise mounting the rootfs will fail and we'll probably
+ * panic.
+ *
+ * Consequently, the 'backgrounded' autoneg behavior is turned off
+ * by default and we actually sit and wait 5 seconds for autonegotiation
+ * to complete before proceeding with the other device probes. If you
+ * choose to use the other behavior, you can uncomment this #define and
+ * recompile.
+ */
+/* #define XL_BACKGROUND_AUTONEG */
+
#include <pci/if_xlreg.h>
#ifndef lint
static char rcsid[] =
- "$Id: if_xl.c,v 1.9 1998/09/04 16:22:15 wpaul Exp $";
+ "$Id: if_xl.c,v 1.53 1998/09/08 16:05:04 wpaul Exp $";
#endif
/*
@@ -777,7 +797,7 @@ static void xl_autoneg_mii(sc, flag, verbose)
* is really bad manners.
*/
xl_autoneg_xmit(sc);
- DELAY(3000000);
+ DELAY(5000000);
break;
case XL_FLAG_SCHEDDELAY:
/*
@@ -968,6 +988,20 @@ static void xl_setmode_mii(sc, media)
{
u_int16_t bmcr;
u_int32_t icfg;
+ struct ifnet *ifp;
+
+ ifp = &sc->arpcom.ac_if;
+
+ /*
+ * If an autoneg session is in progress, stop it.
+ */
+ if (sc->xl_autoneg) {
+ printf("xl%d: canceling autoneg session\n", sc->xl_unit);
+ ifp->if_timer = sc->xl_autoneg = sc->xl_want_auto = 0;
+ bmcr = xl_phy_readreg(sc, PHY_BMCR);
+ bmcr &= ~PHY_BMCR_AUTONEGENBL;
+ xl_phy_writereg(sc, PHY_BMCR, bmcr);
+ }
printf("xl%d: selecting MII, ", sc->xl_unit);
@@ -1582,12 +1616,20 @@ xl_attach(config_id, unit)
break;
case XL_XCVR_AUTO:
media = IFM_ETHER|IFM_AUTO;
+#ifdef XL_BACKGROUND_AUTONEG
xl_autoneg_mii(sc, XL_FLAG_SCHEDDELAY, 1);
+#else
+ xl_autoneg_mii(sc, XL_FLAG_FORCEDELAY, 1);
+#endif
break;
case XL_XCVR_100BTX:
case XL_XCVR_MII:
media = sc->ifmedia.ifm_media;
+#ifdef XL_BACKGROUND_AUTONEG
xl_autoneg_mii(sc, XL_FLAG_SCHEDDELAY, 1);
+#else
+ xl_autoneg_mii(sc, XL_FLAG_FORCEDELAY, 1);
+#endif
break;
case XL_XCVR_100BFX:
media = IFM_ETHER|IFM_100_FX;
@@ -1595,6 +1637,11 @@ xl_attach(config_id, unit)
default:
printf("xl%d: unknown XCVR type: %d\n", sc->xl_unit,
sc->xl_xcvr);
+ /*
+ * This will probably be wrong, but it prevents
+ * the ifmedia code from panicking.
+ */
+ media = IFM_ETHER|IFM_10_T;
break;
}
@@ -1876,7 +1923,8 @@ static void xl_txeof(sc)
if (sc->xl_want_auto)
xl_autoneg_mii(sc, XL_FLAG_SCHEDDELAY, 1);
} else {
- if (CSR_READ_4(sc, XL_DMACTL) & XL_DMACTL_DOWN_STALLED) {
+ if (CSR_READ_4(sc, XL_DMACTL) & XL_DMACTL_DOWN_STALLED ||
+ !CSR_READ_4(sc, XL_DOWNLIST_PTR)) {
CSR_WRITE_4(sc, XL_DOWNLIST_PTR,
vtophys(sc->xl_cdata.xl_tx_head->xl_ptr));
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_DOWN_UNSTALL);
@@ -2144,6 +2192,22 @@ static void xl_start(ifp)
}
/*
+ * If the OACTIVE flag is set, make sure the transmitter
+ * isn't wedged. Call the txeoc handler to make sure the
+ * transmitter is enabled and then call the txeof handler
+ * to see if any descriptors can be reclaimed and reload
+ * the downlist pointer register if necessary. If after
+ * that the OACTIVE flag is still set, return, otherwise
+ * proceed and queue up some more frames.
+ */
+ if (ifp->if_flags & IFF_OACTIVE) {
+ xl_txeoc(sc);
+ xl_txeof(sc);
+ if (ifp->if_flags & IFF_OACTIVE)
+ return;
+ }
+
+ /*
* Check for an available queue slot. If there are none,
* punt.
*/
OpenPOWER on IntegriCloud