Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 18 Mar 2011 18:54:00 +0000 (UTC)
From:      Jack F Vogel <jfv@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r219753 - head/sys/dev/e1000
Message-ID:  <201103181854.p2IIs0G1077313@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jfv
Date: Fri Mar 18 18:54:00 2011
New Revision: 219753
URL: http://svn.freebsd.org/changeset/base/219753

Log:
  This delta updates the em driver to version 7.2.2 which has
  been undergoing test for some weeks. This improves the RX
  mbuf handling to avoid system hang due to depletion. Thanks
  to all those who have been testing the code, and to Beezar
  Liu for the design changes.
  
  Next the igb driver is updated for similar RX changes, but
  also to add new features support for our upcoming i350 family
  of adapters.
  
  MFC after a week

Modified:
  head/sys/dev/e1000/e1000_82575.c
  head/sys/dev/e1000/e1000_82575.h
  head/sys/dev/e1000/e1000_defines.h
  head/sys/dev/e1000/e1000_phy.c
  head/sys/dev/e1000/if_em.c
  head/sys/dev/e1000/if_em.h
  head/sys/dev/e1000/if_igb.c
  head/sys/dev/e1000/if_igb.h
  head/sys/dev/e1000/if_lem.h

Modified: head/sys/dev/e1000/e1000_82575.c
==============================================================================
--- head/sys/dev/e1000/e1000_82575.c	Fri Mar 18 17:49:11 2011	(r219752)
+++ head/sys/dev/e1000/e1000_82575.c	Fri Mar 18 18:54:00 2011	(r219753)
@@ -36,7 +36,6 @@
  * 82575EB Gigabit Network Connection
  * 82575EB Gigabit Backplane Connection
  * 82575GB Gigabit Network Connection
- * 82575GB Gigabit Network Connection
  * 82576 Gigabit Network Connection
  * 82576 Quad Port Gigabit Mezzanine Adapter
  */
@@ -44,7 +43,6 @@
 #include "e1000_api.h"
 
 static s32  e1000_init_phy_params_82575(struct e1000_hw *hw);
-static s32  e1000_init_nvm_params_82575(struct e1000_hw *hw);
 static s32  e1000_init_mac_params_82575(struct e1000_hw *hw);
 static s32  e1000_acquire_phy_82575(struct e1000_hw *hw);
 static void e1000_release_phy_82575(struct e1000_hw *hw);
