ixgbe: always enable vlan strip/insert when DCB is enabled
[safe/jmp/linux-2.6] / drivers / net / e1000e / lib.c
index f1f4e9d..a968e3a 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel PRO/1000 Linux driver
-  Copyright(c) 1999 - 2008 Intel Corporation.
+  Copyright(c) 1999 - 2009 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
 
 *******************************************************************************/
 
-#include <linux/netdevice.h>
-#include <linux/ethtool.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-
 #include "e1000.h"
 
 enum e1000_mng_mode {
@@ -56,10 +51,10 @@ enum e1000_mng_mode {
  **/
 s32 e1000e_get_bus_info_pcie(struct e1000_hw *hw)
 {
+       struct e1000_mac_info *mac = &hw->mac;
        struct e1000_bus_info *bus = &hw->bus;
        struct e1000_adapter *adapter = hw->adapter;
-       u32 status;
-       u16 pcie_link_status, pci_header_type, cap_offset;
+       u16 pcie_link_status, cap_offset;
 
        cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP);
        if (!cap_offset) {
@@ -73,21 +68,64 @@ s32 e1000e_get_bus_info_pcie(struct e1000_hw *hw)
                                                    PCIE_LINK_WIDTH_SHIFT);
        }
 
-       pci_read_config_word(adapter->pdev, PCI_HEADER_TYPE_REGISTER,
-                            &pci_header_type);
-       if (pci_header_type & PCI_HEADER_TYPE_MULTIFUNC) {
-               status = er32(STATUS);
-               bus->func = (status & E1000_STATUS_FUNC_MASK)
-                           >> E1000_STATUS_FUNC_SHIFT;
-       } else {
-               bus->func = 0;
-       }
+       mac->ops.set_lan_id(hw);
 
        return 0;
 }
 
 /**
- *  e1000e_write_vfta - Write value to VLAN filter table
+ *  e1000_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices
+ *
+ *  @hw: pointer to the HW structure
+ *
+ *  Determines the LAN function id by reading memory-mapped registers
+ *  and swaps the port value if requested.
+ **/
+void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw)
+{
+       struct e1000_bus_info *bus = &hw->bus;
+       u32 reg;
+
+       /*
+        * The status register reports the correct function number
+        * for the device regardless of function swap state.
+        */
+       reg = er32(STATUS);
+       bus->func = (reg & E1000_STATUS_FUNC_MASK) >> E1000_STATUS_FUNC_SHIFT;
+}
+
+/**
+ *  e1000_set_lan_id_single_port - Set LAN id for a single port device
+ *  @hw: pointer to the HW structure
+ *
+ *  Sets the LAN function id to zero for a single port device.
+ **/
+void e1000_set_lan_id_single_port(struct e1000_hw *hw)
+{
+       struct e1000_bus_info *bus = &hw->bus;
+
+       bus->func = 0;
+}
+
+/**
+ *  e1000_clear_vfta_generic - Clear VLAN filter table
+ *  @hw: pointer to the HW structure
+ *
+ *  Clears the register array which contains the VLAN filter table by
+ *  setting all the values to 0.
+ **/
+void e1000_clear_vfta_generic(struct e1000_hw *hw)
+{
+       u32 offset;
+
+       for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
+               E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, 0);
+               e1e_flush();
+       }
+}
+
+/**
+ *  e1000_write_vfta_generic - Write value to VLAN filter table
  *  @hw: pointer to the HW structure
  *  @offset: register offset in VLAN filter table
  *  @value: register value written to VLAN filter table
@@ -95,7 +133,7 @@ s32 e1000e_get_bus_info_pcie(struct e1000_hw *hw)
  *  Writes value at the given offset in the register array which stores
  *  the VLAN filter table.
  **/
-void e1000e_write_vfta(struct e1000_hw *hw, u32 offset, u32 value)
+void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value)
 {
        E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value);
        e1e_flush();
