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/pci/if_vr.c | |
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/pci/if_vr.c')
-rw-r--r-- | sys/pci/if_vr.c | 38 |
1 files changed, 25 insertions, 13 deletions
diff --git a/sys/pci/if_vr.c b/sys/pci/if_vr.c index 76326b7..18f8fde 100644 --- a/sys/pci/if_vr.c +++ b/sys/pci/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. */ |