changeset 12992:c2b4f6c2d38a

6935725 igb driver does not follow Kawela spec for setting the device up for external loopback mode 6963343 igb_tx_recycle_head_wb can't distinguish between empty and full of circular descriptor queue 6963350 tx reschedule may never get dispatched when tx ring size is set too small 6966781 system panic during tcptx transferring on igb when disabling tx head wb
author Guoqing Zhu <Guoqing.Zhu@Sun.COM>
date Mon, 02 Aug 2010 11:02:38 +0800
parents 99d5baececdc
children 2ec828581df0
files usr/src/uts/common/io/igb/igb_buf.c usr/src/uts/common/io/igb/igb_gld.c usr/src/uts/common/io/igb/igb_main.c usr/src/uts/common/io/igb/igb_sw.h usr/src/uts/common/io/igb/igb_tx.c
diffstat 5 files changed, 88 insertions(+), 59 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/io/igb/igb_buf.c	Sun Aug 01 14:25:26 2010 +0800
+++ b/usr/src/uts/common/io/igb/igb_buf.c	Mon Aug 02 11:02:38 2010 +0800
@@ -1,19 +1,17 @@
 /*
  * CDDL HEADER START
  *
- * Copyright(c) 2007-2009 Intel Corporation. All rights reserved.
  * The contents of this file are subject to the terms of the
  * Common Development and Distribution License (the "License").
  * You may not use this file except in compliance with the License.
  *
- * You can obtain a copy of the license at:
- *	http://www.opensolaris.org/os/licensing.
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
  * See the License for the specific language governing permissions
  * and limitations under the License.
  *
- * When using or redistributing this file, you may do so under the
- * License only. No other modification of this header is permitted.
- *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  * If applicable, add the following below this CDDL HEADER, with the
  * fields enclosed by brackets "[]" replaced with your own identifying
  * information: Portions Copyright [yyyy] [name of copyright owner]
@@ -22,8 +20,11 @@
  */
 
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright(c) 2007-2010 Intel Corporation. All rights reserved.
+ */
+
+/*
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #include "igb_sw.h"
@@ -756,6 +757,7 @@
 			igb_error(igb, "Allocate tx dma buffer failed");
 			goto alloc_tcb_lists_fail;
 		}
+		tcb->last_index = MAX_TX_RING_SIZE;
 	}
 
 	return (IGB_SUCCESS);
--- a/usr/src/uts/common/io/igb/igb_gld.c	Sun Aug 01 14:25:26 2010 +0800
+++ b/usr/src/uts/common/io/igb/igb_gld.c	Mon Aug 02 11:02:38 2010 +0800
@@ -20,12 +20,11 @@
  */
 
 /*
- * Copyright(c) 2007-2008 Intel Corporation. All rights reserved.
+ * Copyright(c) 2007-2010 Intel Corporation. All rights reserved.
  */
 
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #include "igb_sw.h"
@@ -1435,7 +1434,8 @@
 		}
 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
 		if (result < MIN_TX_RESCHED_THRESHOLD ||
-		    result > MAX_TX_RESCHED_THRESHOLD)
+		    result > MAX_TX_RESCHED_THRESHOLD ||
+		    result > igb->tx_ring_size)
 			err = EINVAL;
 		else {
 			igb->tx_resched_thresh = (uint32_t)result;
--- a/usr/src/uts/common/io/igb/igb_main.c	Sun Aug 01 14:25:26 2010 +0800
+++ b/usr/src/uts/common/io/igb/igb_main.c	Mon Aug 02 11:02:38 2010 +0800
@@ -30,7 +30,7 @@
 #include "igb_sw.h"
 
 static char ident[] = "Intel 1Gb Ethernet";
-static char igb_version[] = "igb 1.1.16";
+static char igb_version[] = "igb 1.1.17";
 
 /*
  * Local function protoypes
@@ -2841,8 +2841,10 @@
 	    MIN_TX_OVERLOAD_THRESHOLD, MAX_TX_OVERLOAD_THRESHOLD,
 	    DEFAULT_TX_OVERLOAD_THRESHOLD);
 	igb->tx_resched_thresh = igb_get_prop(igb, PROP_TX_RESCHED_THRESHOLD,
-	    MIN_TX_RESCHED_THRESHOLD, MAX_TX_RESCHED_THRESHOLD,
-	    DEFAULT_TX_RESCHED_THRESHOLD);
+	    MIN_TX_RESCHED_THRESHOLD,
+	    MIN(igb->tx_ring_size, MAX_TX_RESCHED_THRESHOLD),
+	    igb->tx_ring_size > DEFAULT_TX_RESCHED_THRESHOLD ?
+	    DEFAULT_TX_RESCHED_THRESHOLD : DEFAULT_TX_RESCHED_THRESHOLD_LOW);
 
 	igb->rx_copy_thresh = igb_get_prop(igb, PROP_RX_COPY_THRESHOLD,
 	    MIN_RX_COPY_THRESHOLD, MAX_RX_COPY_THRESHOLD,
@@ -3732,14 +3734,17 @@
 igb_set_external_loopback(igb_t *igb)
 {
 	struct e1000_hw *hw;
+	uint32_t ctrl_ext;
 
 	hw = &igb->hw;
 
-	/* Set phy to known state */
-	(void) e1000_phy_hw_reset(hw);
+	/* Set link mode to PHY (00b) in the Extended Control register */
+	ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
+	ctrl_ext &= ~E1000_CTRL_EXT_LINK_MODE_MASK;
+	E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
 
 	(void) e1000_write_phy_reg(hw, 0x0, 0x0140);
-	(void) e1000_write_phy_reg(hw, 0x9, 0x1b00);
+	(void) e1000_write_phy_reg(hw, 0x9, 0x1a00);
 	(void) e1000_write_phy_reg(hw, 0x12, 0x1610);
 	(void) e1000_write_phy_reg(hw, 0x1f37, 0x3f1c);
 }