@@ -113,20 +151,79 @@ void e1000e_write_vfta(struct e1000_hw *hw, u32 offset, u32 value)
 void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count)
 {
        u32 i;
+       u8 mac_addr[ETH_ALEN] = {0};
 
        /* Setup the receive address */
-       hw_dbg(hw, "Programming MAC Address into RAR[0]\n");
+       e_dbg("Programming MAC Address into RAR[0]\n");
 
        e1000e_rar_set(hw, hw->mac.addr, 0);
 
        /* Zero out the other (rar_entry_count - 1) receive addresses */
-       hw_dbg(hw, "Clearing RAR[1-%u]\n", rar_count-1);
-       for (i = 1; i < rar_count; i++) {
-               E1000_WRITE_REG_ARRAY(hw, E1000_RA, (i << 1), 0);
-               e1e_flush();
-               E1000_WRITE_REG_ARRAY(hw, E1000_RA, ((i << 1) + 1), 0);
-               e1e_flush();
+       e_dbg("Clearing RAR[1-%u]\n", rar_count-1);
+       for (i = 1; i < rar_count; i++)
+               e1000e_rar_set(hw, mac_addr, i);
+}
+
+/**
+ *  e1000_check_alt_mac_addr_generic - Check for alternate MAC addr
+ *  @hw: pointer to the HW structure
+ *
+ *  Checks the nvm for an alternate MAC address.  An alternate MAC address
+ *  can be setup by pre-boot software and must be treated like a permanent
+ *  address and must override the actual permanent MAC address. If an
+ *  alternate MAC address is found it is programmed into RAR0, replacing
+ *  the permanent address that was installed into RAR0 by the Si on reset.
+ *  This function will return SUCCESS unless it encounters an error while
+ *  reading the EEPROM.
+ **/
+s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
+{
+       u32 i;
+       s32 ret_val = 0;
+       u16 offset, nvm_alt_mac_addr_offset, nvm_data;
+       u8 alt_mac_addr[ETH_ALEN];
+
+       ret_val = e1000_read_nvm(hw, NVM_ALT_MAC_ADDR_PTR, 1,
+                                &nvm_alt_mac_addr_offset);
+       if (ret_val) {
+               e_dbg("NVM Read Error\n");
+               goto out;
+       }
+
+       if (nvm_alt_mac_addr_offset == 0xFFFF) {
+               /* There is no Alternate MAC Address */
+               goto out;
+       }
+
+       if (hw->bus.func == E1000_FUNC_1)
+               nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN1;
+       for (i = 0; i < ETH_ALEN; i += 2) {
+               offset = nvm_alt_mac_addr_offset + (i >> 1);
+               ret_val = e1000_read_nvm(hw, offset, 1, &nvm_data);
+               if (ret_val) {
+                       e_dbg("NVM Read Error\n");
+                       goto out;
+               }
+
+               alt_mac_addr[i] = (u8)(nvm_data & 0xFF);
+               alt_mac_addr[i + 1] = (u8)(nvm_data >> 8);
        }
+
+       /* if multicast bit is set, the alternate address will not be used */
+       if (alt_mac_addr[0] & 0x01) {
+               e_dbg("Ignoring Alternate Mac Address with MC bit set\n");
+               goto out;
+       }
+
+       /*
+        * We have a valid alternate MAC address, and we want to treat it the
+        * same as the normal permanent MAC address stored by the HW into the
+        * RAR. Do this by mapping this address into RAR0.
+        */
+       e1000e_rar_set(hw, alt_mac_addr, 0);
+
+out:
+       return ret_val;
 }
 
 /**
@@ -152,44 +249,18 @@ void e1000e_rar_set(struct e1000_hw *hw, u8 *addr, u32 index)
 
        rar_high = ((u32) addr[4] | ((u32) addr[5] << 8));
 
-       rar_high |= E1000_RAH_AV;
-
-       E1000_WRITE_REG_ARRAY(hw, E1000_RA, (index << 1), rar_low);
-       E1000_WRITE_REG_ARRAY(hw, E1000_RA, ((index << 1) + 1), rar_high);
-}
-
-/**
- *  e1000_mta_set - Set multicast filter table address
- *  @hw: pointer to the HW structure
- *  @hash_value: determines the MTA register and bit to set
- *
- *  The multicast table address is a register array of 32-bit registers.
- *  The hash_value is used to determine what register the bit is in, the
- *  current value is read, the new bit is OR'd in and the new value is
- *  written back into the register.
- **/
-static void e1000_mta_set(struct e1000_hw *hw, u32 hash_value)
-{
-       u32 hash_bit, hash_reg, mta;
+       /* If MAC address zero, no need to set the AV bit */
+       if (rar_low || rar_high)
+               rar_high |= E1000_RAH_AV;
 
        /*
-        * The MTA is a register array of 32-bit registers. It is
-        * treated like an array of (32*mta_reg_count) bits.  We want to
-        * set bit BitArray[hash_value]. So we figure out what register
-        * the bit is in, read it, OR in the new bit, then write
-        * back the new value.  The (hw->mac.mta_reg_count - 1) serves as a
-        * mask to bits 31:5 of the hash value which gives us the
-        * register we're modifying.  The hash bit within that register
-        * is determined by the lower 5 bits of the hash value.
+        * Some bridges will combine consecutive 32-bit writes into
+        * a single burst write, which will malfunction on some parts.
+        * The flushes avoid this.
         */
-       hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1);
-       hash_bit = hash_value & 0x1F;
-
-       mta = E1000_READ_REG_ARRAY(hw, E1000_MTA, hash_reg);
-
-       mta |= (1 << hash_bit);
-
-       E1000_WRITE_REG_ARRAY(hw, E1000_MTA, hash_reg, mta);
+       ew32(RAL(index), rar_low);
+       e1e_flush();
+       ew32(RAH(index), rar_high);
        e1e_flush();
 }
 
@@ -269,53 +340,34 @@ static u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
  *  @hw: pointer to the HW structure
  *  @mc_addr_list: array of multicast addresses to program
  *  @mc_addr_count: number of multicast addresses to program
- *  @rar_used_count: the first RAR register free to program
- *  @rar_count: total number of supported Receive Address Registers
  *
- *  Updates the Receive Address Registers and Multicast Table Array.
+ *  Updates entire Multicast Table Array.
  *  The caller must have a packed mc_addr_list of multicast addresses.
- *  The parameter rar_count will usually be hw->mac.rar_entry_count
- *  unless there are workarounds that change this.
  **/
 void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw,
-                                       u8 *mc_addr_list, u32 mc_addr_count,
-                                       u32 rar_used_count, u32 rar_count)
+                                       u8 *mc_addr_list, u32 mc_addr_count)
 {
-       u32 hash_value;
-       u32 i;
-
-       /*
-        * Load the first set of multicast addresses into the exact
-        * filters (RAR).  If there are not enough to fill the RAR
-        * array, clear the filters.
-        */
-       for (i = rar_used_count; i < rar_count; i++) {
-               if (mc_addr_count) {
-                       e1000e_rar_set(hw, mc_addr_list, i);
-                       mc_addr_count--;
-                       mc_addr_list += ETH_ALEN;
-               } else {
-                       E1000_WRITE_REG_ARRAY(hw, E1000_RA, i << 1, 0);
-                       e1e_flush();
-                       E1000_WRITE_REG_ARRAY(hw, E1000_RA, (i << 1) + 1, 0);
-                       e1e_flush();
-               }
-       }
+       u32 hash_value, hash_bit, hash_reg;
+       int i;
 
-       /* Clear the old settings from the MTA */
-       hw_dbg(hw, "Clearing MTA\n");
-       for (i = 0; i < hw->mac.mta_reg_count; i++) {
-               E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
-               e1e_flush();
-       }
+       /* clear mta_shadow */
+       memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow));
 
-       /* Load any remaining multicast addresses into the hash table. */
-       for (; mc_addr_count > 0; mc_addr_count--) {
+       /* update mta_shadow from mc_addr_list */
+       for (i = 0; (u32) i < mc_addr_count; i++) {
                hash_value = e1000_hash_mc_addr(hw, mc_addr_list);
-               hw_dbg(hw, "Hash value = 0x%03X\n", hash_value);
-               e1000_mta_set(hw, hash_value);
-               mc_addr_list += ETH_ALEN;
+
+               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_ALEN);
        }
