changeset 12865:636a63adb7b9

6861114 System Panics with FMA ereport.io.fire.epkt 6876953 Memory leaks found in e1000g_alloc_rx_sw_packet on snv_111b 6945160 netlbtest fails with Can't set loopback mode on device e1000g6 6960959 panic in e1000g_receive 6965855 e1000g(intel 82571 adapter) needs to support MTU size of 9000 6967530 Need version in e1000g driver 6967873 e1000g needs to clear the link-down status when being unplumbed
author changqing li - Sun Microsystems - Beijing China <Changqing.Li@Sun.COM>
date Mon, 19 Jul 2010 11:06:32 +0800
parents 30d581e817b8
children d1953f8e5b5f
files usr/src/uts/common/io/e1000g/README usr/src/uts/common/io/e1000g/e1000g_alloc.c usr/src/uts/common/io/e1000g/e1000g_main.c usr/src/uts/common/io/e1000g/e1000g_rx.c usr/src/uts/common/io/e1000g/e1000g_sw.h
diffstat 5 files changed, 132 insertions(+), 66 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/io/e1000g/README	Sat Jul 17 18:14:22 2010 -0400
+++ b/usr/src/uts/common/io/e1000g/README	Mon Jul 19 11:06:32 2010 +0800
@@ -17,12 +17,12 @@
 # See the License for the specific language governing permissions
 # and limitations under the License.
 #
-#
-# Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
 #
 #
 
+
+
 4.0.4 code drop from Intel on 1/30/2003
 =======================================
   This version is used as the base for putback into both s10 and
@@ -757,3 +757,13 @@
    6925276 e1000g not consistent with link_lock usage
    6933844 NULL ptr deref in e1000g_rx_setup() due to inconsistency between recv_list & rx_desc_num
 
+5.3.24
+=====
+  This version has the following fixes:
+   6861114 System Panics with FMA ereport.io.fire.epkt
+   6876953 Memory leaks found in e1000g_alloc_rx_sw_packet on snv_111b
+   6945160 netlbtest fails with Can't set loopback mode on device e1000g6
+   6960959 panic in e1000g_receive
+   6965855 e1000g(intel 82571 adapter) needs to support MTU size of 9000
+   6967530 Need version in e1000g driver
+   6967873 e1000g needs to clear the link-down status when being unplumbed
--- a/usr/src/uts/common/io/e1000g/e1000g_alloc.c	Sat Jul 17 18:14:22 2010 -0400
+++ b/usr/src/uts/common/io/e1000g/e1000g_alloc.c	Mon Jul 19 11:06:32 2010 +0800
@@ -19,8 +19,7 @@
  */
 
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 /*
@@ -48,7 +47,7 @@
 static int e1000g_alloc_tx_packets(e1000g_tx_ring_t *);
 static int e1000g_alloc_rx_packets(e1000g_rx_data_t *);
 static void e1000g_free_tx_packets(e1000g_tx_ring_t *);
-static void e1000g_free_rx_packets(e1000g_rx_data_t *);
+static void e1000g_free_rx_packets(e1000g_rx_data_t *, boolean_t);
 static int e1000g_alloc_dma_buffer(struct e1000g *,
     dma_buffer_t *, size_t, ddi_dma_attr_t *p_dma_attr);
 
@@ -175,8 +174,7 @@
 	while ((result != DDI_SUCCESS) &&
 	    (Adapter->tx_desc_num >= MIN_NUM_TX_DESCRIPTOR) &&
 	    (Adapter->rx_desc_num >= MIN_NUM_RX_DESCRIPTOR) &&
-	    (Adapter->tx_freelist_num >= MIN_NUM_TX_FREELIST) &&
-	    (Adapter->rx_freelist_num >= MIN_NUM_RX_FREELIST)) {
+	    (Adapter->tx_freelist_num >= MIN_NUM_TX_FREELIST)) {
 
 		result = e1000g_alloc_descriptors(Adapter);
 
@@ -203,7 +201,6 @@
 			    (Adapter->rx_desc_num >> 4) << 3;
 
 			Adapter->tx_freelist_num >>= 1;
-			Adapter->rx_freelist_num >>= 1;
 		}
 	}
 
@@ -773,7 +770,7 @@
 	rx_data = Adapter->rx_ring->rx_data;
 
 	e1000g_free_tx_packets(tx_ring);
-	e1000g_free_rx_packets(rx_data);
+	e1000g_free_rx_packets(rx_data, B_FALSE);
 }
 
 #ifdef __sparc
@@ -1243,6 +1240,44 @@
 	return (DDI_FAILURE);
 }
 
+
+int
+e1000g_increase_rx_packets(e1000g_rx_data_t *rx_data)
+{
+	int i;
+	p_rx_sw_packet_t packet;
+	p_rx_sw_packet_t cur, next;
+	struct e1000g *Adapter;
+	ddi_dma_attr_t dma_attr;
+
+	Adapter = rx_data->rx_ring->adapter;
+	dma_attr = e1000g_buf_dma_attr;
+	dma_attr.dma_attr_align = Adapter->rx_buf_align;
+	cur = NULL;
+
+	for (i = 0; i < RX_FREELIST_INCREASE_SIZE; i++) {
+		packet = e1000g_alloc_rx_sw_packet(rx_data, &dma_attr);
+		if (packet == NULL)
+			break;
+		packet->next = cur;
+		cur = packet;
+	}
+	Adapter->rx_freelist_num += i;
+	rx_data->avail_freepkt += i;
+
+	while (cur != NULL) {
+		QUEUE_PUSH_TAIL(&rx_data->free_list, &cur->Link);
+		next = cur->next;
+		cur->next = rx_data->packet_area;
+		rx_data->packet_area = cur;
+
+		cur = next;
+	}
+
+	return (DDI_SUCCESS);
+}
+
+
 static int
 e1000g_alloc_rx_packets(e1000g_rx_data_t *rx_data)
 {
@@ -1264,7 +1299,7 @@
 	 * need is equal to the number of receive descriptors plus the freelist
 	 * size.
 	 */
