freebsd-current

[Prev] Thread [Next]  |  [Prev] Date [Next]

VMWare if_em breakage (was: Re: svn commit: r194865 - in head/sys: dev/e1000 modules/igb) Robert Watson Thu Jun 25 08:00:36 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 ***

_______________________________________________
[EMAIL PROTECTED] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to "[EMAIL PROTECTED]"