changeset 4349:53be14f175bd

6507422 Dynamic Reconfiguration detach fails for e1000g
author xy150489
date Tue, 29 May 2007 23:14:26 -0700
parents f06efcce7faa
children cd92987240fb
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_sw.h
diffstat 4 files changed, 169 insertions(+), 83 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/io/e1000g/README	Tue May 29 17:13:54 2007 -0700
+++ b/usr/src/uts/common/io/e1000g/README	Tue May 29 23:14:26 2007 -0700
@@ -504,3 +504,8 @@
    6548711 e1000g: recursive mutex_enter in e1000g_link_check() on ESB2 platforms
    6550086 e1000g: detaching driver immediately after attach induces panic
 
+5.1.9
+======
+  This version has the following fix:
+   6507422 Dynamic Reconfiguration detach fails for e1000g
+
--- a/usr/src/uts/common/io/e1000g/e1000g_alloc.c	Tue May 29 17:13:54 2007 -0700
+++ b/usr/src/uts/common/io/e1000g/e1000g_alloc.c	Tue May 29 23:14:26 2007 -0700
@@ -558,9 +558,9 @@
 	 * the ddi_dma_mem_alloc call.
 	 */
 	mystat = ddi_dma_addr_bind_handle(rx_ring->rbd_dma_handle,
-		(struct as *)NULL, (caddr_t)rx_ring->rbd_area,
-		len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
-		DDI_DMA_SLEEP, 0, &cookie, &cookie_count);
+	    (struct as *)NULL, (caddr_t)rx_ring->rbd_area,
+	    len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
+	    DDI_DMA_SLEEP, 0, &cookie, &cookie_count);
 
 	if (mystat != DDI_SUCCESS) {
 		e1000g_log(Adapter, CE_WARN,
@@ -748,7 +748,10 @@
 	dev_info_t *devinfo;
 	ddi_dma_cookie_t cookie;
 
-	devinfo = Adapter->dip;
+	if (e1000g_force_detach)
+		devinfo = Adapter->priv_dip;
+	else
+		devinfo = Adapter->dip;
 
 	mystat = dvma_reserve(devinfo,
 	    &e1000g_dma_limits,
@@ -820,7 +823,10 @@
 	size_t len;
 	uint_t count;
 
-	devinfo = Adapter->dip;
+	if (e1000g_force_detach)
+		devinfo = Adapter->priv_dip;
+	else
+		devinfo = Adapter->dip;
 
 	mystat = ddi_dma_alloc_handle(devinfo,
 	    &buf_dma_attr,
@@ -1200,28 +1206,33 @@
 static void
 e1000g_free_rx_packets(e1000g_rx_ring_t *rx_ring)
 {
-	PRX_SW_PACKET packet, next_packet;
+	PRX_SW_PACKET packet, next_packet, free_list;
 
 	rw_enter(&e1000g_rx_detach_lock, RW_WRITER);
-	for (packet = rx_ring->packet_area; packet != NULL;
-	    packet = packet->next) {
+
+	free_list = NULL;
+	packet = rx_ring->packet_area;
+	for (; packet != NULL; packet = next_packet) {
+		next_packet = packet->next;
+
 		if (packet->flag & E1000G_RX_SW_SENDUP) {
 			e1000g_mblks_pending++;
 			packet->flag |= E1000G_RX_SW_DETACHED;
+			packet->next = NULL;
+		} else {
+			packet->next = free_list;
+			free_list = packet;
 		}
 	}
+	rx_ring->packet_area = NULL;
+
 	rw_exit(&e1000g_rx_detach_lock);
 
-	packet = rx_ring->packet_area;
-	rx_ring->packet_area = NULL;
-
+	packet = free_list;
 	for (; packet != NULL; packet = next_packet) {
 		next_packet = packet->next;
 
-		if (packet->flag & E1000G_RX_SW_DETACHED)
-			continue;
-
-		ASSERT((packet->flag & E1000G_RX_SW_SENDUP) == 0);
+		ASSERT(packet->flag == E1000G_RX_SW_FREE);
 		e1000g_free_rx_sw_packet(packet);
 	}
 }
--- a/usr/src/uts/common/io/e1000g/e1000g_main.c	Tue May 29 17:13:54 2007 -0700
+++ b/usr/src/uts/common/io/e1000g/e1000g_main.c	Tue May 29 23:14:26 2007 -0700
@@ -53,9 +53,9 @@
 #define	E1000_RX_INTPT_TIME	128
 #define	E1000_RX_PKT_CNT	8
 
-static char ident[] = "Intel PRO/1000 Ethernet 5.1.8";
+static char ident[] = "Intel PRO/1000 Ethernet 5.1.9";
 static char e1000g_string[] = "Intel(R) PRO/1000 Network Connection";
-static char e1000g_version[] = "Driver Ver. 5.1.8";
+static char e1000g_version[] = "Driver Ver. 5.1.9";
 
 /*
  * Proto types for DDI entry points
@@ -216,9 +216,20 @@
 /*
  * Global variables
  */
-boolean_t force_detach_enabled = B_FALSE;
+boolean_t e1000g_force_detach = B_TRUE;
 uint32_t e1000g_mblks_pending = 0;
 /*
+ * Here we maintain a private dev_info list if e1000g_force_detach is
+ * enabled. If we force the driver to detach while there are still some
+ * rx buffers retained in the upper layer, we have to keep a copy of the
+ * dev_info. In some cases (Dynamic Reconfiguration), the dev_info data
+ * structure will be freed after the driver is detached. However when we
+ * finally free those rx buffers released by the upper layer, we need to
+ * refer to the dev_info to free the dma buffers. So we save a copy of
+ * the dev_info for this purpose.
+ */
+private_devi_list_t *e1000g_private_devi_list = NULL;
+/*
  * The rwlock is defined to protect the whole processing of rx recycling
  * and the rx packets release in detach processing to make them mutually
  * exclusive.
@@ -314,6 +325,24 @@
 	status = mod_remove(&modlinkage);
 	if (status == DDI_SUCCESS) {
 		mac_fini_ops(&ws_ops);
+
+		if (e1000g_force_detach) {
+			private_devi_list_t *devi_node;
+
+			rw_enter(&e1000g_rx_detach_lock, RW_WRITER);
+			while (e1000g_private_devi_list != NULL) {
+				devi_node = e1000g_private_devi_list;
+				e1000g_private_devi_list =
+				    e1000g_private_devi_list->next;
+
+				kmem_free(devi_node->priv_dip,
+				    sizeof (struct dev_info));
+				kmem_free(devi_node,
+				    sizeof (private_devi_list_t));
+			}
+			rw_exit(&e1000g_rx_detach_lock);
+		}
+
 		rw_destroy(&e1000g_rx_detach_lock);
 		rw_destroy(&e1000g_dma_type_lock);
 	}
@@ -419,6 +448,40 @@
 
 	ddi_set_driver_private(devinfo, (caddr_t)Adapter);
 
+	if (e1000g_force_detach) {
+		private_devi_list_t *devi_node;
+		boolean_t devi_existed;
+
+		devi_existed = B_FALSE;
+		devi_node = e1000g_private_devi_list;
+		while (devi_node != NULL) {
+			if (devi_node->dip == devinfo) {
+				devi_existed = B_TRUE;
+				break;
+			}
+			devi_node = devi_node->next;
+		}
+
+		if (devi_existed) {
+			Adapter->priv_dip = devi_node->priv_dip;
+		} else {
+			Adapter->priv_dip =
+			    kmem_zalloc(sizeof (struct dev_info), KM_SLEEP);
+			bcopy(DEVI(devinfo), DEVI(Adapter->priv_dip),
+			    sizeof (struct dev_info));
+
+			devi_node =
+			    kmem_zalloc(sizeof (private_devi_list_t), KM_SLEEP);
+
+			rw_enter(&e1000g_rx_detach_lock, RW_WRITER);
+			devi_node->dip = devinfo;
+			devi_node->priv_dip = Adapter->priv_dip;
+			devi_node->next = e1000g_private_devi_list;
+			e1000g_private_devi_list = devi_node;
+			rw_exit(&e1000g_rx_detach_lock);
+		}
+	}
+
 	hw = &Adapter->Shared;
 
 	/*
@@ -433,9 +496,9 @@
 	    (off_t *)&mem_size);
 
 	if ((ddi_regs_map_setup(devinfo, 1, /* register of interest */
-		(caddr_t *)&hw->hw_addr,
-		0, mem_size, &accattr1, &Adapter->E1000_handle))
-		!= DDI_SUCCESS) {
+	    (caddr_t *)&hw->hw_addr,
+	    0, mem_size, &accattr1, &Adapter->E1000_handle))
+	    != DDI_SUCCESS) {
 		e1000g_log(Adapter, CE_WARN, "ddi_regs_map_setup failed");
 		goto attach_fail;
 	}