-	packet_num = Adapter->rx_desc_num + Adapter->rx_freelist_num;
+	packet_num = Adapter->rx_desc_num + RX_FREELIST_INCREASE_SIZE;
 	rx_data->packet_area = NULL;
 
 	for (i = 0; i < packet_num; i++) {
@@ -1276,14 +1311,15 @@
 		rx_data->packet_area = packet;
 	}
 
+	Adapter->rx_freelist_num = RX_FREELIST_INCREASE_SIZE;
 	return (DDI_SUCCESS);
 
 rx_pkt_fail:
-	e1000g_free_rx_packets(rx_data);
-
+	e1000g_free_rx_packets(rx_data, B_TRUE);
 	return (DDI_FAILURE);
 }
 
+
 static p_rx_sw_packet_t
 e1000g_alloc_rx_sw_packet(e1000g_rx_data_t *rx_data, ddi_dma_attr_t *p_dma_attr)
 {
@@ -1397,7 +1433,7 @@
 }
 
 static void
-e1000g_free_rx_packets(e1000g_rx_data_t *rx_data)
+e1000g_free_rx_packets(e1000g_rx_data_t *rx_data, boolean_t full_release)
 {
 	p_rx_sw_packet_t packet, next_packet;
 	uint32_t ref_cnt;
@@ -1413,7 +1449,7 @@
 			atomic_inc_32(&rx_data->pending_count);
 			atomic_inc_32(&e1000g_mblks_pending);
 		} else {
-			e1000g_free_rx_sw_packet(packet, B_FALSE);
+			e1000g_free_rx_sw_packet(packet, full_release);
 		}
 
 		packet = next_packet;
--- a/usr/src/uts/common/io/e1000g/e1000g_main.c	Sat Jul 17 18:14:22 2010 -0400
+++ b/usr/src/uts/common/io/e1000g/e1000g_main.c	Mon Jul 19 11:06:32 2010 +0800
@@ -19,8 +19,7 @@
  */
 
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 /*
@@ -45,6 +44,8 @@
 #include "e1000g_debug.h"
 
 static char ident[] = "Intel PRO/1000 Ethernet";
+/* LINTED E_STATIC_UNUSED */
+static char e1000g_version[] = "Driver Ver. 5.3.24";
 
 /*
  * Proto types for DDI entry points
@@ -253,6 +254,7 @@
 /*
  * Global variables
  */
