diff options
author | silby <silby@FreeBSD.org> | 2002-08-15 04:04:53 +0000 |
---|---|---|
committer | silby <silby@FreeBSD.org> | 2002-08-15 04:04:53 +0000 |
commit | e4af9029cce2e19945be82d95c075561d2e80ae9 (patch) | |
tree | d6f049cd22ccbbf3bfe7dbad3878defeefef92d5 /sys/dev/vr | |
parent | 849f861756ce407ff63685e6bee7aa674929e2fb (diff) | |
download | FreeBSD-src-e4af9029cce2e19945be82d95c075561d2e80ae9.zip FreeBSD-src-e4af9029cce2e19945be82d95c075561d2e80ae9.tar.gz |
Improve handling of TX errors. Early reports indicate that this
elimiates the driver lockup problem reported by many.
Concepts used were taken from Via's if_fet driver. Verification
and implementation were done by Thomas Nystrom.
Submitted by: Thomas Nystrom <thn@saeab.se>
MFC after: 3 days
Diffstat (limited to 'sys/dev/vr')
-rw-r--r-- | sys/dev/vr/if_vr.c | 38 | ||||
-rw-r--r-- | sys/dev/vr/if_vrreg.h | 3 |
2 files changed, 28 insertions, 13 deletions
diff --git a/sys/dev/vr/if_vr.c b/sys/dev/vr/if_vr.c index 76326b7..18f8fde 100644 --- a/sys/dev/vr/if_vr.c +++ b/sys/dev/vr/if_vr.c @@ -1088,6 +1088,15 @@ static void vr_txeof(sc) cur_tx = sc->vr_cdata.vr_tx_head; txstat = cur_tx->vr_ptr->vr_status; + if ((txstat & VR_TXSTAT_ABRT) || + (txstat & VR_TXSTAT_UDF)) { + while (CSR_READ_2(sc, VR_COMMAND) & VR_CMD_TX_ON) + ; /* Wait for chip to shutdown */ + VR_TXOWN(cur_tx) = VR_TXSTAT_OWN; + CSR_WRITE_4(sc, VR_TXADDR, vtophys(cur_tx->vr_ptr)); + break; + } + if (txstat & VR_TXSTAT_OWN) break; @@ -1196,24 +1205,27 @@ static void vr_intr(arg) vr_rxeoc(sc); } - if (status & VR_ISR_TX_OK) { - vr_txeof(sc); - vr_txeoc(sc); + if ((status & VR_ISR_BUSERR) || (status & VR_ISR_TX_UNDERRUN)) { + vr_reset(sc); + vr_init(sc); + break; } - if ((status & VR_ISR_TX_UNDERRUN)||(status & VR_ISR_TX_ABRT)){ - ifp->if_oerrors++; + if ((status & VR_ISR_TX_OK) || (status & VR_ISR_TX_ABRT) || + (status & VR_ISR_TX_ABRT2) || (status & VR_ISR_UDFI)) { vr_txeof(sc); - if (sc->vr_cdata.vr_tx_head != NULL) { - VR_SETBIT16(sc, VR_COMMAND, VR_CMD_TX_ON); - VR_SETBIT16(sc, VR_COMMAND, VR_CMD_TX_GO); - } + if ((status & VR_ISR_UDFI) || + (status & VR_ISR_TX_ABRT2) || + (status & VR_ISR_TX_ABRT)) { + ifp->if_oerrors++; + if (sc->vr_cdata.vr_tx_head != NULL) { + VR_SETBIT16(sc, VR_COMMAND, VR_CMD_TX_ON); + VR_SETBIT16(sc, VR_COMMAND, VR_CMD_TX_GO); + } + } else + vr_txeoc(sc); } - if (status & VR_ISR_BUSERR) { - vr_reset(sc); - vr_init(sc); - } } /* Re-enable interrupts. */ diff --git a/sys/dev/vr/if_vrreg.h b/sys/dev/vr/if_vrreg.h index 73b074e..47718bb 100644 --- a/sys/dev/vr/if_vrreg.h +++ b/sys/dev/vr/if_vrreg.h @@ -149,6 +149,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_ETI 0x0200 /* Tx early (3043/3071) */ +#define VR_ISR_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 @@ -368,6 +370,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 |