+
+       /* 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]);
+       e1e_flush();
 }
 
 /**
@@ -326,45 +378,43 @@ void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw,
  **/
 void e1000e_clear_hw_cntrs_base(struct e1000_hw *hw)
 {
-       u32 temp;
-
-       temp = er32(CRCERRS);
-       temp = er32(SYMERRS);
-       temp = er32(MPC);
-       temp = er32(SCC);
-       temp = er32(ECOL);
-       temp = er32(MCC);
-       temp = er32(LATECOL);
-       temp = er32(COLC);
-       temp = er32(DC);
-       temp = er32(SEC);
-       temp = er32(RLEC);
-       temp = er32(XONRXC);
-       temp = er32(XONTXC);
-       temp = er32(XOFFRXC);
-       temp = er32(XOFFTXC);
-       temp = er32(FCRUC);
-       temp = er32(GPRC);
-       temp = er32(BPRC);
-       temp = er32(MPRC);
-       temp = er32(GPTC);
-       temp = er32(GORCL);
-       temp = er32(GORCH);
-       temp = er32(GOTCL);
-       temp = er32(GOTCH);
-       temp = er32(RNBC);
-       temp = er32(RUC);
-       temp = er32(RFC);
-       temp = er32(ROC);
-       temp = er32(RJC);
-       temp = er32(TORL);
-       temp = er32(TORH);
-       temp = er32(TOTL);
-       temp = er32(TOTH);
-       temp = er32(TPR);
-       temp = er32(TPT);
-       temp = er32(MPTC);
-       temp = er32(BPTC);
+       er32(CRCERRS);
+       er32(SYMERRS);
+       er32(MPC);
+       er32(SCC);
+       er32(ECOL);
+       er32(MCC);
+       er32(LATECOL);
+       er32(COLC);
+       er32(DC);
+       er32(SEC);
+       er32(RLEC);
+       er32(XONRXC);
+       er32(XONTXC);
+       er32(XOFFRXC);
+       er32(XOFFTXC);
+       er32(FCRUC);
+       er32(GPRC);
+       er32(BPRC);
+       er32(MPRC);
+       er32(GPTC);
+       er32(GORCL);
+       er32(GORCH);
+       er32(GOTCL);
+       er32(GOTCH);
+       er32(RNBC);
+       er32(RUC);
+       er32(RFC);
+       er32(ROC);
+       er32(RJC);
+       er32(TORL);
+       er32(TORH);
+       er32(TOTL);
+       er32(TOTH);
+       er32(TPR);
+       er32(TPT);
+       er32(MPTC);
+       er32(BPTC);
 }
 
 /**
@@ -402,7 +452,7 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw)
        if (!link)
                return ret_val; /* No link detected */
 
-       mac->get_link_status = 0;
+       mac->get_link_status = false;
 
        /*
         * Check if there was DownShift, must be checked
@@ -434,7 +484,7 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw)
         */
        ret_val = e1000e_config_fc_after_link_up(hw);
        if (ret_val) {
-               hw_dbg(hw, "Error configuring flow control\n");
+               e_dbg("Error configuring flow control\n");
        }
 
        return ret_val;
@@ -474,7 +524,7 @@ s32 e1000e_check_for_fiber_link(struct e1000_hw *hw)
                        mac->autoneg_failed = 1;
                        return 0;
                }
-               hw_dbg(hw, "NOT RXing /C/, disable AutoNeg and force link.\n");
+               e_dbg("NOT RXing /C/, disable AutoNeg and force link.\n");
 
                /* Disable auto-negotiation in the TXCW register */
                ew32(TXCW, (mac->txcw & ~E1000_TXCW_ANE));
@@ -487,7 +537,7 @@ s32 e1000e_check_for_fiber_link(struct e1000_hw *hw)
                /* Configure Flow Control after forcing link up. */
                ret_val = e1000e_config_fc_after_link_up(hw);
                if (ret_val) {
-                       hw_dbg(hw, "Error configuring flow control\n");
+                       e_dbg("Error configuring flow control\n");
                        return ret_val;
                }
        } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
@@ -497,11 +547,11 @@ s32 e1000e_check_for_fiber_link(struct e1000_hw *hw)
                 * and disable forced link in the Device Control register
                 * in an attempt to auto-negotiate with our link partner.
                 */
-               hw_dbg(hw, "RXing /C/, enable AutoNeg and stop forcing link.\n");
+               e_dbg("RXing /C/, enable AutoNeg and stop forcing link.\n");
                ew32(TXCW, mac->txcw);
                ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
 
-               mac->serdes_has_link = 1;
+               mac->serdes_has_link = true;
        }
 
        return 0;
@@ -539,7 +589,7 @@ s32 e1000e_check_for_serdes_link(struct e1000_hw *hw)
                        mac->autoneg_failed = 1;
                        return 0;
                }
-               hw_dbg(hw, "NOT RXing /C/, disable AutoNeg and force link.\n");
+               e_dbg("NOT RXing /C/, disable AutoNeg and force link.\n");
 
                /* Disable auto-negotiation in the TXCW register */
                ew32(TXCW, (mac->txcw & ~E1000_TXCW_ANE));
@@ -552,7 +602,7 @@ s32 e1000e_check_for_serdes_link(struct e1000_hw *hw)
                /* Configure Flow Control after forcing link up. */
                ret_val = e1000e_config_fc_after_link_up(hw);
                if (ret_val) {
-                       hw_dbg(hw, "Error configuring flow control\n");
+                       e_dbg("Error configuring flow control\n");
                        return ret_val;
                }
        } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
@@ -562,11 +612,11 @@ s32 e1000e_check_for_serdes_link(struct e1000_hw *hw)
                 * and disable forced link in the Device Control register
                 * in an attempt to auto-negotiate with our link partner.
                 */
-               hw_dbg(hw, "RXing /C/, enable AutoNeg and stop forcing link.\n");
+               e_dbg("RXing /C/, enable AutoNeg and stop forcing link.\n");
                ew32(TXCW, mac->txcw);
                ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
 
