set version to 1.3.0
[dpdk.git] / lib / librte_pmd_e1000 / e1000 / e1000_mac.c
index 746cd74..429e319 100644 (file)
@@ -33,11 +33,10 @@ POSSIBILITY OF SUCH DAMAGE.
 
 #include "e1000_api.h"
 
-static s32 e1000_set_default_fc_generic(struct e1000_hw *hw);
-static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw);
-static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw);
 STATIC s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw);
 STATIC void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw);
+STATIC void e1000_config_collision_dist_generic(struct e1000_hw *hw);
+STATIC void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index);
 
 /**
  *  e1000_init_mac_ops_generic - Initialize MAC function pointers
@@ -179,8 +178,8 @@ s32 e1000_get_bus_info_pci_generic(struct e1000_hw *hw)
        /* Bus speed */
        if (bus->type == e1000_bus_type_pci) {
                bus->speed = (status & E1000_STATUS_PCI66)
-                            ? e1000_bus_speed_66
-                            : e1000_bus_speed_33;
+                            ? e1000_bus_speed_66
+                            : e1000_bus_speed_33;
        } else {
                switch (status & E1000_STATUS_PCIX_SPEED) {
                case E1000_STATUS_PCIX_SPEED_66:
@@ -200,8 +199,8 @@ s32 e1000_get_bus_info_pci_generic(struct e1000_hw *hw)
 
        /* Bus width */
        bus->width = (status & E1000_STATUS_BUS64)
-                    ? e1000_bus_width_64
-                    : e1000_bus_width_32;
+                    ? e1000_bus_width_64
+                    : e1000_bus_width_32;
 
        /* Which PCI(-X) function? */
        mac->ops.set_lan_id(hw);
@@ -229,7 +228,7 @@ s32 e1000_get_bus_info_pcie_generic(struct e1000_hw *hw)
        bus->type = e1000_bus_type_pci_express;
 
        ret_val = e1000_read_pcie_cap_reg(hw, PCIE_LINK_STATUS,
-                                         &pcie_link_status);
+                                         &pcie_link_status);
        if (ret_val) {
                bus->width = e1000_bus_width_unknown;
                bus->speed = e1000_bus_speed_unknown;
@@ -292,7 +291,7 @@ void e1000_set_lan_id_multi_port_pci(struct e1000_hw *hw)
        if (pci_header_type & PCI_HEADER_TYPE_MULTIFUNC) {
                status = E1000_READ_REG(hw, E1000_STATUS);
                bus->func = (status & E1000_STATUS_FUNC_MASK)
-                           >> E1000_STATUS_FUNC_SHIFT;
+                           >> E1000_STATUS_FUNC_SHIFT;
        } else {
                bus->func = 0;
        }
@@ -397,22 +396,30 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
 
        ret_val = hw->nvm.ops.read(hw, NVM_COMPAT, 1, &nvm_data);
        if (ret_val)
-               goto out;
+               return ret_val;
 
-       if (!(nvm_data & NVM_COMPAT_LOM))
-               goto out;
+       /* not supported on older hardware or 82573 */
+       if ((hw->mac.type < e1000_82571) || (hw->mac.type == e1000_82573))
+               return E1000_SUCCESS;
+
+       /*
+        * Alternate MAC address is handled by the option ROM for 82580
+        * and newer. SW support not required.
+        */
+       if (hw->mac.type >= e1000_82580)
+               return E1000_SUCCESS;
 
        ret_val = hw->nvm.ops.read(hw, NVM_ALT_MAC_ADDR_PTR, 1,
-                                &nvm_alt_mac_addr_offset);
+                                  &nvm_alt_mac_addr_offset);
        if (ret_val) {
                DEBUGOUT("NVM Read Error\n");
-               goto out;
+               return ret_val;
        }
 
-       if (nvm_alt_mac_addr_offset == 0xFFFF) {
+       if ((nvm_alt_mac_addr_offset == 0xFFFF) ||
+           (nvm_alt_mac_addr_offset == 0x0000))
                /* There is no Alternate MAC Address */
-               goto out;
-       }
+               return E1000_SUCCESS;
 
        if (hw->bus.func == E1000_FUNC_1)
                nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN1;
@@ -426,7 +433,7 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
                ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data);
                if (ret_val) {
                        DEBUGOUT("NVM Read Error\n");
-                       goto out;
+                       return ret_val;
                }
 
                alt_mac_addr[i] = (u8)(nvm_data & 0xFF);
@@ -436,7 +443,7 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
        /* if multicast bit is set, the alternate address will not be used */
        if (alt_mac_addr[0] & 0x01) {
                DEBUGOUT("Ignoring Alternate Mac Address with MC bit set\n");
-               goto out;
+               return E1000_SUCCESS;
        }
 
        /*
@@ -446,8 +453,7 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
         */
        hw->mac.ops.rar_set(hw, alt_mac_addr, 0);
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
@@ -470,7 +476,7 @@ STATIC void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index)
         * from network order (big endian) to little endian
         */
        rar_low = ((u32) addr[0] | ((u32) addr[1] << 8) |
-                  ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
+                  ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
 
        rar_high = ((u32) addr[4] | ((u32) addr[5] << 8));
 
@@ -489,43 +495,6 @@ STATIC void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index)
        E1000_WRITE_FLUSH(hw);
 }
 
