Skip site navigation (1)Skip section navigation (2)
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>