Perform an RX reset and TX reset in xl_reset() along with the master

reset command.

I observed some anomalous behavior while testing a 3c905C with a
Dell PowerEdge 4300/500 dual PIII 500Mhz system. The NIC would seem
to work correctly most of the time but would sometimes fail to receive
certain packets, in particular NFS create requests. I could mount
an NFS filesystem from the PowerEdge and do an ls on it, but trying
to do a "touch foo" would hang. Monitoring traffic from another host
revealed that the client was properly sending an NFS create request
but the server was not receiving it. It *did* receive it when I
ran the same test with an Intel fxp card.

I don't understand the exact mechanics of this strange behavior, but
resetting the receiver and transmitter seems to get rid of it. I used
to perform an RX and TX reset in xl_init(), but stopped doing it there
because on 3c905B and later cards this causes the autoneg session to
restart, which would lead to the NIC waiting a long time before exchanging
traffic after being brought up the first time. Apparently the receiver
and transmitter resets should be performed at least once when initializing
the card.

Hopefully this will cure problems that people have been having with the
3c905C -- this was the only strange behavior that I have observed with
the 3c905C so far which does not appear with the 3c905B or 3c905.
This commit is contained in:
Bill Paul 1999-08-02 21:06:16 +00:00
parent 962e236ec0
commit 9a65a1c94d

View File

@ -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.44 1999/07/08 00:42:02 wpaul Exp $
* $Id: if_xl.c,v 1.48 1999/07/23 02:06:57 wpaul Exp $
*/
/*
@ -163,7 +163,7 @@
#if !defined(lint)
static const char rcsid[] =
"$Id: if_xl.c,v 1.44 1999/07/08 00:42:02 wpaul Exp $";
"$Id: if_xl.c,v 1.48 1999/07/23 02:06:57 wpaul Exp $";
#endif
/*
@ -1261,6 +1261,12 @@ static void xl_reset(sc)
if (i == XL_TIMEOUT)
printf("xl%d: reset didn't complete\n", sc->xl_unit);
/* Reset TX and RX. */
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_RESET);
xl_wait(sc);
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_RESET);
xl_wait(sc);
/* Wait a little while for the chip to get its brains in order. */
DELAY(100000);
return;
@ -1787,11 +1793,15 @@ static int xl_attach(dev)
case XL_XCVR_AUTO:
#ifdef XL_BACKGROUND_AUTONEG
xl_autoneg_mii(sc, XL_FLAG_SCHEDDELAY, 1);
xl_stop(sc);
#else
if (cold)
if (cold) {
xl_autoneg_mii(sc, XL_FLAG_FORCEDELAY, 1);
else
xl_stop(sc);
} else {
xl_init(sc);
xl_autoneg_mii(sc, XL_FLAG_SCHEDDELAY, 1);
}
#endif
media = sc->ifmedia.ifm_media;
break;
@ -1799,11 +1809,15 @@ static int xl_attach(dev)
case XL_XCVR_MII:
#ifdef XL_BACKGROUND_AUTONEG
xl_autoneg_mii(sc, XL_FLAG_SCHEDDELAY, 1);
xl_stop(sc);
#else
if (cold)
if (cold) {
xl_autoneg_mii(sc, XL_FLAG_FORCEDELAY, 1);
else
xl_stop(sc);
} else {
xl_init(sc);
xl_autoneg_mii(sc, XL_FLAG_SCHEDDELAY, 1);
}
#endif
media = sc->ifmedia.ifm_media;
break;
@ -2895,6 +2909,8 @@ static void xl_watchdog(ifp)
if (sc->xl_autoneg) {
xl_autoneg_mii(sc, XL_FLAG_DELAYTIMEO, 1);
if (!(ifp->if_flags & IFF_UP))
xl_stop(sc);
return;
}
@ -2909,6 +2925,7 @@ static void xl_watchdog(ifp)
xl_txeoc(sc);
xl_txeof(sc);
xl_rxeof(sc);
xl_reset(sc);
xl_init(sc);
if (ifp->if_snd.ifq_head != NULL)