-/**
- *  e1000_update_mc_addr_list_generic - Update Multicast addresses
- *  @hw: pointer to the HW structure
- *  @mc_addr_list: array of multicast addresses to program
- *  @mc_addr_count: number of multicast addresses to program
- *
- *  Updates entire Multicast Table Array.
- *  The caller must have a packed mc_addr_list of multicast addresses.
- **/
-void e1000_update_mc_addr_list_generic(struct e1000_hw *hw,
-                                       u8 *mc_addr_list, u32 mc_addr_count)
-{
-       u32 hash_value, hash_bit, hash_reg;
-       int i;
-
-       DEBUGFUNC("e1000_update_mc_addr_list_generic");
-
-       /* clear mta_shadow */
-       memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow));
-
-       /* update mta_shadow from mc_addr_list */
-       for (i = 0; (u32) i < mc_addr_count; i++) {
-               hash_value = e1000_hash_mc_addr_generic(hw, mc_addr_list);
-
-               hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1);
-               hash_bit = hash_value & 0x1F;
-
-               hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit);
-               mc_addr_list += (ETH_ADDR_LEN);
-       }
-
-       /* replace the entire MTA table */
-       for (i = hw->mac.mta_reg_count - 1; i >= 0; i--)
-               E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, hw->mac.mta_shadow[i]);
-       E1000_WRITE_FLUSH(hw);
-}
-
 /**
  *  e1000_hash_mc_addr_generic - Generate a multicast hash value
  *  @hw: pointer to the HW structure
@@ -570,7 +539,7 @@ u32 e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr)
         * values resulting from each mc_filter_type...
         * [0] [1] [2] [3] [4] [5]
         * 01  AA  00  12  34  56
-        * LSB                 MSB
+        * LSB           MSB
         *
         * case 0: hash_value = ((0x34 >> 4) | (0x56 << 4)) & 0xFFF = 0x563
         * case 1: hash_value = ((0x34 >> 3) | (0x56 << 5)) & 0xFFF = 0xAC6
@@ -593,11 +562,48 @@ u32 e1000_hash_mc_addr_generic(struct e1000_hw *hw, u8 *mc_addr)
        }
 
        hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) |
-                                 (((u16) mc_addr[5]) << bit_shift)));
+                                 (((u16) mc_addr[5]) << bit_shift)));
 
        return hash_value;
 }
 
+/**
+ *  e1000_update_mc_addr_list_generic - Update Multicast addresses
+ *  @hw: pointer to the HW structure
+ *  @mc_addr_list: array of multicast addresses to program
+ *  @mc_addr_count: number of multicast addresses to program
+ *
+ *  Updates entire Multicast Table Array.
+ *  The caller must have a packed mc_addr_list of multicast addresses.
+ **/
+void e1000_update_mc_addr_list_generic(struct e1000_hw *hw,
+                                      u8 *mc_addr_list, u32 mc_addr_count)
+{
+       u32 hash_value, hash_bit, hash_reg;
+       int i;
+
+       DEBUGFUNC("e1000_update_mc_addr_list_generic");
+
+       /* clear mta_shadow */
+       memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow));
+
+       /* update mta_shadow from mc_addr_list */
+       for (i = 0; (u32) i < mc_addr_count; i++) {
+               hash_value = e1000_hash_mc_addr_generic(hw, mc_addr_list);
+
+               hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1);
+               hash_bit = hash_value & 0x1F;
+
+               hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit);
+               mc_addr_list += (ETH_ADDR_LEN);
+       }
+
+       /* replace the entire MTA table */
+       for (i = hw->mac.mta_reg_count - 1; i >= 0; i--)
+               E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, hw->mac.mta_shadow[i]);
+       E1000_WRITE_FLUSH(hw);
+}
+
 /**
  *  e1000_pcix_mmrbc_workaround_generic - Fix incorrect MMRBC value
  *  @hw: pointer to the HW structure
@@ -623,9 +629,9 @@ void e1000_pcix_mmrbc_workaround_generic(struct e1000_hw *hw)
        e1000_read_pci_cfg(hw, PCIX_COMMAND_REGISTER, &pcix_cmd);
        e1000_read_pci_cfg(hw, PCIX_STATUS_REGISTER_HI, &pcix_stat_hi_word);
        cmd_mmrbc = (pcix_cmd & PCIX_COMMAND_MMRBC_MASK) >>
-                    PCIX_COMMAND_MMRBC_SHIFT;
+                    PCIX_COMMAND_MMRBC_SHIFT;
        stat_mmrbc = (pcix_stat_hi_word & PCIX_STATUS_HI_MMRBC_MASK) >>
-                     PCIX_STATUS_HI_MMRBC_SHIFT;
+                     PCIX_STATUS_HI_MMRBC_SHIFT;
        if (stat_mmrbc == PCIX_STATUS_HI_MMRBC_4K)
                stat_mmrbc = PCIX_STATUS_HI_MMRBC_2K;
        if (cmd_mmrbc > stat_mmrbc) {
@@ -706,10 +712,8 @@ s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw)
         * get_link_status flag is set upon receiving a Link Status
         * Change or Rx Sequence Error interrupt.
         */
-       if (!mac->get_link_status) {
-               ret_val = E1000_SUCCESS;
-               goto out;
-       }
+       if (!mac->get_link_status)
+               return E1000_SUCCESS;
 
        /*
         * First we want to see if the MII Status Register reports
@@ -718,10 +722,10 @@ s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw)
         */
        ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        if (!link)
-               goto out; /* No link detected */
+               return E1000_SUCCESS; /* No link detected */
 
        mac->get_link_status = false;
 
@@ -735,10 +739,8 @@ s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw)
         * If we are forcing speed/duplex, then we simply return since
         * we have already determined whether we have link or not.
         */
-       if (!mac->autoneg) {
-               ret_val = -E1000_ERR_CONFIG;
-               goto out;
-       }
+       if (!mac->autoneg)
+               return -E1000_ERR_CONFIG;
 
        /*
         * Auto-Neg is enabled.  Auto Speed Detection takes care
@@ -757,7 +759,6 @@ s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw)
        if (ret_val)
                DEBUGOUT("Error configuring flow control\n");
 
-out:
        return ret_val;
 }
 
@@ -774,7 +775,7 @@ s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw)
        u32 rxcw;
        u32 ctrl;
        u32 status;
-       s32 ret_val = E1000_SUCCESS;
+       s32 ret_val;
 
        DEBUGFUNC("e1000_check_for_fiber_link_generic");
 
@@ -791,11 +792,11 @@ s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw)
         * was just plugged in. The autoneg_failed flag does this.
         */
        /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */
-       if ((ctrl & E1000_CTRL_SWDPIN1) && (!(status & E1000_STATUS_LU)) &&
-           (!(rxcw & E1000_RXCW_C))) {
-               if (mac->autoneg_failed == 0) {
-                       mac->autoneg_failed = 1;
-                       goto out;
+       if ((ctrl & E1000_CTRL_SWDPIN1) && !(status & E1000_STATUS_LU) &&
+           !(rxcw & E1000_RXCW_C)) {
+               if (!mac->autoneg_failed) {
+                       mac->autoneg_failed = true;
+                       return E1000_SUCCESS;
                }
                DEBUGOUT("NOT Rx'ing /C/, disable AutoNeg and force link.\n");
 
@@ -811,7 +812,7 @@ s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw)
                ret_val = e1000_config_fc_after_link_up_generic(hw);
                if (ret_val) {
                        DEBUGOUT("Error configuring flow control\n");
-                       goto out;
+                       return ret_val;
                }
        } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
                /*
@@ -827,8 +828,7 @@ s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw)
                mac->serdes_has_link = true;
        }
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
@@ -844,7 +844,7 @@ s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw)
        u32 rxcw;
        u32 ctrl;
        u32 status;
-       s32 ret_val = E1000_SUCCESS;
+       s32 ret_val;
 
        DEBUGFUNC("e1000_check_for_serdes_link_generic");
 
@@ -860,10 +860,10 @@ s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw)
         * time to complete.
         */
        /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */
-       if ((!(status & E1000_STATUS_LU)) && (!(rxcw & E1000_RXCW_C))) {
-               if (mac->autoneg_failed == 0) {
-                       mac->autoneg_failed = 1;
-                       goto out;
+       if (!(status & E1000_STATUS_LU) && !(rxcw & E1000_RXCW_C)) {
+               if (!mac->autoneg_failed) {
+                       mac->autoneg_failed = true;
+                       return E1000_SUCCESS;
                }
                DEBUGOUT("NOT Rx'ing /C/, disable AutoNeg and force link.\n");
 
@@ -879,7 +879,7 @@ s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw)
                ret_val = e1000_config_fc_after_link_up_generic(hw);
                if (ret_val) {
                        DEBUGOUT("Error configuring flow control\n");
-                       goto out;
+                       return ret_val;
                }
        } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
                /*
@@ -921,26 +921,64 @@ s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw)
                        rxcw = E1000_READ_REG(hw, E1000_RXCW);
                        if (rxcw & E1000_RXCW_SYNCH) {
                                if (!(rxcw & E1000_RXCW_IV)) {
-                                       mac->serdes_has_link = TRUE;
-                                       DEBUGOUT("SERDES: Link up - autoneg "
-                                          "completed sucessfully.\n");
+                                       mac->serdes_has_link = true;
+                                       DEBUGOUT("SERDES: Link up - autoneg completed successfully.\n");
                                } else {
-                                       mac->serdes_has_link = FALSE;
-                                       DEBUGOUT("SERDES: Link down - invalid"
-                                          "codewords detected in autoneg.\n");
+                                       mac->serdes_has_link = false;
+                                       DEBUGOUT("SERDES: Link down - invalid codewords detected in autoneg.\n");
                                }
                        } else {
-                               mac->serdes_has_link = FALSE;
+                               mac->serdes_has_link = false;
                                DEBUGOUT("SERDES: Link down - no sync.\n");
                        }
                } else {
-                       mac->serdes_has_link = FALSE;
+                       mac->serdes_has_link = false;
                        DEBUGOUT("SERDES: Link down - autoneg failed\n");
                }
        }
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_set_default_fc_generic - Set flow control default values
+ *  @hw: pointer to the HW structure
+ *
+ *  Read the EEPROM for the default values for flow control and store the
+ *  values.
+ **/
+s32 e1000_set_default_fc_generic(struct e1000_hw *hw)
+{
+       s32 ret_val;
+       u16 nvm_data;
+
+       DEBUGFUNC("e1000_set_default_fc_generic");
+
+       /*
+        * Read and store word 0x0F of the EEPROM. This word contains bits
+        * that determine the hardware's default PAUSE (flow control) mode,
+        * a bit that determines whether the HW defaults to enabling or
+        * disabling auto-negotiation, and the direction of the
+        * SW defined pins. If there is no SW over-ride of the flow
+        * control setting, then the variable hw->fc will
+        * be initialized based on a value in the EEPROM.
+        */
+       ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data);
+
+       if (ret_val) {
+               DEBUGOUT("NVM Read Error\n");
+               return ret_val;
+       }
+
+       if (!(nvm_data & NVM_WORD0F_PAUSE_MASK))
+               hw->fc.requested_mode = e1000_fc_none;
+       else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) ==
+                NVM_WORD0F_ASM_DIR)
+               hw->fc.requested_mode = e1000_fc_tx_pause;
+       else
+               hw->fc.requested_mode = e1000_fc_full;
+
+       return E1000_SUCCESS;
 }
 
 /**
@@ -955,7 +993,7 @@ out:
  **/
 s32 e1000_setup_link_generic(struct e1000_hw *hw)
 {
-       s32 ret_val = E1000_SUCCESS;
+       s32 ret_val;
 
        DEBUGFUNC("e1000_setup_link_generic");
 
@@ -963,8 +1001,8 @@ s32 e1000_setup_link_generic(struct e1000_hw *hw)
         * In the case of the phy reset being blocked, we already have a link.
         * We do not need to set it up again.
         */
-       if (e1000_check_reset_block(hw))
-               goto out;
+       if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw))
+               return E1000_SUCCESS;
 
        /*
         * If requested flow control is set to default, set flow control
@@ -973,7 +1011,7 @@ s32 e1000_setup_link_generic(struct e1000_hw *hw)
        if (hw->fc.requested_mode == e1000_fc_default) {
                ret_val = e1000_set_default_fc_generic(hw);
                if (ret_val)
-                       goto out;
+                       return ret_val;
        }
 
        /*
@@ -988,7 +1026,7 @@ s32 e1000_setup_link_generic(struct e1000_hw *hw)
        /* Call the necessary media_type subroutine to configure the link. */
        ret_val = hw->mac.ops.setup_physical_interface(hw);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        /*
         * Initialize the flow control address, type, and PAUSE timer
@@ -1003,87 +1041,80 @@ s32 e1000_setup_link_generic(struct e1000_hw *hw)
 
        E1000_WRITE_REG(hw, E1000_FCTTV, hw->fc.pause_time);
 
-       ret_val = e1000_set_fc_watermarks_generic(hw);
-
-out:
-       return ret_val;
+       return e1000_set_fc_watermarks_generic(hw);
 }
 
 /**
- *  e1000_setup_fiber_serdes_link_generic - Setup link for fiber/serdes
+ *  e1000_commit_fc_settings_generic - Configure flow control
  *  @hw: pointer to the HW structure
  *
- *  Configures collision distance and flow control for fiber and serdes
- *  links.  Upon successful setup, poll for link.
+ *  Write the flow control settings to the Transmit Config Word Register (TXCW)
+ *  base on the flow control settings in e1000_mac_info.
  **/