@@ -833,7 +896,7 @@
 		e1000g_stop(Adapter);
 
 	if (!e1000g_rx_drain(Adapter)) {
-		if (!force_detach_enabled)
+		if (!e1000g_force_detach)
 			return (DDI_FAILURE);
 	}
 
@@ -1092,7 +1155,7 @@
 		else
 			pba = E1000_PBA_48K;	/* 48K for Rx, 16K for Tx */
 	} else if (hw->mac_type >= e1000_82571 &&
-			hw->mac_type <= e1000_82572) {
+	    hw->mac_type <= e1000_82572) {
 		/*
 		 * Total FIFO is 48K
 		 */
@@ -1242,7 +1305,7 @@
 	if ((E1000_READ_REG(hw, STATUS) & E1000_STATUS_LU) ||
 	    ((!hw->get_link_status) && (hw->mac_type == e1000_82543)) ||
 	    ((hw->media_type == e1000_media_type_internal_serdes) &&
-		(!hw->serdes_link_down))) {
+	    (!hw->serdes_link_down))) {
 		link_up = B_TRUE;
 	} else {
 		link_up = B_FALSE;
@@ -1309,7 +1372,7 @@
 		 * Error, reply with a NAK and EINVAL or the specified error
 		 */
 		miocnak(q, mp, 0, iocp->ioc_error == 0 ?
-			EINVAL : iocp->ioc_error);
+		    EINVAL : iocp->ioc_error);
 		break;
 
 	case IOC_DONE:
