Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 25 Jun 2009 15:08:21 +0100 (BST)
From:      Robert Watson <rwatson@FreeBSD.org>
To:        Jack F Vogel <jfv@FreeBSD.org>
Cc:        current@FreeBSD.org
Subject:   VMWare if_em breakage (was: Re: svn commit: r194865 - in head/sys: dev/e1000 modules/igb)
Message-ID:  <alpine.BSF.2.00.0906251507090.75138@fledge.watson.org>
In-Reply-To: <200906241741.n5OHfTaw022417@svn.freebsd.org>
References:  <200906241741.n5OHfTaw022417@svn.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Wed, 24 Jun 2009, Jack F Vogel wrote:

> Log:
>  Updates for both the em and igb drivers, add support
>  for multiqueue tx, shared code updates, new device
>  support, and some bug fixes.

Since this change (and the two followups), I'm no longer able to use if_em 
reliable in VMWare Fusion.  I get a bit of traffic, and then interrupts cease 
firing from the (virtual) card.  If I lower the interface and raise it, it 
will recover for a short period, and then the same result.  I'm running VMWare 
2.0.5, which is the latest version available; if I locally back out the update 
changes, then it works fine so it seems unlikely to be other on-going network 
stack work.  I realize that VMWare's driver is probably not part of your 
official test suite (not actually being a product manafactured by Intel :-), 
but keeping VMWare working is pretty important from a FreeBSD perspective!

Robert N M Watson
Computer Laboratory
University of Cambridge