+uint32_t e1000g_jumbo_mtu = MAXIMUM_MTU_9K;
 uint32_t e1000g_mblks_pending = 0;
 /*
  * Workaround for Dynamic Reconfiguration support, for x86 platform only.
@@ -580,7 +582,6 @@
 	}
 
 	Adapter->e1000g_state = E1000G_INITIALIZED;
-
 	return (DDI_SUCCESS);
 
 attach_fail:
@@ -886,13 +887,17 @@
 	case e1000_82574:
 	case e1000_80003es2lan:
 	case e1000_ich10lan:
-		Adapter->max_mtu = MAXIMUM_MTU_9K;
+		if (e1000g_jumbo_mtu >= ETHERMTU &&
+		    e1000g_jumbo_mtu <= MAXIMUM_MTU_9K) {
+			Adapter->max_mtu = e1000g_jumbo_mtu;
+		} else {
+			Adapter->max_mtu = MAXIMUM_MTU_9K;
+		}
 		break;
 	/* default limit is 16K */
 	default:
 		Adapter->max_mtu = FRAME_SIZE_UPTO_16K -
-		    sizeof (struct ether_vlan_header) - ETHERFCSL -
-		    E1000G_IPALIGNPRESERVEROOM;
+		    sizeof (struct ether_vlan_header) - ETHERFCSL;
 		break;
 	}
 }
@@ -938,10 +943,9 @@
 	    ((mac->type == e1000_82545) ||
 	    (mac->type == e1000_82546) ||
 	    (mac->type == e1000_82546_rev_3))) {
-		Adapter->rx_buffer_size = E1000_RX_BUFFER_SIZE_2K +
-		    E1000G_IPALIGNROOM;
+		Adapter->rx_buffer_size = E1000_RX_BUFFER_SIZE_2K;
 	} else {
-		rx_size = Adapter->max_frame_size + E1000G_IPALIGNPRESERVEROOM;
+		rx_size = Adapter->max_frame_size;
 		if ((rx_size > FRAME_SIZE_UPTO_2K) &&
 		    (rx_size <= FRAME_SIZE_UPTO_4K))
 			Adapter->rx_buffer_size = E1000_RX_BUFFER_SIZE_4K;
@@ -954,6 +958,7 @@
 		else
 			Adapter->rx_buffer_size = E1000_RX_BUFFER_SIZE_2K;
 	}
+	Adapter->rx_buffer_size += E1000G_IPALIGNROOM;
 
 	tx_size = Adapter->max_frame_size;
 	if ((tx_size > FRAME_SIZE_UPTO_2K) && (tx_size <= FRAME_SIZE_UPTO_4K))
@@ -1660,7 +1665,12 @@
 	case e1000_media_type_copper:
 		if (hw->mac.get_link_status) {
 			(void) e1000_check_for_link(hw);
-			link_up = !hw->mac.get_link_status;
+			if ((E1000_READ_REG(hw, E1000_STATUS) &
+			    E1000_STATUS_LU)) {
+				link_up = B_TRUE;
+			} else {
+				link_up = !hw->mac.get_link_status;
+			}
 		} else {
 			link_up = B_TRUE;
 		}
@@ -1993,7 +2003,7 @@
 		mutex_exit(&e1000g_rx_detach_lock);
 	}
 
