diff options
author | wpaul <wpaul@FreeBSD.org> | 1998-09-08 23:42:10 +0000 |
---|---|---|
committer | wpaul <wpaul@FreeBSD.org> | 1998-09-08 23:42:10 +0000 |
commit | 166efce87664bcc58f164d78dd7f0710ea66a474 (patch) | |
tree | b5c872fd9db2698215f5bbe7b4445c7c4981ed0f /sys | |
parent | 347d8d653af3d3e6592aa5cf28282feb71ba8efe (diff) | |
download | FreeBSD-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.c | 72 |
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. */ |