-s32 e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw)
+s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
-       u32 ctrl;
-       s32 ret_val = E1000_SUCCESS;
-
-       DEBUGFUNC("e1000_setup_fiber_serdes_link_generic");
-
-       ctrl = E1000_READ_REG(hw, E1000_CTRL);
-
-       /* Take the link out of reset */
-       ctrl &= ~E1000_CTRL_LRST;
-
-       mac->ops.config_collision_dist(hw);
-
-       ret_val = e1000_commit_fc_settings_generic(hw);
-       if (ret_val)
-               goto out;
-
-       /*
-        * Since auto-negotiation is enabled, take the link out of reset (the
-        * link will be in reset, because we previously reset the chip). This
-        * will restart auto-negotiation.  If auto-negotiation is successful
-        * then the link-up status bit will be set and the flow control enable
-        * bits (RFCE and TFCE) will be set according to their negotiated value.
-        */
-       DEBUGOUT("Auto-negotiation enabled\n");
+       u32 txcw;
 
-       E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
-       E1000_WRITE_FLUSH(hw);
-       msec_delay(1);
+       DEBUGFUNC("e1000_commit_fc_settings_generic");
 
        /*
-        * For these adapters, the SW definable pin 1 is set when the optics
-        * detect a signal.  If we have a signal, then poll for a "Link-Up"
-        * indication.
+        * Check for a software override of the flow control settings, and
+        * setup the device accordingly.  If auto-negotiation is enabled, then
+        * software will have to set the "PAUSE" bits to the correct value in
+        * the Transmit Config Word Register (TXCW) and re-start auto-
+        * negotiation.  However, if auto-negotiation is disabled, then
+        * software will have to manually configure the two flow control enable
+        * bits in the CTRL register.
+        *
+        * The possible values of the "fc" parameter are:
+        *      0:  Flow control is completely disabled
+        *      1:  Rx flow control is enabled (we can receive pause frames,
+        *          but not send pause frames).
+        *      2:  Tx flow control is enabled (we can send pause frames but we
+        *          do not support receiving pause frames).
+        *      3:  Both Rx and Tx flow control (symmetric) are enabled.
         */
-       if (hw->phy.media_type == e1000_media_type_internal_serdes ||
-           (E1000_READ_REG(hw, E1000_CTRL) & E1000_CTRL_SWDPIN1)) {
-               ret_val = e1000_poll_fiber_serdes_link_generic(hw);
-       } else {
-               DEBUGOUT("No signal detected\n");
+       switch (hw->fc.current_mode) {
+       case e1000_fc_none:
+               /* Flow control completely disabled by a software over-ride. */
+               txcw = (E1000_TXCW_ANE | E1000_TXCW_FD);
+               break;
+       case e1000_fc_rx_pause:
+               /*
+                * Rx Flow control is enabled and Tx Flow control is disabled
+                * by a software over-ride. Since there really isn't a way to
+                * advertise that we are capable of Rx Pause ONLY, we will
+                * advertise that we support both symmetric and asymmetric Rx
+                * PAUSE.  Later, we will disable the adapter's ability to send
+                * PAUSE frames.
+                */
+               txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
+               break;
+       case e1000_fc_tx_pause:
+               /*
+                * Tx Flow control is enabled, and Rx Flow control is disabled,
+                * by a software over-ride.
+                */
+               txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR);
+               break;
+       case e1000_fc_full:
+               /*
+                * Flow control (both Rx and Tx) is enabled by a software
+                * over-ride.
+                */
+               txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
+               break;
+       default:
+               DEBUGOUT("Flow control param set incorrectly\n");
+               return -E1000_ERR_CONFIG;
+               break;
        }
 
-out:
-       return ret_val;
-}
-
-/**
- *  e1000_config_collision_dist_generic - Configure collision distance
- *  @hw: pointer to the HW structure
- *
- *  Configures the collision distance to the default value and is used
- *  during link setup.
- **/
-void e1000_config_collision_dist_generic(struct e1000_hw *hw)
-{
-       u32 tctl;
-
-       DEBUGFUNC("e1000_config_collision_dist_generic");
-
-       tctl = E1000_READ_REG(hw, E1000_TCTL);
-
-       tctl &= ~E1000_TCTL_COLD;
-       tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT;
+       E1000_WRITE_REG(hw, E1000_TXCW, txcw);
+       mac->txcw = txcw;
 
-       E1000_WRITE_REG(hw, E1000_TCTL, tctl);
-       E1000_WRITE_FLUSH(hw);
+       return E1000_SUCCESS;
 }
 
 /**
@@ -1093,11 +1124,11 @@ void e1000_config_collision_dist_generic(struct e1000_hw *hw)
  *  Polls for link up by reading the status register, if link fails to come
  *  up with auto-negotiation, then the link is forced if a signal is detected.
  **/
-static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw)
+s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
        u32 i, status;
-       s32 ret_val = E1000_SUCCESS;
+       s32 ret_val;
 
        DEBUGFUNC("e1000_poll_fiber_serdes_link_generic");
 
