Date: Sat, 14 Dec 2002 23:12:55 +0100 From: Thomas Nystrom <thn@saeab.se> To: stable@freebsd.org Subject: Fix for hanging of vr interface (Rhine Ethernet) Message-ID: <3DFBACE7.1D60335F@saeab.se>
next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------8361301D639C7819FBE5AD82
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit
Hello list!
There have been some issues with hanging of the vr-type of
ethernetcontrollers. I have made a patch that solves some problems and I'm
now seeking people to test it. Please apply the attached patch to your
vr-driver and see if it solves any problems for you. I have tested (and
made) the patch on a 4.7-RELEASE with the latest vr-drivers.
/thn
--
---------------------------------------------------------------
Svensk Aktuell Elektronik AB Thomas Nyström
Box 10 Phone: +46 8 35 92 85
S-191 21 Sollentuna Fax: +46 8 59 47 45 36
Sweden Email: thn@saeab.se
---------------------------------------------------------------
--------------8361301D639C7819FBE5AD82
Content-Type: text/plain; charset=us-ascii;
name="vr.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="vr.patch"
--- /root/vr/if_vr.c Thu Dec 12 15:05:50 2002
+++ if_vr.c Fri Dec 13 15:25:13 2002
@@ -991,33 +991,23 @@
*/
if (rxstat & VR_RXSTAT_RXERR) {
ifp->if_ierrors++;
- printf("vr%d: rx error: ", sc->vr_unit);
- switch(rxstat & 0x000000FF) {
- case VR_RXSTAT_CRCERR:
- printf("crc error\n");
- break;
- case VR_RXSTAT_FRAMEALIGNERR:
- printf("frame alignment error\n");
- break;
- case VR_RXSTAT_FIFOOFLOW:
- printf("FIFO overflow\n");
- break;
- case VR_RXSTAT_GIANT:
- printf("received giant packet\n");
- break;
- case VR_RXSTAT_RUNT:
- printf("received runt packet\n");
- break;
- case VR_RXSTAT_BUSERR:
- printf("system bus error\n");
- break;
- case VR_RXSTAT_BUFFERR:
- printf("rx buffer error\n");
- break;
- default:
- printf("unknown rx error\n");
- break;
- }
+ printf("vr%d: rx error (%02x):",
+ sc->vr_unit, rxstat & 0x000000ff);
+ if (rxstat & VR_RXSTAT_CRCERR)
+ printf(" crc error");
+ if (rxstat & VR_RXSTAT_FRAMEALIGNERR)
+ printf(" frame alignment error\n");
+ if (rxstat & VR_RXSTAT_FIFOOFLOW)
+ printf(" FIFO overflow");
+ if (rxstat & VR_RXSTAT_GIANT)
+ printf(" received giant packet");
+ if (rxstat & VR_RXSTAT_RUNT)
+ printf(" received runt packet");
+ if (rxstat & VR_RXSTAT_BUSERR)
+ printf(" system bus error");
+ if (rxstat & VR_RXSTAT_BUFFERR)
+ printf("rx buffer error");
+ printf("\n");
vr_newbuf(sc, cur_rx, m);
continue;
}
@@ -1058,9 +1048,29 @@
void vr_rxeoc(sc)
struct vr_softc *sc;
{
+ struct ifnet *ifp;
+ int i;
+
+ ifp = &sc->arpcom.ac_if;
+
+ ifp->if_ierrors++;
+
+ VR_CLRBIT16(sc, VR_COMMAND, VR_CMD_RX_ON);
+ DELAY(10000);
+
+ for (i = 0x400;
+ i && (CSR_READ_2(sc, VR_COMMAND) & VR_CMD_RX_ON);
+ i--)
+ ; /* Wait for receiver to stop */
+
+ if (!i) {
+ printf("vr%d: rx shutdown error!\n", sc->vr_unit);
+ sc->vr_flags |= VR_F_RESTART;
+ return;
+ }
vr_rxeof(sc);
- VR_CLRBIT16(sc, VR_COMMAND, VR_CMD_RX_ON);
+
CSR_WRITE_4(sc, VR_RXADDR, vtophys(sc->vr_cdata.vr_rx_head->vr_ptr));
VR_SETBIT16(sc, VR_COMMAND, VR_CMD_RX_ON);
VR_SETBIT16(sc, VR_COMMAND, VR_CMD_RX_GO);
@@ -1094,14 +1104,22 @@
*/
while(sc->vr_cdata.vr_tx_head->vr_mbuf != NULL) {
u_int32_t txstat;
+ int i;
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)
+ for (i = 0x400;
+ i && (CSR_READ_2(sc, VR_COMMAND) & VR_CMD_TX_ON);
+ i--)
; /* Wait for chip to shutdown */
+ if (!i) {
+ printf("vr%d: tx shutdown timeout\n", sc->vr_unit);
+ sc->vr_flags |= VR_F_RESTART;
+ break;
+ }
VR_TXOWN(cur_tx) = VR_TXSTAT_OWN;
CSR_WRITE_4(sc, VR_TXADDR, vtophys(cur_tx->vr_ptr));
break;
@@ -1167,6 +1185,14 @@
s = splimp();
sc = xsc;
+ if (sc->vr_flags & VR_F_RESTART) {
+ printf("vr%d: restarting\n", sc->vr_unit);
+ vr_stop(sc);
+ vr_reset(sc);
+ vr_init(sc);
+ sc->vr_flags &= ~VR_F_RESTART;
+ }
+
mii = device_get_softc(sc->vr_miibus);
mii_tick(mii);
@@ -1208,10 +1234,22 @@
if (status & VR_ISR_RX_OK)
vr_rxeof(sc);
+ if (status & VR_ISR_RX_DROPPED) {
+ printf("vr%d: rx packet lost\n", sc->vr_unit);
+ ifp->if_ierrors++;
+ }
+
if ((status & VR_ISR_RX_ERR) || (status & VR_ISR_RX_NOBUF) ||
- (status & VR_ISR_RX_NOBUF) || (status & VR_ISR_RX_OFLOW) ||
- (status & VR_ISR_RX_DROPPED)) {
- vr_rxeof(sc);
+ (status & VR_ISR_RX_NOBUF) || (status & VR_ISR_RX_OFLOW)) {
+ printf("vr%d: receive error (%04x)",
+ sc->vr_unit, status);
+ if (status & VR_ISR_RX_NOBUF)
+ printf(" no buffers");
+ if (status & VR_ISR_RX_OFLOW)
+ printf(" overflow");
+ if (status & VR_ISR_RX_DROPPED)
+ printf(" packet lost");
+ printf("\n");
vr_rxeoc(sc);
}
@@ -1430,13 +1468,13 @@
* so we must set both.
*/
VR_CLRBIT(sc, VR_BCR0, VR_BCR0_RX_THRESH);
- VR_SETBIT(sc, VR_BCR0, VR_BCR0_RXTHRESHSTORENFWD);
+ VR_SETBIT(sc, VR_BCR0, VR_BCR0_RXTHRESH128BYTES);
VR_CLRBIT(sc, VR_BCR1, VR_BCR1_TX_THRESH);
VR_SETBIT(sc, VR_BCR1, VR_BCR1_TXTHRESHSTORENFWD);
VR_CLRBIT(sc, VR_RXCFG, VR_RXCFG_RX_THRESH);
- VR_SETBIT(sc, VR_RXCFG, VR_RXTHRESH_STORENFWD);
+ VR_SETBIT(sc, VR_RXCFG, VR_RXTHRESH_128BYTES);
VR_CLRBIT(sc, VR_TXCFG, VR_TXCFG_TX_THRESH);
VR_SETBIT(sc, VR_TXCFG, VR_TXTHRESH_STORENFWD);
--- /root/vr/if_vrreg.h Thu Dec 12 15:07:25 2002
+++ if_vrreg.h Thu Dec 12 14:35:44 2002
@@ -464,10 +464,13 @@
u_int8_t vr_unit; /* interface number */
u_int8_t vr_type;
u_int8_t vr_revid; /* Rhine chip revision */
+ u_int8_t vr_flags; /* See VR_F_* below */
struct vr_list_data *vr_ldata;
struct vr_chain_data vr_cdata;
struct callout_handle vr_stat_ch;
};
+
+#define VR_F_RESTART 0x01 /* Restart unit on next tick */
/*
* register space access macros
--------------8361301D639C7819FBE5AD82--
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-stable" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3DFBACE7.1D60335F>