-	if (Adapter->link_state == LINK_STATE_UP) {
+	if (Adapter->link_state != LINK_STATE_UNKNOWN) {
 		Adapter->link_state = LINK_STATE_UNKNOWN;
 		if (!Adapter->reset_flag)
 			mac_link_update(Adapter->mh, Adapter->link_state);
@@ -3234,9 +3244,7 @@
 				 * resource consumption
 				 */
 				if (Adapter->max_frame_size >=
-				    (FRAME_SIZE_UPTO_4K -
-				    E1000G_IPALIGNPRESERVEROOM)) {
-
+				    (FRAME_SIZE_UPTO_4K)) {
 					if (Adapter->tx_desc_num_flag == 0)
 						Adapter->tx_desc_num =
 						    DEFAULT_JUMBO_NUM_TX_DESC;
@@ -3250,7 +3258,7 @@
 						    DEFAULT_JUMBO_NUM_TX_BUF;
 
 					if (Adapter->rx_buf_num_flag == 0)
-						Adapter->rx_freelist_num =
+						Adapter->rx_freelist_limit =
 						    DEFAULT_JUMBO_NUM_RX_BUF;
 				} else {
 					if (Adapter->tx_desc_num_flag == 0)
@@ -3266,7 +3274,7 @@
 						    DEFAULT_NUM_TX_FREELIST;
 
 					if (Adapter->rx_buf_num_flag == 0)
-						Adapter->rx_freelist_num =
+						Adapter->rx_freelist_limit =
 						    DEFAULT_NUM_RX_FREELIST;
 				}
 			}
@@ -3827,9 +3835,7 @@
 	 * decrease the number of descriptors and free packets
 	 * for jumbo frames to reduce tx/rx resource consumption
 	 */
-	if (Adapter->max_frame_size >=
-	    (FRAME_SIZE_UPTO_4K -
-	    E1000G_IPALIGNPRESERVEROOM)) {
+	if (Adapter->max_frame_size >= FRAME_SIZE_UPTO_4K) {
 		is_jumbo = B_TRUE;
 	}
 
@@ -3865,7 +3871,7 @@
 	    MIN_NUM_RX_FREELIST, MAX_NUM_RX_FREELIST,
 	    is_jumbo ? DEFAULT_JUMBO_NUM_RX_BUF
 	    : DEFAULT_NUM_RX_FREELIST, &propval);
-	Adapter->rx_freelist_num = propval;
+	Adapter->rx_freelist_limit = propval;
 
 	/*
 	 * NumTxPacketList
@@ -4502,24 +4508,17 @@
 	case 0:
 		Adapter->default_mtu = ETHERMTU;
 		break;
-	/*
-	 * To avoid excessive memory allocation for rx buffers,
-	 * the bytes of E1000G_IPALIGNPRESERVEROOM are reserved.
-	 */
 	case 1:
 		Adapter->default_mtu = FRAME_SIZE_UPTO_4K -
-		    sizeof (struct ether_vlan_header) - ETHERFCSL -
-		    E1000G_IPALIGNPRESERVEROOM;
+		    sizeof (struct ether_vlan_header) - ETHERFCSL;
 		break;
 	case 2:
 		Adapter->default_mtu = FRAME_SIZE_UPTO_8K -
-		    sizeof (struct ether_vlan_header) - ETHERFCSL -
-		    E1000G_IPALIGNPRESERVEROOM;
+		    sizeof (struct ether_vlan_header) - ETHERFCSL;
 		break;
 	case 3:
 		Adapter->default_mtu = FRAME_SIZE_UPTO_16K -
-		    sizeof (struct ether_vlan_header) - ETHERFCSL -
-		    E1000G_IPALIGNPRESERVEROOM;
+		    sizeof (struct ether_vlan_header) - ETHERFCSL;
 		break;
 	default:
 		Adapter->default_mtu = ETHERMTU;
--- a/usr/src/uts/common/io/e1000g/e1000g_rx.c	Sat Jul 17 18:14:22 2010 -0400
+++ b/usr/src/uts/common/io/e1000g/e1000g_rx.c	Mon Jul 19 11:06:32 2010 +0800
@@ -19,8 +19,7 @@
  */
 
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 /*
@@ -266,11 +265,13 @@
 	 */
 	rctl = E1000_RCTL_EN |		/* Enable Receive Unit */
 	    E1000_RCTL_BAM |		/* Accept Broadcast Packets */
-	    E1000_RCTL_LPE |		/* Large Packet Enable bit */
 	    (hw->mac.mc_filter_type << E1000_RCTL_MO_SHIFT) |
 	    E1000_RCTL_RDMTS_HALF |
 	    E1000_RCTL_LBM_NO;		/* Loopback Mode = none */
 
+	if (Adapter->default_mtu > ETHERMTU)
+		rctl |= E1000_RCTL_LPE;  /* Large Packet Enable bit */
+
 	if (Adapter->strip_crc)
 		rctl |= E1000_RCTL_SECRC;	/* Strip Ethernet CRC */
 
@@ -368,29 +369,44 @@
 e1000g_get_buf(e1000g_rx_data_t *rx_data)
 {
 	p_rx_sw_packet_t packet;
+	struct e1000g *Adapter;
+
+	Adapter = rx_data->rx_ring->adapter;
 
 	mutex_enter(&rx_data->freelist_lock);
 	packet = (p_rx_sw_packet_t)
 	    QUEUE_POP_HEAD(&rx_data->free_list);
 	if (packet != NULL) {
 		rx_data->avail_freepkt--;
-	} else {
-		/*
-		 * If the freelist has no packets, check the recycle list
-		 * to see if there are any available descriptor there.
-		 */
-		mutex_enter(&rx_data->recycle_lock);
-		QUEUE_SWITCH(&rx_data->free_list, &rx_data->recycle_list);
-		rx_data->avail_freepkt = rx_data->recycle_freepkt;
-		rx_data->recycle_freepkt = 0;
-		mutex_exit(&rx_data->recycle_lock);
+		goto end;
+	}
+
+	/*
+	 * If the freelist has no packets, check the recycle list
+	 * to see if there are any available descriptor there.
+	 */
+	mutex_enter(&rx_data->recycle_lock);
+	QUEUE_SWITCH(&rx_data->free_list, &rx_data->recycle_list);
+	rx_data->avail_freepkt = rx_data->recycle_freepkt;
+	rx_data->recycle_freepkt = 0;
+	mutex_exit(&rx_data->recycle_lock);
+	packet = (p_rx_sw_packet_t)QUEUE_POP_HEAD(&rx_data->free_list);
+	if (packet != NULL) {
+		rx_data->avail_freepkt--;
+		goto end;
+	}
+
+	if (Adapter->rx_freelist_num < Adapter->rx_freelist_limit) {
+		(void) e1000g_increase_rx_packets(rx_data);
 		packet = (p_rx_sw_packet_t)
 		    QUEUE_POP_HEAD(&rx_data->free_list);
-		if (packet != NULL)
+		if (packet != NULL) {
 			rx_data->avail_freepkt--;
+		}
 	}
+
+end:
 	mutex_exit(&rx_data->freelist_lock);
-
 	return (packet);
 }
 
@@ -580,12 +596,15 @@
 				 * drop this fragment, do the processing of
 				 * the end of the packet.
 				 */
-				ASSERT(rx_data->rx_mblk_tail != NULL);
+				if (rx_data->rx_mblk_tail == NULL) {
+					E1000G_STAT(rx_ring->stat_crc_only_pkt);
+					goto rx_next_desc;
+				}
+
 				rx_data->rx_mblk_tail->b_wptr -=
 				    ETHERFCSL - length;
 				rx_data->rx_mblk_len -=
 				    ETHERFCSL - length;
-
 				goto rx_end_of_packet;
 			}
 		}