>
> Modified:
>  head/sys/dev/e1000/e1000_82540.c
>  head/sys/dev/e1000/e1000_82541.c
>  head/sys/dev/e1000/e1000_82571.c
>  head/sys/dev/e1000/e1000_82575.c
>  head/sys/dev/e1000/e1000_82575.h
>  head/sys/dev/e1000/e1000_api.c
>  head/sys/dev/e1000/e1000_defines.h
>  head/sys/dev/e1000/e1000_hw.h
>  head/sys/dev/e1000/e1000_ich8lan.c
>  head/sys/dev/e1000/e1000_ich8lan.h
>  head/sys/dev/e1000/e1000_mac.c
>  head/sys/dev/e1000/e1000_osdep.c
>  head/sys/dev/e1000/e1000_phy.c
>  head/sys/dev/e1000/e1000_phy.h
>  head/sys/dev/e1000/e1000_regs.h
>  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/modules/igb/Makefile
>
> Modified: head/sys/dev/e1000/e1000_82540.c
> ==============================================================================
> --- head/sys/dev/e1000/e1000_82540.c	Wed Jun 24 17:31:37 2009	(r194864)
> +++ head/sys/dev/e1000/e1000_82540.c	Wed Jun 24 17:41:29 2009	(r194865)
> @@ -57,6 +57,7 @@ static s32  e1000_set_vco_speed_82540(st
> static s32  e1000_setup_copper_link_82540(struct e1000_hw *hw);
> static s32  e1000_setup_fiber_serdes_link_82540(struct e1000_hw *hw);
> static void e1000_power_down_phy_copper_82540(struct e1000_hw *hw);
> +static s32  e1000_read_mac_addr_82540(struct e1000_hw *hw);
>
> /**
>  * e1000_init_phy_params_82540 - Init PHY func ptrs.
> @@ -229,6 +230,8 @@ static s32 e1000_init_mac_params_82540(s
> 	mac->ops.clear_vfta = e1000_clear_vfta_generic;
> 	/* setting MTA */
> 	mac->ops.mta_set = e1000_mta_set_generic;
> +	/* read mac address */
> +	mac->ops.read_mac_addr = e1000_read_mac_addr_82540;
> 	/* ID LED init */
> 	mac->ops.id_led_init = e1000_id_led_init_generic;
> 	/* setup LED */
> @@ -676,3 +679,45 @@ static void e1000_clear_hw_cntrs_82540(s
> 	E1000_READ_REG(hw, E1000_MGTPTC);
> }
>
> +/**
> + *  e1000_read_mac_addr_82540 - Read device MAC address
> + *  @hw: pointer to the HW structure
> + *
> + *  Reads the device MAC address from the EEPROM and stores the value.
> + *  Since devices with two ports use the same EEPROM, we increment the
> + *  last bit in the MAC address for the second port.
> + *
> + *  This version is being used over generic because of customer issues
> + *  with VmWare and Virtual Box when using generic. It seems in
> + *  the emulated 82545, RAR[0] does NOT have a valid address after a
> + *  reset, this older method works and using this breaks nothing for
> + *  these legacy adapters.
> + **/
> +s32 e1000_read_mac_addr_82540(struct e1000_hw *hw)
> +{
> +	s32  ret_val = E1000_SUCCESS;
> +	u16 offset, nvm_data, i;
> +
> +	DEBUGFUNC("e1000_read_mac_addr");
> +
> +	for (i = 0; i < ETH_ADDR_LEN; i += 2) {
> +		offset = i >> 1;
> +		ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data);
> +		if (ret_val) {
> +			DEBUGOUT("NVM Read Error\n");
> +			goto out;
> +		}
> +		hw->mac.perm_addr[i] = (u8)(nvm_data & 0xFF);
> +		hw->mac.perm_addr[i+1] = (u8)(nvm_data >> 8);
> +	}
> +
> +	/* Flip last bit of mac address if we're on second port */
> +	if (hw->bus.func == E1000_FUNC_1)
> +		hw->mac.perm_addr[5] ^= 1;
> +
> +	for (i = 0; i < ETH_ADDR_LEN; i++)
> +		hw->mac.addr[i] = hw->mac.perm_addr[i];
> +
> +out:
> +	return ret_val;
> +}
>
> Modified: head/sys/dev/e1000/e1000_82541.c
> ==============================================================================
> --- head/sys/dev/e1000/e1000_82541.c	Wed Jun 24 17:31:37 2009	(r194864)
> +++ head/sys/dev/e1000/e1000_82541.c	Wed Jun 24 17:41:29 2009	(r194865)
> @@ -377,6 +377,7 @@ static s32 e1000_reset_hw_82541(struct e
> static s32 e1000_init_hw_82541(struct e1000_hw *hw)
> {
> 	struct e1000_mac_info *mac = &hw->mac;
> +	struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
> 	u32 i, txdctl;
> 	s32 ret_val;
>
> @@ -388,6 +389,13 @@ static s32 e1000_init_hw_82541(struct e1
> 		DEBUGOUT("Error initializing identification LED\n");
> 		/* This is not fatal and we should not stop init due to this */
> 	}
> +
> +	/* Storing the Speed Power Down  value for later use */
> +	ret_val = hw->phy.ops.read_reg(hw,
> +	                               IGP01E1000_GMII_FIFO,
> +	                               &dev_spec->spd_default);
> +	if (ret_val)
> +		goto out;
>
> 	/* Disabling VLAN filtering */
> 	DEBUGOUT("Initializing the IEEE VLAN\n");
> @@ -425,6 +433,7 @@ static s32 e1000_init_hw_82541(struct e1
> 	 */
> 	e1000_clear_hw_cntrs_82541(hw);
>
> +out:
> 	return ret_val;
> }
>
>
> Modified: head/sys/dev/e1000/e1000_82571.c
> ==============================================================================
> --- head/sys/dev/e1000/e1000_82571.c	Wed Jun 24 17:31:37 2009	(r194864)
> +++ head/sys/dev/e1000/e1000_82571.c	Wed Jun 24 17:41:29 2009	(r194865)
> @@ -47,6 +47,7 @@
>  * 82573L Gigabit Ethernet Controller
>  * 82574L Gigabit Network Connection
>  * 82574L Gigabit Network Connection
> + * 82583V Gigabit Network Connection
>  */
>
> #include "e1000_api.h"
> @@ -154,6 +155,7 @@ static s32 e1000_init_phy_params_82571(s
> 			goto out;
> 		}
> 		break;
> +	case e1000_82583:
> 	case e1000_82574:
> 		phy->type                   = e1000_phy_bm;
> 		phy->ops.get_cfg_done       = e1000_get_cfg_done_generic;
> @@ -215,6 +217,7 @@ static s32 e1000_init_nvm_params_82571(s
> 	switch (hw->mac.type) {
> 	case e1000_82573:
> 	case e1000_82574:
> +	case e1000_82583:
> 		if (((eecd >> 15) & 0x3) == 0x3) {
> 			nvm->type = e1000_nvm_flash_hw;
> 			nvm->word_size = 2048;
> @@ -264,6 +267,9 @@ static s32 e1000_init_mac_params_82571(s
> {
> 	struct e1000_mac_info *mac = &hw->mac;
> 	s32 ret_val = E1000_SUCCESS;
> +	u32 swsm = 0;
> +	u32 swsm2 = 0;
> +	bool force_clear_smbi = FALSE;
>
> 	DEBUGFUNC("e1000_init_mac_params_82571");
>
> @@ -304,6 +310,7 @@ static s32 e1000_init_mac_params_82571(s
> 	switch (hw->mac.type) {
> 	case e1000_82573:
> 	case e1000_82574:
> +	case e1000_82583:
> 		mac->ops.set_lan_id = e1000_set_lan_id_single_port;
> 		break;
> 	default:
> @@ -339,6 +346,7 @@ static s32 e1000_init_mac_params_82571(s
> 	/* check management mode */
> 	switch (hw->mac.type) {
> 	case e1000_82574:
> +	case e1000_82583:
> 		mac->ops.check_mng_mode = e1000_check_mng_mode_82574;
> 		break;
> 	default:
> @@ -366,6 +374,7 @@ static s32 e1000_init_mac_params_82571(s
> 	/* turn on/off LED */
> 	switch (hw->mac.type) {
> 	case e1000_82574:
> +	case e1000_82583:
> 		mac->ops.led_on = e1000_led_on_82574;
> 		break;
> 	default:
> @@ -381,6 +390,50 @@ static s32 e1000_init_mac_params_82571(s
> 	                ? e1000_get_speed_and_duplex_copper_generic
> 	                : e1000_get_speed_and_duplex_fiber_serdes_generic;
>
> +	/*
> +	 * Ensure that the inter-port SWSM.SMBI lock bit is clear before
> +	 * first NVM or PHY acess. This should be done for single-port
> +	 * devices, and for one port only on dual-port devices so that
> +	 * for those devices we can still use the SMBI lock to synchronize
> +	 * inter-port accesses to the PHY & NVM.
> +	 */
> +	switch (hw->mac.type) {
> +	case e1000_82571:
> +	case e1000_82572:
> +		swsm2 = E1000_READ_REG(hw, E1000_SWSM2);
> +
> +		if (!(swsm2 & E1000_SWSM2_LOCK)) {
> +			/* Only do this for the first interface on this card */
> +			E1000_WRITE_REG(hw, E1000_SWSM2,
> +			    swsm2 | E1000_SWSM2_LOCK);
> +			force_clear_smbi = TRUE;
> +		} else
> +			force_clear_smbi = FALSE;
> +		break;
> +	default:
> +		force_clear_smbi = TRUE;
> +		break;
> +	}
> +
> +	if (force_clear_smbi) {
> +		/* Make sure SWSM.SMBI is clear */
> +		swsm = E1000_READ_REG(hw, E1000_SWSM);
> +		if (swsm & E1000_SWSM_SMBI) {
> +			/* This bit should not be set on a first interface, and
> +			 * indicates that the bootagent or EFI code has
> +			 * improperly left this bit enabled
> +			 */
> +			DEBUGOUT("Please update your 82571 Bootagent\n");
> +		}
> +		E1000_WRITE_REG(hw, E1000_SWSM, swsm & ~E1000_SWSM_SMBI);
> +	}
> +
> +	/*
> +	 * Initialze device specific counter of SMBI acquisition
> +	 * timeouts.
> +	 */
> +	 hw->dev_spec._82571.smb_counter = 0;
> +
> out:
> 	return ret_val;
> }
> @@ -430,6 +483,7 @@ static s32 e1000_get_phy_id_82571(struct
> 		ret_val = e1000_get_phy_id(hw);
> 		break;
> 	case e1000_82574:
> +	case e1000_82583:
> 		ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id);
> 		if (ret_val)
> 			goto out;
> @@ -458,17 +512,43 @@ out:
>  *
>  *  Acquire the HW semaphore to access the PHY or NVM
>  **/
> -static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw)
> +s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw)
> {
> 	u32 swsm;
> 	s32 ret_val = E1000_SUCCESS;
> -	s32 timeout = hw->nvm.word_size + 1;
> +	s32 sw_timeout = hw->nvm.word_size + 1;
> +	s32 fw_timeout = hw->nvm.word_size + 1;
> 	s32 i = 0;
>
> 	DEBUGFUNC("e1000_get_hw_semaphore_82571");
>
> +	/*
> +	 * If we have timedout 3 times on trying to acquire
> +	 * the inter-port SMBI semaphore, there is old code
> +	 * operating on the other port, and it is not
> +	 * releasing SMBI. Modify the number of times that
> +	 * we try for the semaphore to interwork with this
> +	 * older code.
> +	 */
> +	if (hw->dev_spec._82571.smb_counter > 2)
> +		sw_timeout = 1;
> +
> +	/* Get the SW semaphore */
> +	while (i < sw_timeout) {
> +		swsm = E1000_READ_REG(hw, E1000_SWSM);
> +		if (!(swsm & E1000_SWSM_SMBI))
> +			break;
> +
> +		usec_delay(50);
> +		i++;
> +	}
> +
> +	if (i == sw_timeout) {
> +		DEBUGOUT("Driver can't access device - SMBI bit is set.\n");
> +		hw->dev_spec._82571.smb_counter++;
> +	}
> 	/* Get the FW semaphore. */
> -	for (i = 0; i < timeout; i++) {
> +	for (i = 0; i < fw_timeout; i++) {
> 		swsm = E1000_READ_REG(hw, E1000_SWSM);
> 		E1000_WRITE_REG(hw, E1000_SWSM, swsm | E1000_SWSM_SWESMBI);
>
> @@ -479,9 +559,9 @@ static s32 e1000_get_hw_semaphore_82571(
> 		usec_delay(50);
> 	}
>
> -	if (i == timeout) {
> +	if (i == fw_timeout) {
> 		/* Release semaphores */
> -		e1000_put_hw_semaphore_generic(hw);
> +		e1000_put_hw_semaphore_82571(hw);
> 		DEBUGOUT("Driver can't access the NVM\n");
> 		ret_val = -E1000_ERR_NVM;
> 		goto out;
> @@ -497,15 +577,15 @@ out:
>  *
>  *  Release hardware semaphore used to access the PHY or NVM
>  **/
> -static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw)
> +void e1000_put_hw_semaphore_82571(struct e1000_hw *hw)
> {
> 	u32 swsm;
>
> -	DEBUGFUNC("e1000_put_hw_semaphore_82571");
> +	DEBUGFUNC("e1000_put_hw_semaphore_generic");
>
> 	swsm = E1000_READ_REG(hw, E1000_SWSM);
>
> -	swsm &= ~E1000_SWSM_SWESMBI;
> +	swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI);
>
> 	E1000_WRITE_REG(hw, E1000_SWSM, swsm);
> }
> @@ -531,6 +611,7 @@ static s32 e1000_acquire_nvm_82571(struc
>
> 	switch (hw->mac.type) {
> 	case e1000_82574:
> +	case e1000_82583:
> 	case e1000_82573:
> 		break;
> 	default:
> @@ -581,6 +662,7 @@ static s32 e1000_write_nvm_82571(struct
> 	switch (hw->mac.type) {
> 	case e1000_82573:
> 	case e1000_82574:
> +	case e1000_82583:
> 		ret_val = e1000_write_nvm_eewr_82571(hw, offset, words, data);
> 		break;
> 	case e1000_82571:
> @@ -885,6 +967,7 @@ static s32 e1000_reset_hw_82571(struct e
> 	 */
> 	switch (hw->mac.type) {
> 	case e1000_82574:
> +	case e1000_82583:
> 	case e1000_82573:
> 		extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL);
> 		extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
> @@ -932,6 +1015,7 @@ static s32 e1000_reset_hw_82571(struct e
>
> 	switch (hw->mac.type) {
> 	case e1000_82574:
> +	case e1000_82583:
> 	case e1000_82573:
> 		msec_delay(25);
> 		break;
> @@ -1014,6 +1098,7 @@ static s32 e1000_init_hw_82571(struct e1
> 	/* ...for both queues. */
> 	switch (mac->type) {
> 	case e1000_82574:
> +	case e1000_82583:
> 	case e1000_82573:
> 		e1000_enable_tx_pkt_filtering_generic(hw);
> 		reg_data = E1000_READ_REG(hw, E1000_GCR);
> @@ -1096,6 +1181,7 @@ static void e1000_initialize_hw_bits_825
>
> 	switch (hw->mac.type) {
> 	case e1000_82574:
> +	case e1000_82583:
> 	case e1000_82573:
> 		reg = E1000_READ_REG(hw, E1000_CTRL);
> 		reg &= ~(1 << 29);
> @@ -1108,6 +1194,7 @@ static void e1000_initialize_hw_bits_825
> 	/* Extended Device Control */
> 	switch (hw->mac.type) {
> 	case e1000_82574:
> +	case e1000_82583:
> 	case e1000_82573:
> 		reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
> 		reg &= ~(1 << 23);
> @@ -1141,6 +1228,7 @@ static void e1000_initialize_hw_bits_825
>
> 	switch (hw->mac.type) {
> 	case e1000_82574:
> +	case e1000_82583:
> 		reg = E1000_READ_REG(hw, E1000_GCR);
> 		reg |= (1 << 22);
> 		E1000_WRITE_REG(hw, E1000_GCR, reg);
> @@ -1180,6 +1268,7 @@ static void e1000_clear_vfta_82571(struc
>
> 	switch (hw->mac.type) {
> 	case e1000_82574:
> +	case e1000_82583:
> 	case e1000_82573:
> 		if (hw->mng_cookie.vlan_id != 0) {
> 			/*
> @@ -1281,6 +1370,7 @@ static s32 e1000_setup_link_82571(struct
> 	 */
> 	switch (hw->mac.type) {
> 	case e1000_82574:
> +	case e1000_82583:
> 	case e1000_82573:
> 		if (hw->fc.requested_mode == e1000_fc_default)
> 			hw->fc.requested_mode = e1000_fc_full;
> @@ -1301,7 +1391,7 @@ static s32 e1000_setup_link_82571(struct
>  **/
> static s32 e1000_setup_copper_link_82571(struct e1000_hw *hw)
> {
> -	u32 ctrl, led_ctrl;
> +	u32 ctrl;
> 	s32  ret_val;
>
> 	DEBUGFUNC("e1000_setup_copper_link_82571");
> @@ -1318,11 +1408,6 @@ static s32 e1000_setup_copper_link_82571
> 		break;
> 	case e1000_phy_igp_2:
> 		ret_val = e1000_copper_link_setup_igp(hw);
> -		/* Setup activity LED */
> -		led_ctrl = E1000_READ_REG(hw, E1000_LEDCTL);
> -		led_ctrl &= IGP_ACTIVITY_LED_MASK;
> -		led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
> -		E1000_WRITE_REG(hw, E1000_LEDCTL, led_ctrl);
> 		break;
> 	default:
> 		ret_val = -E1000_ERR_PHY;
> @@ -1372,8 +1457,20 @@ static s32 e1000_setup_fiber_serdes_link
>  *  e1000_check_for_serdes_link_82571 - Check for link (Serdes)
>  *  @hw: pointer to the HW structure
>  *
> - *  Checks for link up on the hardware.  If link is not up and we have
> - *  a signal, then we need to force link up.
> + *  Reports the link state as up or down.
> + *
> + *  If autonegotiation is supported by the link partner, the link state is
> + *  determined by the result of autongotiation. This is the most likely case.
> + *  If autonegotiation is not supported by the link partner, and the link
> + *  has a valid signal, force the link up.
> + *
> + *  The link state is represented internally here by 4 states:
> + *
> + *  1) down
> + *  2) autoneg_progress
> + *  3) autoneg_complete (the link sucessfully autonegotiated)
> + *  4) forced_up (the link has been forced up, it did not autonegotiate)
> + *
>  **/
> s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
> {
> @@ -1401,6 +1498,7 @@ s32 e1000_check_for_serdes_link_82571(st
> 				 */
> 				mac->serdes_link_state =
> 				    e1000_serdes_link_autoneg_progress;
> +				mac->serdes_has_link = FALSE;
> 				DEBUGOUT("AN_UP     -> AN_PROG\n");
> 			}
> 		break;
> @@ -1419,28 +1517,35 @@ s32 e1000_check_for_serdes_link_82571(st
> 				    (ctrl & ~E1000_CTRL_SLU));
> 				mac->serdes_link_state =
> 				    e1000_serdes_link_autoneg_progress;
> +				mac->serdes_has_link = FALSE;
> 				DEBUGOUT("FORCED_UP -> AN_PROG\n");
> 			}
> 			break;
>
> 		case e1000_serdes_link_autoneg_progress:
> -			/*
> -			 * If the LU bit is set in the STATUS register,
> -			 * autoneg has completed sucessfully. If not,
> -			 * try foring the link because the far end may be
> -			 * available but not capable of autonegotiation.
> -			 */
> -			if (status & E1000_STATUS_LU)  {
> -				mac->serdes_link_state =
> -				    e1000_serdes_link_autoneg_complete;
> -				DEBUGOUT("AN_PROG   -> AN_UP\n");
> +			if (rxcw & E1000_RXCW_C) {
> +				/* We received /C/ ordered sets, meaning the
> +				 * link partner has autonegotiated, and we can
> +				 * trust the Link Up (LU) status bit
> +				 */
> +				if (status & E1000_STATUS_LU) {
> +					mac->serdes_link_state =
> +					    e1000_serdes_link_autoneg_complete;
> +					DEBUGOUT("AN_PROG   -> AN_UP\n");
> +					mac->serdes_has_link = TRUE;
> +				} else {
> +					/* Autoneg completed, but failed */
> +					mac->serdes_link_state =
> +					    e1000_serdes_link_down;
> +					DEBUGOUT("AN_PROG   -> DOWN\n");
> +				}
> 			} else {
> -				/*
> -				 * Disable autoneg, force link up and
> -				 * full duplex, and change state to forced
> +				/* The link partner did not autoneg.
> +				 * Force link up and full duplex, and change
> +				 * state to forced.
> 				 */
> 				E1000_WRITE_REG(hw, E1000_TXCW,
> -				    (mac->txcw & ~E1000_TXCW_ANE));
> +				(mac->txcw & ~E1000_TXCW_ANE));
> 				ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
> 				E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
>
> @@ -1452,10 +1557,10 @@ s32 e1000_check_for_serdes_link_82571(st
> 					break;
> 				}
> 				mac->serdes_link_state =
> -				    e1000_serdes_link_forced_up;
> +				e1000_serdes_link_forced_up;
> +				mac->serdes_has_link = TRUE;
> 				DEBUGOUT("AN_PROG   -> FORCED_UP\n");
> 			}
> -			mac->serdes_has_link = TRUE;
> 			break;
>
> 		case e1000_serdes_link_down:
> @@ -1517,6 +1622,7 @@ static s32 e1000_valid_led_default_82571
>
> 	switch (hw->mac.type) {
> 	case e1000_82574:
> +	case e1000_82583:
> 	case e1000_82573:
> 		if(*data == ID_LED_RESERVED_F746)
> 			*data = ID_LED_DEFAULT_82573;
>
> Modified: head/sys/dev/e1000/e1000_82575.c
> ==============================================================================
> --- head/sys/dev/e1000/e1000_82575.c	Wed Jun 24 17:31:37 2009	(r194864)
> +++ head/sys/dev/e1000/e1000_82575.c	Wed Jun 24 17:41:29 2009	(r194865)
> @@ -38,6 +38,7 @@
>  * 82575GB Gigabit Network Connection
>  * 82575GB Gigabit Network Connection
>  * 82576 Gigabit Network Connection
> + * 82576 Quad Port Gigabit Mezzanine Adapter
>  */
>
> #include "e1000_api.h"
> @@ -77,6 +78,7 @@ static s32  e1000_reset_init_script_8257
> static s32  e1000_read_mac_addr_82575(struct e1000_hw *hw);
> static void e1000_power_down_phy_copper_82575(struct e1000_hw *hw);
> void e1000_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw);
> +static s32 e1000_set_pcie_completion_timeout(struct e1000_hw *hw);
>
> /**
>  *  e1000_init_phy_params_82575 - Init PHY func ptrs.
> @@ -326,11 +328,12 @@ void e1000_init_function_pointers_82575(
>  **/
> static s32 e1000_acquire_phy_82575(struct e1000_hw *hw)
> {
> -	u16 mask;
> +	u16 mask = E1000_SWFW_PHY0_SM;
>
> 	DEBUGFUNC("e1000_acquire_phy_82575");
>
> -	mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM;
> +	if (hw->bus.func == E1000_FUNC_1)
> +		mask = E1000_SWFW_PHY1_SM;
>
> 	return e1000_acquire_swfw_sync_82575(hw, mask);
> }
> @@ -343,11 +346,13 @@ static s32 e1000_acquire_phy_82575(struc
>  **/
> static void e1000_release_phy_82575(struct e1000_hw *hw)
> {
> -	u16 mask;
> +	u16 mask = E1000_SWFW_PHY0_SM;
>
> 	DEBUGFUNC("e1000_release_phy_82575");
>
> -	mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM;
> +	if (hw->bus.func == E1000_FUNC_1)
> +		mask = E1000_SWFW_PHY1_SM;
> +
> 	e1000_release_swfw_sync_82575(hw, mask);
> }
>
> @@ -785,9 +790,8 @@ static s32 e1000_get_cfg_done_82575(stru
>
> 	DEBUGFUNC("e1000_get_cfg_done_82575");
>
> -	if (hw->bus.func == 1)
> +	if (hw->bus.func == E1000_FUNC_1)
> 		mask = E1000_NVM_CFG_DONE_PORT_1;
> -
> 	while (timeout) {
> 		if (E1000_READ_REG(hw, E1000_EEMNGCTL) & mask)
> 			break;
> @@ -937,13 +941,13 @@ void e1000_shutdown_fiber_serdes_link_82
> 	u32 reg;
> 	u16 eeprom_data = 0;
>
> -	if (hw->mac.type != e1000_82576 ||
> -	   (hw->phy.media_type != e1000_media_type_fiber &&
> -	    hw->phy.media_type != e1000_media_type_internal_serdes))
> +	if (hw->phy.media_type != e1000_media_type_internal_serdes)
> 		return;
>
> -	if (hw->bus.func == 0)
> +	if (hw->bus.func == E1000_FUNC_0)
> 		hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data);
> +	else if (hw->bus.func == E1000_FUNC_1)
> +		hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_B, 1, &eeprom_data);
>
> 	/*
> 	 * If APM is not enabled in the EEPROM and management interface is
> @@ -970,250 +974,42 @@ void e1000_shutdown_fiber_serdes_link_82
> }
>
> /**
> - *  e1000_vmdq_loopback_enable_pf- Enables VM to VM queue loopback replication
> - *  @hw: pointer to the HW structure
> - **/
> -void e1000_vmdq_loopback_enable_pf(struct e1000_hw *hw)
> -{
> -	u32 reg;
> -
> -	reg = E1000_READ_REG(hw, E1000_DTXSWC);
> -	reg |= E1000_DTXSWC_VMDQ_LOOPBACK_EN;
> -	E1000_WRITE_REG(hw, E1000_DTXSWC, reg);
> -}
> -
> -/**
> - *  e1000_vmdq_loopback_disable_pf - Disable VM to VM queue loopbk replication
> + *  e1000_vmdq_set_loopback_pf - enable or disable vmdq loopback
>  *  @hw: pointer to the HW structure
> + *  @enable: state to enter, either enabled or disabled
> + *
> + *  enables/disables L2 switch loopback functionality
>  **/
> -void e1000_vmdq_loopback_disable_pf(struct e1000_hw *hw)
> +void e1000_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable)
> {
> 	u32 reg;
>
> 	reg = E1000_READ_REG(hw, E1000_DTXSWC);
> -	reg &= ~(E1000_DTXSWC_VMDQ_LOOPBACK_EN);
> +	if (enable)
> +		reg |= E1000_DTXSWC_VMDQ_LOOPBACK_EN;
> +	else
> +		reg &= ~(E1000_DTXSWC_VMDQ_LOOPBACK_EN);
> 	E1000_WRITE_REG(hw, E1000_DTXSWC, reg);
> }
>
> /**
> - *  e1000_vmdq_replication_enable_pf - Enable replication of brdcst & multicst
> - *  @hw: pointer to the HW structure
> - *
> - *  Enables replication of broadcast and multicast packets from the network
> - *  to VM's which have their respective broadcast and multicast accept
> - *  bits set in the VM Offload Register.  This gives the PF driver per
> - *  VM granularity control over which VM's get replicated broadcast traffic.
> - **/
> -void e1000_vmdq_replication_enable_pf(struct e1000_hw *hw, u32 enables)
> -{
> -	u32 reg;
> -	u32 i;
> -
> -	for (i = 0; i < MAX_NUM_VFS; i++) {
> -		if (enables & (1 << i)) {
> -			reg = E1000_READ_REG(hw, E1000_VMOLR(i));
> -			reg |= (E1000_VMOLR_AUPE |
> -				E1000_VMOLR_BAM |
> -				E1000_VMOLR_MPME);
> -			E1000_WRITE_REG(hw, E1000_VMOLR(i), reg);
> -		}
> -	}
> -
> -	reg = E1000_READ_REG(hw, E1000_VT_CTL);
> -	reg |= E1000_VT_CTL_VM_REPL_EN;
> -	E1000_WRITE_REG(hw, E1000_VT_CTL, reg);
> -}
> -
> -/**
> - *  e1000_vmdq_replication_disable_pf - Disable replication of brdcst & multicst
> + *  e1000_vmdq_set_replication_pf - enable or disable vmdq replication
>  *  @hw: pointer to the HW structure
> + *  @enable: state to enter, either enabled or disabled
>  *
> - *  Disables replication of broadcast and multicast packets to the VM's.
> + *  enables/disables replication of packets across multiple pools
>  **/
> -void e1000_vmdq_replication_disable_pf(struct e1000_hw *hw)
> +void e1000_vmdq_set_replication_pf(struct e1000_hw *hw, bool enable)
> {
> 	u32 reg;
>
> 	reg = E1000_READ_REG(hw, E1000_VT_CTL);
> -	reg &= ~(E1000_VT_CTL_VM_REPL_EN);
> -	E1000_WRITE_REG(hw, E1000_VT_CTL, reg);
> -}
> -
> -/**
> - *  e1000_vmdq_enable_replication_mode_pf - Enables replication mode in the device
> - *  @hw: pointer to the HW structure
> - **/
> -void e1000_vmdq_enable_replication_mode_pf(struct e1000_hw *hw)
> -{
> -	u32 reg;
> -
> -	reg = E1000_READ_REG(hw, E1000_VT_CTL);
> -	reg |= E1000_VT_CTL_VM_REPL_EN;
> -	E1000_WRITE_REG(hw, E1000_VT_CTL, reg);
> -}
> -
> -/**
> - *  e1000_vmdq_broadcast_replication_enable_pf - Enable replication of brdcst
> - *  @hw: pointer to the HW structure
> - *  @enables: PoolSet Bit - if set to ALL_QUEUES, apply to all pools.
> - *
> - *  Enables replication of broadcast packets from the network
> - *  to VM's which have their respective broadcast accept
> - *  bits set in the VM Offload Register.  This gives the PF driver per
> - *  VM granularity control over which VM's get replicated broadcast traffic.
> - **/
> -void e1000_vmdq_broadcast_replication_enable_pf(struct e1000_hw *hw,
> -						u32 enables)
> -{
> -	u32 reg;
> -	u32 i;
> -
> -	for (i = 0; i < MAX_NUM_VFS; i++) {
> -		if ((enables == ALL_QUEUES) || (enables & (1 << i))) {
> -			reg = E1000_READ_REG(hw, E1000_VMOLR(i));
> -			reg |= E1000_VMOLR_BAM;
> -			E1000_WRITE_REG(hw, E1000_VMOLR(i), reg);
> -		}
> -	}
> -}
> -
> -/**
> - *  e1000_vmdq_broadcast_replication_disable_pf - Disable replication
> - *  of broadcast packets
> - *  @hw: pointer to the HW structure
> - *  @disables: PoolSet Bit - if set to ALL_QUEUES, apply to all pools.
> - *
> - *  Disables replication of broadcast packets for specific pools.
> - *  If bam/mpe is disabled on all pools then replication mode is
> - *  turned off.
> - **/
> -void e1000_vmdq_broadcast_replication_disable_pf(struct e1000_hw *hw,
> -						 u32 disables)
> -{
> -	u32 reg;
> -	u32 i;
> -	u32 oneenabled = 0;
> -
> -	for (i = 0; i < MAX_NUM_VFS; i++) {
> -		reg = E1000_READ_REG(hw, E1000_VMOLR(i));
> -		if ((disables == ALL_QUEUES) || (disables & (1 << i))) {
> -			reg &= ~(E1000_VMOLR_BAM);
> -			E1000_WRITE_REG(hw, E1000_VMOLR(i), reg);
> -		}
> -		if (!oneenabled && (reg & (E1000_VMOLR_AUPE |
> -				E1000_VMOLR_BAM |
> -				E1000_VMOLR_MPME)))
> -				oneenabled = 1;
> -	}
> -	if (!oneenabled) {
> -		reg = E1000_READ_REG(hw, E1000_VT_CTL);
> +	if (enable)
> +		reg |= E1000_VT_CTL_VM_REPL_EN;
> +	else
> 		reg &= ~(E1000_VT_CTL_VM_REPL_EN);
> -		E1000_WRITE_REG(hw, E1000_VT_CTL, reg);
> -	}
> -}
>
> -/**
> - *  e1000_vmdq_multicast_promiscuous_enable_pf - Enable promiscuous reception
> - *  @hw: pointer to the HW structure
> - *  @enables: PoolSet Bit - if set to ALL_QUEUES, apply to all pools.
> - *
> - *  Enables promiscuous reception of multicast packets from the network
> - *  to VM's which have their respective multicast promiscuous mode enable
> - *  bits set in the VM Offload Register.  This gives the PF driver per
> - *  VM granularity control over which VM's get all multicast traffic.
> - **/
> -void e1000_vmdq_multicast_promiscuous_enable_pf(struct e1000_hw *hw,
> -						u32 enables)
> -{
> -	u32 reg;
> -	u32 i;
> -
> -	for (i = 0; i < MAX_NUM_VFS; i++) {
> -		if ((enables == ALL_QUEUES) || (enables & (1 << i))) {
> -			reg = E1000_READ_REG(hw, E1000_VMOLR(i));
> -			reg |= E1000_VMOLR_MPME;
> -			E1000_WRITE_REG(hw, E1000_VMOLR(i), reg);
> -		}
> -	}
> -}
> -
> -/**
> - *  e1000_vmdq_multicast_promiscuous_disable_pf - Disable promiscuous
> - *  reception of multicast packets
> - *  @hw: pointer to the HW structure
> - *  @disables: PoolSet Bit - if set to ALL_QUEUES, apply to all pools.
> - *
> - *  Disables promiscuous reception of multicast packets for specific pools.
> - *  If bam/mpe is disabled on all pools then replication mode is
> - *  turned off.
> - **/
> -void e1000_vmdq_multicast_promiscuous_disable_pf(struct e1000_hw *hw,
> -						 u32 disables)
> -{
> -	u32 reg;
> -	u32 i;
> -	u32 oneenabled = 0;
> -
> -	for (i = 0; i < MAX_NUM_VFS; i++) {
> -		reg = E1000_READ_REG(hw, E1000_VMOLR(i));
> -		if ((disables == ALL_QUEUES) || (disables & (1 << i))) {
> -			reg &= ~(E1000_VMOLR_MPME);
> -			E1000_WRITE_REG(hw, E1000_VMOLR(i), reg);
> -		}
> -		if (!oneenabled && (reg & (E1000_VMOLR_AUPE |
> -				E1000_VMOLR_BAM |
> -				E1000_VMOLR_MPME)))
> -				oneenabled = 1;
> -	}
> -	if (!oneenabled) {
> -		reg = E1000_READ_REG(hw, E1000_VT_CTL);
> -		reg &= ~(E1000_VT_CTL_VM_REPL_EN);
> -		E1000_WRITE_REG(hw, E1000_VT_CTL, reg);
> -	}
> -}
> -
> -/**
> - *  e1000_vmdq_aupe_enable_pf - Enable acceptance of untagged packets
> - *  @hw: pointer to the HW structure
> - *  @enables: PoolSet Bit - if set to ALL_QUEUES, apply to all pools.
> - *
> - *  Enables acceptance of packets from the network which do not have
> - *  a VLAN tag but match the exact MAC filter of a given VM.
> - **/
> -void e1000_vmdq_aupe_enable_pf(struct e1000_hw *hw, u32 enables)
> -{
> -	u32 reg;
> -	u32 i;
> -
> -	for (i = 0; i < MAX_NUM_VFS; i++) {
> -	if ((enables == ALL_QUEUES) || (enables & (1 << i))) {
> -			reg = E1000_READ_REG(hw, E1000_VMOLR(i));
> -			reg |= E1000_VMOLR_AUPE;
> -			E1000_WRITE_REG(hw, E1000_VMOLR(i), reg);
> -		}
> -	}
> -}
> -
> -/**
> - *  e1000_vmdq_aupe_disable_pf - Disable acceptance of untagged packets
> - *  @hw: pointer to the HW structure
> - *  @disables: PoolSet Bit - if set to ALL_QUEUES, apply to all pools.
> - *
> - *  Disables acceptance of packets from the network which do not have
> - *  a VLAN tag but match the exact MAC filter of a given VM.
> - **/
> -void e1000_vmdq_aupe_disable_pf(struct e1000_hw *hw, u32 disables)
> -{
> -	u32 reg;
> -	u32 i;
> -
> -	for (i = 0; i < MAX_NUM_VFS; i++) {
> -		if ((disables == ALL_QUEUES) || (disables & (1 << i))) {
> -			reg = E1000_READ_REG(hw, E1000_VMOLR(i));
> -			reg &= ~E1000_VMOLR_AUPE;
> -			E1000_WRITE_REG(hw, E1000_VMOLR(i), reg);
> -		}
> -	}
> +	E1000_WRITE_REG(hw, E1000_VT_CTL, reg);
> }
>
> /**
> @@ -1238,6 +1034,12 @@ static s32 e1000_reset_hw_82575(struct e
> 		DEBUGOUT("PCI-E Master disable polling has failed.\n");
> 	}
>
> +	/* set the completion timeout for interface */
> +	ret_val = e1000_set_pcie_completion_timeout(hw);
> +	if (ret_val) {
> +		DEBUGOUT("PCI-E Set completion timeout has failed.\n");
> +	}
> +
> 	DEBUGOUT("Masking off all interrupts\n");
> 	E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
>
> @@ -1333,7 +1135,7 @@ static s32 e1000_init_hw_82575(struct e1
>  **/
> static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw)
> {
> -	u32 ctrl, led_ctrl;
> +	u32 ctrl;
> 	s32  ret_val;
> 	bool link;
>
> @@ -1350,11 +1152,6 @@ static s32 e1000_setup_copper_link_82575
> 		break;
> 	case e1000_phy_igp_3:
> 		ret_val = e1000_copper_link_setup_igp(hw);
> -		/* Setup activity LED */
> -		led_ctrl = E1000_READ_REG(hw, E1000_LEDCTL);
> -		led_ctrl &= IGP_ACTIVITY_LED_MASK;
> -		led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
> -		E1000_WRITE_REG(hw, E1000_LEDCTL, led_ctrl);
> 		break;
> 	default:
> 		ret_val = -E1000_ERR_PHY;
> @@ -1433,15 +1230,14 @@ static s32 e1000_setup_fiber_serdes_link
> 	 */
> 	E1000_WRITE_REG(hw, E1000_SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK);
>
> -	/* Force link up, set 1gb, set both sw defined pins */
> +	/* Force link up, set 1gb */
> 	reg = E1000_READ_REG(hw, E1000_CTRL);
> -	reg |= E1000_CTRL_SLU |
> -	       E1000_CTRL_SPD_1000 |
> -	       E1000_CTRL_FRCSPD |
> -	       E1000_CTRL_SWDPIN0 |
> -	       E1000_CTRL_SWDPIN1;
> +	reg |= E1000_CTRL_SLU | E1000_CTRL_SPD_1000 | E1000_CTRL_FRCSPD;
> +	if (hw->mac.type == e1000_82575 || hw->mac.type == e1000_82576) {
> +		/* set both sw defined pins */
> +		reg |= E1000_CTRL_SWDPIN0 | E1000_CTRL_SWDPIN1;
> +	}
> 	E1000_WRITE_REG(hw, E1000_CTRL, reg);
> -
> 	/* Power on phy for 82576 fiber adapters */
> 	if (hw->mac.type == e1000_82576) {
> 		reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
> @@ -1514,7 +1310,6 @@ static s32 e1000_valid_led_default_82575
>
> 	if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) {
> 		switch(hw->phy.media_type) {
> -		case e1000_media_type_fiber:
> 		case e1000_media_type_internal_serdes:
> 			*data = ID_LED_DEFAULT_82575_SERDES;
> 			break;
> @@ -1605,12 +1400,6 @@ out:
> static bool e1000_sgmii_active_82575(struct e1000_hw *hw)
> {
> 	struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575;
> -
> -	DEBUGFUNC("e1000_sgmii_active_82575");
> -
> -	if (hw->mac.type != e1000_82575 && hw->mac.type != e1000_82576)
> -		return FALSE;
> -
> 	return dev_spec->sgmii_active;
> }
>
> @@ -1762,6 +1551,7 @@ static void e1000_clear_hw_cntrs_82575(s
> 	if (hw->phy.media_type == e1000_media_type_internal_serdes)
> 		E1000_READ_REG(hw, E1000_SCVPC);
> }
> +
> /**
>  *  e1000_rx_fifo_flush_82575 - Clean rx fifo after RX enable
>  *  @hw: pointer to the HW structure
> @@ -1836,3 +1626,54 @@ void e1000_rx_fifo_flush_82575(struct e1
> 	E1000_READ_REG(hw, E1000_MPC);
> }
>
> +/**
> + *  e1000_set_pcie_completion_timeout - set pci-e completion timeout
> + *  @hw: pointer to the HW structure
> + *
> + *  The defaults for 82575 and 82576 should be in the range of 50us to 50ms,
> + *  however the hardware default for these parts is 500us to 1ms which is less
> + *  than the 10ms recommended by the pci-e spec.  To address this we need to
> + *  increase the value to either 10ms to 200ms for capability version 1 config,
> + *  or 16ms to 55ms for version 2.
> + **/
> +static s32 e1000_set_pcie_completion_timeout(struct e1000_hw *hw)
> +{
> +	u32 gcr = E1000_READ_REG(hw, E1000_GCR);
> +	s32 ret_val = E1000_SUCCESS;
> +	u16 pcie_devctl2;
> +
> +	/* only take action if timeout value is defaulted to 0 */
> +	if (gcr & E1000_GCR_CMPL_TMOUT_MASK)
> +		goto out;
> +
> +	/*
> +	 * if capababilities version is type 1 we can write the
> +	 * timeout of 10ms to 200ms through the GCR register
> +	 */
> +	if (!(gcr & E1000_GCR_CAP_VER2)) {
> +		gcr |= E1000_GCR_CMPL_TMOUT_10ms;
> +		goto out;
> +	}
> +
> +	/*
> +	 * for version 2 capabilities we need to write the config space
> +	 * directly in order to set the completion timeout value for
> +	 * 16ms to 55ms
> +	 */
> +	ret_val = e1000_read_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2,
> +	                                  &pcie_devctl2);
> +	if (ret_val)
> +		goto out;
> +
> +	pcie_devctl2 |= PCIE_DEVICE_CONTROL2_16ms;
> +
> +	ret_val = e1000_write_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2,
> +	                                   &pcie_devctl2);
> +out:
> +	/* disable completion timeout resend */
> +	gcr &= ~E1000_GCR_CMPL_TMOUT_RESEND;
> +
> +	E1000_WRITE_REG(hw, E1000_GCR, gcr);
> +	return ret_val;
> +}
> +
>
> Modified: head/sys/dev/e1000/e1000_82575.h
> ==============================================================================
> --- head/sys/dev/e1000/e1000_82575.h	Wed Jun 24 17:31:37 2009	(r194864)
> +++ head/sys/dev/e1000/e1000_82575.h	Wed Jun 24 17:41:29 2009	(r194865)
> @@ -214,7 +214,7 @@ union e1000_adv_rx_desc {
> 	} wb;  /* writeback */
> };
>
> -#define E1000_RXDADV_RSSTYPE_MASK        0x0000F000
> +#define E1000_RXDADV_RSSTYPE_MASK        0x0000000F
> #define E1000_RXDADV_RSSTYPE_SHIFT       12
> #define E1000_RXDADV_HDRBUFLEN_MASK      0x7FE0
> #define E1000_RXDADV_HDRBUFLEN_SHIFT     5
> @@ -421,21 +421,11 @@ struct e1000_adv_tx_context_desc {
> #define E1000_IOVCTL 0x05BBC
> #define E1000_IOVCTL_REUSE_VFQ 0x00000001
>
> +#define E1000_RPLOLR_STRVLAN   0x40000000
> +#define E1000_RPLOLR_STRCRC    0x80000000
>
> *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
>



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