@@ -1116,7 +1147,7 @@ static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw)
        }
        if (i == FIBER_LINK_UP_LIMIT) {
                DEBUGOUT("Never got a valid link from auto-neg!!!\n");
-               mac->autoneg_failed = 1;
+               mac->autoneg_failed = true;
                /*
                 * AutoNeg failed to achieve a link, so we'll call
                 * mac->check_for_link. This routine will force the
@@ -1126,92 +1157,90 @@ static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw)
                ret_val = mac->ops.check_for_link(hw);
                if (ret_val) {
                        DEBUGOUT("Error while checking for link\n");
-                       goto out;
+                       return ret_val;
                }
-               mac->autoneg_failed = 0;
+               mac->autoneg_failed = false;
        } else {
-               mac->autoneg_failed = 0;
+               mac->autoneg_failed = false;
                DEBUGOUT("Valid Link Found\n");
        }
 
-out:
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_setup_fiber_serdes_link_generic - Setup link for fiber/serdes
+ *  @hw: pointer to the HW structure
+ *
+ *  Configures collision distance and flow control for fiber and serdes
+ *  links.  Upon successful setup, poll for link.
+ **/
+s32 e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw)
+{
+       u32 ctrl;
+       s32 ret_val;
+
+       DEBUGFUNC("e1000_setup_fiber_serdes_link_generic");
+
+       ctrl = E1000_READ_REG(hw, E1000_CTRL);
+
+       /* Take the link out of reset */
+       ctrl &= ~E1000_CTRL_LRST;
+
+       hw->mac.ops.config_collision_dist(hw);
+
+       ret_val = e1000_commit_fc_settings_generic(hw);
+       if (ret_val)
+               return ret_val;
+
+       /*
+        * Since auto-negotiation is enabled, take the link out of reset (the
+        * link will be in reset, because we previously reset the chip). This
+        * will restart auto-negotiation.  If auto-negotiation is successful
+        * then the link-up status bit will be set and the flow control enable
+        * bits (RFCE and TFCE) will be set according to their negotiated value.
+        */
+       DEBUGOUT("Auto-negotiation enabled\n");
+
+       E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+       E1000_WRITE_FLUSH(hw);
+       msec_delay(1);
+
+       /*
+        * For these adapters, the SW definable pin 1 is set when the optics
+        * detect a signal.  If we have a signal, then poll for a "Link-Up"
+        * indication.
+        */
+       if (hw->phy.media_type == e1000_media_type_internal_serdes ||
+           (E1000_READ_REG(hw, E1000_CTRL) & E1000_CTRL_SWDPIN1)) {
+               ret_val = e1000_poll_fiber_serdes_link_generic(hw);
+       } else {
+               DEBUGOUT("No signal detected\n");
+       }
+
        return ret_val;
 }
 
 /**
- *  e1000_commit_fc_settings_generic - Configure flow control
+ *  e1000_config_collision_dist_generic - Configure collision distance
  *  @hw: pointer to the HW structure
  *
- *  Write the flow control settings to the Transmit Config Word Register (TXCW)
- *  base on the flow control settings in e1000_mac_info.
+ *  Configures the collision distance to the default value and is used
+ *  during link setup.
  **/
-static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw)
+STATIC void e1000_config_collision_dist_generic(struct e1000_hw *hw)
 {
-       struct e1000_mac_info *mac = &hw->mac;
-       u32 txcw;
-       s32 ret_val = E1000_SUCCESS;
+       u32 tctl;
 
-       DEBUGFUNC("e1000_commit_fc_settings_generic");
+       DEBUGFUNC("e1000_config_collision_dist_generic");
 
-       /*
-        * Check for a software override of the flow control settings, and
-        * setup the device accordingly.  If auto-negotiation is enabled, then
-        * software will have to set the "PAUSE" bits to the correct value in
-        * the Transmit Config Word Register (TXCW) and re-start auto-
-        * negotiation.  However, if auto-negotiation is disabled, then
-        * software will have to manually configure the two flow control enable
-        * bits in the CTRL register.
-        *
-        * The possible values of the "fc" parameter are:
-        *      0:  Flow control is completely disabled
-        *      1:  Rx flow control is enabled (we can receive pause frames,
-        *          but not send pause frames).
-        *      2:  Tx flow control is enabled (we can send pause frames but we
-        *          do not support receiving pause frames).
-        *      3:  Both Rx and Tx flow control (symmetric) are enabled.
-        */
-       switch (hw->fc.current_mode) {
-       case e1000_fc_none:
-               /* Flow control completely disabled by a software over-ride. */
-               txcw = (E1000_TXCW_ANE | E1000_TXCW_FD);
-               break;
-       case e1000_fc_rx_pause:
-               /*
-                * Rx Flow control is enabled and Tx Flow control is disabled
-                * by a software over-ride. Since there really isn't a way to
-                * advertise that we are capable of Rx Pause ONLY, we will
-                * advertise that we support both symmetric and asymmetric Rx
-                * PAUSE.  Later, we will disable the adapter's ability to send
-                * PAUSE frames.
-                */
-               txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
-               break;
-       case e1000_fc_tx_pause:
-               /*
-                * Tx Flow control is enabled, and Rx Flow control is disabled,
-                * by a software over-ride.
-                */
-               txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR);
-               break;
-       case e1000_fc_full:
-               /*
-                * Flow control (both Rx and Tx) is enabled by a software
-                * over-ride.
-                */
-               txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
-               break;
-       default:
-               DEBUGOUT("Flow control param set incorrectly\n");
-               ret_val = -E1000_ERR_CONFIG;
-               goto out;
-               break;
-       }
+       tctl = E1000_READ_REG(hw, E1000_TCTL);
 
-       E1000_WRITE_REG(hw, E1000_TXCW, txcw);
-       mac->txcw = txcw;
+       tctl &= ~E1000_TCTL_COLD;
+       tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT;
 
-out:
-       return ret_val;
+       E1000_WRITE_REG(hw, E1000_TCTL, tctl);
+       E1000_WRITE_FLUSH(hw);
 }
 
 /**
@@ -1253,48 +1282,6 @@ s32 e1000_set_fc_watermarks_generic(struct e1000_hw *hw)
        return E1000_SUCCESS;
 }
 
-/**
- *  e1000_set_default_fc_generic - Set flow control default values
- *  @hw: pointer to the HW structure
- *
- *  Read the EEPROM for the default values for flow control and store the
- *  values.
- **/
-static s32 e1000_set_default_fc_generic(struct e1000_hw *hw)
-{
-       s32 ret_val = E1000_SUCCESS;
-       u16 nvm_data;
-
-       DEBUGFUNC("e1000_set_default_fc_generic");
-
-       /*
-        * Read and store word 0x0F of the EEPROM. This word contains bits
-        * that determine the hardware's default PAUSE (flow control) mode,
-        * a bit that determines whether the HW defaults to enabling or
-        * disabling auto-negotiation, and the direction of the
-        * SW defined pins. If there is no SW over-ride of the flow
-        * control setting, then the variable hw->fc will
-        * be initialized based on a value in the EEPROM.
-        */
-       ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data);
-
-       if (ret_val) {
-               DEBUGOUT("NVM Read Error\n");
-               goto out;
-       }
-
-       if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == 0)
-               hw->fc.requested_mode = e1000_fc_none;
-       else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) ==
-                NVM_WORD0F_ASM_DIR)
-               hw->fc.requested_mode = e1000_fc_tx_pause;
-       else
-               hw->fc.requested_mode = e1000_fc_full;
-
-out:
-       return ret_val;
-}
-
 /**
  *  e1000_force_mac_fc_generic - Force the MAC's flow control settings
  *  @hw: pointer to the HW structure
@@ -1308,7 +1295,6 @@ out:
 s32 e1000_force_mac_fc_generic(struct e1000_hw *hw)
 {
        u32 ctrl;
-       s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_force_mac_fc_generic");
 
@@ -1351,14 +1337,12 @@ s32 e1000_force_mac_fc_generic(struct e1000_hw *hw)
                break;
        default:
                DEBUGOUT("Flow control param set incorrectly\n");
-               ret_val = -E1000_ERR_CONFIG;
-               goto out;
+               return -E1000_ERR_CONFIG;
        }
 
        E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
@@ -1375,6 +1359,7 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
        s32 ret_val = E1000_SUCCESS;
+       u32 pcs_status_reg, pcs_adv_reg, pcs_lp_ability_reg, pcs_ctrl_reg;
        u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg;
        u16 speed, duplex;
 
@@ -1396,7 +1381,7 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw)
 
        if (ret_val) {
                DEBUGOUT("Error forcing flow control settings\n");
-               goto out;
+               return ret_val;
        }
 
        /*
@@ -1413,15 +1398,14 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw)
                 */
                ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg);
                if (ret_val)