--- a/usr/src/uts/common/io/e1000g/e1000g_sw.h	Sat Jul 17 18:14:22 2010 -0400
+++ b/usr/src/uts/common/io/e1000g/e1000g_sw.h	Mon Jul 19 11:06:32 2010 +0800
@@ -19,8 +19,7 @@
  */
 
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #ifndef _E1000G_SW_H
@@ -145,6 +144,7 @@
 #define	DEFAULT_JUMBO_NUM_RX_BUF	2048
 #define	DEFAULT_JUMBO_NUM_TX_BUF	1152
 #define	DEFAULT_RX_LIMIT_ON_INTR	128
+#define	RX_FREELIST_INCREASE_SIZE	512
 
 #ifdef __sparc
 #define	MAX_INTR_PER_SEC		7100
@@ -224,8 +224,7 @@
  * Defined for IP header alignment. We also need to preserve space for
  * VLAN tag (4 bytes)
  */
-#define	E1000G_IPALIGNROOM		6
-#define	E1000G_IPALIGNPRESERVEROOM	64
+#define	E1000G_IPALIGNROOM		2
 
 /*
  * bit flags for 'attach_progress' which is a member variable in struct e1000g
@@ -833,6 +832,7 @@
 	uint32_t stat_allocb_fail;
 	uint32_t stat_exceed_pkt;
 	uint32_t stat_size_error;
+	uint32_t stat_crc_only_pkt;
 #ifdef E1000G_DEBUG
 	uint32_t stat_none;
 	uint32_t stat_multi_desc;
@@ -877,6 +877,7 @@
 	uint32_t tx_freelist_num;
 	uint32_t rx_desc_num;
 	uint32_t rx_freelist_num;
+	uint32_t rx_freelist_limit;
 	uint32_t tx_buffer_size;
 	uint32_t rx_buffer_size;
 
@@ -1042,6 +1043,7 @@
 void e1000g_free_rx_sw_packet(p_rx_sw_packet_t packet, boolean_t full_release);
 void e1000g_tx_setup(struct e1000g *Adapter);
 void e1000g_rx_setup(struct e1000g *Adapter);
+int e1000g_increase_rx_packets(e1000g_rx_data_t *rx_data);
 
 int e1000g_recycle(e1000g_tx_ring_t *tx_ring);
 void e1000g_free_tx_swpkt(p_tx_sw_packet_t packet);