@@ -1330,7 +1393,7 @@
 		 * OK, send prepared reply as ACK or NAK
 		 */
 		mp->b_datap->db_type = iocp->ioc_error == 0 ?
-			M_IOCACK : M_IOCNAK;
+		    M_IOCACK : M_IOCNAK;
 		qreply(q, mp);
 		break;
 	}
@@ -2167,7 +2230,7 @@
 	struct e1000g *Adapter = (struct e1000g *)arg;
 
 	return ((add) ? multicst_add(Adapter, addr)
-		: multicst_remove(Adapter, addr));
+	    : multicst_remove(Adapter, addr));
 }
 
 int
@@ -2334,32 +2397,32 @@
 	 */
 	Adapter->NumTxDescriptors =
 	    e1000g_getprop(Adapter, "NumTxDescriptors",
-		MINNUMTXDESCRIPTOR, MAXNUMTXDESCRIPTOR,
-		DEFAULTNUMTXDESCRIPTOR);
+	    MINNUMTXDESCRIPTOR, MAXNUMTXDESCRIPTOR,
+	    DEFAULTNUMTXDESCRIPTOR);
 
 	/*
 	 * NumRxDescriptors
 	 */
 	Adapter->NumRxDescriptors =
 	    e1000g_getprop(Adapter, "NumRxDescriptors",
-		MINNUMRXDESCRIPTOR, MAXNUMRXDESCRIPTOR,
-		DEFAULTNUMRXDESCRIPTOR);
+	    MINNUMRXDESCRIPTOR, MAXNUMRXDESCRIPTOR,
+	    DEFAULTNUMRXDESCRIPTOR);
 
 	/*
 	 * NumRxFreeList
 	 */
 	Adapter->NumRxFreeList =
 	    e1000g_getprop(Adapter, "NumRxFreeList",
-		MINNUMRXFREELIST, MAXNUMRXFREELIST,
-		DEFAULTNUMRXFREELIST);
+	    MINNUMRXFREELIST, MAXNUMRXFREELIST,
+	    DEFAULTNUMRXFREELIST);
 
 	/*
 	 * NumTxPacketList
 	 */
 	Adapter->NumTxSwPacket =
 	    e1000g_getprop(Adapter, "NumTxPacketList",
-		MINNUMTXSWPACKET, MAXNUMTXSWPACKET,
-		DEFAULTNUMTXSWPACKET);
+	    MINNUMTXSWPACKET, MAXNUMTXSWPACKET,
+	    DEFAULTNUMTXSWPACKET);
 
 	/*
 	 * FlowControl
@@ -2532,9 +2595,9 @@
 			e1000g_log(Adapter, CE_NOTE,
 			    "Adapter %dMbps %s %s link is up.", speed,
 			    ((duplex == FULL_DUPLEX) ?
-				"full duplex" : "half duplex"),
+			    "full duplex" : "half duplex"),
 			    ((hw->media_type == e1000_media_type_copper) ?
-				"copper" : "fiber"));
+			    "copper" : "fiber"));
 		}
 		Adapter->smartspeed = 0;
 	} else {
@@ -2547,7 +2610,7 @@
 			e1000g_log(Adapter, CE_NOTE,
 			    "Adapter %s link is down.",
 			    ((hw->media_type == e1000_media_type_copper) ?
-				"copper" : "fiber"));
+			    "copper" : "fiber"));
 
 			/*
 			 * SmartSpeed workaround for Tabor/TanaX, When the
@@ -2756,8 +2819,8 @@
 		Adapter->Shared.autoneg = B_TRUE;
 		Adapter->Shared.autoneg_advertised =
 		    (uint16_t)e1000g_getprop(Adapter, "AutoNegAdvertised",
-			0, AUTONEG_ADVERTISE_SPEED_DEFAULT,
-			AUTONEG_ADVERTISE_SPEED_DEFAULT);
+		    0, AUTONEG_ADVERTISE_SPEED_DEFAULT,
+		    AUTONEG_ADVERTISE_SPEED_DEFAULT);
 		break;
 	}	/* switch */
 }
@@ -3039,7 +3102,7 @@
 			 */
 			if (!e1000_phy_setup_autoneg(&adapter->Shared) &&
 			    !e1000_read_phy_reg(&adapter->Shared, PHY_CTRL,
-				&phy_ctrl)) {
+			    &phy_ctrl)) {
 				phy_ctrl |= (MII_CR_AUTO_NEG_EN |
 				    MII_CR_RESTART_AUTO_NEG);
 				e1000_write_phy_reg(&adapter->Shared,
@@ -3075,7 +3138,7 @@
 		 */
 		if (!e1000_phy_setup_autoneg(&adapter->Shared) &&
 		    !e1000_read_phy_reg(&adapter->Shared, PHY_CTRL,
-			&phy_ctrl)) {
+		    &phy_ctrl)) {
 			phy_ctrl |=
 			    (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
 			e1000_write_phy_reg(&adapter->Shared, PHY_CTRL,
@@ -3171,8 +3234,8 @@
 
 	deault:
 		e1000g_DEBUGLOG_1(e1000gp, e1000g_INFO_LEVEL,
-			"e1000g_diag_ioctl: invalid ioctl command 0x%X\n",
-			iocp->ioc_cmd);
+		    "e1000g_diag_ioctl: invalid ioctl command 0x%X\n",
+		    iocp->ioc_cmd);
 		return (IOC_INVAL);
 	}
 
@@ -3193,8 +3256,8 @@
 
 	default:
 		e1000g_DEBUGLOG_1(e1000gp, e1000g_INFO_LEVEL,
-			"e1000g_diag_ioctl: invalid access space 0x%X\n",
-			ppd->pp_acc_space);
+		    "e1000g_diag_ioctl: invalid access space 0x%X\n",
+		    ppd->pp_acc_space);
 		return (IOC_INVAL);
 
 	case E1000G_PP_SPACE_REG:
@@ -3245,7 +3308,7 @@
 	uint32_t *regaddr;
 
 	handle =
-	    ((struct e1000g_osdep *)(&e1000gp->Shared)->back)->E1000_handle,
+	    ((struct e1000g_osdep *)(&e1000gp->Shared)->back)->E1000_handle;
 	regaddr =
 	    (uint32_t *)((&e1000gp->Shared)->hw_addr + ppd->pp_acc_offset);
 
@@ -3260,7 +3323,7 @@
 	uint32_t value;
 
 	handle =
-	    ((struct e1000g_osdep *)(&e1000gp->Shared)->back)->E1000_handle,
+	    ((struct e1000g_osdep *)(&e1000gp->Shared)->back)->E1000_handle;
 	regaddr =
 	    (uint32_t *)((&e1000gp->Shared)->hw_addr + ppd->pp_acc_offset);
 	value = (uint32_t)ppd->pp_acc_data;
@@ -3295,8 +3358,8 @@
 	}
 
 	e1000g_DEBUGLOG_4(e1000gp, e1000g_INFO_LEVEL,
-		"e1000g_ioc_peek_mem($%p, $%p) peeked 0x%llx from $%p\n",
-		(void *)e1000gp, (void *)ppd, value, vaddr);
+	    "e1000g_ioc_peek_mem($%p, $%p) peeked 0x%llx from $%p\n",
+	    (void *)e1000gp, (void *)ppd, value, vaddr);
 
 	ppd->pp_acc_data = value;
 }
@@ -3311,8 +3374,8 @@
 	value = ppd->pp_acc_data;
 
 	e1000g_DEBUGLOG_4(e1000gp, e1000g_INFO_LEVEL,
-		"e1000g_ioc_poke_mem($%p, $%p) poking 0x%llx at $%p\n",
-		(void *)e1000gp, (void *)ppd, value, vaddr);
+	    "e1000g_ioc_poke_mem($%p, $%p) poking 0x%llx at $%p\n",
+	    (void *)e1000gp, (void *)ppd, value, vaddr);
 
 	switch (ppd->pp_acc_size) {
 	case 1:
@@ -3590,10 +3653,10 @@
 		e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, 0x0808);
 		/* Reset PHY to update Auto-MDI/MDIX */
 		e1000_write_phy_reg(hw, PHY_CTRL,
-			phy_ctrl | MII_CR_RESET | MII_CR_AUTO_NEG_EN);
+		    phy_ctrl | MII_CR_RESET | MII_CR_AUTO_NEG_EN);
 		/* Reset PHY to auto-neg off and force 1000 */
 		e1000_write_phy_reg(hw, PHY_CTRL,
-			phy_ctrl | MII_CR_RESET);
+		    phy_ctrl | MII_CR_RESET);
 		break;
 	}
 
@@ -3606,9 +3669,9 @@
 	ctrl = E1000_READ_REG(hw, CTRL);
 	ctrl &= ~E1000_CTRL_SPD_SEL;	/* Clear the speed sel bits */
 	ctrl |= (E1000_CTRL_FRCSPD |	/* Set the Force Speed Bit */
-		E1000_CTRL_FRCDPX |	/* Set the Force Duplex Bit */
-		E1000_CTRL_SPD_1000 |	/* Force Speed to 1000 */
-		E1000_CTRL_FD);		/* Force Duplex to FULL */
+	    E1000_CTRL_FRCDPX |		/* Set the Force Duplex Bit */
+	    E1000_CTRL_SPD_1000 |	/* Force Speed to 1000 */
+	    E1000_CTRL_FD);		/* Force Duplex to FULL */
 
 	switch (hw->mac_type) {
 	case e1000_82540:
@@ -3697,20 +3760,20 @@
 
 		rctl = E1000_READ_REG(hw, RCTL);
 		rctl |= (E1000_RCTL_EN |
-			E1000_RCTL_SBP |
-			E1000_RCTL_UPE |
-			E1000_RCTL_MPE |
-			E1000_RCTL_LPE |
-			E1000_RCTL_BAM);		/* 0x803E */
+		    E1000_RCTL_SBP |
+		    E1000_RCTL_UPE |
+		    E1000_RCTL_MPE |
+		    E1000_RCTL_LPE |
+		    E1000_RCTL_BAM);		/* 0x803E */
 		E1000_WRITE_REG(hw, RCTL, rctl);
 
 		ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
 		ctrl_ext |= (E1000_CTRL_EXT_SDP4_DATA |
-			E1000_CTRL_EXT_SDP6_DATA |
-			E1000_CTRL_EXT_SDP7_DATA |
-			E1000_CTRL_EXT_SDP4_DIR |
-			E1000_CTRL_EXT_SDP6_DIR |
-			E1000_CTRL_EXT_SDP7_DIR);	/* 0x0DD0 */
+		    E1000_CTRL_EXT_SDP6_DATA |
+		    E1000_CTRL_EXT_SDP7_DATA |
+		    E1000_CTRL_EXT_SDP4_DIR |
+		    E1000_CTRL_EXT_SDP6_DIR |
+		    E1000_CTRL_EXT_SDP7_DIR);	/* 0x0DD0 */
 		E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
 
 		/*
@@ -3775,26 +3838,26 @@
 	phy_spd_state(hw, B_FALSE);
 
 	phy_ctrl = (MII_CR_FULL_DUPLEX |
-		MII_CR_SPEED_100);
+	    MII_CR_SPEED_100);
 
 	/* Force 100/FD, reset PHY */
 	e1000_write_phy_reg(hw, PHY_CTRL,
-		phy_ctrl | MII_CR_RESET);	/* 0xA100 */
+	    phy_ctrl | MII_CR_RESET);	/* 0xA100 */
 	msec_delay(10);
 
 	/* Force 100/FD */
 	e1000_write_phy_reg(hw, PHY_CTRL,
-		phy_ctrl);			/* 0x2100 */
+	    phy_ctrl);			/* 0x2100 */
 	msec_delay(10);
 
 	/* Now setup the MAC to the same speed/duplex as the PHY. */
 	ctrl = E1000_READ_REG(hw, CTRL);
 	ctrl &= ~E1000_CTRL_SPD_SEL;	/* Clear the speed sel bits */
 	ctrl |= (E1000_CTRL_SLU |	/* Force Link Up */
-		E1000_CTRL_FRCSPD |	/* Set the Force Speed Bit */
-		E1000_CTRL_FRCDPX |	/* Set the Force Duplex Bit */
-		E1000_CTRL_SPD_100 |	/* Force Speed to 100 */
-		E1000_CTRL_FD);		/* Force Duplex to FULL */
+	    E1000_CTRL_FRCSPD |		/* Set the Force Speed Bit */
+	    E1000_CTRL_FRCDPX |		/* Set the Force Duplex Bit */
+	    E1000_CTRL_SPD_100 |	/* Force Speed to 100 */
+	    E1000_CTRL_FD);		/* Force Duplex to FULL */
 
 	E1000_WRITE_REG(hw, CTRL, ctrl);
 }
