Pull several fixes which improve TX error handling

from FreeBSD's if_vr.c rev 1.52:
- check more error status in TX descriptor and restart TX module
  appropriately in vr_txeof()
- check more error interrupt status in vr_intr()

I can't confirm whether these changes actually fix TX stalls because
I can't reproduce the problem I had about seven years ago (I guess
it might be caused by excessive collisions on a dumb hub), but at least
they don't seem to have bad side effects on normal operations on my macppc.
This commit is contained in:
tsutsui 2006-11-03 08:41:05 +00:00
parent 57a0051fe5
commit 690e60f366
2 changed files with 46 additions and 25 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_vr.c,v 1.81 2006/11/02 17:32:11 tsutsui Exp $ */
/* $NetBSD: if_vr.c,v 1.82 2006/11/03 08:41:05 tsutsui Exp $ */
/*-
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
@ -104,7 +104,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: if_vr.c,v 1.81 2006/11/02 17:32:11 tsutsui Exp $");
__KERNEL_RCSID(0, "$NetBSD: if_vr.c,v 1.82 2006/11/03 08:41:05 tsutsui Exp $");
#include "rnd.h"
@ -832,7 +832,7 @@ vr_txeof(struct vr_softc *sc)
struct vr_desc *d;
struct vr_descsoft *ds;
u_int32_t txstat;
int i;
int i, j;
ifp->if_flags &= ~IFF_OACTIVE;
@ -848,6 +848,25 @@ vr_txeof(struct vr_softc *sc)
VR_CDTXSYNC(sc, i, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
txstat = le32toh(d->vr_status);
if (txstat & (VR_TXSTAT_ABRT | VR_TXSTAT_UDF)) {
VR_CLRBIT16(sc, VR_COMMAND, VR_CMD_TX_ON);
for (j = 0; j < VR_TIMEOUT; j++) {
DELAY(10);
if ((CSR_READ_2(sc, VR_COMMAND) &
VR_CMD_TX_ON) == 0)
break;
}
if (j == VR_TIMEOUT) {
/* XXX need reset? */
printf("%s: TX shutdown never complete\n",
sc->vr_dev.dv_xname);
}
d->vr_status = htole32(VR_TXSTAT_OWN);
CSR_WRITE_4(sc, VR_TXADDR, VR_CDTXADDR(sc, i));
break;
}
if (txstat & VR_TXSTAT_OWN)
break;
@ -927,18 +946,33 @@ vr_intr(void *arg)
(VR_ISR_RX_ERR | VR_ISR_RX_NOBUF | VR_ISR_RX_OFLOW))
vr_rxeoc(sc);
if (status & (VR_ISR_BUSERR | VR_ISR_TX_UNDERRUN)) {
if (status & VR_ISR_BUSERR)
printf("%s: PCI bus error\n",
sc->vr_dev.dv_xname);
if (status & VR_ISR_TX_UNDERRUN)
printf("%s: transmit underrun\n",
sc->vr_dev.dv_xname);
/* vr_init() calls vr_start() */
dotx = 0;
(void)vr_init(ifp);
}
if (status & VR_ISR_TX_OK) {
dotx = 1;
vr_txeof(sc);
}
if (status & (VR_ISR_TX_UNDERRUN | VR_ISR_TX_ABRT)) {
if (status & VR_ISR_TX_UNDERRUN)
printf("%s: transmit underrun\n",
sc->vr_dev.dv_xname);
if (status & VR_ISR_TX_ABRT)
if (status &
(VR_ISR_TX_ABRT | VR_ISR_TX_ABRT2 | VR_ISR_TX_UDFI)) {
if (status & (VR_ISR_TX_ABRT | VR_ISR_TX_ABRT2))
printf("%s: transmit aborted\n",
sc->vr_dev.dv_xname);
if (status & VR_ISR_TX_UDFI)
printf("%s: transmit underflow\n",
sc->vr_dev.dv_xname);
ifp->if_oerrors++;
dotx = 1;
vr_txeof(sc);
@ -946,22 +980,6 @@ vr_intr(void *arg)
VR_SETBIT16(sc, VR_COMMAND, VR_CMD_TX_ON);
VR_SETBIT16(sc, VR_COMMAND, VR_CMD_TX_GO);
}
/*
* Unfortunately many cards get stuck after
* aborted transmits, so we reset them.
*/
if (status & VR_ISR_TX_ABRT) {
printf("%s: restarting\n", sc->vr_dev.dv_xname);
dotx = 0;
(void) vr_init(ifp);
}
}
if (status & VR_ISR_BUSERR) {
printf("%s: PCI bus error\n", sc->vr_dev.dv_xname);
/* vr_init() calls vr_start() */
dotx = 0;
(void) vr_init(ifp);
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_vrreg.h,v 1.14 2006/11/02 10:44:30 tsutsui Exp $ */
/* $NetBSD: if_vrreg.h,v 1.15 2006/11/03 08:41:05 tsutsui Exp $ */
/*
* Copyright (c) 1997, 1998
@ -155,6 +155,8 @@
#define VR_ISR_STATSOFLOW 0x0080 /* stats counter oflow */
#define VR_ISR_RX_EARLY 0x0100 /* rx early */
#define VR_ISR_LINKSTAT 0x0200 /* MII status change */
#define VR_ISR_TX_ETI 0x0200 /* TX early (3043/3071) */
#define VR_ISR_TX_UDFI 0x0200 /* TX FIFO underflow (3065) */
#define VR_ISR_RX_OFLOW 0x0400 /* rx FIFO overflow */
#define VR_ISR_RX_DROPPED 0x0800
#define VR_ISR_RX_NOBUF2 0x1000
@ -371,6 +373,7 @@ struct vr_desc {
#define VR_TXSTAT_ABRT 0x00000100
#define VR_TXSTAT_LATECOLL 0x00000200
#define VR_TXSTAT_CARRLOST 0x00000400
#define VR_TXSTAT_UDF 0x00000800
#define VR_TXSTAT_BUSERR 0x00002000
#define VR_TXSTAT_JABTIMEO 0x00004000
#define VR_TXSTAT_ERRSUM 0x00008000