--- a/usr/src/uts/common/io/igb/igb_sw.h	Sun Aug 01 14:25:26 2010 +0800
+++ b/usr/src/uts/common/io/igb/igb_sw.h	Mon Aug 02 11:02:38 2010 +0800
@@ -159,6 +159,7 @@
 #define	DEFAULT_TX_RECYCLE_THRESHOLD	(MAX_COOKIE + 1)
 #define	DEFAULT_TX_OVERLOAD_THRESHOLD	MIN_NUM_TX_DESC
 #define	DEFAULT_TX_RESCHED_THRESHOLD	128
+#define	DEFAULT_TX_RESCHED_THRESHOLD_LOW	32
 #define	DEFAULT_MCAST_NUM		4096
 
 #define	IGB_LSO_MAXLEN			65535
@@ -379,6 +380,7 @@
  */
 typedef struct tx_control_block {
 	single_link_t		link;
+	uint32_t		last_index;
 	uint32_t		frag_num;
 	uint32_t		desc_num;
 	mblk_t			*mp;
--- a/usr/src/uts/common/io/igb/igb_tx.c	Sun Aug 01 14:25:26 2010 +0800
+++ b/usr/src/uts/common/io/igb/igb_tx.c	Mon Aug 02 11:02:38 2010 +0800
@@ -1,7 +1,6 @@
 /*
  * CDDL HEADER START
  *
- * Copyright(c) 2007-2009 Intel Corporation. All rights reserved.
  * The contents of this file are subject to the terms of the
  * Common Development and Distribution License (the "License").
  * You may not use this file except in compliance with the License.
@@ -21,8 +20,11 @@
  */
 
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright(c) 2007-2010 Intel Corporation. All rights reserved.
+ */
+
+/*
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #include "igb_sw.h"
@@ -392,8 +394,10 @@
 	 * Before fill the tx descriptor ring with the data, we need to
 	 * ensure there are adequate free descriptors for transmit
 	 * (including one context descriptor).
+	 * Do not use up all the tx descriptors.
+	 * Otherwise tx recycle will fail and cause false hang.
 	 */
-	if (tx_ring->tbd_free < (desc_total + 1)) {
+	if (tx_ring->tbd_free <= (desc_total + 1)) {
 		tx_ring->tx_recycle(tx_ring);
 	}
 
@@ -407,7 +411,7 @@
 	 * ensure the correctness when multiple threads access it in
 	 * parallel.
 	 */
-	if (tx_ring->tbd_free < (desc_total + 1)) {
+	if (tx_ring->tbd_free <= (desc_total + 1)) {
 		IGB_DEBUG_STAT(tx_ring->stat_fail_no_tbd);
 		mutex_exit(&tx_ring->tx_lock);
 		goto tx_failure;
@@ -882,8 +886,6 @@
 		 */
 		load_context = igb_check_tx_context(tx_ring, ctx);
 		if (load_context) {
-			first_tcb = (tx_control_block_t *)
-			    LIST_GET_HEAD(pending_list);
 			tbd = &tx_ring->tbd_ring[index];
 
 			/*
@@ -920,6 +922,7 @@
 	 * control block.
 	 */
 	tcb = (tx_control_block_t *)LIST_POP_HEAD(pending_list);
+	first_tcb = tcb;
 	while (tcb != NULL) {
 
 		for (i = 0; i < tcb->desc_num; i++) {
@@ -938,15 +941,6 @@
 			desc_num++;
 		}
 
-		if (first_tcb != NULL) {
-			/*
-			 * Count the checksum context descriptor for
-			 * the first tx control block.
-			 */
-			first_tcb->desc_num++;
-			first_tcb = NULL;
-		}
-
 		/*
 		 * Add the tx control block to the work list
 		 */
@@ -957,6 +951,15 @@
 		tcb = (tx_control_block_t *)LIST_POP_HEAD(pending_list);
 	}
 
+	if (load_context) {
+		/*
+		 * Count the checksum context descriptor for
+		 * the first tx control block.
+		 */
+		first_tcb->desc_num++;
+	}
+	first_tcb->last_index = PREV_INDEX(index, 1, tx_ring->ring_size);
+
 	/*
 	 * The Insert Ethernet CRC (IFCS) bit and the checksum fields are only
 	 * valid in the first descriptor of the packet.
@@ -1064,7 +1067,7 @@
 uint32_t
 igb_tx_recycle_legacy(igb_tx_ring_t *tx_ring)
 {
-	uint32_t index, last_index;
+	uint32_t index, last_index, next_index;
 	int desc_num;
 	boolean_t desc_done;
 	tx_control_block_t *tcb;
@@ -1107,18 +1110,26 @@
 	tcb = tx_ring->work_list[index];
 	ASSERT(tcb != NULL);
 
-	desc_done = B_TRUE;
-	while (desc_done && (tcb != NULL)) {
+	while (tcb != NULL) {
 
 		/*
-		 * Get the last tx descriptor of the tx control block.
-		 * If the last tx descriptor is done, it is done with
-		 * all the tx descriptors of the tx control block.
-		 * Then the tx control block and all the corresponding
-		 * tx descriptors can be recycled.
+		 * Get the last tx descriptor of this packet.
+		 * If the last tx descriptor is done, then
+		 * we can recycle all descriptors of a packet
+		 * which usually includes several tx control blocks.
+		 * For some chips, LSO descriptors can not be recycled
+		 * unless the whole packet's transmission is done.
+		 * That's why packet level recycling is used here.
 		 */
-		last_index = NEXT_INDEX(index, tcb->desc_num - 1,
-		    tx_ring->ring_size);
+		last_index = tcb->last_index;
+		/*
+		 * MAX_TX_RING_SIZE is used to judge whether
+		 * the index is a valid value or not.
+		 */
+		if (last_index == MAX_TX_RING_SIZE)
+			break;
+
+		next_index = NEXT_INDEX(last_index, 1, tx_ring->ring_size);
 
 		/*
 		 * Check if the Descriptor Done bit is set
@@ -1126,24 +1137,32 @@
 		desc_done = tx_ring->tbd_ring[last_index].wb.status &
 		    E1000_TXD_STAT_DD;
 		if (desc_done) {
-			/*
-			 * Strip off the tx control block from the work list,
-			 * and add it to the pending list.
-			 */
-			tx_ring->work_list[index] = NULL;
-			LIST_PUSH_TAIL(&pending_list, &tcb->link);
+			while (tcb != NULL) {
+				/*
+				 * Strip off the tx control block from the work
+				 * list, and add it to the pending list.
+				 */
+				tx_ring->work_list[index] = NULL;
+				LIST_PUSH_TAIL(&pending_list, &tcb->link);
 
-			/*
-			 * Count the total number of the tx descriptors recycled
-			 */
-			desc_num += tcb->desc_num;
+				/*
+				 * Count the total number of the tx descriptors
+				 * recycled.
+				 */
+				desc_num += tcb->desc_num;
 
-			/*
-			 * Advance the index of the tx descriptor ring
-			 */
-			index = NEXT_INDEX(last_index, 1, tx_ring->ring_size);
+				/*
+				 * Advance the index of the tx descriptor ring
+				 */
+				index = NEXT_INDEX(index, tcb->desc_num,
+				    tx_ring->ring_size);
 
-			tcb = tx_ring->work_list[index];
+				tcb = tx_ring->work_list[index];
+				if (index == next_index)
+					break;
+			}
+		} else {
+			break;
 		}
 	}
 
@@ -1372,6 +1391,7 @@
 	}
 
 	tcb->tx_type = USE_NONE;
+	tcb->last_index = MAX_TX_RING_SIZE;
 	tcb->frag_num = 0;
 	tcb->desc_num = 0;
 }