-                       goto out;
+                       return ret_val;
                ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg);
                if (ret_val)
-                       goto out;
+                       return ret_val;
 
                if (!(mii_status_reg & MII_SR_AUTONEG_COMPLETE)) {
-                       DEBUGOUT("Copper PHY and Auto Neg "
-                                "has not completed.\n");
-                       goto out;
+                       DEBUGOUT("Copper PHY and Auto Neg has not completed.\n");
+                       return ret_val;
                }
 
                /*
@@ -1432,13 +1416,13 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw)
                 * flow control was negotiated.
                 */
                ret_val = hw->phy.ops.read_reg(hw, PHY_AUTONEG_ADV,
-                                            &mii_nway_adv_reg);
+                                              &mii_nway_adv_reg);
                if (ret_val)
-                       goto out;
+                       return ret_val;
                ret_val = hw->phy.ops.read_reg(hw, PHY_LP_ABILITY,
-                                            &mii_nway_lp_ability_reg);
+                                              &mii_nway_lp_ability_reg);
                if (ret_val)
-                       goto out;
+                       return ret_val;
 
                /*
                 * Two bits in the Auto Negotiation Advertisement Register
@@ -1500,9 +1484,9 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw)
                 *   0   |    1    |   1   |    1    | e1000_fc_tx_pause
                 */
                else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) &&
