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>