-               mac->serdes_has_link = 1;
+               mac->serdes_has_link = true;
        } else if (!(E1000_TXCW_ANE & er32(TXCW))) {
                /*
                 * If we force link for non-auto-negotiation switch, check
@@ -575,20 +625,42 @@ s32 e1000e_check_for_serdes_link(struct e1000_hw *hw)
                 */
                /* SYNCH bit and IV bit are sticky. */
                udelay(10);
-               if (E1000_RXCW_SYNCH & er32(RXCW)) {
+               rxcw = er32(RXCW);
+               if (rxcw & E1000_RXCW_SYNCH) {
                        if (!(rxcw & E1000_RXCW_IV)) {
-                               mac->serdes_has_link = 1;
-                               hw_dbg(hw, "SERDES: Link is up.\n");
+                               mac->serdes_has_link = true;
+                               e_dbg("SERDES: Link up - forced.\n");
                        }
                } else {
-                       mac->serdes_has_link = 0;
-                       hw_dbg(hw, "SERDES: Link is down.\n");
+                       mac->serdes_has_link = false;
+                       e_dbg("SERDES: Link down - force failed.\n");
                }
        }
 
        if (E1000_TXCW_ANE & er32(TXCW)) {
                status = er32(STATUS);
-               mac->serdes_has_link = (status & E1000_STATUS_LU);
+               if (status & E1000_STATUS_LU) {
+                       /* SYNCH bit and IV bit are sticky, so reread rxcw.  */
+                       udelay(10);
+                       rxcw = er32(RXCW);
+                       if (rxcw & E1000_RXCW_SYNCH) {
+                               if (!(rxcw & E1000_RXCW_IV)) {
+                                       mac->serdes_has_link = true;
+                                       e_dbg("SERDES: Link up - autoneg "
+                                          "completed successfully.\n");
+                               } else {
+                                       mac->serdes_has_link = false;
+                                       e_dbg("SERDES: Link down - invalid"
+                                          "codewords detected in autoneg.\n");
+                               }
+                       } else {
+                               mac->serdes_has_link = false;
+                               e_dbg("SERDES: Link down - no sync.\n");
+                       }
+               } else {
+                       mac->serdes_has_link = false;
+                       e_dbg("SERDES: Link down - autoneg failed\n");
+               }
        }
 
        return 0;
@@ -618,17 +690,17 @@ static s32 e1000_set_default_fc_generic(struct e1000_hw *hw)
        ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data);
 
        if (ret_val) {
-               hw_dbg(hw, "NVM Read Error\n");
+               e_dbg("NVM Read Error\n");
                return ret_val;
        }
 
        if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == 0)
-               hw->fc.type = e1000_fc_none;
+               hw->fc.requested_mode = e1000_fc_none;
        else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) ==
                 NVM_WORD0F_ASM_DIR)
-               hw->fc.type = e1000_fc_tx_pause;
+               hw->fc.requested_mode = e1000_fc_tx_pause;
        else
-               hw->fc.type = e1000_fc_full;
+               hw->fc.requested_mode = e1000_fc_full;
 
        return 0;
 }
@@ -656,23 +728,23 @@ s32 e1000e_setup_link(struct e1000_hw *hw)
                return 0;
 
        /*
-        * If flow control is set to default, set flow control based on
-        * the EEPROM flow control settings.
+        * If requested flow control is set to default, set flow control
+        * based on the EEPROM flow control settings.
         */
-       if (hw->fc.type == e1000_fc_default) {
+       if (hw->fc.requested_mode == e1000_fc_default) {
                ret_val = e1000_set_default_fc_generic(hw);
                if (ret_val)
                        return ret_val;
        }
 
        /*
-        * We want to save off the original Flow Control configuration just
-        * in case we get disconnected and then reconnected into a different
-        * hub or switch with different Flow Control capabilities.
+        * Save off the requested flow control mode for use later.  Depending
+        * on the link partner's capabilities, we may or may not use this mode.
         */
-       hw->fc.original_type = hw->fc.type;
+       hw->fc.current_mode = hw->fc.requested_mode;
 
-       hw_dbg(hw, "After fix-ups FlowControl is now = %x\n", hw->fc.type);
+       e_dbg("After fix-ups FlowControl is now = %x\n",
+               hw->fc.current_mode);
 
        /* Call the necessary media_type subroutine to configure the link. */
        ret_val = mac->ops.setup_physical_interface(hw);
@@ -685,7 +757,7 @@ s32 e1000e_setup_link(struct e1000_hw *hw)
         * control is disabled, because it does not hurt anything to
         * initialize these registers.
         */
-       hw_dbg(hw, "Initializing the Flow Control address, type and timer regs\n");
+       e_dbg("Initializing the Flow Control address, type and timer regs\n");
        ew32(FCT, FLOW_CONTROL_TYPE);
        ew32(FCAH, FLOW_CONTROL_ADDRESS_HIGH);
        ew32(FCAL, FLOW_CONTROL_ADDRESS_LOW);
@@ -724,7 +796,7 @@ static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw)
         *        do not support receiving pause frames).
         *      3:  Both Rx and Tx flow control (symmetric) are enabled.
         */
-       switch (hw->fc.type) {
+       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);
@@ -755,7 +827,7 @@ static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw)
                txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
                break;
        default:
-               hw_dbg(hw, "Flow control param set incorrectly\n");
+               e_dbg("Flow control param set incorrectly\n");
                return -E1000_ERR_CONFIG;
                break;
        }
@@ -793,7 +865,7 @@ static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw)
                        break;
        }
        if (i == FIBER_LINK_UP_LIMIT) {
-               hw_dbg(hw, "Never got a valid link from auto-neg!!!\n");
+               e_dbg("Never got a valid link from auto-neg!!!\n");
                mac->autoneg_failed = 1;
                /*
                 * AutoNeg failed to achieve a link, so we'll call
@@ -803,13 +875,13 @@ static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw)
                 */
                ret_val = mac->ops.check_for_link(hw);
                if (ret_val) {
-                       hw_dbg(hw, "Error while checking for link\n");
+                       e_dbg("Error while checking for link\n");
                        return ret_val;
                }
                mac->autoneg_failed = 0;
        } else {
                mac->autoneg_failed = 0;
-               hw_dbg(hw, "Valid Link Found\n");
+               e_dbg("Valid Link Found\n");
        }
 
        return 0;
@@ -845,7 +917,7 @@ s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw)
         * 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.
         */
-       hw_dbg(hw, "Auto-negotiation enabled\n");
+       e_dbg("Auto-negotiation enabled\n");
 
        ew32(CTRL, ctrl);
        e1e_flush();
@@ -860,7 +932,7 @@ s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw)
            (er32(CTRL) & E1000_CTRL_SWDPIN1)) {
                ret_val = e1000_poll_fiber_serdes_link_generic(hw);
        } else {
-               hw_dbg(hw, "No signal detected\n");
+               e_dbg("No signal detected\n");
        }
 
        return 0;
@@ -906,7 +978,7 @@ s32 e1000e_set_fc_watermarks(struct e1000_hw *hw)
         * ability to transmit pause frames is not enabled, then these
         * registers will be set to 0.
         */