-                         (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
-                         (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
-                         (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
+                         (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
+                         (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
+                         (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
                        hw->fc.current_mode = e1000_fc_tx_pause;
                        DEBUGOUT("Flow Control = Tx PAUSE frames only.\n");
                }
@@ -1515,9 +1499,9 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw)
                 *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
                 */
                else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
-                        (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
-                        !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
-                        (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
+                        (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
+                        !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
+                        (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
                        hw->fc.current_mode = e1000_fc_rx_pause;
                        DEBUGOUT("Flow Control = Rx PAUSE frames only.\n");
                } else {
@@ -1537,7 +1521,7 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw)
                ret_val = mac->ops.get_link_up_info(hw, &speed, &duplex);
                if (ret_val) {
                        DEBUGOUT("Error getting link speed and duplex\n");
-                       goto out;
+                       return ret_val;
                }
 
                if (duplex == HALF_DUPLEX)
@@ -1550,12 +1534,144 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw)
                ret_val = e1000_force_mac_fc_generic(hw);
                if (ret_val) {
                        DEBUGOUT("Error forcing flow control settings\n");
-                       goto out;
+                       return ret_val;
                }
        }
 
-out:
-       return ret_val;
+       /*
+        * Check for the case where we have SerDes media and auto-neg is
+        * enabled.  In this case, we need to check and see if Auto-Neg
+        * has completed, and if so, how the PHY and link partner has
+        * flow control configured.
+        */
+       if ((hw->phy.media_type == e1000_media_type_internal_serdes)
+               && mac->autoneg) {
+               /*
+                * Read the PCS_LSTS and check to see if AutoNeg
+                * has completed.
+                */
+               pcs_status_reg = E1000_READ_REG(hw, E1000_PCS_LSTAT);
+
+               if (!(pcs_status_reg & E1000_PCS_LSTS_AN_COMPLETE)) {
+                       DEBUGOUT("PCS Auto Neg has not completed.\n");
+                       return ret_val;
+               }
+
+               /*
+                * The AutoNeg process has completed, so we now need to
+                * read both the Auto Negotiation Advertisement
+                * Register (PCS_ANADV) and the Auto_Negotiation Base
+                * Page Ability Register (PCS_LPAB) to determine how
+                * flow control was negotiated.
+                */
+               pcs_adv_reg = E1000_READ_REG(hw, E1000_PCS_ANADV);
+               pcs_lp_ability_reg = E1000_READ_REG(hw, E1000_PCS_LPAB);
+
+               /*
+                * Two bits in the Auto Negotiation Advertisement Register
+                * (PCS_ANADV) and two bits in the Auto Negotiation Base
+                * Page Ability Register (PCS_LPAB) determine flow control
+                * for both the PHY and the link partner.  The following
+                * table, taken out of the IEEE 802.3ab/D6.0 dated March 25,
+                * 1999, describes these PAUSE resolution bits and how flow
+                * control is determined based upon these settings.
+                * NOTE:  DC = Don't Care
+                *
+                *   LOCAL DEVICE  |   LINK PARTNER
+                * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution
+                *-------|---------|-------|---------|--------------------
+                *   0   |    0    |  DC   |   DC    | e1000_fc_none
+                *   0   |    1    |   0   |   DC    | e1000_fc_none
+                *   0   |    1    |   1   |    0    | e1000_fc_none
+                *   0   |    1    |   1   |    1    | e1000_fc_tx_pause
+                *   1   |    0    |   0   |   DC    | e1000_fc_none
+                *   1   |   DC    |   1   |   DC    | e1000_fc_full
+                *   1   |    1    |   0   |    0    | e1000_fc_none
+                *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
+                *
+                * Are both PAUSE bits set to 1?  If so, this implies
+                * Symmetric Flow Control is enabled at both ends.  The
+                * ASM_DIR bits are irrelevant per the spec.
+                *
+                * For Symmetric Flow Control:
+                *
+                *   LOCAL DEVICE  |   LINK PARTNER
+                * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+                *-------|---------|-------|---------|--------------------
+                *   1   |   DC    |   1   |   DC    | e1000_fc_full
+                *
+                */
+               if ((pcs_adv_reg & E1000_TXCW_PAUSE) &&
+                   (pcs_lp_ability_reg & E1000_TXCW_PAUSE)) {
+                       /*
+                        * Now we need to check if the user selected Rx ONLY
+                        * of pause frames.  In this case, we had to advertise
+                        * FULL flow control because we could not advertise Rx
+                        * ONLY. Hence, we must now check to see if we need to
+                        * turn OFF the TRANSMISSION of PAUSE frames.
+                        */
+                       if (hw->fc.requested_mode == e1000_fc_full) {
+                               hw->fc.current_mode = e1000_fc_full;
+                               DEBUGOUT("Flow Control = FULL.\n");
+                       } else {
+                               hw->fc.current_mode = e1000_fc_rx_pause;
+                               DEBUGOUT("Flow Control = Rx PAUSE frames only.\n");
+                       }
+               }
+               /*
+                * For receiving PAUSE frames ONLY.
+                *
+                *   LOCAL DEVICE  |   LINK PARTNER
+                * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+                *-------|---------|-------|---------|--------------------
+                *   0   |    1    |   1   |    1    | e1000_fc_tx_pause
+                */
+               else if (!(pcs_adv_reg & E1000_TXCW_PAUSE) &&
+                         (pcs_adv_reg & E1000_TXCW_ASM_DIR) &&
+                         (pcs_lp_ability_reg & E1000_TXCW_PAUSE) &&
+                         (pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) {
+                       hw->fc.current_mode = e1000_fc_tx_pause;
+                       DEBUGOUT("Flow Control = Tx PAUSE frames only.\n");
+               }
+               /*
+                * For transmitting PAUSE frames ONLY.
+                *
+                *   LOCAL DEVICE  |   LINK PARTNER
+                * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+                *-------|---------|-------|---------|--------------------
+                *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
+                */
+               else if ((pcs_adv_reg & E1000_TXCW_PAUSE) &&
+                        (pcs_adv_reg & E1000_TXCW_ASM_DIR) &&
+                        !(pcs_lp_ability_reg & E1000_TXCW_PAUSE) &&
+                        (pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) {
+                       hw->fc.current_mode = e1000_fc_rx_pause;
+                       DEBUGOUT("Flow Control = Rx PAUSE frames only.\n");
+               } else {
+                       /*
+                        * Per the IEEE spec, at this point flow control
+                        * should be disabled.
+                        */
+                       hw->fc.current_mode = e1000_fc_none;
+                       DEBUGOUT("Flow Control = NONE.\n");
+               }
+
+               /*
+                * Now we call a subroutine to actually force the MAC
+                * controller to use the correct flow control settings.
+                */
+               pcs_ctrl_reg = E1000_READ_REG(hw, E1000_PCS_LCTL);
+               pcs_ctrl_reg |= E1000_PCS_LCTL_FORCE_FCTRL;
+               E1000_WRITE_REG(hw, E1000_PCS_LCTL, pcs_ctrl_reg);
+
+               ret_val = e1000_force_mac_fc_generic(hw);
+               if (ret_val) {
+                       DEBUGOUT("Error forcing flow control settings\n");
+                       return ret_val;
+               }
+       }
+
+       return E1000_SUCCESS;
 }
 
 /**
@@ -1568,7 +1684,7 @@ out:
  *  speed and duplex for copper connections.
  **/
 s32 e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed,
-                                              u16 *duplex)
+                                             u16 *duplex)
 {
        u32 status;
 
@@ -1607,7 +1723,7 @@ s32 e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed,
  *  for fiber/serdes links.
  **/
 s32 e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw *hw,
-                                                    u16 *speed, u16 *duplex)
+                                                   u16 *speed, u16 *duplex)
 {
        DEBUGFUNC("e1000_get_speed_and_duplex_fiber_serdes_generic");
 
@@ -1626,7 +1742,6 @@ s32 e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw *hw,
 s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw)
 {
        u32 swsm;
-       s32 ret_val = E1000_SUCCESS;
        s32 timeout = hw->nvm.word_size + 1;
        s32 i = 0;
 
@@ -1644,8 +1759,7 @@ s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw)
 
        if (i == timeout) {
                DEBUGOUT("Driver can't access device - SMBI bit is set.\n");
-               ret_val = -E1000_ERR_NVM;
-               goto out;
+               return -E1000_ERR_NVM;
        }
 
        /* Get the FW semaphore. */
@@ -1664,12 +1778,10 @@ s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw)
                /* Release semaphores */
                e1000_put_hw_semaphore_generic(hw);
                DEBUGOUT("Driver can't access the NVM\n");
-               ret_val = -E1000_ERR_NVM;
-               goto out;
+               return -E1000_ERR_NVM;
        }
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
@@ -1700,7 +1812,6 @@ void e1000_put_hw_semaphore_generic(struct e1000_hw *hw)
 s32 e1000_get_auto_rd_done_generic(struct e1000_hw *hw)
 {
        s32 i = 0;
-       s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_get_auto_rd_done_generic");
 
@@ -1713,12 +1824,10 @@ s32 e1000_get_auto_rd_done_generic(struct e1000_hw *hw)
 
        if (i == AUTO_READ_DONE_TIMEOUT) {
                DEBUGOUT("Auto read by HW from NVM has not completed.\n");
-               ret_val = -E1000_ERR_RESET;
-               goto out;
+               return -E1000_ERR_RESET;
        }
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
@@ -1738,14 +1847,13 @@ s32 e1000_valid_led_default_generic(struct e1000_hw *hw, u16 *data)
        ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);
        if (ret_val) {
                DEBUGOUT("NVM Read Error\n");
-               goto out;
+               return ret_val;
        }
 
        if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF)
                *data = ID_LED_DEFAULT;
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
@@ -1767,7 +1875,7 @@ s32 e1000_id_led_init_generic(struct e1000_hw *hw)
 
        ret_val = hw->nvm.ops.valid_led_default(hw, &data);
        if (ret_val)
-               goto out;
+               return ret_val;
 
        mac->ledctl_default = E1000_READ_REG(hw, E1000_LEDCTL);
        mac->ledctl_mode1 = mac->ledctl_default;
