VMWare if_em breakage (was: Re: svn commit: r194865 - in head/sys:
dev/e1000 modules/igb)
Robert Watson
rwatson at FreeBSD.org
Thu Jun 25 14:08:23 UTC 2009
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 ***
>
More information about the freebsd-current
mailing list