-       if (hw->fc.type & e1000_fc_tx_pause) {
+       if (hw->fc.current_mode & e1000_fc_tx_pause) {
                /*
                 * We need to set up the Receive Threshold high and low water
                 * marks as well as (optionally) enabling the transmission of
@@ -945,7 +1017,7 @@ s32 e1000e_force_mac_fc(struct e1000_hw *hw)
         * receive flow control.
         *
         * The "Case" statement below enables/disable flow control
-        * according to the "hw->fc.type" parameter.
+        * according to the "hw->fc.current_mode" parameter.
         *
         * The possible values of the "fc" parameter are:
         *      0:  Flow control is completely disabled
@@ -956,9 +1028,9 @@ s32 e1000e_force_mac_fc(struct e1000_hw *hw)
         *      3:  Both Rx and Tx flow control (symmetric) is enabled.
         *  other:  No other values should be possible at this point.
         */
-       hw_dbg(hw, "hw->fc.type = %u\n", hw->fc.type);
+       e_dbg("hw->fc.current_mode = %u\n", hw->fc.current_mode);
 
-       switch (hw->fc.type) {
+       switch (hw->fc.current_mode) {
        case e1000_fc_none:
                ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE));
                break;
@@ -974,7 +1046,7 @@ s32 e1000e_force_mac_fc(struct e1000_hw *hw)
                ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE);
                break;
        default:
-               hw_dbg(hw, "Flow control param set incorrectly\n");
+               e_dbg("Flow control param set incorrectly\n");
                return -E1000_ERR_CONFIG;
        }
 
@@ -1015,7 +1087,7 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
        }
 
        if (ret_val) {
-               hw_dbg(hw, "Error forcing flow control settings\n");
+               e_dbg("Error forcing flow control settings\n");
                return ret_val;
        }
 
@@ -1039,7 +1111,7 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
                        return ret_val;
 
                if (!(mii_status_reg & MII_SR_AUTONEG_COMPLETE)) {
-                       hw_dbg(hw, "Copper PHY and Auto Neg "
+                       e_dbg("Copper PHY and Auto Neg "
                                 "has not completed.\n");
                        return ret_val;
                }
@@ -1080,7 +1152,6 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
                 *   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.
@@ -1102,12 +1173,12 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
                         * ONLY. Hence, we must now check to see if we need to
                         * turn OFF  the TRANSMISSION of PAUSE frames.
                         */
-                       if (hw->fc.original_type == e1000_fc_full) {
-                               hw->fc.type = e1000_fc_full;
-                               hw_dbg(hw, "Flow Control = FULL.\r\n");
+                       if (hw->fc.requested_mode == e1000_fc_full) {
+                               hw->fc.current_mode = e1000_fc_full;
+                               e_dbg("Flow Control = FULL.\r\n");
                        } else {
-                               hw->fc.type = e1000_fc_rx_pause;
-                               hw_dbg(hw, "Flow Control = "
+                               hw->fc.current_mode = e1000_fc_rx_pause;
+                               e_dbg("Flow Control = "
                                         "RX PAUSE frames only.\r\n");
                        }
                }
@@ -1118,14 +1189,13 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
                 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
                 *-------|---------|-------|---------|--------------------
                 *   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)) {
-                       hw->fc.type = e1000_fc_tx_pause;
-                       hw_dbg(hw, "Flow Control = Tx PAUSE frames only.\r\n");
+                       hw->fc.current_mode = e1000_fc_tx_pause;
+                       e_dbg("Flow Control = Tx PAUSE frames only.\r\n");
                }
                /*
                 * For transmitting PAUSE frames ONLY.
@@ -1134,21 +1204,20 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
                 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
                 *-------|---------|-------|---------|--------------------
                 *   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)) {
-                       hw->fc.type = e1000_fc_rx_pause;
-                       hw_dbg(hw, "Flow Control = Rx PAUSE frames only.\r\n");
+                       hw->fc.current_mode = e1000_fc_rx_pause;
+                       e_dbg("Flow Control = Rx PAUSE frames only.\r\n");
                } else {
                        /*
                         * Per the IEEE spec, at this point flow control
                         * should be disabled.
                         */
-                       hw->fc.type = e1000_fc_none;
-                       hw_dbg(hw, "Flow Control = NONE.\r\n");
+                       hw->fc.current_mode = e1000_fc_none;
+                       e_dbg("Flow Control = NONE.\r\n");
                }
 
                /*
@@ -1158,12 +1227,12 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
                 */
                ret_val = mac->ops.get_link_up_info(hw, &speed, &duplex);
                if (ret_val) {
-                       hw_dbg(hw, "Error getting link speed and duplex\n");
+                       e_dbg("Error getting link speed and duplex\n");
                        return ret_val;
                }
 
                if (duplex == HALF_DUPLEX)
-                       hw->fc.type = e1000_fc_none;
+                       hw->fc.current_mode = e1000_fc_none;
 
                /*
                 * Now we call a subroutine to actually force the MAC
@@ -1171,7 +1240,7 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
                 */
                ret_val = e1000e_force_mac_fc(hw);
                if (ret_val) {
-                       hw_dbg(hw, "Error forcing flow control settings\n");
+                       e_dbg("Error forcing flow control settings\n");
                        return ret_val;
                }
        }
@@ -1193,24 +1262,21 @@ s32 e1000e_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed, u16 *dup
        u32 status;
 
        status = er32(STATUS);
-       if (status & E1000_STATUS_SPEED_1000) {
+       if (status & E1000_STATUS_SPEED_1000)
                *speed = SPEED_1000;
-               hw_dbg(hw, "1000 Mbs, ");
-       } else if (status & E1000_STATUS_SPEED_100) {
+       else if (status & E1000_STATUS_SPEED_100)
                *speed = SPEED_100;
-               hw_dbg(hw, "100 Mbs, ");
-       } else {
+       else
                *speed = SPEED_10;
-               hw_dbg(hw, "10 Mbs, ");
-       }
 
-       if (status & E1000_STATUS_FD) {
+       if (status & E1000_STATUS_FD)
                *duplex = FULL_DUPLEX;
-               hw_dbg(hw, "Full Duplex\n");
-       } else {
+       else
                *duplex = HALF_DUPLEX;
-               hw_dbg(hw, "Half Duplex\n");
-       }
+
+       e_dbg("%u Mbps, %s Duplex\n",
+             *speed == SPEED_1000 ? 1000 : *speed == SPEED_100 ? 100 : 10,
+             *duplex == FULL_DUPLEX ? "Full" : "Half");
 
        return 0;
 }
@@ -1255,7 +1321,7 @@ s32 e1000e_get_hw_semaphore(struct e1000_hw *hw)
        }
 
        if (i == timeout) {
-               hw_dbg(hw, "Driver can't access device - SMBI bit is set.\n");
+               e_dbg("Driver can't access device - SMBI bit is set.\n");
                return -E1000_ERR_NVM;
        }
 
@@ -1274,7 +1340,7 @@ s32 e1000e_get_hw_semaphore(struct e1000_hw *hw)
        if (i == timeout) {
                /* Release semaphores */
                e1000e_put_hw_semaphore(hw);
-               hw_dbg(hw, "Driver can't access the NVM\n");
+               e_dbg("Driver can't access the NVM\n");
                return -E1000_ERR_NVM;
        }
 
@@ -1314,7 +1380,7 @@ s32 e1000e_get_auto_rd_done(struct e1000_hw *hw)
        }
 
        if (i == AUTO_READ_DONE_TIMEOUT) {
-               hw_dbg(hw, "Auto read by HW from NVM has not completed.\n");
+               e_dbg("Auto read by HW from NVM has not completed.\n");
                return -E1000_ERR_RESET;
        }
 
@@ -1335,7 +1401,7 @@ s32 e1000e_valid_led_default(struct e1000_hw *hw, u16 *data)
 
        ret_val = e1000_read_nvm(hw, NVM_ID_LED_SETTINGS, 1, data);
        if (ret_val) {
-               hw_dbg(hw, "NVM Read Error\n");
+               e_dbg("NVM Read Error\n");
                return ret_val;
        }
 
@@ -1410,6 +1476,38 @@ s32 e1000e_id_led_init(struct e1000_hw *hw)
 }
 
 /**
+ *  e1000e_setup_led_generic - Configures SW controllable LED
+ *  @hw: pointer to the HW structure
+ *
+ *  This prepares the SW controllable LED for use and saves the current state
+ *  of the LED so it can be later restored.
+ **/
+s32 e1000e_setup_led_generic(struct e1000_hw *hw)
+{
+       u32 ledctl;
+
+       if (hw->mac.ops.setup_led != e1000e_setup_led_generic) {
+               return -E1000_ERR_CONFIG;
+       }
+
+       if (hw->phy.media_type == e1000_media_type_fiber) {
+               ledctl = er32(LEDCTL);
+               hw->mac.ledctl_default = ledctl;
+               /* Turn off LED0 */
+               ledctl &= ~(E1000_LEDCTL_LED0_IVRT |
+                           E1000_LEDCTL_LED0_BLINK |
+                           E1000_LEDCTL_LED0_MODE_MASK);
+               ledctl |= (E1000_LEDCTL_MODE_LED_OFF <<
+                          E1000_LEDCTL_LED0_MODE_SHIFT);
+               ew32(LEDCTL, ledctl);
+       } else if (hw->phy.media_type == e1000_media_type_copper) {
+               ew32(LEDCTL, hw->mac.ledctl_mode1);
+       }
+
+       return 0;
+}
+
+/**
  *  e1000e_cleanup_led_generic - Set LED config to default operation
  *  @hw: pointer to the HW structure
  *
@@ -1557,7 +1655,7 @@ s32 e1000e_disable_pcie_master(struct e1000_hw *hw)
        }
 
        if (!timeout) {
-               hw_dbg(hw, "Master requests are pending.\n");
+               e_dbg("Master requests are pending.\n");
                return -E1000_ERR_MASTER_REQUESTS_PENDING;
        }
 
@@ -1574,14 +1672,21 @@ void e1000e_reset_adaptive(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
 
+       if (!mac->adaptive_ifs) {
+               e_dbg("Not in Adaptive IFS mode!\n");
+               goto out;
+       }
+
        mac->current_ifs_val = 0;
        mac->ifs_min_val = IFS_MIN;
        mac->ifs_max_val = IFS_MAX;
        mac->ifs_step_size = IFS_STEP;
        mac->ifs_ratio = IFS_RATIO;
 
-       mac->in_ifs_mode = 0;
+       mac->in_ifs_mode = false;
        ew32(AIT, 0);
+out:
+       return;
 }
 
 /**
@@ -1595,9 +1700,14 @@ void e1000e_update_adaptive(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
 
+       if (!mac->adaptive_ifs) {
+               e_dbg("Not in Adaptive IFS mode!\n");
+               goto out;
+       }
+
        if ((mac->collision_delta * mac->ifs_ratio) > mac->tx_packet_delta) {
                if (mac->tx_packet_delta > MIN_NUM_XMITS) {
-                       mac->in_ifs_mode = 1;
+                       mac->in_ifs_mode = true;
                        if (mac->current_ifs_val < mac->ifs_max_val) {
                                if (!mac->current_ifs_val)
                                        mac->current_ifs_val = mac->ifs_min_val;
@@ -1611,10 +1721,12 @@ void e1000e_update_adaptive(struct e1000_hw *hw)
                if (mac->in_ifs_mode &&
                    (mac->tx_packet_delta <= MIN_NUM_XMITS)) {
                        mac->current_ifs_val = 0;
-                       mac->in_ifs_mode = 0;
+                       mac->in_ifs_mode = false;
                        ew32(AIT, 0);
                }
        }
+out:
+       return;
 }
 
 /**
@@ -1781,7 +1893,7 @@ s32 e1000e_acquire_nvm(struct e1000_hw *hw)
        if (!timeout) {
                eecd &= ~E1000_EECD_REQ;
                ew32(EECD, eecd);
-               hw_dbg(hw, "Could not acquire NVM grant\n");
+               e_dbg("Could not acquire NVM grant\n");
                return -E1000_ERR_NVM;
        }
 
@@ -1886,7 +1998,7 @@ static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw)
                }
 
                if (!timeout) {
-                       hw_dbg(hw, "SPI NVM Status error\n");
+                       e_dbg("SPI NVM Status error\n");
                        return -E1000_ERR_NVM;
                }
        }
@@ -1915,7 +2027,7 @@ s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
         */
        if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
            (words == 0)) {
-               hw_dbg(hw, "nvm parameter(s) out of bounds\n");
+               e_dbg("nvm parameter(s) out of bounds\n");
                return -E1000_ERR_NVM;
        }
 
@@ -1958,11 +2070,11 @@ s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
         */
        if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
            (words == 0)) {
-               hw_dbg(hw, "nvm parameter(s) out of bounds\n");
+               e_dbg("nvm parameter(s) out of bounds\n");
                return -E1000_ERR_NVM;
        }
 
-       ret_val = nvm->ops.acquire_nvm(hw);
+       ret_val = nvm->ops.acquire(hw);
        if (ret_val)
                return ret_val;
 
@@ -1973,7 +2085,7 @@ s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
 
                ret_val = e1000_ready_nvm_eeprom(hw);
                if (ret_val) {
-                       nvm->ops.release_nvm(hw);
+                       nvm->ops.release(hw);
                        return ret_val;
                }
 
@@ -2012,71 +2124,32 @@ s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
        }
 
        msleep(10);
+       nvm->ops.release(hw);
        return 0;
 }
 
 /**
- *  e1000e_read_mac_addr - Read device MAC address
+ *  e1000_read_mac_addr_generic - 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.
  **/
-s32 e1000e_read_mac_addr(struct e1000_hw *hw)
+s32 e1000_read_mac_addr_generic(struct e1000_hw *hw)
 {
-       s32 ret_val;
-       u16 offset, nvm_data, i;
-       u16 mac_addr_offset = 0;
-
-       if (hw->mac.type == e1000_82571) {
-               /* Check for an alternate MAC address.  An alternate MAC
-                * address can be setup by pre-boot software and must be
-                * treated like a permanent address and must override the
-                * actual permanent MAC address.*/
-               ret_val = e1000_read_nvm(hw, NVM_ALT_MAC_ADDR_PTR, 1,
-                                        &mac_addr_offset);
-               if (ret_val) {
-                       hw_dbg(hw, "NVM Read Error\n");
-                       return ret_val;
-               }
-               if (mac_addr_offset == 0xFFFF)
-                       mac_addr_offset = 0;
-
-               if (mac_addr_offset) {
-                       if (hw->bus.func == E1000_FUNC_1)
-                               mac_addr_offset += ETH_ALEN/sizeof(u16);
-
-                       /* make sure we have a valid mac address here
-                       * before using it */
-                       ret_val = e1000_read_nvm(hw, mac_addr_offset, 1,
-                                                &nvm_data);
-                       if (ret_val) {
-                               hw_dbg(hw, "NVM Read Error\n");
-                               return ret_val;
-                       }
-                       if (nvm_data & 0x0001)
-                               mac_addr_offset = 0;
-               }
+       u32 rar_high;
+       u32 rar_low;
+       u16 i;
 
-               if (mac_addr_offset)
-               hw->dev_spec.e82571.alt_mac_addr_is_present = 1;
-       }
+       rar_high = er32(RAH(0));
+       rar_low = er32(RAL(0));
 
-       for (i = 0; i < ETH_ALEN; i += 2) {
-               offset = mac_addr_offset + (i >> 1);
-               ret_val = e1000_read_nvm(hw, offset, 1, &nvm_data);
-               if (ret_val) {
-                       hw_dbg(hw, "NVM Read Error\n");
-                       return ret_val;
-               }
-               hw->mac.perm_addr[i] = (u8)(nvm_data & 0xFF);
-               hw->mac.perm_addr[i+1] = (u8)(nvm_data >> 8);
-       }
+       for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++)
+               hw->mac.perm_addr[i] = (u8)(rar_low >> (i*8));
 
-       /* Flip last bit of mac address if we're on second port */
-       if (!mac_addr_offset && hw->bus.func == E1000_FUNC_1)
-               hw->mac.perm_addr[5] ^= 1;
+       for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++)
+               hw->mac.perm_addr[i+4] = (u8)(rar_high >> (i*8));
 
        for (i = 0; i < ETH_ALEN; i++)
                hw->mac.addr[i] = hw->mac.perm_addr[i];
@@ -2100,14 +2173,14 @@ s32 e1000e_validate_nvm_checksum_generic(struct e1000_hw *hw)
        for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) {
                ret_val = e1000_read_nvm(hw, i, 1, &nvm_data);
                if (ret_val) {
-                       hw_dbg(hw, "NVM Read Error\n");
+                       e_dbg("NVM Read Error\n");
                        return ret_val;
                }
                checksum += nvm_data;
        }
 
        if (checksum != (u16) NVM_SUM) {
-               hw_dbg(hw, "NVM Checksum Invalid\n");
+               e_dbg("NVM Checksum Invalid\n");
                return -E1000_ERR_NVM;
        }
 
@@ -2131,7 +2204,7 @@ s32 e1000e_update_nvm_checksum_generic(struct e1000_hw *hw)
        for (i = 0; i < NVM_CHECKSUM_REG; i++) {
                ret_val = e1000_read_nvm(hw, i, 1, &nvm_data);
                if (ret_val) {
-                       hw_dbg(hw, "NVM Read Error while updating checksum.\n");
+                       e_dbg("NVM Read Error while updating checksum.\n");
                        return ret_val;
                }
                checksum += nvm_data;
@@ -2139,7 +2212,7 @@ s32 e1000e_update_nvm_checksum_generic(struct e1000_hw *hw)
        checksum = (u16) NVM_SUM - checksum;
        ret_val = e1000_write_nvm(hw, NVM_CHECKSUM_REG, 1, &checksum);
        if (ret_val)
-               hw_dbg(hw, "NVM Write Error while updating checksum.\n");
+               e_dbg("NVM Write Error while updating checksum.\n");
 
        return ret_val;
 }
@@ -2199,10 +2272,15 @@ static s32 e1000_mng_enable_host_if(struct e1000_hw *hw)
        u32 hicr;
        u8 i;
 
+       if (!(hw->mac.arc_subsystem_valid)) {
+               e_dbg("ARC subsystem not valid.\n");
+               return -E1000_ERR_HOST_INTERFACE_COMMAND;
+       }
+
        /* Check that the host interface is enabled. */
        hicr = er32(HICR);
        if ((hicr & E1000_HICR_EN) == 0) {
-               hw_dbg(hw, "E1000_HOST_EN bit disabled.\n");
+               e_dbg("E1000_HOST_EN bit disabled.\n");
                return -E1000_ERR_HOST_INTERFACE_COMMAND;
        }
        /* check the previous command is completed */
@@ -2214,7 +2292,7 @@ static s32 e1000_mng_enable_host_if(struct e1000_hw *hw)
        }
 
        if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
-               hw_dbg(hw, "Previous command timeout failed .\n");
+               e_dbg("Previous command timeout failed .\n");
                return -E1000_ERR_HOST_INTERFACE_COMMAND;
        }
 
@@ -2222,17 +2300,18 @@ static s32 e1000_mng_enable_host_if(struct e1000_hw *hw)
 }
 
 /**
- *  e1000e_check_mng_mode - check management mode
+ *  e1000e_check_mng_mode_generic - check management mode
  *  @hw: pointer to the HW structure
  *
  *  Reads the firmware semaphore register and returns true (>0) if
  *  manageability is enabled, else false (0).
  **/
-bool e1000e_check_mng_mode(struct e1000_hw *hw)
+bool e1000e_check_mng_mode_generic(struct e1000_hw *hw)
 {
        u32 fwsm = er32(FWSM);
 
-       return (fwsm & E1000_FWSM_MODE_MASK) == hw->mac.ops.mng_mode_enab;
+       return (fwsm & E1000_FWSM_MODE_MASK) ==
+               (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT);
 }
 
 /**
@@ -2250,10 +2329,12 @@ bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw)
        s32 ret_val, hdr_csum, csum;
        u8 i, len;
 
+       hw->mac.tx_pkt_filtering = true;
+
        /* No manageability, no filtering */
        if (!e1000e_check_mng_mode(hw)) {
-               hw->mac.tx_pkt_filtering = 0;
-               return 0;
+               hw->mac.tx_pkt_filtering = false;
+               goto out;
        }
 
        /*
@@ -2261,9 +2342,9 @@ bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw)
         * reason, disable filtering.
         */
        ret_val = e1000_mng_enable_host_if(hw);
-       if (ret_val != 0) {
-               hw->mac.tx_pkt_filtering = 0;
-               return ret_val;
+       if (ret_val) {
+               hw->mac.tx_pkt_filtering = false;
+               goto out;
        }
 
        /* Read in the header.  Length and offset are in dwords. */
@@ -2281,18 +2362,18 @@ bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw)
         * take the safe route of assuming Tx filtering is enabled.
         */
        if ((hdr_csum != csum) || (hdr->signature != E1000_IAMT_SIGNATURE)) {
-               hw->mac.tx_pkt_filtering = 1;
-               return 1;
+               hw->mac.tx_pkt_filtering = true;
+               goto out;
        }
 
        /* Cookie area is valid, make the final check for filtering. */
        if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING)) {
-               hw->mac.tx_pkt_filtering = 0;
-               return 0;
+               hw->mac.tx_pkt_filtering = false;
+               goto out;
        }
 
-       hw->mac.tx_pkt_filtering = 1;
-       return 1;
+out:
+       return hw->mac.tx_pkt_filtering;
 }
 
 /**
@@ -2323,7 +2404,7 @@ static s32 e1000_mng_write_cmd_header(struct e1000_hw *hw,
 }
 
 /**
- *  e1000_mng_host_if_write - Writes to the manageability host interface
+ *  e1000_mng_host_if_write - Write to the manageability host interface
  *  @hw: pointer to the HW structure
  *  @buffer: pointer to the host interface buffer
  *  @length: size of the buffer
@@ -2439,41 +2520,53 @@ s32 e1000e_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length)
 }
 
 /**
- *  e1000e_enable_mng_pass_thru - Enable processing of ARP's
+ *  e1000e_enable_mng_pass_thru - Check if management passthrough is needed
  *  @hw: pointer to the HW structure
  *
- *  Verifies the hardware needs to allow ARPs to be processed by the host.
+ *  Verifies the hardware needs to leave interface enabled so that frames can
+ *  be directed to and from the management interface.
  **/
 bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw)
 {
        u32 manc;
        u32 fwsm, factps;
-       bool ret_val = 0;
+       bool ret_val = false;
 
        manc = er32(MANC);
 
-       if (!(manc & E1000_MANC_RCV_TCO_EN) ||
-           !(manc & E1000_MANC_EN_MAC_ADDR_FILTER))
-               return ret_val;
+       if (!(manc & E1000_MANC_RCV_TCO_EN))
+               goto out;
 
-       if (hw->mac.arc_subsystem_valid) {
+       if (hw->mac.has_fwsm) {
                fwsm = er32(FWSM);
                factps = er32(FACTPS);
 
                if (!(factps & E1000_FACTPS_MNGCG) &&
                    ((fwsm & E1000_FWSM_MODE_MASK) ==
                     (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) {
-                       ret_val = 1;
-                       return ret_val;
+                       ret_val = true;
+                       goto out;
                }
-       } else {
-               if ((manc & E1000_MANC_SMBUS_EN) &&
-                   !(manc & E1000_MANC_ASF_EN)) {
-                       ret_val = 1;
-                       return ret_val;
+       } else if ((hw->mac.type == e1000_82574) ||
+                  (hw->mac.type == e1000_82583)) {
+               u16 data;
+
+               factps = er32(FACTPS);
+               e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data);
+
+               if (!(factps & E1000_FACTPS_MNGCG) &&
+                   ((data & E1000_NVM_INIT_CTRL2_MNGM) ==
+                    (e1000_mng_mode_pt << 13))) {
+                       ret_val = true;
+                       goto out;
                }
+       } else if ((manc & E1000_MANC_SMBUS_EN) &&
+                   !(manc & E1000_MANC_ASF_EN)) {
+                       ret_val = true;
+                       goto out;
        }
 
+out:
        return ret_val;
 }
 
@@ -2484,14 +2577,14 @@ s32 e1000e_read_pba_num(struct e1000_hw *hw, u32 *pba_num)
 
        ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
        if (ret_val) {
-               hw_dbg(hw, "NVM Read Error\n");
+               e_dbg("NVM Read Error\n");
                return ret_val;
        }
        *pba_num = (u32)(nvm_data << 16);
 
        ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_1, 1, &nvm_data);
        if (ret_val) {
-               hw_dbg(hw, "NVM Read Error\n");
+               e_dbg("NVM Read Error\n");
                return ret_val;
        }
        *pba_num |= nvm_data;