@@ -197,12 +195,14 @@ static s32 e1000_init_phy_params_82575(s
 	switch (phy->id) {
 	case I347AT4_E_PHY_ID:
 	case M88E1112_E_PHY_ID:
+	case M88E1340M_E_PHY_ID:
 	case M88E1111_I_PHY_ID:
 		phy->type                   = e1000_phy_m88;
 		phy->ops.check_polarity     = e1000_check_polarity_m88;
 		phy->ops.get_info           = e1000_get_phy_info_m88;
 		if (phy->id == I347AT4_E_PHY_ID ||
-		    phy->id == M88E1112_E_PHY_ID)
+		    phy->id == M88E1112_E_PHY_ID ||
+		    phy->id == M88E1340M_E_PHY_ID)
 			phy->ops.get_cable_length = e1000_get_cable_length_m88_gen2;
 		else
 			phy->ops.get_cable_length = e1000_get_cable_length_m88;
@@ -241,7 +241,7 @@ out:
  *  e1000_init_nvm_params_82575 - Init NVM func ptrs.
  *  @hw: pointer to the HW structure
  **/
-static s32 e1000_init_nvm_params_82575(struct e1000_hw *hw)
+s32 e1000_init_nvm_params_82575(struct e1000_hw *hw)
 {
 	struct e1000_nvm_info *nvm = &hw->nvm;
 	u32 eecd = E1000_READ_REG(hw, E1000_EECD);
@@ -258,7 +258,6 @@ static s32 e1000_init_nvm_params_82575(s
 	size += NVM_WORD_SIZE_BASE_SHIFT;
 
 	nvm->word_size = 1 << size;
-
 	nvm->opcode_bits        = 8;
 	nvm->delay_usec         = 1;
 	switch (nvm->override) {
@@ -278,20 +277,23 @@ static s32 e1000_init_nvm_params_82575(s
 
 	nvm->type = e1000_nvm_eeprom_spi;
 
-	if (nvm->word_size == (1 << 15)) {
+	if (nvm->word_size == (1 << 15))
 		nvm->page_size = 128;
-	}
-
 
 	/* Function Pointers */
-	nvm->ops.acquire = e1000_acquire_nvm_82575;
-	if (nvm->word_size < (1 << 15)) {
-		nvm->ops.read = e1000_read_nvm_eerd;
-	} else {
-		nvm->ops.read = e1000_read_nvm_spi;
-	}
-	nvm->ops.release = e1000_release_nvm_82575;
-	nvm->ops.valid_led_default = e1000_valid_led_default_82575;
+	nvm->ops.acquire    = e1000_acquire_nvm_82575;
+	nvm->ops.release    = e1000_release_nvm_82575;
+	if (nvm->word_size < (1 << 15))
+		nvm->ops.read    = e1000_read_nvm_eerd;
+	else
+		nvm->ops.read    = e1000_read_nvm_spi;
+
+	nvm->ops.write              = e1000_write_nvm_spi;
+	nvm->ops.validate           = e1000_validate_nvm_checksum_generic;
+	nvm->ops.update             = e1000_update_nvm_checksum_generic;
+	nvm->ops.valid_led_default  = e1000_valid_led_default_82575;
+
+	/* override genric family function pointers for specific descendants */
 	switch (hw->mac.type) {
 	case e1000_82580:
 		nvm->ops.validate = e1000_validate_nvm_checksum_82580;
@@ -302,10 +304,8 @@ static s32 e1000_init_nvm_params_82575(s
 		nvm->ops.update = e1000_update_nvm_checksum_i350;
 		break;
 	default:
-		nvm->ops.validate = e1000_validate_nvm_checksum_generic;
-		nvm->ops.update = e1000_update_nvm_checksum_generic;
+		break;
 	}
-	nvm->ops.write = e1000_write_nvm_spi;
 
 	return E1000_SUCCESS;
 }
@@ -889,9 +889,7 @@ static s32 e1000_acquire_nvm_82575(struc
 	ret_val = e1000_acquire_swfw_sync_82575(hw, E1000_SWFW_EEP_SM);
 	if (ret_val)
 		goto out;
-
 	ret_val = e1000_acquire_nvm_generic(hw);
-
 	if (ret_val)
 		e1000_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM);
 
@@ -910,7 +908,6 @@ static void e1000_release_nvm_82575(stru
 {
 	DEBUGFUNC("e1000_release_nvm_82575");
 
-	e1000_release_nvm_generic(hw);
 	e1000_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM);
 }
 
@@ -1365,7 +1362,8 @@ static s32 e1000_setup_copper_link_82575
 	switch (hw->phy.type) {
 	case e1000_phy_m88:
 		if (hw->phy.id == I347AT4_E_PHY_ID ||
-		    hw->phy.id == M88E1112_E_PHY_ID)
+		    hw->phy.id == M88E1112_E_PHY_ID ||
+		    hw->phy.id == M88E1340M_E_PHY_ID)
 			ret_val = e1000_copper_link_setup_m88_gen2(hw);
 		else
 			ret_val = e1000_copper_link_setup_m88(hw);
@@ -1840,7 +1838,6 @@ out:
 	return ret_val;
 }
 
-
 /**
  *  e1000_vmdq_set_anti_spoofing_pf - enable or disable anti-spoofing
  *  @hw: pointer to the hardware struct
@@ -1986,7 +1983,7 @@ out:
  *  e1000_reset_mdicnfg_82580 - Reset MDICNFG destination and com_mdio bits
  *  @hw: pointer to the HW structure
  *
- *  This resets the MDICNFG.Destination and MDICNFG.Com_MDIO bits based on
+ *  This resets the the MDICNFG.Destination and MDICNFG.Com_MDIO bits based on
  *  the values found in the EEPROM.  This addresses an issue in which these
  *  bits are not restored from EEPROM after reset.
  **/

Modified: head/sys/dev/e1000/e1000_82575.h
==============================================================================
--- head/sys/dev/e1000/e1000_82575.h	Fri Mar 18 17:49:11 2011	(r219752)
+++ head/sys/dev/e1000/e1000_82575.h	Fri Mar 18 18:54:00 2011	(r219753)
@@ -469,6 +469,8 @@ struct e1000_adv_tx_context_desc {
 void e1000_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable);
 void e1000_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf);
 void e1000_vmdq_set_replication_pf(struct e1000_hw *hw, bool enable);
+s32 e1000_init_nvm_params_82575(struct e1000_hw *hw);
+
 enum e1000_promisc_type {
 	e1000_promisc_disabled = 0,   /* all promisc modes disabled */
 	e1000_promisc_unicast = 1,    /* unicast promiscuous enabled */

Modified: head/sys/dev/e1000/e1000_defines.h
==============================================================================
--- head/sys/dev/e1000/e1000_defines.h	Fri Mar 18 17:49:11 2011	(r219752)
+++ head/sys/dev/e1000/e1000_defines.h	Fri Mar 18 18:54:00 2011	(r219753)
@@ -76,8 +76,8 @@
 #define E1000_WUFC_FLX3 0x00080000 /* Flexible Filter 3 Enable */
 #define E1000_WUFC_FLX4 0x00100000 /* Flexible Filter 4 Enable */
 #define E1000_WUFC_FLX5 0x00200000 /* Flexible Filter 5 Enable */
-#define E1000_WUFC_FLX6  0x00400000 /* Flexible Filter 6 Enable */
-#define E1000_WUFC_FLX7  0x00800000 /* Flexible Filter 7 Enable */
+#define E1000_WUFC_FLX6 0x00400000 /* Flexible Filter 6 Enable */
+#define E1000_WUFC_FLX7 0x00800000 /* Flexible Filter 7 Enable */
 #define E1000_WUFC_FW_RST 0x80000000 /* Wake on FW Reset Enable */
 #define E1000_WUFC_ALL_FILTERS_PHY_4 0x0000F0FF /*Mask for all wakeup filters*/
 #define E1000_WUFC_FLX_OFFSET_PHY 12 /* Offset to the Flexible Filters bits */
@@ -249,6 +249,7 @@
 #define E1000_RXD_SPC_CFI_MASK  0x1000  /* CFI is bit 12 */
 #define E1000_RXD_SPC_CFI_SHIFT 12
 
+#define E1000_RXDEXT_STATERR_LB    0x00040000
 #define E1000_RXDEXT_STATERR_CE    0x01000000
 #define E1000_RXDEXT_STATERR_SE    0x02000000
 #define E1000_RXDEXT_STATERR_SEQ   0x04000000
@@ -1478,7 +1479,8 @@
 #define M88E1011_I_REV_4     0x04
 #define M88E1111_I_PHY_ID    0x01410CC0
 #define M88E1112_E_PHY_ID    0x01410C90
-#define I347AT4_E_PHY_ID    0x01410DC0
+#define I347AT4_E_PHY_ID     0x01410DC0
+#define M88E1340M_E_PHY_ID   0x01410DF0
 #define GG82563_E_PHY_ID     0x01410CA0
 #define IGP03E1000_E_PHY_ID  0x02A80390
 #define IFE_E_PHY_ID         0x02A80330
@@ -1764,11 +1766,10 @@
 #define E1000_RTTBCNRC_RF_INT_MASK	\
 	(E1000_RTTBCNRC_RF_DEC_MASK << E1000_RTTBCNRC_RF_INT_SHIFT)
 
-
 /* DMA Coalescing register fields */
 #define E1000_DMACR_DMACWT_MASK         0x00003FFF /* DMA Coalescing
                                                     * Watchdog Timer */
-#define E1000_DMACR_DMACTHR_MASK        0x00FF0000 /* DMA Coalescing Receive
+#define E1000_DMACR_DMACTHR_MASK        0x00FF0000 /* DMA Coalescing Rx
                                                     * Threshold */
 #define E1000_DMACR_DMACTHR_SHIFT       16
 #define E1000_DMACR_DMAC_LX_MASK        0x30000000 /* Lx when no PCIe
@@ -1781,15 +1782,15 @@
 
 #define E1000_DMCTLX_TTLX_MASK          0x00000FFF /* Time to LX request */
 
-#define E1000_DMCRTRH_UTRESH_MASK       0x0007FFFF /* Receive Traffic Rate
+#define E1000_DMCRTRH_UTRESH_MASK       0x0007FFFF /* Rx Traffic Rate
                                                     * Threshold */
-#define E1000_DMCRTRH_LRPRCW            0x80000000 /* Rcv packet rate in
+#define E1000_DMCRTRH_LRPRCW            0x80000000 /* Rx packet rate in
                                                     * current window */
 
-#define E1000_DMCCNT_CCOUNT_MASK        0x01FFFFFF /* DMA Coal Rcv Traffic
+#define E1000_DMCCNT_CCOUNT_MASK        0x01FFFFFF /* DMA Coal Rx Traffic
                                                     * Current Cnt */
 
-#define E1000_FCRTC_RTH_COAL_MASK       0x0003FFF0 /* Flow ctrl Rcv Threshold
+#define E1000_FCRTC_RTH_COAL_MASK       0x0003FFF0 /* Flow ctrl Rx Threshold
                                                     * High val */
 #define E1000_FCRTC_RTH_COAL_SHIFT      4
 #define E1000_PCIEMISC_LX_DECISION      0x00000080 /* Lx power decision based

Modified: head/sys/dev/e1000/e1000_phy.c
==============================================================================
--- head/sys/dev/e1000/e1000_phy.c	Fri Mar 18 17:49:11 2011	(r219752)
+++ head/sys/dev/e1000/e1000_phy.c	Fri Mar 18 18:54:00 2011	(r219753)
@@ -255,10 +255,6 @@ s32 e1000_read_phy_reg_mdic(struct e1000
 
 	E1000_WRITE_REG(hw, E1000_MDIC, mdic);
 
-	/* Workaround for Si errata */
-	if ((hw->phy.type == e1000_phy_82577) && (hw->revision_id <= 2))
-		msec_delay(10);
-
 	/*
 	 * Poll the ready bit to see if the MDI read completed
 	 * Increasing the time out as testing showed failures with
@@ -326,10 +322,6 @@ s32 e1000_write_phy_reg_mdic(struct e100
 
 	E1000_WRITE_REG(hw, E1000_MDIC, mdic);
 
-	/* Workaround for Si errata */
-	if ((hw->phy.type == e1000_phy_82577) && (hw->revision_id <= 2))
-		msec_delay(10);
-
 	/*
 	 * Poll the ready bit to see if the MDI read completed
 	 * Increasing the time out as testing showed failures with
@@ -1656,6 +1648,7 @@ s32 e1000_phy_force_speed_duplex_m88(str
 		if (!link) {
 			if (hw->phy.type != e1000_phy_m88 ||
 			    hw->phy.id == I347AT4_E_PHY_ID ||
+			    hw->phy.id == M88E1340M_E_PHY_ID ||
 			    hw->phy.id == M88E1112_E_PHY_ID) {
 				DEBUGOUT("Link taking longer than expected.\n");
 			} else {
@@ -1683,6 +1676,7 @@ s32 e1000_phy_force_speed_duplex_m88(str
 
 	if (hw->phy.type != e1000_phy_m88 ||
 	    hw->phy.id == I347AT4_E_PHY_ID ||
+	    hw->phy.id == M88E1340M_E_PHY_ID ||
 	    hw->phy.id == M88E1112_E_PHY_ID)
 		goto out;
 
@@ -2233,6 +2227,7 @@ s32 e1000_get_cable_length_m88_gen2(stru
 	DEBUGFUNC("e1000_get_cable_length_m88_gen2");
 
 	switch (hw->phy.id) {
+	case M88E1340M_E_PHY_ID:
 	case I347AT4_E_PHY_ID:
 		/* Remember the original page select and set it to 7 */
 		ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT,
@@ -2787,6 +2782,7 @@ enum e1000_phy_type e1000_get_phy_type_f
 	case M88E1011_I_PHY_ID:
 	case I347AT4_E_PHY_ID:
 	case M88E1112_E_PHY_ID:
+	case M88E1340M_E_PHY_ID:
 		phy_type = e1000_phy_m88;
 		break;
 	case IGP01E1000_I_PHY_ID: /* IGP 1 & 2 share this */

Modified: head/sys/dev/e1000/if_em.c
==============================================================================
--- head/sys/dev/e1000/if_em.c	Fri Mar 18 17:49:11 2011	(r219752)
+++ head/sys/dev/e1000/if_em.c	Fri Mar 18 18:54:00 2011	(r219753)
@@ -93,7 +93,7 @@ int	em_display_debug_stats = 0;
 /*********************************************************************
  *  Driver version:
  *********************************************************************/
-char em_driver_version[] = "7.1.9";
+char em_driver_version[] = "7.2.2";
 
 /*********************************************************************
  *  PCI Device ID Table
@@ -284,9 +284,7 @@ static void	em_handle_tx(void *context, 
 static void	em_handle_rx(void *context, int pending);
 static void	em_handle_link(void *context, int pending);
 
-static void	em_add_rx_process_limit(struct adapter *, const char *,
-		    const char *, int *, int);
-static void	em_set_flow_cntrl(struct adapter *, const char *,
+static void	em_set_sysctl_value(struct adapter *, const char *,
 		    const char *, int *, int);
 
 static __inline void em_rx_discard(struct rx_ring *, int);
@@ -365,6 +363,10 @@ TUNABLE_INT("hw.em.rx_process_limit", &e
 static int em_fc_setting = e1000_fc_full;
 TUNABLE_INT("hw.em.fc_setting", &em_fc_setting);
 
+/* Energy efficient ethernet - default to OFF */
+static int eee_setting = 0;
+TUNABLE_INT("hw.em.eee_setting", &eee_setting);
+
 /* Global used in WOL setup with multiport cards */
 static int global_quad_port_a = 0;
 
@@ -433,12 +435,14 @@ static int
 em_attach(device_t dev)
 {
 	struct adapter	*adapter;
+	struct e1000_hw	*hw;
 	int		error = 0;
 
 	INIT_DEBUGOUT("em_attach: begin");
 
 	adapter = device_get_softc(dev);
 	adapter->dev = adapter->osdep.dev = dev;
+	hw = &adapter->hw;
 	EM_CORE_LOCK_INIT(adapter, device_get_nameunit(dev));
 
 	/* SYSCTL stuff */
@@ -470,11 +474,11 @@ em_attach(device_t dev)
 	** must happen after the MAC is 
 	** identified
 	*/
-	if ((adapter->hw.mac.type == e1000_ich8lan) ||
-	    (adapter->hw.mac.type == e1000_ich9lan) ||
-	    (adapter->hw.mac.type == e1000_ich10lan) ||
-	    (adapter->hw.mac.type == e1000_pchlan) ||
-	    (adapter->hw.mac.type == e1000_pch2lan)) {
+	if ((hw->mac.type == e1000_ich8lan) ||
+	    (hw->mac.type == e1000_ich9lan) ||
+	    (hw->mac.type == e1000_ich10lan) ||
+	    (hw->mac.type == e1000_pchlan) ||
+	    (hw->mac.type == e1000_pch2lan)) {
 		int rid = EM_BAR_TYPE_FLASH;
 		adapter->flash = bus_alloc_resource_any(dev,
 		    SYS_RES_MEMORY, &rid, RF_ACTIVE);
@@ -484,7 +488,7 @@ em_attach(device_t dev)
 			goto err_pci;
 		}
 		/* This is used in the shared code */
-		adapter->hw.flash_address = (u8 *)adapter->flash;
+		hw->flash_address = (u8 *)adapter->flash;
 		adapter->osdep.flash_bus_space_tag =
 		    rman_get_bustag(adapter->flash);
 		adapter->osdep.flash_bus_space_handle =
@@ -492,39 +496,39 @@ em_attach(device_t dev)
 	}
 
 	/* Do Shared Code initialization */
-	if (e1000_setup_init_funcs(&adapter->hw, TRUE)) {
+	if (e1000_setup_init_funcs(hw, TRUE)) {
 		device_printf(dev, "Setup of Shared code failed\n");
 		error = ENXIO;
 		goto err_pci;
 	}
 
-	e1000_get_bus_info(&adapter->hw);
+	e1000_get_bus_info(hw);
 
 	/* Set up some sysctls for the tunable interrupt delays */
 	em_add_int_delay_sysctl(adapter, "rx_int_delay",
 	    "receive interrupt delay in usecs", &adapter->rx_int_delay,
-	    E1000_REGISTER(&adapter->hw, E1000_RDTR), em_rx_int_delay_dflt);
+	    E1000_REGISTER(hw, E1000_RDTR), em_rx_int_delay_dflt);
 	em_add_int_delay_sysctl(adapter, "tx_int_delay",
 	    "transmit interrupt delay in usecs", &adapter->tx_int_delay,
-	    E1000_REGISTER(&adapter->hw, E1000_TIDV), em_tx_int_delay_dflt);
+	    E1000_REGISTER(hw, E1000_TIDV), em_tx_int_delay_dflt);
 	em_add_int_delay_sysctl(adapter, "rx_abs_int_delay",
 	    "receive interrupt delay limit in usecs",
 	    &adapter->rx_abs_int_delay,
-	    E1000_REGISTER(&adapter->hw, E1000_RADV),
+	    E1000_REGISTER(hw, E1000_RADV),
 	    em_rx_abs_int_delay_dflt);
 	em_add_int_delay_sysctl(adapter, "tx_abs_int_delay",
 	    "transmit interrupt delay limit in usecs",
 	    &adapter->tx_abs_int_delay,
-	    E1000_REGISTER(&adapter->hw, E1000_TADV),
+	    E1000_REGISTER(hw, E1000_TADV),
 	    em_tx_abs_int_delay_dflt);
 
 	/* Sysctl for limiting the amount of work done in the taskqueue */
-	em_add_rx_process_limit(adapter, "rx_processing_limit",
+	em_set_sysctl_value(adapter, "rx_processing_limit",
 	    "max number of rx packets to process", &adapter->rx_process_limit,
 	    em_rx_process_limit);
 
 	/* Sysctl for setting the interface flow control */
-	em_set_flow_cntrl(adapter, "flow_control",
+	em_set_sysctl_value(adapter, "flow_control",
 	    "configure flow control",
 	    &adapter->fc_setting, em_fc_setting);
 
@@ -549,15 +553,15 @@ em_attach(device_t dev)
 	} else
 		adapter->num_rx_desc = em_rxd;
 
-	adapter->hw.mac.autoneg = DO_AUTO_NEG;
-	adapter->hw.phy.autoneg_wait_to_complete = FALSE;
-	adapter->hw.phy.autoneg_advertised = AUTONEG_ADV_DEFAULT;
+	hw->mac.autoneg = DO_AUTO_NEG;
+	hw->phy.autoneg_wait_to_complete = FALSE;
+	hw->phy.autoneg_advertised = AUTONEG_ADV_DEFAULT;
 
 	/* Copper options */
-	if (adapter->hw.phy.media_type == e1000_media_type_copper) {
-		adapter->hw.phy.mdix = AUTO_ALL_MODES;
-		adapter->hw.phy.disable_polarity_correction = FALSE;
-		adapter->hw.phy.ms_type = EM_MASTER_SLAVE;
+	if (hw->phy.media_type == e1000_media_type_copper) {
+		hw->phy.mdix = AUTO_ALL_MODES;
+		hw->phy.disable_polarity_correction = FALSE;
+		hw->phy.ms_type = EM_MASTER_SLAVE;
 	}
 
 	/*
@@ -571,7 +575,7 @@ em_attach(device_t dev)
 	 * This controls when hardware reports transmit completion
 	 * status.
 	 */
-	adapter->hw.mac.report_tx_early = 1;
+	hw->mac.report_tx_early = 1;
 
 	/* 
 	** Get queue/ring memory
@@ -591,25 +595,31 @@ em_attach(device_t dev)
 	}
 
 	/* Check SOL/IDER usage */
-	if (e1000_check_reset_block(&adapter->hw))
+	if (e1000_check_reset_block(hw))
 		device_printf(dev, "PHY reset is blocked"
 		    " due to SOL/IDER session.\n");
 
+	/* Sysctl for setting Energy Efficient Ethernet */
+	em_set_sysctl_value(adapter, "eee_control",
+	    "enable Energy Efficient Ethernet",
+	    &hw->dev_spec.ich8lan.eee_disable, eee_setting);
+
 	/*
 	** Start from a known state, this is
 	** important in reading the nvm and
 	** mac from that.
 	*/
-	e1000_reset_hw(&adapter->hw);
+	e1000_reset_hw(hw);
+
 
 	/* Make sure we have a good EEPROM before we read from it */
-	if (e1000_validate_nvm_checksum(&adapter->hw) < 0) {
+	if (e1000_validate_nvm_checksum(hw) < 0) {
 		/*
 		** Some PCI-E parts fail the first check due to
 		** the link being in sleep state, call it again,
 		** if it fails a second time its a real issue.
 		*/
-		if (e1000_validate_nvm_checksum(&adapter->hw) < 0) {
+		if (e1000_validate_nvm_checksum(hw) < 0) {
 			device_printf(dev,
 			    "The EEPROM Checksum Is Not Valid\n");
 			error = EIO;
@@ -618,14 +628,14 @@ em_attach(device_t dev)
 	}
 
 	/* Copy the permanent MAC address out of the EEPROM */
-	if (e1000_read_mac_addr(&adapter->hw) < 0) {
+	if (e1000_read_mac_addr(hw) < 0) {
 		device_printf(dev, "EEPROM read error while reading MAC"
 		    " address\n");
 		error = EIO;
 		goto err_late;
 	}
 
-	if (!em_is_valid_ether_addr(adapter->hw.mac.addr)) {
+	if (!em_is_valid_ether_addr(hw->mac.addr)) {
 		device_printf(dev, "Invalid MAC address\n");
 		error = EIO;
 		goto err_late;
@@ -655,7 +665,7 @@ em_attach(device_t dev)
 	/* Initialize statistics */
 	em_update_stats_counters(adapter);
 
-	adapter->hw.mac.get_link_status = 1;
+	hw->mac.get_link_status = 1;
 	em_update_link_status(adapter);
 
 	/* Register for VLAN events */
@@ -927,11 +937,10 @@ em_start_locked(struct ifnet *ifp, struc
 	if (!adapter->link_active)
 		return;
 
-        /* Call cleanup if number of TX descriptors low */
-	if (txr->tx_avail <= EM_TX_CLEANUP_THRESHOLD)
-		em_txeof(txr);
-
 	while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
+        	/* Call cleanup if number of TX descriptors low */
+		if (txr->tx_avail <= EM_TX_CLEANUP_THRESHOLD)
+			em_txeof(txr);
 		if (txr->tx_avail < EM_MAX_SCATTER) {
 			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
 			break;
@@ -1411,8 +1420,7 @@ em_poll(struct ifnet *ifp, enum poll_cmd
 	if (!drbr_empty(ifp, txr->br))
 		em_mq_start_locked(ifp, txr, NULL);
 #else
-	if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
-		em_start_locked(ifp, txr);
+	em_start_locked(ifp, txr);
 #endif
 	EM_TX_UNLOCK(txr);
 
@@ -1475,24 +1483,20 @@ em_handle_que(void *context, int pending
 	struct ifnet	*ifp = adapter->ifp;
 	struct tx_ring	*txr = adapter->tx_rings;
 	struct rx_ring	*rxr = adapter->rx_rings;
-	bool		more;
 
 
 	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
-		more = em_rxeof(rxr, adapter->rx_process_limit, NULL);
-
+		bool more = em_rxeof(rxr, adapter->rx_process_limit, NULL);
 		EM_TX_LOCK(txr);
 		em_txeof(txr);
 #ifdef EM_MULTIQUEUE
 		if (!drbr_empty(ifp, txr->br))
 			em_mq_start_locked(ifp, txr, NULL);
 #else
-		if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
-			em_start_locked(ifp, txr);
+		em_start_locked(ifp, txr);
 #endif
-		em_txeof(txr);
 		EM_TX_UNLOCK(txr);
-		if (more) {
+		if (more || (ifp->if_drv_flags & IFF_DRV_OACTIVE)) {
 			taskqueue_enqueue(adapter->tq, &adapter->que_task);
 			return;
 		}
@@ -1601,10 +1605,8 @@ em_handle_tx(void *context, int pending)
 	if (!drbr_empty(ifp, txr->br))
 		em_mq_start_locked(ifp, txr, NULL);
 #else
-	if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
-		em_start_locked(ifp, txr);
+	em_start_locked(ifp, txr);
 #endif
-	em_txeof(txr);
 	E1000_WRITE_REG(&adapter->hw, E1000_IMS, txr->ims);
 	EM_TX_UNLOCK(txr);
 }
@@ -2179,6 +2181,7 @@ em_local_timer(void *arg)
 	struct adapter	*adapter = arg;
 	struct ifnet	*ifp = adapter->ifp;
 	struct tx_ring	*txr = adapter->tx_rings;
+	struct rx_ring	*rxr = adapter->rx_rings;
 
 	EM_CORE_LOCK_ASSERT(adapter);
 
@@ -2190,6 +2193,13 @@ em_local_timer(void *arg)
 	    e1000_get_laa_state_82571(&adapter->hw))
 		e1000_rar_set(&adapter->hw, adapter->hw.mac.addr, 0);
 
+	/* trigger tq to refill rx ring queue if it is empty */
+	for (int i = 0; i < adapter->num_queues; i++, rxr++) {
+		if (rxr->next_to_check == rxr->next_to_refresh) {
+			taskqueue_enqueue(rxr->tq, &rxr->rx_task);
+		}
+	}
+
 	/* 
 	** Don't do TX watchdog check if we've been paused
 	*/
@@ -3730,17 +3740,17 @@ em_txeof(struct tx_ring *txr)
 		txr->queue_status = EM_QUEUE_HUNG;
 
         /*
-         * If we have enough room, clear IFF_DRV_OACTIVE
+         * If we have a minimum free, clear IFF_DRV_OACTIVE
          * to tell the stack that it is OK to send packets.
          */
-        if (txr->tx_avail > EM_TX_CLEANUP_THRESHOLD) {                
+        if (txr->tx_avail > EM_MAX_SCATTER)
                 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
-		/* Disable watchdog if all clean */
-                if (txr->tx_avail == adapter->num_tx_desc) {
-			txr->queue_status = EM_QUEUE_IDLE;
-			return (FALSE);
-		} 
-        }
+
+	/* Disable watchdog if all clean */
+	if (txr->tx_avail == adapter->num_tx_desc) {
+		txr->queue_status = EM_QUEUE_IDLE;
+		return (FALSE);
+	} 
 
 	return (TRUE);
 }
@@ -3758,11 +3768,19 @@ em_refresh_mbufs(struct rx_ring *rxr, in
 	struct mbuf		*m;
 	bus_dma_segment_t	segs[1];
 	struct em_buffer	*rxbuf;
-	int			i, error, nsegs, cleaned;
+	int			i, j, error, nsegs;
+	bool			cleaned = FALSE;
+
+	i = j = rxr->next_to_refresh;
+	/*
+	** Get one descriptor beyond
+	** our work mark to control
+	** the loop.
+	*/
+	if (++j == adapter->num_rx_desc)
+		j = 0;
 
-	i = rxr->next_to_refresh;
-	cleaned = -1;
-	while (i != limit) {
+	while (j != limit) {
 		rxbuf = &rxr->rx_buffers[i];
 		if (rxbuf->m_head == NULL) {
 			m = m_getjcl(M_DONTWAIT, MT_DATA,
@@ -3796,21 +3814,22 @@ em_refresh_mbufs(struct rx_ring *rxr, in
 		bus_dmamap_sync(rxr->rxtag,
 		    rxbuf->map, BUS_DMASYNC_PREREAD);
 		rxr->rx_base[i].buffer_addr = htole64(segs[0].ds_addr);
+		cleaned = TRUE;
 
-		cleaned = i;
-		/* Calculate next index */
-		if (++i == adapter->num_rx_desc)
-			i = 0;
+		i = j; /* Next is precalulated for us */
 		rxr->next_to_refresh = i;
+		/* Calculate next controlling index */
+		if (++j == adapter->num_rx_desc)
+			j = 0;
 	}
 update:
 	/*
 	** Update the tail pointer only if,
 	** and as far as we have refreshed.
 	*/
-	if (cleaned != -1) /* Update tail index */
+	if (cleaned)
 		E1000_WRITE_REG(&adapter->hw,
-		    E1000_RDT(rxr->me), cleaned);
+		    E1000_RDT(rxr->me), rxr->next_to_refresh);
 
 	return;
 }
@@ -3888,36 +3907,32 @@ em_setup_receive_ring(struct rx_ring *rx
 	struct	adapter 	*adapter = rxr->adapter;
 	struct em_buffer	*rxbuf;
 	bus_dma_segment_t	seg[1];
-	int			rsize, nsegs, error;
+	int			i, j, nsegs, error;
 
 
 	/* Clear the ring contents */
 	EM_RX_LOCK(rxr);
-	rsize = roundup2(adapter->num_rx_desc *
-	    sizeof(struct e1000_rx_desc), EM_DBA_ALIGN);
-	bzero((void *)rxr->rx_base, rsize);
 
-	/*
-	** Free current RX buffer structs and their mbufs
-	*/
-	for (int i = 0; i < adapter->num_rx_desc; i++) {
-		rxbuf = &rxr->rx_buffers[i];
-		if (rxbuf->m_head != NULL) {
-			bus_dmamap_sync(rxr->rxtag, rxbuf->map,
-			    BUS_DMASYNC_POSTREAD);
-			bus_dmamap_unload(rxr->rxtag, rxbuf->map);
-			m_freem(rxbuf->m_head);
-		}
+	/* Invalidate all descriptors */
+	for (i = 0; i < adapter->num_rx_desc; i++) {
+		struct e1000_rx_desc* cur;
+		cur = &rxr->rx_base[i];
+		cur->status = 0;
 	}
 
 	/* Now replenish the mbufs */
-	for (int j = 0; j != adapter->num_rx_desc; ++j) {
+	i = j = rxr->next_to_refresh;
+	if (++j == adapter->num_rx_desc)
+		j = 0;
 
-		rxbuf = &rxr->rx_buffers[j];
+	while(j != rxr->next_to_check) {
+		rxbuf = &rxr->rx_buffers[i];
 		rxbuf->m_head = m_getjcl(M_DONTWAIT, MT_DATA,
 		    M_PKTHDR, adapter->rx_mbuf_sz);
-		if (rxbuf->m_head == NULL)
-			return (ENOBUFS);
+		if (rxbuf->m_head == NULL) {
+			error = ENOBUFS;
+			goto fail;
+		}
 		rxbuf->m_head->m_len = adapter->rx_mbuf_sz;
 		rxbuf->m_head->m_flags &= ~M_HASFCS; /* we strip it */
 		rxbuf->m_head->m_pkthdr.len = adapter->rx_mbuf_sz;
@@ -3929,25 +3944,24 @@ em_setup_receive_ring(struct rx_ring *rx
 		if (error != 0) {
 			m_freem(rxbuf->m_head);
 			rxbuf->m_head = NULL;
-			return (error);
+			goto fail;
 		}
 		bus_dmamap_sync(rxr->rxtag,
 		    rxbuf->map, BUS_DMASYNC_PREREAD);
 
 		/* Update descriptor */
-		rxr->rx_base[j].buffer_addr = htole64(seg[0].ds_addr);
+		rxr->rx_base[i].buffer_addr = htole64(seg[0].ds_addr);
+		i = j;
+		if (++j == adapter->num_rx_desc)
+			j = 0;
 	}
 
-
-	/* Setup our descriptor indices */
-	rxr->next_to_check = 0;
-	rxr->next_to_refresh = 0;
-
+fail:
+	rxr->next_to_refresh = i;
 	bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,
 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
-
 	EM_RX_UNLOCK(rxr);
-	return (0);
+	return (error);
 }
 
 /*********************************************************************
@@ -3959,9 +3973,9 @@ static int
 em_setup_receive_structures(struct adapter *adapter)
 {
 	struct rx_ring *rxr = adapter->rx_rings;
-	int j;
+	int q;
 
-	for (j = 0; j < adapter->num_queues; j++, rxr++)
+	for (q = 0; q < adapter->num_queues; q++, rxr++)
 		if (em_setup_receive_ring(rxr))
 			goto fail;
 
@@ -3970,11 +3984,12 @@ fail:
 	/*
 	 * Free RX buffers allocated so far, we will only handle
 	 * the rings that completed, the failing case will have
-	 * cleaned up for itself. 'j' failed, so its the terminus.
+	 * cleaned up for itself. 'q' failed, so its the terminus.
 	 */
-	for (int i = 0; i < j; ++i) {
+	for (int i = 0, n = 0; i < q; ++i) {
 		rxr = &adapter->rx_rings[i];
-		for (int n = 0; n < adapter->num_rx_desc; n++) {
+		n = rxr->next_to_check;
+		while(n != rxr->next_to_refresh) {
 			struct em_buffer *rxbuf;
 			rxbuf = &rxr->rx_buffers[n];
 			if (rxbuf->m_head != NULL) {
@@ -3984,7 +3999,11 @@ fail:
 				m_freem(rxbuf->m_head);
 				rxbuf->m_head = NULL;
 			}
+			if (++n == adapter->num_rx_desc)
+				n = 0;
 		}
+		rxr->next_to_check = 0;
+		rxr->next_to_refresh = 0;
 	}
 
 	return (ENOBUFS);
@@ -4025,7 +4044,8 @@ em_free_receive_buffers(struct rx_ring *
 	INIT_DEBUGOUT("free_receive_buffers: begin");
 
 	if (rxr->rx_buffers != NULL) {
-		for (int i = 0; i < adapter->num_rx_desc; i++) {
+		int i = rxr->next_to_check;
+		while(i != rxr->next_to_refresh) {
 			rxbuf = &rxr->rx_buffers[i];
 			if (rxbuf->map != NULL) {
 				bus_dmamap_sync(rxr->rxtag, rxbuf->map,
@@ -4037,9 +4057,13 @@ em_free_receive_buffers(struct rx_ring *
 				m_freem(rxbuf->m_head);
 				rxbuf->m_head = NULL;
 			}
+			if (++i == adapter->num_rx_desc)
+				i = 0;
 		}
 		free(rxr->rx_buffers, M_DEVBUF);
 		rxr->rx_buffers = NULL;
+		rxr->next_to_check = 0;
+		rxr->next_to_refresh = 0;
 	}
 
 	if (rxr->rxtag != NULL) {
@@ -4122,8 +4146,8 @@ em_initialize_receive_unit(struct adapte
 		E1000_WRITE_REG(hw, E1000_RDBAH(i), (u32)(bus_addr >> 32));
 		E1000_WRITE_REG(hw, E1000_RDBAL(i), (u32)bus_addr);
 		/* Setup the Head and Tail Descriptor Pointers */
-		E1000_WRITE_REG(hw, E1000_RDH(i), 0);
-		E1000_WRITE_REG(hw, E1000_RDT(i), adapter->num_rx_desc - 1);
+		E1000_WRITE_REG(hw, E1000_RDH(i), rxr->next_to_check);
+		E1000_WRITE_REG(hw, E1000_RDT(i), rxr->next_to_refresh);
 	}
 
 	/* Set early receive threshold on appropriate hw */
@@ -4303,7 +4327,8 @@ next_desc:
 	}
 
 	/* Catch any remaining refresh work */
-	em_refresh_mbufs(rxr, i);
+	if (processed != 0 || i == rxr->next_to_refresh)
+		em_refresh_mbufs(rxr, i);
 
 	rxr->next_to_check = i;
 	if (done != NULL)
@@ -4743,10 +4768,8 @@ em_enable_wakeup(device_t dev)
 	if ((adapter->hw.mac.type == e1000_ich8lan) ||
 	    (adapter->hw.mac.type == e1000_pchlan) ||
 	    (adapter->hw.mac.type == e1000_ich9lan) ||
-	    (adapter->hw.mac.type == e1000_ich10lan)) {
+	    (adapter->hw.mac.type == e1000_ich10lan))
 		e1000_disable_gig_wol_ich8lan(&adapter->hw);
-		e1000_hv_phy_powerdown_workaround_ich8lan(&adapter->hw);
-	}
 
 	/* Keep the laser running on Fiber adapters */
 	if (adapter->hw.phy.media_type == e1000_media_type_fiber ||
@@ -5442,17 +5465,7 @@ em_add_int_delay_sysctl(struct adapter *
 }
 
 static void
-em_add_rx_process_limit(struct adapter *adapter, const char *name,
-	const char *description, int *limit, int value)
-{
-	*limit = value;
-	SYSCTL_ADD_INT(device_get_sysctl_ctx(adapter->dev),
-	    SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)),
-	    OID_AUTO, name, CTLTYPE_INT|CTLFLAG_RW, limit, value, description);
-}
-
-static void
-em_set_flow_cntrl(struct adapter *adapter, const char *name,
+em_set_sysctl_value(struct adapter *adapter, const char *name,
 	const char *description, int *limit, int value)
 {
 	*limit = value;

Modified: head/sys/dev/e1000/if_em.h
==============================================================================
--- head/sys/dev/e1000/if_em.h	Fri Mar 18 17:49:11 2011	(r219752)
+++ head/sys/dev/e1000/if_em.h	Fri Mar 18 18:54:00 2011	(r219753)
@@ -212,6 +212,10 @@
 #define EM_BAR_MEM_TYPE_64BIT	0x00000004
 #define EM_MSIX_BAR		3	/* On 82575 */
 
+#if !defined(SYSTCL_ADD_UQUAD)
+#define SYSCTL_ADD_UQUAD SYSCTL_ADD_QUAD
+#endif
+
 /* Defines for printing debug information */
 #define DEBUG_INIT  0
 #define DEBUG_IOCTL 0

Modified: head/sys/dev/e1000/if_igb.c
==============================================================================
--- head/sys/dev/e1000/if_igb.c	Fri Mar 18 17:49:11 2011	(r219752)
+++ head/sys/dev/e1000/if_igb.c	Fri Mar 18 18:54:00 2011	(r219753)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2011, Intel Corporation 
+  Copyright (c) 2001-2010, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -99,7 +99,7 @@ int	igb_display_debug_stats = 0;
 /*********************************************************************
  *  Driver version:
  *********************************************************************/
-char igb_driver_version[] = "version - 2.1.4";
+char igb_driver_version[] = "version - 2.1.7";
 
 
 /*********************************************************************
@@ -255,14 +255,13 @@ static void     igb_enable_wakeup(device
 static void     igb_led_func(void *, int);
 
 static int	igb_irq_fast(void *);
-static void	igb_add_rx_process_limit(struct adapter *, const char *,
-		    const char *, int *, int);
+static void	igb_msix_que(void *);
+static void	igb_msix_link(void *);
 static void	igb_handle_que(void *context, int pending);
 static void	igb_handle_link(void *context, int pending);
 
-/* These are MSIX only irq handlers */
-static void	igb_msix_que(void *);
-static void	igb_msix_link(void *);
+static void	igb_set_sysctl_value(struct adapter *, const char *,
+		    const char *, int *, int);
 
 #ifdef DEVICE_POLLING
 static poll_handler_t igb_poll;
@@ -350,6 +349,17 @@ TUNABLE_INT("hw.igb.rx_process_limit", &
 static int igb_fc_setting = e1000_fc_full;
 TUNABLE_INT("hw.igb.fc_setting", &igb_fc_setting);
 
+/* Energy Efficient Ethernet - default to off */
+static int igb_eee_setting = FALSE;
+TUNABLE_INT("hw.igb.ee_setting", &igb_eee_setting);
+
+/*
+** DMA Coalescing, only for i350 - default to off,
+** this feature is for power savings
+*/
+static int igb_dma_coalesce = FALSE;
+TUNABLE_INT("hw.igb.dma_coalesce", &igb_dma_coalesce);
+
 /*********************************************************************
  *  Device identification routine
  *
@@ -430,11 +440,6 @@ igb_attach(device_t dev)
 	    OID_AUTO, "nvm", CTLTYPE_INT|CTLFLAG_RW, adapter, 0,
 	    igb_sysctl_nvm_info, "I", "NVM Information");
 
-	SYSCTL_ADD_INT(device_get_sysctl_ctx(adapter->dev),
-	    SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)),
-	    OID_AUTO, "flow_control", CTLTYPE_INT|CTLFLAG_RW,
-	    &igb_fc_setting, 0, "Flow Control");
-
 	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
 	    OID_AUTO, "enable_aim", CTLTYPE_INT|CTLFLAG_RW,
@@ -461,11 +466,16 @@ igb_attach(device_t dev)
 
 	e1000_get_bus_info(&adapter->hw);
 
-	/* Sysctls for limiting the amount of work done in the taskqueue */
-	igb_add_rx_process_limit(adapter, "rx_processing_limit",
+	/* Sysctl for limiting the amount of work done in the taskqueue */
+	igb_set_sysctl_value(adapter, "rx_processing_limit",
 	    "max number of rx packets to process", &adapter->rx_process_limit,
 	    igb_rx_process_limit);
 
+       /* Sysctl for setting the interface flow control */
+	igb_set_sysctl_value(adapter, "flow_control",
+	    "configure flow control",
+	    &adapter->fc_setting, igb_fc_setting);
+
 	/*
 	 * Validate number of transmit and receive descriptors. It
 	 * must not exceed hardware maximum, and must be multiple
@@ -537,6 +547,18 @@ igb_attach(device_t dev)
 		goto err_late;
 	}
 
+	/* Some adapter-specific advanced features */
+	if (adapter->hw.mac.type >= e1000_i350) {
+		igb_set_sysctl_value(adapter, "dma_coalesce",
+		    "configure dma coalesce",
+		    &adapter->dma_coalesce, igb_dma_coalesce);
+		igb_set_sysctl_value(adapter, "eee_control",
+		    "enable Energy Efficient Ethernet",
+		    &adapter->hw.dev_spec._82575.eee_disable,
+		    igb_eee_setting);
+		e1000_set_eee_i350(&adapter->hw);
+	}
+
 	/*
 	** Start from a known state, this is
 	** important in reading the nvm and
@@ -1436,6 +1458,10 @@ igb_msix_que(void *arg)
 	more_tx = igb_txeof(txr);
 	IGB_TX_UNLOCK(txr);
 
+	/* If RX ring is depleted do refresh first */
+	if (rxr->next_to_check == rxr->next_to_refresh)
+		igb_refresh_mbufs(rxr, rxr->next_to_check);
+
 	more_rx = igb_rxeof(que, adapter->rx_process_limit, NULL);
 
 	if (igb_enable_aim == FALSE)
@@ -1938,7 +1964,7 @@ igb_local_timer(void *arg)
 out:
 	callout_reset(&adapter->timer, hz, igb_local_timer, adapter);
 #ifndef DEVICE_POLLING
-	/* Fire off all queue interrupts - deadlock protection */
+	/* Schedule all queue interrupts - deadlock protection */
 	E1000_WRITE_REG(&adapter->hw, E1000_EICS, adapter->que_mask);
 #endif
 	return;
@@ -1963,7 +1989,9 @@ igb_update_link_status(struct adapter *a
 	struct ifnet *ifp = adapter->ifp;
 	device_t dev = adapter->dev;

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201103181854.p2IIs0G1077313>