@@ -3812,26 +3875,26 @@
 	phy_spd_state(hw, B_FALSE);
 
 	phy_ctrl = (MII_CR_FULL_DUPLEX |
-		MII_CR_SPEED_10);
+	    MII_CR_SPEED_10);
 
 	/* Force 10/FD, reset PHY */
 	e1000_write_phy_reg(hw, PHY_CTRL,
-		phy_ctrl | MII_CR_RESET);	/* 0x8100 */
+	    phy_ctrl | MII_CR_RESET);	/* 0x8100 */
 	msec_delay(10);
 
 	/* Force 10/FD */
 	e1000_write_phy_reg(hw, PHY_CTRL,
-		phy_ctrl);			/* 0x0100 */
+	    phy_ctrl);			/* 0x0100 */
 	msec_delay(10);
 
 	/* Now setup the MAC to the same speed/duplex as the PHY. */
 	ctrl = E1000_READ_REG(hw, CTRL);
 	ctrl &= ~E1000_CTRL_SPD_SEL;	/* Clear the speed sel bits */
 	ctrl |= (E1000_CTRL_SLU |	/* Force Link Up */
-		E1000_CTRL_FRCSPD |	/* Set the Force Speed Bit */
-		E1000_CTRL_FRCDPX |	/* Set the Force Duplex Bit */
-		E1000_CTRL_SPD_10 |	/* Force Speed to 10 */
-		E1000_CTRL_FD);		/* Force Duplex to FULL */
+	    E1000_CTRL_FRCSPD |		/* Set the Force Speed Bit */
+	    E1000_CTRL_FRCDPX |		/* Set the Force Duplex Bit */
+	    E1000_CTRL_SPD_10 |		/* Force Speed to 10 */
+	    E1000_CTRL_FD);		/* Force Duplex to FULL */
 
 	E1000_WRITE_REG(hw, CTRL, ctrl);
 }
@@ -4240,7 +4303,7 @@
 e1000_read_pcie_cap_reg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
 {
 	*value = pci_config_get16(((struct e1000g_osdep *)hw->back)->handle,
-		PCI_EX_CONF_CAP + reg);
+	    PCI_EX_CONF_CAP + reg);
 
 	return (0);
 }
--- a/usr/src/uts/common/io/e1000g/e1000g_sw.h	Tue May 29 17:13:54 2007 -0700
+++ b/usr/src/uts/common/io/e1000g/e1000g_sw.h	Tue May 29 23:14:26 2007 -0700
@@ -584,6 +584,12 @@
 };
 #endif
 
+typedef struct _private_devi_list {
+	dev_info_t *dip;
+	dev_info_t *priv_dip;
+	struct _private_devi_list *next;
+} private_devi_list_t;
+
 /*
  * A structure that points to the next entry in the queue.
  */
@@ -871,6 +877,7 @@
 typedef struct e1000g {
 	mac_handle_t mh;
 	dev_info_t *dip;
+	dev_info_t *priv_dip;
 	ddi_acc_handle_t handle;
 	ddi_acc_handle_t E1000_handle;		/* Ws-PCI handle to regs */
 	int AdapterInstance;
@@ -1117,7 +1124,7 @@
 /*
  * Global variables
  */
-extern boolean_t force_detach_enabled;
+extern boolean_t e1000g_force_detach;
 extern uint32_t e1000g_mblks_pending;
 extern krwlock_t e1000g_rx_detach_lock;