6913754 rge with rtl8169sc caused tx errors repeatedly on plumb
authorWinson Wang - Sun Microsystems - Beijing China <Zhen.W@Sun.COM>
Fri, 15 Jan 2010 08:52:23 +0800
changeset 11499 6190684fb6c4
parent 11498 2fc576d74742
child 11500 cfac7cfbdcb2
6913754 rge with rtl8169sc caused tx errors repeatedly on plumb 6913756 rge tx performance is very slow for rtl8169sc 6914906 rge with RTL8169S hangs during test12 of nicdrv Contributed by Masa Murayama ([email protected])
usr/src/uts/common/io/rge/rge.h
usr/src/uts/common/io/rge/rge_chip.c
usr/src/uts/common/io/rge/rge_rxtx.c
--- a/usr/src/uts/common/io/rge/rge.h	Thu Jan 14 14:38:50 2010 -0800
+++ b/usr/src/uts/common/io/rge/rge.h	Fri Jan 15 08:52:23 2010 +0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -494,6 +494,7 @@
 	clock_t			tick_delta;
 	uint64_t		last_opackets;
 	uint64_t		last_rpackets;
+	uint32_t		rx_fifo_ovf;
 } rge_t;
 
 /*
--- a/usr/src/uts/common/io/rge/rge_chip.c	Thu Jan 14 14:38:50 2010 -0800
+++ b/usr/src/uts/common/io/rge/rge_chip.c	Fri Jan 15 08:52:23 2010 +0800
@@ -43,6 +43,7 @@
  */
 #define	RGE_DBG		RGE_DBG_REGS	/* debug flag for this code	*/
 static uint32_t rge_watchdog_count	= 1 << 5;
+static uint32_t rge_rx_watchdog_count	= 1 << 3;
 
 /*
  * Operating register get/set access routines
@@ -716,6 +717,7 @@
 	/* set pci latency timer */
 	if (chip->mac_ver == MAC_VER_8169 ||
 	    chip->mac_ver == MAC_VER_8169S_D ||
+	    chip->mac_ver == MAC_VER_8169S_E ||
 	    chip->mac_ver == MAC_VER_8169SC)
 		pci_config_put8(rgep->cfg_handle, PCI_CONF_LATENCY_TIMER, 0x40);
 
@@ -723,9 +725,9 @@
 		val16 = rge_reg_get16(rgep, RT_CONFIG_1_REG);
 		val16 &= 0x0300;
 		if (val16 == 0x1)	/* 66Mhz PCI */
-			pci_config_put32(rgep->cfg_handle, 0x7c, 0x00ff00ff);
+			rge_reg_put32(rgep, 0x7c, 0x000700ff);
 		else if (val16 == 0x0) /* 33Mhz PCI */
-			pci_config_put32(rgep->cfg_handle, 0x7c, 0x00ffff00);
+			rge_reg_put32(rgep, 0x7c, 0x0007ff00);
 	}
 
 	/*
@@ -921,6 +923,10 @@
 		val16 |= CPLUS_BIT14 | MUL_PCI_RW_ENABLE;
 		rge_reg_put8(rgep, RESV_82_REG, 0x01);
 	}
+	if (chip->mac_ver == MAC_VER_8169S_E ||
+	    chip->mac_ver == MAC_VER_8169SC) {
+		val16 |= MUL_PCI_RW_ENABLE;
+	}
 	rge_reg_put16(rgep, CPLUS_COMMAND_REG, val16 & (~0x03));
 
 	/*
@@ -1060,6 +1066,8 @@
 	if (rgep->chipid.is_pcie) {
 		rgep->int_mask |= NO_TXDESC_INT;
 	}
+	rgep->rx_fifo_ovf = 0;
+	rgep->int_mask |= RX_FIFO_OVERFLOW_INT;
 	rge_reg_put16(rgep, INT_MASK_REG, rgep->int_mask);
 
 	/*
@@ -1470,6 +1478,22 @@
 		rge_chip_cyclic(rgep);
 	}
 
+	if (int_status & RX_FIFO_OVERFLOW_INT) {
+		/* start rx watchdog timeout detection */
+		rgep->rx_fifo_ovf = 1;
+		if (rgep->int_mask & RX_FIFO_OVERFLOW_INT) {
+			rgep->int_mask &= ~RX_FIFO_OVERFLOW_INT;
+			update_int_mask = B_TRUE;
+		}
+	} else if (int_status & RGE_RX_INT) {
+		/* stop rx watchdog timeout detection */
+		rgep->rx_fifo_ovf = 0;
+		if ((rgep->int_mask & RX_FIFO_OVERFLOW_INT) == 0) {
+			rgep->int_mask |= RX_FIFO_OVERFLOW_INT;
+			update_int_mask = B_TRUE;
+		}
+	}
+
 	mutex_exit(rgep->genlock);
 
 	/*
@@ -1567,6 +1591,15 @@
 	ASSERT(mutex_owned(rgep->genlock));
 
 	/*
+	 * Specific check for RX stall ...
+	 */
+	rgep->rx_fifo_ovf <<= 1;
+	if (rgep->rx_fifo_ovf > rge_rx_watchdog_count) {
+		RGE_REPORT((rgep, "rx_hang detected"));
+		return (B_TRUE);
+	}
+
+	/*
 	 * Specific check for Tx stall ...
 	 *
 	 * The 'watchdog' counter is incremented whenever a packet
--- a/usr/src/uts/common/io/rge/rge_rxtx.c	Thu Jan 14 14:38:50 2010 -0800
+++ b/usr/src/uts/common/io/rge/rge_rxtx.c	Fri Jan 15 08:52:23 2010 +0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -697,10 +697,12 @@
 
 	rw_enter(rgep->errlock, RW_READER);
 	if ((rgep->rge_mac_state != RGE_MAC_STARTED) ||
-	    (rgep->rge_chip_state != RGE_CHIP_RUNNING)) {
+	    (rgep->rge_chip_state != RGE_CHIP_RUNNING) ||
+	    (rgep->param_link_up != LINK_STATE_UP)) {
+		rw_exit(rgep->errlock);
 		RGE_DEBUG(("rge_m_tx: tx doesn't work"));
-		rw_exit(rgep->errlock);
-		return (mp);
+		freemsgchain(mp);
+		return (NULL);
 	}
 
 	while (mp != NULL) {