@@ -1811,8 +1919,7 @@ s32 e1000_id_led_init_generic(struct e1000_hw *hw)
                }
        }
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
@@ -1825,30 +1932,26 @@ out:
 s32 e1000_setup_led_generic(struct e1000_hw *hw)
 {
        u32 ledctl;
-       s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_setup_led_generic");
 
-       if (hw->mac.ops.setup_led != e1000_setup_led_generic) {
-               ret_val = -E1000_ERR_CONFIG;
-               goto out;
-       }
+       if (hw->mac.ops.setup_led != e1000_setup_led_generic)
+               return -E1000_ERR_CONFIG;
 
        if (hw->phy.media_type == e1000_media_type_fiber) {
                ledctl = E1000_READ_REG(hw, E1000_LEDCTL);
                hw->mac.ledctl_default = ledctl;
                /* Turn off LED0 */
                ledctl &= ~(E1000_LEDCTL_LED0_IVRT | E1000_LEDCTL_LED0_BLINK |
-                           E1000_LEDCTL_LED0_MODE_MASK);
+                           E1000_LEDCTL_LED0_MODE_MASK);
                ledctl |= (E1000_LEDCTL_MODE_LED_OFF <<
-                          E1000_LEDCTL_LED0_MODE_SHIFT);
+                          E1000_LEDCTL_LED0_MODE_SHIFT);
                E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl);
        } else if (hw->phy.media_type == e1000_media_type_copper) {
                E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1);
        }
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
@@ -1893,7 +1996,7 @@ s32 e1000_blink_led_generic(struct e1000_hw *hw)
                        if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) ==
                            E1000_LEDCTL_MODE_LED_ON)
                                ledctl_blink |= (E1000_LEDCTL_LED0_BLINK <<
-                                                (i * 8));
+                                                (i * 8));
        }
 
        E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl_blink);
@@ -1973,7 +2076,7 @@ void e1000_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop)
        DEBUGFUNC("e1000_set_pcie_no_snoop_generic");
 
        if (hw->bus.type != e1000_bus_type_pci_express)
-               goto out;
+               return;
 
        if (no_snoop) {
                gcr = E1000_READ_REG(hw, E1000_GCR);
@@ -1981,8 +2084,6 @@ void e1000_set_pcie_no_snoop_generic(struct e1000_hw *hw, u32 no_snoop)
                gcr |= no_snoop;
                E1000_WRITE_REG(hw, E1000_GCR, gcr);
        }
-out:
-       return;
 }
 
 /**
@@ -2000,12 +2101,11 @@ s32 e1000_disable_pcie_master_generic(struct e1000_hw *hw)
 {
        u32 ctrl;
        s32 timeout = MASTER_DISABLE_TIMEOUT;
-       s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_disable_pcie_master_generic");
 
        if (hw->bus.type != e1000_bus_type_pci_express)
-               goto out;
+               return E1000_SUCCESS;
 
        ctrl = E1000_READ_REG(hw, E1000_CTRL);
        ctrl |= E1000_CTRL_GIO_MASTER_DISABLE;
@@ -2021,11 +2121,10 @@ s32 e1000_disable_pcie_master_generic(struct e1000_hw *hw)
 
        if (!timeout) {
                DEBUGOUT("Master requests are pending.\n");
-               ret_val = -E1000_ERR_MASTER_REQUESTS_PENDING;
+               return -E1000_ERR_MASTER_REQUESTS_PENDING;
        }
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
@@ -2042,7 +2141,7 @@ void e1000_reset_adaptive_generic(struct e1000_hw *hw)
 
        if (!mac->adaptive_ifs) {
                DEBUGOUT("Not in Adaptive IFS mode!\n");
-               goto out;
+               return;
        }
 
        mac->current_ifs_val = 0;
@@ -2053,8 +2152,6 @@ void e1000_reset_adaptive_generic(struct e1000_hw *hw)
 
        mac->in_ifs_mode = false;
        E1000_WRITE_REG(hw, E1000_AIT, 0);
-out:
-       return;
 }
 
 /**
@@ -2072,7 +2169,7 @@ void e1000_update_adaptive_generic(struct e1000_hw *hw)
 
        if (!mac->adaptive_ifs) {
                DEBUGOUT("Not in Adaptive IFS mode!\n");
-               goto out;
+               return;
        }
 
        if ((mac->collision_delta * mac->ifs_ratio) > mac->tx_packet_delta) {
@@ -2096,8 +2193,6 @@ void e1000_update_adaptive_generic(struct e1000_hw *hw)
                        E1000_WRITE_REG(hw, E1000_AIT, 0);
                }
        }
-out:
-       return;
 }
 
 /**
@@ -2109,19 +2204,29 @@ out:
  **/
 STATIC s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw)
 {
-       s32 ret_val = E1000_SUCCESS;
-
        DEBUGFUNC("e1000_validate_mdi_setting_generic");
 
        if (!hw->mac.autoneg && (hw->phy.mdix == 0 || hw->phy.mdix == 3)) {
                DEBUGOUT("Invalid MDI setting detected\n");
                hw->phy.mdix = 1;
-               ret_val = -E1000_ERR_CONFIG;
-               goto out;
+               return -E1000_ERR_CONFIG;
        }
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_validate_mdi_setting_crossover_generic - Verify MDI/MDIx settings
+ *  @hw: pointer to the HW structure
+ *
+ *  Validate the MDI/MDIx setting, allowing for auto-crossover during forced
+ *  operation.
+ **/
+s32 e1000_validate_mdi_setting_crossover_generic(struct e1000_hw *hw)
+{
+       DEBUGFUNC("e1000_validate_mdi_setting_crossover_generic");
+
+       return E1000_SUCCESS;
 }
 
 /**
@@ -2136,10 +2241,9 @@ out:
  *  completion.
  **/
 s32 e1000_write_8bit_ctrl_reg_generic(struct e1000_hw *hw, u32 reg,
-                                      u32 offset, u8 data)
+                                     u32 offset, u8 data)
 {
        u32 i, regvalue = 0;
-       s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_write_8bit_ctrl_reg_generic");
 
@@ -2156,10 +2260,8 @@ s32 e1000_write_8bit_ctrl_reg_generic(struct e1000_hw *hw, u32 reg,
        }
        if (!(regvalue & E1000_GEN_CTL_READY)) {
                DEBUGOUT1("Reg %08x did not indicate ready\n", reg);
-               ret_val = -E1000_ERR_PHY;
-               goto out;
+               return -E1000_ERR_PHY;
        }
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }