Print this page
XXXX Intel X540 support
        
@@ -1,8 +1,8 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2010, Intel Corporation 
+  Copyright (c) 2001-2012, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
   modification, are permitted provided that the following conditions are met:
   
@@ -28,11 +28,11 @@
   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE.
 
 ******************************************************************************/
-/*$FreeBSD$*/
+/*$FreeBSD: src/sys/dev/ixgbe/ixgbe_common.c,v 1.14 2012/07/05 20:51:44 jfv Exp $*/
 
 #include "ixgbe_common.h"
 #include "ixgbe_phy.h"
 #include "ixgbe_api.h"
 
@@ -49,19 +49,17 @@
 static void ixgbe_release_eeprom(struct ixgbe_hw *hw);
 
 static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr);
 static s32 ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw,
                                         u16 *san_mac_offset);
-static s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw);
-static s32 ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw);
-static s32 ixgbe_fc_autoneg_copper(struct ixgbe_hw *hw);
-static s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw);
-static s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
-                              u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm);
+static s32 ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset,
+                                             u16 words, u16 *data);
+static s32 ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset,
+                                              u16 words, u16 *data);
+static s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw,
+                                                 u16 offset);
 
-s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan);
-
 /**
  *  ixgbe_init_ops_generic - Inits function ptrs
  *  @hw: pointer to the hardware structure
  *
  *  Initialize the function pointers.
@@ -75,15 +73,20 @@
         DEBUGFUNC("ixgbe_init_ops_generic");
 
         /* EEPROM */
         eeprom->ops.init_params = &ixgbe_init_eeprom_params_generic;
         /* If EEPROM is valid (bit 8 = 1), use EERD otherwise use bit bang */
-        if (eec & (1 << 8))
+        if (eec & IXGBE_EEC_PRES) {
                 eeprom->ops.read = &ixgbe_read_eerd_generic;
-        else
+                eeprom->ops.read_buffer = &ixgbe_read_eerd_buffer_generic;
+        } else {
                 eeprom->ops.read = &ixgbe_read_eeprom_bit_bang_generic;
+                eeprom->ops.read_buffer =
+                                 &ixgbe_read_eeprom_buffer_bit_bang_generic;
+        }
         eeprom->ops.write = &ixgbe_write_eeprom_generic;
+        eeprom->ops.write_buffer = &ixgbe_write_eeprom_buffer_bit_bang_generic;
         eeprom->ops.validate_checksum =
                                       &ixgbe_validate_eeprom_checksum_generic;
         eeprom->ops.update_checksum = &ixgbe_update_eeprom_checksum_generic;
         eeprom->ops.calc_checksum = &ixgbe_calc_eeprom_checksum_generic;
 
@@ -119,10 +122,11 @@
         mac->ops.update_mc_addr_list = &ixgbe_update_mc_addr_list_generic;
         mac->ops.enable_mc = &ixgbe_enable_mc_generic;
         mac->ops.disable_mc = &ixgbe_disable_mc_generic;
         mac->ops.clear_vfta = NULL;
         mac->ops.set_vfta = NULL;
+        mac->ops.set_vlvf = NULL;
         mac->ops.init_uta_tables = NULL;
 
         /* Flow Control */
         mac->ops.fc_enable = &ixgbe_fc_enable_generic;
 
@@ -133,10 +137,180 @@
 
         return IXGBE_SUCCESS;
 }
 
 /**
+ *  ixgbe_device_supports_autoneg_fc - Check if phy supports autoneg flow
+ *  control
+ *  @hw: pointer to hardware structure
+ *
+ *  There are several phys that do not support autoneg flow control. This
+ *  function check the device id to see if the associated phy supports
+ *  autoneg flow control.
+ **/
+static s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
+{
+
+        DEBUGFUNC("ixgbe_device_supports_autoneg_fc");
+
+        switch (hw->device_id) {
+        case IXGBE_DEV_ID_X540T:
+        case IXGBE_DEV_ID_X540T1:
+                return IXGBE_SUCCESS;
+        case IXGBE_DEV_ID_82599_T3_LOM:
+                return IXGBE_SUCCESS;
+        default:
+                return IXGBE_ERR_FC_NOT_SUPPORTED;
+        }
+}
+
+/**
+ *  ixgbe_setup_fc - Set up flow control
+ *  @hw: pointer to hardware structure
+ *
+ *  Called at init time to set up flow control.
+ **/
+static s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
+{
+        s32 ret_val = IXGBE_SUCCESS;
+        u32 reg = 0, reg_bp = 0;
+        u16 reg_cu = 0;
+
+        DEBUGFUNC("ixgbe_setup_fc");
+
+        /*
+         * Validate the requested mode.  Strict IEEE mode does not allow
+         * ixgbe_fc_rx_pause because it will cause us to fail at UNH.
+         */
+        if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
+                DEBUGOUT("ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
+                ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
+                goto out;
+        }
+
+        /*
+         * 10gig parts do not have a word in the EEPROM to determine the
+         * default flow control setting, so we explicitly set it to full.
+         */
+        if (hw->fc.requested_mode == ixgbe_fc_default)
+                hw->fc.requested_mode = ixgbe_fc_full;
+
+        /*
+         * Set up the 1G and 10G flow control advertisement registers so the
+         * HW will be able to do fc autoneg once the cable is plugged in.  If
+         * we link at 10G, the 1G advertisement is harmless and vice versa.
+         */
+        switch (hw->phy.media_type) {
+        case ixgbe_media_type_fiber:
+        case ixgbe_media_type_backplane:
+                reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
+                reg_bp = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+                break;
+        case ixgbe_media_type_copper:
+                hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT,
+                                     IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®_cu);
+                break;
+        default:
+                break;
+        }
+
+        /*
+         * The possible values of fc.requested_mode 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.
+         * other: Invalid.
+         */
+        switch (hw->fc.requested_mode) {
+        case ixgbe_fc_none:
+                /* Flow control completely disabled by software override. */
+                reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
+                if (hw->phy.media_type == ixgbe_media_type_backplane)
+                        reg_bp &= ~(IXGBE_AUTOC_SYM_PAUSE |
+                                    IXGBE_AUTOC_ASM_PAUSE);
+                else if (hw->phy.media_type == ixgbe_media_type_copper)
+                        reg_cu &= ~(IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE);
+                break;
+        case ixgbe_fc_tx_pause:
+                /*
+                 * Tx Flow control is enabled, and Rx Flow control is
+                 * disabled by software override.
+                 */
+                reg |= IXGBE_PCS1GANA_ASM_PAUSE;
+                reg &= ~IXGBE_PCS1GANA_SYM_PAUSE;
+                if (hw->phy.media_type == ixgbe_media_type_backplane) {
+                        reg_bp |= IXGBE_AUTOC_ASM_PAUSE;
+                        reg_bp &= ~IXGBE_AUTOC_SYM_PAUSE;
+                } else if (hw->phy.media_type == ixgbe_media_type_copper) {
+                        reg_cu |= IXGBE_TAF_ASM_PAUSE;
+                        reg_cu &= ~IXGBE_TAF_SYM_PAUSE;
+                }
+                break;
+        case ixgbe_fc_rx_pause:
+                /*
+                 * Rx Flow control is enabled and Tx Flow control is
+                 * disabled by software override. 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, as such we fall
+                 * through to the fc_full statement.  Later, we will
+                 * disable the adapter's ability to send PAUSE frames.
+                 */
+        case ixgbe_fc_full:
+                /* Flow control (both Rx and Tx) is enabled by SW override. */
+                reg |= IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE;
+                if (hw->phy.media_type == ixgbe_media_type_backplane)
+                        reg_bp |= IXGBE_AUTOC_SYM_PAUSE |
+                                  IXGBE_AUTOC_ASM_PAUSE;
+                else if (hw->phy.media_type == ixgbe_media_type_copper)
+                        reg_cu |= IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE;
+                break;
+        default:
+                DEBUGOUT("Flow control param set incorrectly\n");
+                ret_val = IXGBE_ERR_CONFIG;
+                goto out;
+        }
+
+        if (hw->mac.type != ixgbe_mac_X540) {
+                /*
+                 * Enable auto-negotiation between the MAC & PHY;
+                 * the MAC will advertise clause 37 flow control.
+                 */
+                IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg);
+                reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL);
+
+                /* Disable AN timeout */
+                if (hw->fc.strict_ieee)
+                        reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN;
+
+                IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg);
+                DEBUGOUT1("Set up FC; PCS1GLCTL = 0x%08X\n", reg);
+        }
+
+        /*
+         * AUTOC restart handles negotiation of 1G and 10G on backplane
+         * and copper. There is no need to set the PCS1GCTL register.
+         *
+         */
+        if (hw->phy.media_type == ixgbe_media_type_backplane) {
+                reg_bp |= IXGBE_AUTOC_AN_RESTART;
+                IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_bp);
+        } else if ((hw->phy.media_type == ixgbe_media_type_copper) &&
+                    (ixgbe_device_supports_autoneg_fc(hw) == IXGBE_SUCCESS)) {
+                hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT,
+                                      IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg_cu);
+        }
+
+        DEBUGOUT1("Set up FC; IXGBE_AUTOC = 0x%08X\n", reg);
+out:
+        return ret_val;
+}
+
+/**
  *  ixgbe_start_hw_generic - Prepare hardware for Tx/Rx
  *  @hw: pointer to hardware structure
  *
  *  Starts the hardware by filling the bus info structure and media type, clears
  *  all on chip counters, initializes receive address registers, multicast
@@ -143,10 +317,11 @@
  *  table, VLAN filter table, calls routine to set up link and flow control
  *  settings, and leaves transmit and receive units disabled and uninitialized
  **/
 s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw)
 {
+        s32 ret_val;
         u32 ctrl_ext;
 
         DEBUGFUNC("ixgbe_start_hw_generic");
 
         /* Set the media type */
@@ -165,16 +340,19 @@
         ctrl_ext |= IXGBE_CTRL_EXT_NS_DIS;
         IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
         IXGBE_WRITE_FLUSH(hw);
 
         /* Setup flow control */
-        (void) ixgbe_setup_fc(hw, 0);
+        ret_val = ixgbe_setup_fc(hw);
+        if (ret_val != IXGBE_SUCCESS)
+                goto out;
 
         /* Clear adapter stopped flag */
         hw->adapter_stopped = FALSE;
 
-        return IXGBE_SUCCESS;
+out:
+        return ret_val;
 }
 
 /**
  *  ixgbe_start_hw_gen2 - Init sequence for common device family
  *  @hw: pointer to hw structure
@@ -198,18 +376,18 @@
         IXGBE_WRITE_FLUSH(hw);
 
         /* Disable relaxed ordering */
         for (i = 0; i < hw->mac.max_tx_queues; i++) {
                 regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i));
-                regval &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN;
+                regval &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN;
                 IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), regval);
         }
 
         for (i = 0; i < hw->mac.max_rx_queues; i++) {
                 regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i));
-                regval &= ~(IXGBE_DCA_RXCTRL_DESC_WRO_EN |
-                                        IXGBE_DCA_RXCTRL_DESC_HSRO_EN);
+                regval &= ~(IXGBE_DCA_RXCTRL_DATA_WRO_EN |
+                            IXGBE_DCA_RXCTRL_HEAD_WRO_EN);
                 IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval);
         }
 
         return IXGBE_SUCCESS;
 }
@@ -252,94 +430,108 @@
 {
         u16 i = 0;
 
         DEBUGFUNC("ixgbe_clear_hw_cntrs_generic");
 
-        (void) IXGBE_READ_REG(hw, IXGBE_CRCERRS);
-        (void) IXGBE_READ_REG(hw, IXGBE_ILLERRC);
-        (void) IXGBE_READ_REG(hw, IXGBE_ERRBC);
-        (void) IXGBE_READ_REG(hw, IXGBE_MSPDC);
+        IXGBE_READ_REG(hw, IXGBE_CRCERRS);
+        IXGBE_READ_REG(hw, IXGBE_ILLERRC);
+        IXGBE_READ_REG(hw, IXGBE_ERRBC);
+        IXGBE_READ_REG(hw, IXGBE_MSPDC);
         for (i = 0; i < 8; i++)
-                (void) IXGBE_READ_REG(hw, IXGBE_MPC(i));
+                IXGBE_READ_REG(hw, IXGBE_MPC(i));
 
-        (void) IXGBE_READ_REG(hw, IXGBE_MLFC);
-        (void) IXGBE_READ_REG(hw, IXGBE_MRFC);
-        (void) IXGBE_READ_REG(hw, IXGBE_RLEC);
-        (void) IXGBE_READ_REG(hw, IXGBE_LXONTXC);
-        (void) IXGBE_READ_REG(hw, IXGBE_LXOFFTXC);
+        IXGBE_READ_REG(hw, IXGBE_MLFC);
+        IXGBE_READ_REG(hw, IXGBE_MRFC);
+        IXGBE_READ_REG(hw, IXGBE_RLEC);
+        IXGBE_READ_REG(hw, IXGBE_LXONTXC);
+        IXGBE_READ_REG(hw, IXGBE_LXOFFTXC);
         if (hw->mac.type >= ixgbe_mac_82599EB) {
-                (void) IXGBE_READ_REG(hw, IXGBE_LXONRXCNT);
-                (void) IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT);
+                IXGBE_READ_REG(hw, IXGBE_LXONRXCNT);
+                IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT);
         } else {
-                (void) IXGBE_READ_REG(hw, IXGBE_LXONRXC);
-                (void) IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
+                IXGBE_READ_REG(hw, IXGBE_LXONRXC);
+                IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
         }
 
         for (i = 0; i < 8; i++) {
-                (void) IXGBE_READ_REG(hw, IXGBE_PXONTXC(i));
-                (void) IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i));
+                IXGBE_READ_REG(hw, IXGBE_PXONTXC(i));
+                IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i));
                 if (hw->mac.type >= ixgbe_mac_82599EB) {
-                        (void) IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i));
-                        (void) IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i));
+                        IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i));
+                        IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i));
                 } else {
-                        (void) IXGBE_READ_REG(hw, IXGBE_PXONRXC(i));
-                        (void) IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i));
+                        IXGBE_READ_REG(hw, IXGBE_PXONRXC(i));
+                        IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i));
                 }
         }
         if (hw->mac.type >= ixgbe_mac_82599EB)
                 for (i = 0; i < 8; i++)
-                        (void) IXGBE_READ_REG(hw, IXGBE_PXON2OFFCNT(i));
-        (void) IXGBE_READ_REG(hw, IXGBE_PRC64);
-        (void) IXGBE_READ_REG(hw, IXGBE_PRC127);
-        (void) IXGBE_READ_REG(hw, IXGBE_PRC255);
-        (void) IXGBE_READ_REG(hw, IXGBE_PRC511);
-        (void) IXGBE_READ_REG(hw, IXGBE_PRC1023);
-        (void) IXGBE_READ_REG(hw, IXGBE_PRC1522);
-        (void) IXGBE_READ_REG(hw, IXGBE_GPRC);
-        (void) IXGBE_READ_REG(hw, IXGBE_BPRC);
-        (void) IXGBE_READ_REG(hw, IXGBE_MPRC);
-        (void) IXGBE_READ_REG(hw, IXGBE_GPTC);
-        (void) IXGBE_READ_REG(hw, IXGBE_GORCL);
-        (void) IXGBE_READ_REG(hw, IXGBE_GORCH);
-        (void) IXGBE_READ_REG(hw, IXGBE_GOTCL);
-        (void) IXGBE_READ_REG(hw, IXGBE_GOTCH);
+                        IXGBE_READ_REG(hw, IXGBE_PXON2OFFCNT(i));
+        IXGBE_READ_REG(hw, IXGBE_PRC64);
+        IXGBE_READ_REG(hw, IXGBE_PRC127);
+        IXGBE_READ_REG(hw, IXGBE_PRC255);
+        IXGBE_READ_REG(hw, IXGBE_PRC511);
+        IXGBE_READ_REG(hw, IXGBE_PRC1023);
+        IXGBE_READ_REG(hw, IXGBE_PRC1522);
+        IXGBE_READ_REG(hw, IXGBE_GPRC);
+        IXGBE_READ_REG(hw, IXGBE_BPRC);
+        IXGBE_READ_REG(hw, IXGBE_MPRC);
+        IXGBE_READ_REG(hw, IXGBE_GPTC);
+        IXGBE_READ_REG(hw, IXGBE_GORCL);
+        IXGBE_READ_REG(hw, IXGBE_GORCH);
+        IXGBE_READ_REG(hw, IXGBE_GOTCL);
+        IXGBE_READ_REG(hw, IXGBE_GOTCH);
+        if (hw->mac.type == ixgbe_mac_82598EB)
         for (i = 0; i < 8; i++)
-                (void) IXGBE_READ_REG(hw, IXGBE_RNBC(i));
-        (void) IXGBE_READ_REG(hw, IXGBE_RUC);
-        (void) IXGBE_READ_REG(hw, IXGBE_RFC);
-        (void) IXGBE_READ_REG(hw, IXGBE_ROC);
-        (void) IXGBE_READ_REG(hw, IXGBE_RJC);
-        (void) IXGBE_READ_REG(hw, IXGBE_MNGPRC);
-        (void) IXGBE_READ_REG(hw, IXGBE_MNGPDC);
-        (void) IXGBE_READ_REG(hw, IXGBE_MNGPTC);
-        (void) IXGBE_READ_REG(hw, IXGBE_TORL);
-        (void) IXGBE_READ_REG(hw, IXGBE_TORH);
-        (void) IXGBE_READ_REG(hw, IXGBE_TPR);
-        (void) IXGBE_READ_REG(hw, IXGBE_TPT);
-        (void) IXGBE_READ_REG(hw, IXGBE_PTC64);
-        (void) IXGBE_READ_REG(hw, IXGBE_PTC127);
-        (void) IXGBE_READ_REG(hw, IXGBE_PTC255);
-        (void) IXGBE_READ_REG(hw, IXGBE_PTC511);
-        (void) IXGBE_READ_REG(hw, IXGBE_PTC1023);
-        (void) IXGBE_READ_REG(hw, IXGBE_PTC1522);
-        (void) IXGBE_READ_REG(hw, IXGBE_MPTC);
-        (void) IXGBE_READ_REG(hw, IXGBE_BPTC);
+                        IXGBE_READ_REG(hw, IXGBE_RNBC(i));
+        IXGBE_READ_REG(hw, IXGBE_RUC);
+        IXGBE_READ_REG(hw, IXGBE_RFC);
+        IXGBE_READ_REG(hw, IXGBE_ROC);
+        IXGBE_READ_REG(hw, IXGBE_RJC);
+        IXGBE_READ_REG(hw, IXGBE_MNGPRC);
+        IXGBE_READ_REG(hw, IXGBE_MNGPDC);
+        IXGBE_READ_REG(hw, IXGBE_MNGPTC);
+        IXGBE_READ_REG(hw, IXGBE_TORL);
+        IXGBE_READ_REG(hw, IXGBE_TORH);
+        IXGBE_READ_REG(hw, IXGBE_TPR);
+        IXGBE_READ_REG(hw, IXGBE_TPT);
+        IXGBE_READ_REG(hw, IXGBE_PTC64);
+        IXGBE_READ_REG(hw, IXGBE_PTC127);
+        IXGBE_READ_REG(hw, IXGBE_PTC255);
+        IXGBE_READ_REG(hw, IXGBE_PTC511);
+        IXGBE_READ_REG(hw, IXGBE_PTC1023);
+        IXGBE_READ_REG(hw, IXGBE_PTC1522);
+        IXGBE_READ_REG(hw, IXGBE_MPTC);
+        IXGBE_READ_REG(hw, IXGBE_BPTC);
         for (i = 0; i < 16; i++) {
-                (void) IXGBE_READ_REG(hw, IXGBE_QPRC(i));
-                (void) IXGBE_READ_REG(hw, IXGBE_QPTC(i));
+                IXGBE_READ_REG(hw, IXGBE_QPRC(i));
+                IXGBE_READ_REG(hw, IXGBE_QPTC(i));
                 if (hw->mac.type >= ixgbe_mac_82599EB) {
-                        (void) IXGBE_READ_REG(hw, IXGBE_QBRC_L(i));
-                        (void) IXGBE_READ_REG(hw, IXGBE_QBRC_H(i));
-                        (void) IXGBE_READ_REG(hw, IXGBE_QBTC_L(i));
-                        (void) IXGBE_READ_REG(hw, IXGBE_QBTC_H(i));
-                        (void) IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
+                        IXGBE_READ_REG(hw, IXGBE_QBRC_L(i));
+                        IXGBE_READ_REG(hw, IXGBE_QBRC_H(i));
+                        IXGBE_READ_REG(hw, IXGBE_QBTC_L(i));
+                        IXGBE_READ_REG(hw, IXGBE_QBTC_H(i));
+                        IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
                 } else {
-                        (void) IXGBE_READ_REG(hw, IXGBE_QBRC(i));
-                        (void) IXGBE_READ_REG(hw, IXGBE_QBTC(i));
+                        IXGBE_READ_REG(hw, IXGBE_QBRC(i));
+                        IXGBE_READ_REG(hw, IXGBE_QBTC(i));
                 }
         }
 
+        if (hw->mac.type == ixgbe_mac_X540) {
+                if (hw->phy.id == 0)
+                        ixgbe_identify_phy(hw);
+                hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECL,
+                                     IXGBE_MDIO_PCS_DEV_TYPE, &i);
+                hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECH,
+                                     IXGBE_MDIO_PCS_DEV_TYPE, &i);
+                hw->phy.ops.read_reg(hw, IXGBE_LDPCECL,
+                                     IXGBE_MDIO_PCS_DEV_TYPE, &i);
+                hw->phy.ops.read_reg(hw, IXGBE_LDPCECH,
+                                     IXGBE_MDIO_PCS_DEV_TYPE, &i);
+        }
+
         return IXGBE_SUCCESS;
 }
 
 /**
  *  ixgbe_read_pba_string_generic - Reads part number string from EEPROM
@@ -451,70 +643,10 @@
 
         return IXGBE_SUCCESS;
 }
 
 /**
- *  ixgbe_read_pba_length_generic - Reads part number length from EEPROM
- *  @hw: pointer to hardware structure
- *  @pba_num_size: part number string buffer length
- *
- *  Reads the part number length from the EEPROM.
- *  Returns expected buffer size in pba_num_size
- **/
-s32 ixgbe_read_pba_length_generic(struct ixgbe_hw *hw, u32 *pba_num_size)
-{
-        s32 ret_val;
-        u16 data;
-        u16 pba_ptr;
-        u16 length;
-
-        DEBUGFUNC("ixgbe_read_pba_length_generic");
-
-        if (pba_num_size == NULL) {
-                DEBUGOUT("PBA buffer size was null\n");
-                return IXGBE_ERR_INVALID_ARGUMENT;
-        }
-
-        ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data);
-        if (ret_val) {
-                DEBUGOUT("NVM Read Error\n");
-                return ret_val;
-        }
-
-        ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM1_PTR, &pba_ptr);
-        if (ret_val) {
-                DEBUGOUT("NVM Read Error\n");
-                return ret_val;
-        }
-
-         /* if data is not ptr guard the PBA must be in legacy format */
-        if (data != IXGBE_PBANUM_PTR_GUARD) {
-                *pba_num_size = 11;
-                return IXGBE_SUCCESS;
-        }
-
-        ret_val = hw->eeprom.ops.read(hw, pba_ptr, &length);
-        if (ret_val) {
-                DEBUGOUT("NVM Read Error\n");
-                return ret_val;
-        }
-
-        if (length == 0xFFFF || length == 0) {
-                DEBUGOUT("NVM PBA number section invalid length\n");
-                return IXGBE_ERR_PBA_SECTION;
-        }
-
-        /*
-         * Convert from length in u16 values to u8 chars, add 1 for NULL,
-         * and subtract 2 because length field is included in length.
-         */
-        *pba_num_size = ((u32)length * 2) - 1;
-
-        return IXGBE_SUCCESS;
-}
-
-/**
  *  ixgbe_read_pba_num_generic - Reads part number from EEPROM
  *  @hw: pointer to hardware structure
  *  @pba_num: stores the part number from the EEPROM
  *
  *  Reads the part number from the EEPROM.
@@ -616,10 +748,13 @@
                 hw->bus.speed = ixgbe_bus_speed_2500;
                 break;
         case IXGBE_PCI_LINK_SPEED_5000:
                 hw->bus.speed = ixgbe_bus_speed_5000;
                 break;
+        case IXGBE_PCI_LINK_SPEED_8000:
+                hw->bus.speed = ixgbe_bus_speed_8000;
+                break;
         default:
                 hw->bus.speed = ixgbe_bus_speed_unknown;
                 break;
         }
 
@@ -661,11 +796,10 @@
  *  the shared code and drivers to determine if the adapter is in a stopped
  *  state and should not touch the hardware.
  **/
 s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw)
 {
-        u32 number_of_queues;
         u32 reg_val;
         u16 i;
 
         DEBUGFUNC("ixgbe_stop_adapter_generic");
 
@@ -674,39 +808,39 @@
          * the hardware
          */
         hw->adapter_stopped = TRUE;
 
         /* Disable the receive unit */
-        reg_val = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
-        reg_val &= ~(IXGBE_RXCTRL_RXEN);
-        IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, reg_val);
-        IXGBE_WRITE_FLUSH(hw);
-        msec_delay(2);
+        IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, 0);
 
-        /* Clear interrupt mask to stop from interrupts being generated */
+        /* Clear interrupt mask to stop interrupts from being generated */
         IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK);
 
-        /* Clear any pending interrupts */
-        (void) IXGBE_READ_REG(hw, IXGBE_EICR);
+        /* Clear any pending interrupts, flush previous writes */
+        IXGBE_READ_REG(hw, IXGBE_EICR);
 
         /* Disable the transmit unit.  Each queue must be disabled. */
-        number_of_queues = hw->mac.max_tx_queues;
-        for (i = 0; i < number_of_queues; i++) {
-                reg_val = IXGBE_READ_REG(hw, IXGBE_TXDCTL(i));
-                if (reg_val & IXGBE_TXDCTL_ENABLE) {
-                        reg_val &= ~IXGBE_TXDCTL_ENABLE;
-                        IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(i), reg_val);
+        for (i = 0; i < hw->mac.max_tx_queues; i++)
+                IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(i), IXGBE_TXDCTL_SWFLSH);
+
+        /* Disable the receive unit by stopping each queue */
+        for (i = 0; i < hw->mac.max_rx_queues; i++) {
+                reg_val = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i));
+                reg_val &= ~IXGBE_RXDCTL_ENABLE;
+                reg_val |= IXGBE_RXDCTL_SWFLSH;
+                IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(i), reg_val);
                 }
-        }
 
+        /* flush all queues disables */
+        IXGBE_WRITE_FLUSH(hw);
+        msec_delay(2);
+
         /*
          * Prevent the PCI-E bus from from hanging by disabling PCI-E master
          * access and verify no pending requests
          */
-        (void) ixgbe_disable_pcie_master(hw);
-
-        return IXGBE_SUCCESS;
+        return ixgbe_disable_pcie_master(hw);
 }
 
 /**
  *  ixgbe_led_on_generic - Turns on the software controllable LEDs.
  *  @hw: pointer to hardware structure
@@ -765,10 +899,12 @@
         if (eeprom->type == ixgbe_eeprom_uninitialized) {
                 eeprom->type = ixgbe_eeprom_none;
                 /* Set default semaphore delay to 10ms which is a well
                  * tested value */
                 eeprom->semaphore_delay = 10;
+                /* Clear EEPROM page size, it will be initialized as needed */
+                eeprom->word_page_size = 0;
 
                 /*
                  * Check for EEPROM present first.
                  * If not present leave as none
                  */
@@ -781,11 +917,11 @@
                          * change if a future EEPROM is not SPI.
                          */
                         eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >>
                                             IXGBE_EEC_SIZE_SHIFT);
                         eeprom->word_size = 1 << (eeprom_size +
-                                             IXGBE_EEPROM_WORD_SIZE_BASE_SHIFT);
+                                             IXGBE_EEPROM_WORD_SIZE_SHIFT);
                 }
 
                 if (eec & IXGBE_EEC_ADDR_SIZE)
                         eeprom->address_bits = 16;
                 else
@@ -797,32 +933,86 @@
 
         return IXGBE_SUCCESS;
 }
 
 /**
- *  ixgbe_write_eeprom_generic - Writes 16 bit value to EEPROM
+ *  ixgbe_write_eeprom_buffer_bit_bang_generic - Write EEPROM using bit-bang
  *  @hw: pointer to hardware structure
- *  @offset: offset within the EEPROM to be written to
- *  @data: 16 bit word to be written to the EEPROM
+ *  @offset: offset within the EEPROM to write
+ *  @words: number of word(s)
+ *  @data: 16 bit word(s) to write to EEPROM
  *
- *  If ixgbe_eeprom_update_checksum is not called after this function, the
- *  EEPROM will most likely contain an invalid checksum.
+ *  Reads 16 bit word(s) from EEPROM through bit-bang method
  **/
-s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data)
+s32 ixgbe_write_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
+                                               u16 words, u16 *data)
 {
-        s32 status;
-        u8 write_opcode = IXGBE_EEPROM_WRITE_OPCODE_SPI;
+        s32 status = IXGBE_SUCCESS;
+        u16 i, count;
 
-        DEBUGFUNC("ixgbe_write_eeprom_generic");
+        DEBUGFUNC("ixgbe_write_eeprom_buffer_bit_bang_generic");
 
         hw->eeprom.ops.init_params(hw);
 
-        if (offset >= hw->eeprom.word_size) {
+        if (words == 0) {
+                status = IXGBE_ERR_INVALID_ARGUMENT;
+                goto out;
+        }
+
+        if (offset + words > hw->eeprom.word_size) {
                 status = IXGBE_ERR_EEPROM;
                 goto out;
         }
 
+        /*
+         * The EEPROM page size cannot be queried from the chip. We do lazy
+         * initialization. It is worth to do that when we write large buffer.
+         */
+        if ((hw->eeprom.word_page_size == 0) &&
+            (words > IXGBE_EEPROM_PAGE_SIZE_MAX))
+                ixgbe_detect_eeprom_page_size_generic(hw, offset);
+
+        /*
+         * We cannot hold synchronization semaphores for too long
+         * to avoid other entity starvation. However it is more efficient
+         * to read in bursts than synchronizing access for each word.
+         */
+        for (i = 0; i < words; i += IXGBE_EEPROM_RD_BUFFER_MAX_COUNT) {
+                count = (words - i) / IXGBE_EEPROM_RD_BUFFER_MAX_COUNT > 0 ?
+                        IXGBE_EEPROM_RD_BUFFER_MAX_COUNT : (words - i);
+                status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset + i,
+                                                            count, &data[i]);
+
+                if (status != IXGBE_SUCCESS)
+                        break;
+        }
+
+out:
+        return status;
+}
+
+/**
+ *  ixgbe_write_eeprom_buffer_bit_bang - Writes 16 bit word(s) to EEPROM
+ *  @hw: pointer to hardware structure
+ *  @offset: offset within the EEPROM to be written to
+ *  @words: number of word(s)
+ *  @data: 16 bit word(s) to be written to the EEPROM
+ *
+ *  If ixgbe_eeprom_update_checksum is not called after this function, the
+ *  EEPROM will most likely contain an invalid checksum.
+ **/
+static s32 ixgbe_write_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset,
+                                              u16 words, u16 *data)
+{
+        s32 status;
+        u16 word;
+        u16 page_size;
+        u16 i;
+        u8 write_opcode = IXGBE_EEPROM_WRITE_OPCODE_SPI;
+
+        DEBUGFUNC("ixgbe_write_eeprom_buffer_bit_bang");
+
         /* Prepare the EEPROM for writing  */
         status = ixgbe_acquire_eeprom(hw);
 
         if (status == IXGBE_SUCCESS) {
                 if (ixgbe_ready_eeprom(hw) != IXGBE_SUCCESS) {
@@ -830,68 +1020,157 @@
                         status = IXGBE_ERR_EEPROM;
                 }
         }
 
         if (status == IXGBE_SUCCESS) {
+                for (i = 0; i < words; i++) {
                 ixgbe_standby_eeprom(hw);
 
                 /*  Send the WRITE ENABLE command (8 bit opcode )  */
-                ixgbe_shift_out_eeprom_bits(hw, IXGBE_EEPROM_WREN_OPCODE_SPI,
+                        ixgbe_shift_out_eeprom_bits(hw,
+                                                   IXGBE_EEPROM_WREN_OPCODE_SPI,
                                             IXGBE_EEPROM_OPCODE_BITS);
 
                 ixgbe_standby_eeprom(hw);
 
                 /*
-                 * Some SPI eeproms use the 8th address bit embedded in the
-                 * opcode
+                         * Some SPI eeproms use the 8th address bit embedded
+                         * in the opcode
                  */
-                if ((hw->eeprom.address_bits == 8) && (offset >= 128))
+                        if ((hw->eeprom.address_bits == 8) &&
+                            ((offset + i) >= 128))
                         write_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI;
 
                 /* Send the Write command (8-bit opcode + addr) */
                 ixgbe_shift_out_eeprom_bits(hw, write_opcode,
                                             IXGBE_EEPROM_OPCODE_BITS);
-                ixgbe_shift_out_eeprom_bits(hw, (u16)(offset*2),
+                        ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2),
                                             hw->eeprom.address_bits);
 
-                /* Send the data */
-                data = (data >> 8) | (data << 8);
-                ixgbe_shift_out_eeprom_bits(hw, data, 16);
-                ixgbe_standby_eeprom(hw);
+                        page_size = hw->eeprom.word_page_size;
 
+                        /* Send the data in burst via SPI*/
+                        do {
+                                word = data[i];
+                                word = (word >> 8) | (word << 8);
+                                ixgbe_shift_out_eeprom_bits(hw, word, 16);
+
+                                if (page_size == 0)
+                                        break;
+
+                                /* do not wrap around page */
+                                if (((offset + i) & (page_size - 1)) ==
+                                    (page_size - 1))
+                                        break;
+                        } while (++i < words);
+
+                        ixgbe_standby_eeprom(hw);
+                        msec_delay(10);
+                }
                 /* Done with writing - release the EEPROM */
                 ixgbe_release_eeprom(hw);
         }
 
-out:
         return status;
 }
 
 /**
- *  ixgbe_read_eeprom_bit_bang_generic - Read EEPROM word using bit-bang
+ *  ixgbe_write_eeprom_generic - Writes 16 bit value to EEPROM
  *  @hw: pointer to hardware structure
- *  @offset: offset within the EEPROM to be read
- *  @data: read 16 bit value from EEPROM
+ *  @offset: offset within the EEPROM to be written to
+ *  @data: 16 bit word to be written to the EEPROM
  *
- *  Reads 16 bit value from EEPROM through bit-bang method
+ *  If ixgbe_eeprom_update_checksum is not called after this function, the
+ *  EEPROM will most likely contain an invalid checksum.
  **/
-s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
-                                       u16 *data)
+s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data)
 {
         s32 status;
-        u16 word_in;
-        u8 read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI;
 
-        DEBUGFUNC("ixgbe_read_eeprom_bit_bang_generic");
+        DEBUGFUNC("ixgbe_write_eeprom_generic");
 
         hw->eeprom.ops.init_params(hw);
 
         if (offset >= hw->eeprom.word_size) {
                 status = IXGBE_ERR_EEPROM;
                 goto out;
         }
 
+        status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset, 1, &data);
+
+out:
+        return status;
+}
+
+/**
+ *  ixgbe_read_eeprom_buffer_bit_bang_generic - Read EEPROM using bit-bang
+ *  @hw: pointer to hardware structure
+ *  @offset: offset within the EEPROM to be read
+ *  @data: read 16 bit words(s) from EEPROM
+ *  @words: number of word(s)
+ *
+ *  Reads 16 bit word(s) from EEPROM through bit-bang method
+ **/
+s32 ixgbe_read_eeprom_buffer_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
+                                              u16 words, u16 *data)
+{
+        s32 status = IXGBE_SUCCESS;
+        u16 i, count;
+
+        DEBUGFUNC("ixgbe_read_eeprom_buffer_bit_bang_generic");
+
+        hw->eeprom.ops.init_params(hw);
+
+        if (words == 0) {
+                status = IXGBE_ERR_INVALID_ARGUMENT;
+                goto out;
+        }
+
+        if (offset + words > hw->eeprom.word_size) {
+                status = IXGBE_ERR_EEPROM;
+                goto out;
+        }
+
+        /*
+         * We cannot hold synchronization semaphores for too long
+         * to avoid other entity starvation. However it is more efficient
+         * to read in bursts than synchronizing access for each word.
+         */
+        for (i = 0; i < words; i += IXGBE_EEPROM_RD_BUFFER_MAX_COUNT) {
+                count = (words - i) / IXGBE_EEPROM_RD_BUFFER_MAX_COUNT > 0 ?
+                        IXGBE_EEPROM_RD_BUFFER_MAX_COUNT : (words - i);
+
+                status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset + i,
+                                                           count, &data[i]);
+
+                if (status != IXGBE_SUCCESS)
+                        break;
+        }
+
+out:
+        return status;
+}
+
+/**
+ *  ixgbe_read_eeprom_buffer_bit_bang - Read EEPROM using bit-bang
+ *  @hw: pointer to hardware structure
+ *  @offset: offset within the EEPROM to be read
+ *  @words: number of word(s)
+ *  @data: read 16 bit word(s) from EEPROM
+ *
+ *  Reads 16 bit word(s) from EEPROM through bit-bang method
+ **/
+static s32 ixgbe_read_eeprom_buffer_bit_bang(struct ixgbe_hw *hw, u16 offset,
+                                             u16 words, u16 *data)
+{
+        s32 status;
+        u16 word_in;
+        u8 read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI;
+        u16 i;
+
+        DEBUGFUNC("ixgbe_read_eeprom_buffer_bit_bang");
+
         /* Prepare the EEPROM for reading  */
         status = ixgbe_acquire_eeprom(hw);
 
         if (status == IXGBE_SUCCESS) {
                 if (ixgbe_ready_eeprom(hw) != IXGBE_SUCCESS) {
@@ -899,99 +1178,206 @@
                         status = IXGBE_ERR_EEPROM;
                 }
         }
 
         if (status == IXGBE_SUCCESS) {
+                for (i = 0; i < words; i++) {
                 ixgbe_standby_eeprom(hw);
-
                 /*
-                 * Some SPI eeproms use the 8th address bit embedded in the
-                 * opcode
+                         * Some SPI eeproms use the 8th address bit embedded
+                         * in the opcode
                  */
-                if ((hw->eeprom.address_bits == 8) && (offset >= 128))
+                        if ((hw->eeprom.address_bits == 8) &&
+                            ((offset + i) >= 128))
                         read_opcode |= IXGBE_EEPROM_A8_OPCODE_SPI;
 
                 /* Send the READ command (opcode + addr) */
                 ixgbe_shift_out_eeprom_bits(hw, read_opcode,
                                             IXGBE_EEPROM_OPCODE_BITS);
-                ixgbe_shift_out_eeprom_bits(hw, (u16)(offset*2),
+                        ixgbe_shift_out_eeprom_bits(hw, (u16)((offset + i) * 2),
                                             hw->eeprom.address_bits);
 
                 /* Read the data. */
                 word_in = ixgbe_shift_in_eeprom_bits(hw, 16);
-                *data = (word_in >> 8) | (word_in << 8);
+                        data[i] = (word_in >> 8) | (word_in << 8);
+                }
 
                 /* End this read operation */
                 ixgbe_release_eeprom(hw);
         }
 
+        return status;
+}
+
+/**
+ *  ixgbe_read_eeprom_bit_bang_generic - Read EEPROM word using bit-bang
+ *  @hw: pointer to hardware structure
+ *  @offset: offset within the EEPROM to be read
+ *  @data: read 16 bit value from EEPROM
+ *
+ *  Reads 16 bit value from EEPROM through bit-bang method
+ **/
+s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset,
+                                       u16 *data)
+{
+        s32 status;
+
+        DEBUGFUNC("ixgbe_read_eeprom_bit_bang_generic");
+
+        hw->eeprom.ops.init_params(hw);
+
+        if (offset >= hw->eeprom.word_size) {
+                status = IXGBE_ERR_EEPROM;
+                goto out;
+        }
+
+        status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data);
+
 out:
         return status;
 }
 
 /**
- *  ixgbe_read_eerd_generic - Read EEPROM word using EERD
+ *  ixgbe_read_eerd_buffer_generic - Read EEPROM word(s) using EERD
  *  @hw: pointer to hardware structure
  *  @offset: offset of  word in the EEPROM to read
- *  @data: word read from the EEPROM
+ *  @words: number of word(s)
+ *  @data: 16 bit word(s) from the EEPROM
  *
- *  Reads a 16 bit word from the EEPROM using the EERD register.
+ *  Reads a 16 bit word(s) from the EEPROM using the EERD register.
  **/
-s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data)
+s32 ixgbe_read_eerd_buffer_generic(struct ixgbe_hw *hw, u16 offset,
+                                   u16 words, u16 *data)
 {
         u32 eerd;
-        s32 status;
+        s32 status = IXGBE_SUCCESS;
+        u32 i;
 
-        DEBUGFUNC("ixgbe_read_eerd_generic");
+        DEBUGFUNC("ixgbe_read_eerd_buffer_generic");
 
         hw->eeprom.ops.init_params(hw);
 
+        if (words == 0) {
+                status = IXGBE_ERR_INVALID_ARGUMENT;
+                goto out;
+        }
+
         if (offset >= hw->eeprom.word_size) {
                 status = IXGBE_ERR_EEPROM;
                 goto out;
         }
 
-        eerd = (offset << IXGBE_EEPROM_RW_ADDR_SHIFT) +
+        for (i = 0; i < words; i++) {
+                eerd = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) +
                IXGBE_EEPROM_RW_REG_START;
 
         IXGBE_WRITE_REG(hw, IXGBE_EERD, eerd);
         status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_READ);
 
-        if (status == IXGBE_SUCCESS)
-                *data = (IXGBE_READ_REG(hw, IXGBE_EERD) >>
+                if (status == IXGBE_SUCCESS) {
+                        data[i] = (IXGBE_READ_REG(hw, IXGBE_EERD) >>
                          IXGBE_EEPROM_RW_REG_DATA);
-        else
+                } else {
                 DEBUGOUT("Eeprom read timed out\n");
+                        goto out;
+                }
+        }
+out:
+        return status;
+}
 
+/**
+ *  ixgbe_detect_eeprom_page_size_generic - Detect EEPROM page size
+ *  @hw: pointer to hardware structure
+ *  @offset: offset within the EEPROM to be used as a scratch pad
+ *
+ *  Discover EEPROM page size by writing marching data at given offset.
+ *  This function is called only when we are writing a new large buffer
+ *  at given offset so the data would be overwritten anyway.
+ **/
+static s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw,
+                                                 u16 offset)
+{
+        u16 data[IXGBE_EEPROM_PAGE_SIZE_MAX];
+        s32 status = IXGBE_SUCCESS;
+        u16 i;
+
+        DEBUGFUNC("ixgbe_detect_eeprom_page_size_generic");
+
+        for (i = 0; i < IXGBE_EEPROM_PAGE_SIZE_MAX; i++)
+                data[i] = i;
+
+        hw->eeprom.word_page_size = IXGBE_EEPROM_PAGE_SIZE_MAX;
+        status = ixgbe_write_eeprom_buffer_bit_bang(hw, offset,
+                                             IXGBE_EEPROM_PAGE_SIZE_MAX, data);
+        hw->eeprom.word_page_size = 0;
+        if (status != IXGBE_SUCCESS)
+                goto out;
+
+        status = ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data);
+        if (status != IXGBE_SUCCESS)
+                goto out;
+
+        /*
+         * When writing in burst more than the actual page size
+         * EEPROM address wraps around current page.
+         */
+        hw->eeprom.word_page_size = IXGBE_EEPROM_PAGE_SIZE_MAX - data[0];
+
+        DEBUGOUT1("Detected EEPROM page size = %d words.",
+                  hw->eeprom.word_page_size);
 out:
         return status;
 }
 
 /**
- *  ixgbe_write_eewr_generic - Write EEPROM word using EEWR
+ *  ixgbe_read_eerd_generic - Read EEPROM word using EERD
  *  @hw: pointer to hardware structure
+ *  @offset: offset of  word in the EEPROM to read
+ *  @data: word read from the EEPROM
+ *
+ *  Reads a 16 bit word from the EEPROM using the EERD register.
+ **/
+s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data)
+{
+        return ixgbe_read_eerd_buffer_generic(hw, offset, 1, data);
+}
+
+/**
+ *  ixgbe_write_eewr_buffer_generic - Write EEPROM word(s) using EEWR
+ *  @hw: pointer to hardware structure
  *  @offset: offset of  word in the EEPROM to write
- *  @data: word write to the EEPROM
+ *  @words: number of word(s)
+ *  @data: word(s) write to the EEPROM
  *
- *  Write a 16 bit word to the EEPROM using the EEWR register.
+ *  Write a 16 bit word(s) to the EEPROM using the EEWR register.
  **/
-s32 ixgbe_write_eewr_generic(struct ixgbe_hw *hw, u16 offset, u16 data)
+s32 ixgbe_write_eewr_buffer_generic(struct ixgbe_hw *hw, u16 offset,
+                                    u16 words, u16 *data)
 {
         u32 eewr;
-        s32 status;
+        s32 status = IXGBE_SUCCESS;
+        u16 i;
 
         DEBUGFUNC("ixgbe_write_eewr_generic");
 
         hw->eeprom.ops.init_params(hw);
 
+        if (words == 0) {
+                status = IXGBE_ERR_INVALID_ARGUMENT;
+                goto out;
+        }
+
         if (offset >= hw->eeprom.word_size) {
                 status = IXGBE_ERR_EEPROM;
                 goto out;
         }
 
-        eewr = (offset << IXGBE_EEPROM_RW_ADDR_SHIFT) |
-               (data << IXGBE_EEPROM_RW_REG_DATA) | IXGBE_EEPROM_RW_REG_START;
+        for (i = 0; i < words; i++) {
+                eewr = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) |
+                        (data[i] << IXGBE_EEPROM_RW_REG_DATA) |
+                        IXGBE_EEPROM_RW_REG_START;
 
         status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE);
         if (status != IXGBE_SUCCESS) {
                 DEBUGOUT("Eeprom write EEWR timed out\n");
                 goto out;
@@ -1002,16 +1388,30 @@
         status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE);
         if (status != IXGBE_SUCCESS) {
                 DEBUGOUT("Eeprom write EEWR timed out\n");
                 goto out;
         }
+        }
 
 out:
         return status;
 }
 
 /**
+ *  ixgbe_write_eewr_generic - Write EEPROM word using EEWR
+ *  @hw: pointer to hardware structure
+ *  @offset: offset of  word in the EEPROM to write
+ *  @data: word write to the EEPROM
+ *
+ *  Write a 16 bit word to the EEPROM using the EEWR register.
+ **/
+s32 ixgbe_write_eewr_generic(struct ixgbe_hw *hw, u16 offset, u16 data)
+{
+        return ixgbe_write_eewr_buffer_generic(hw, offset, 1, &data);
+}
+
+/**
  *  ixgbe_poll_eerd_eewr_done - Poll EERD read or EEWR write status
  *  @hw: pointer to hardware structure
  *  @ee_reg: EEPROM flag for polling
  *
  *  Polls the status bit (bit 1) of the EERD or EEWR to determine when the
@@ -1053,11 +1453,12 @@
         u32 eec;
         u32 i;
 
         DEBUGFUNC("ixgbe_acquire_eeprom");
 
-        if (ixgbe_acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) != IXGBE_SUCCESS)
+        if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM)
+            != IXGBE_SUCCESS)
                 status = IXGBE_ERR_SWFW_SYNC;
 
         if (status == IXGBE_SUCCESS) {
                 eec = IXGBE_READ_REG(hw, IXGBE_EEC);
 
@@ -1076,11 +1477,11 @@
                 if (!(eec & IXGBE_EEC_GNT)) {
                         eec &= ~IXGBE_EEC_REQ;
                         IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
                         DEBUGOUT("Could not acquire EEPROM grant\n");
 
-                        ixgbe_release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
+                        hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
                         status = IXGBE_ERR_EEPROM;
                 }
 
                 /* Setup EEPROM for Read/Write */
                 if (status == IXGBE_SUCCESS) {
@@ -1122,10 +1523,32 @@
                         break;
                 }
                 usec_delay(50);
         }
 
+        if (i == timeout) {
+                DEBUGOUT("Driver can't access the Eeprom - SMBI Semaphore "
+                         "not granted.\n");
+                /*
+                 * this release is particularly important because our attempts
+                 * above to get the semaphore may have succeeded, and if there
+                 * was a timeout, we should unconditionally clear the semaphore
+                 * bits to free the driver to make progress
+                 */
+                ixgbe_release_eeprom_semaphore(hw);
+
+                usec_delay(50);
+                /*
+                 * one last try
+                 * If the SMBI bit is 0 when we read it, then the bit will be
+                 * set and we have the semaphore
+                 */
+                swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
+                if (!(swsm & IXGBE_SWSM_SMBI))
+                        status = IXGBE_SUCCESS;
+        }
+
         /* Now get the semaphore between SW/FW through the SWESMBI bit */
         if (status == IXGBE_SUCCESS) {
                 for (i = 0; i < timeout; i++) {
                         swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
 
@@ -1402,11 +1825,11 @@
 
         /* Stop requesting EEPROM access */
         eec &= ~IXGBE_EEC_REQ;
         IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
 
-        ixgbe_release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
+        hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
 
         /* Delay before attempt to obtain semaphore again to allow FW access */
         msec_delay(hw->eeprom.semaphore_delay);
 }
 
@@ -1711,11 +2134,11 @@
 
         DEBUGOUT(" Clearing MTA\n");
         for (i = 0; i < hw->mac.mcft_size; i++)
                 IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0);
 
-        (void) ixgbe_init_uta_tables(hw);
+        ixgbe_init_uta_tables(hw);
 
         return IXGBE_SUCCESS;
 }
 
 /**
@@ -1901,18 +2324,18 @@
  *  ixgbe_update_mc_addr_list_generic - Updates MAC list of multicast addresses
  *  @hw: pointer to hardware structure
  *  @mc_addr_list: the list of new multicast addresses
  *  @mc_addr_count: number of addresses
  *  @next: iterator function to walk the multicast address list
+ *  @clear: flag, when set clears the table beforehand
  *
- *  The given list replaces any existing list. Clears the MC addrs from receive
- *  address registers and the multicast table. Uses unused receive address
- *  registers for the first multicast addresses, and hashes the rest into the
- *  multicast table.
+ *  When the clear flag is set, the given list replaces any existing list.
+ *  Hashes the given addresses into the multicast table.
  **/
 s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list,
-                                      u32 mc_addr_count, ixgbe_mc_addr_itr next)
+                                      u32 mc_addr_count, ixgbe_mc_addr_itr next,
+                                      bool clear)
 {
         u32 i;
         u32 vmdq;
 
         DEBUGFUNC("ixgbe_update_mc_addr_list_generic");
@@ -1923,12 +2346,14 @@
          */
         hw->addr_ctrl.num_mc_addrs = mc_addr_count;
         hw->addr_ctrl.mta_in_use = 0;
 
         /* Clear mta_shadow */
+        if (clear) {
         DEBUGOUT(" Clearing MTA\n");
-        (void) memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow));
+                memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow));
+        }
 
         /* Update mta_shadow */
         for (i = 0; i < mc_addr_count; i++) {
                 DEBUGOUT(" Adding the multicast addresses:\n");
                 ixgbe_set_mta(hw, next(hw, &mc_addr_list, &vmdq));
@@ -1985,32 +2410,48 @@
 }
 
 /**
  *  ixgbe_fc_enable_generic - Enable flow control
  *  @hw: pointer to hardware structure
- *  @packetbuf_num: packet buffer number (0-7)
  *
  *  Enable flow control according to the current settings.
  **/
-s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num)
+s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw)
 {
         s32 ret_val = IXGBE_SUCCESS;
         u32 mflcn_reg, fccfg_reg;
         u32 reg;
-        u32 rx_pba_size;
         u32 fcrtl, fcrth;
+        int i;
 
         DEBUGFUNC("ixgbe_fc_enable_generic");
 
-        /* Negotiate the fc mode to use */
-        ret_val = ixgbe_fc_autoneg(hw);
-        if (ret_val == IXGBE_ERR_FLOW_CONTROL)
+        /* Validate the water mark configuration */
+        if (!hw->fc.pause_time) {
+                ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
                 goto out;
+        }
 
+        /* Low water mark of zero causes XOFF floods */
+        for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) {
+                if ((hw->fc.current_mode & ixgbe_fc_tx_pause) &&
+                    hw->fc.high_water[i]) {
+                        if (!hw->fc.low_water[i] ||
+                            hw->fc.low_water[i] >= hw->fc.high_water[i]) {
+                                DEBUGOUT("Invalid water mark configuration\n");
+                                ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
+                                goto out;
+                        }
+                }
+        }
+
+        /* Negotiate the fc mode to use */
+        ixgbe_fc_autoneg(hw);
+
         /* Disable any previous flow control settings */
         mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN);
-        mflcn_reg &= ~(IXGBE_MFLCN_RFCE | IXGBE_MFLCN_RPFCE);
+        mflcn_reg &= ~(IXGBE_MFLCN_RPFCE_MASK | IXGBE_MFLCN_RFCE);
 
         fccfg_reg = IXGBE_READ_REG(hw, IXGBE_FCCFG);
         fccfg_reg &= ~(IXGBE_FCCFG_TFCE_802_3X | IXGBE_FCCFG_TFCE_PRIORITY);
 
         /*
@@ -2062,129 +2503,114 @@
         /* Set 802.3x based flow control settings. */
         mflcn_reg |= IXGBE_MFLCN_DPF;
         IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn_reg);
         IXGBE_WRITE_REG(hw, IXGBE_FCCFG, fccfg_reg);
 
-        rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(packetbuf_num));
-        rx_pba_size >>= IXGBE_RXPBSIZE_SHIFT;
 
-        fcrth = (rx_pba_size - hw->fc.high_water) << 10;
-        fcrtl = (rx_pba_size - hw->fc.low_water) << 10;
+        /* Set up and enable Rx high/low water mark thresholds, enable XON. */
+        for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) {
+                if ((hw->fc.current_mode & ixgbe_fc_tx_pause) &&
+                    hw->fc.high_water[i]) {
+                        fcrtl = (hw->fc.low_water[i] << 10) | IXGBE_FCRTL_XONE;
+                        IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), fcrtl);
+                        fcrth = (hw->fc.high_water[i] << 10) | IXGBE_FCRTH_FCEN;
+                } else {
+                        IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), 0);
+                        /*
+                         * In order to prevent Tx hangs when the internal Tx
+                         * switch is enabled we must set the high water mark
+                         * to the maximum FCRTH value.  This allows the Tx
+                         * switch to function even under heavy Rx workloads.
+                         */
+                        fcrth = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 32;
+                }
 
-        if (hw->fc.current_mode & ixgbe_fc_tx_pause) {
-                fcrth |= IXGBE_FCRTH_FCEN;
-                if (hw->fc.send_xon)
-                        fcrtl |= IXGBE_FCRTL_XONE;
+                IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), fcrth);
         }
 
-        IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(packetbuf_num), fcrth);
-        IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(packetbuf_num), fcrtl);
-
         /* Configure pause time (2 TCs per register) */
-        reg = IXGBE_READ_REG(hw, IXGBE_FCTTV(packetbuf_num / 2));
-        if ((packetbuf_num & 1) == 0)
-                reg = (reg & 0xFFFF0000) | hw->fc.pause_time;
-        else
-                reg = (reg & 0x0000FFFF) | (hw->fc.pause_time << 16);
-        IXGBE_WRITE_REG(hw, IXGBE_FCTTV(packetbuf_num / 2), reg);
+        reg = hw->fc.pause_time * 0x00010001;
+        for (i = 0; i < (IXGBE_DCB_MAX_TRAFFIC_CLASS / 2); i++)
+                IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg);
 
-        IXGBE_WRITE_REG(hw, IXGBE_FCRTV, (hw->fc.pause_time >> 1));
+        /* Configure flow control refresh threshold value */
+        IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2);
 
 out:
         return ret_val;
 }
 
 /**
- *  ixgbe_fc_autoneg - Configure flow control
+ *  ixgbe_negotiate_fc - Negotiate flow control
  *  @hw: pointer to hardware structure
+ *  @adv_reg: flow control advertised settings
+ *  @lp_reg: link partner's flow control settings
+ *  @adv_sym: symmetric pause bit in advertisement
+ *  @adv_asm: asymmetric pause bit in advertisement
+ *  @lp_sym: symmetric pause bit in link partner advertisement
+ *  @lp_asm: asymmetric pause bit in link partner advertisement
  *
- *  Compares our advertised flow control capabilities to those advertised by
- *  our link partner, and determines the proper flow control mode to use.
+ *  Find the intersection between advertised settings and link partner's
+ *  advertised settings
  **/
-s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw)
+static s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
+                              u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm)
 {
-        s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
-        ixgbe_link_speed speed;
-        bool link_up;
+        if ((!(adv_reg)) ||  (!(lp_reg)))
+                return IXGBE_ERR_FC_NOT_NEGOTIATED;
 
-        DEBUGFUNC("ixgbe_fc_autoneg");
-
-        if (hw->fc.disable_fc_autoneg)
-                goto out;
-
+        if ((adv_reg & adv_sym) && (lp_reg & lp_sym)) {
         /*
-         * AN should have completed when the cable was plugged in.
-         * Look for reasons to bail out.  Bail out if:
-         * - FC autoneg is disabled, or if
-         * - link is not up.
-         *
-         * Since we're being called from an LSC, link is already known to be up.
-         * So use link_up_wait_to_complete=FALSE.
+                 * 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.
          */
-        hw->mac.ops.check_link(hw, &speed, &link_up, FALSE);
-        if (!link_up) {
-                ret_val = IXGBE_ERR_FLOW_CONTROL;
-                goto out;
+                if (hw->fc.requested_mode == ixgbe_fc_full) {
+                        hw->fc.current_mode = ixgbe_fc_full;
+                        DEBUGOUT("Flow Control = FULL.\n");
+                } else {
+                        hw->fc.current_mode = ixgbe_fc_rx_pause;
+                        DEBUGOUT("Flow Control=RX PAUSE frames only\n");
         }
-
-        switch (hw->phy.media_type) {
-        /* Autoneg flow control on fiber adapters */
-        case ixgbe_media_type_fiber:
-                if (speed == IXGBE_LINK_SPEED_1GB_FULL)
-                        ret_val = ixgbe_fc_autoneg_fiber(hw);
-                break;
-
-        /* Autoneg flow control on backplane adapters */
-        case ixgbe_media_type_backplane:
-                ret_val = ixgbe_fc_autoneg_backplane(hw);
-                break;
-
-        /* Autoneg flow control on copper adapters */
-        case ixgbe_media_type_copper:
-                if (ixgbe_device_supports_autoneg_fc(hw) == IXGBE_SUCCESS)
-                        ret_val = ixgbe_fc_autoneg_copper(hw);
-                break;
-
-        default:
-                break;
-        }
-
-out:
-        if (ret_val == IXGBE_SUCCESS) {
-                hw->fc.fc_was_autonegged = TRUE;
+        } else if (!(adv_reg & adv_sym) && (adv_reg & adv_asm) &&
+                   (lp_reg & lp_sym) && (lp_reg & lp_asm)) {
+                hw->fc.current_mode = ixgbe_fc_tx_pause;
+                DEBUGOUT("Flow Control = TX PAUSE frames only.\n");
+        } else if ((adv_reg & adv_sym) && (adv_reg & adv_asm) &&
+                   !(lp_reg & lp_sym) && (lp_reg & lp_asm)) {
+                hw->fc.current_mode = ixgbe_fc_rx_pause;
+                DEBUGOUT("Flow Control = RX PAUSE frames only.\n");
         } else {
-                hw->fc.fc_was_autonegged = FALSE;
-                hw->fc.current_mode = hw->fc.requested_mode;
+                hw->fc.current_mode = ixgbe_fc_none;
+                DEBUGOUT("Flow Control = NONE.\n");
         }
-        return ret_val;
+        return IXGBE_SUCCESS;
 }
 
 /**
  *  ixgbe_fc_autoneg_fiber - Enable flow control on 1 gig fiber
  *  @hw: pointer to hardware structure
- *  @speed:
- *  @link_up
  *
  *  Enable flow control according on 1 gig fiber.
  **/
 static s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw)
 {
         u32 pcs_anadv_reg, pcs_lpab_reg, linkstat;
-        s32 ret_val;
+        s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
 
         /*
          * On multispeed fiber at 1g, bail out if
          * - link is up but AN did not complete, or if
          * - link is up and AN completed but timed out
          */
 
         linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
-        if (((linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) ||
-            ((linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) {
-                ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
+        if ((!!(linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) ||
+            (!!(linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1))
                 goto out;
-        }
 
         pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
         pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP);
 
         ret_val =  ixgbe_negotiate_fc(hw, pcs_anadv_reg,
@@ -2204,34 +2630,26 @@
  *  Enable flow control according to IEEE clause 37.
  **/
 static s32 ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw)
 {
         u32 links2, anlp1_reg, autoc_reg, links;
-        s32 ret_val;
+        s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
 
         /*
          * On backplane, bail out if
          * - backplane autoneg was not completed, or if
          * - we are 82599 and link partner is not AN enabled
          */
         links = IXGBE_READ_REG(hw, IXGBE_LINKS);
-        if ((links & IXGBE_LINKS_KX_AN_COMP) == 0) {
-                hw->fc.fc_was_autonegged = FALSE;
-                hw->fc.current_mode = hw->fc.requested_mode;
-                ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
+        if ((links & IXGBE_LINKS_KX_AN_COMP) == 0)
                 goto out;
-        }
 
         if (hw->mac.type == ixgbe_mac_82599EB) {
                 links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2);
-                if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0) {
-                        hw->fc.fc_was_autonegged = FALSE;
-                        hw->fc.current_mode = hw->fc.requested_mode;
-                        ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
+                if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0)
                         goto out;
                 }
-        }
         /*
          * Read the 10g AN autoc and LP ability registers and resolve
          * local flow control settings accordingly
          */
         autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
@@ -2268,226 +2686,66 @@
                                   IXGBE_TAF_SYM_PAUSE, IXGBE_TAF_ASM_PAUSE,
                                   IXGBE_TAF_SYM_PAUSE, IXGBE_TAF_ASM_PAUSE);
 }
 
 /**
- *  ixgbe_negotiate_fc - Negotiate flow control
+ *  ixgbe_fc_autoneg - Configure flow control
  *  @hw: pointer to hardware structure
- *  @adv_reg: flow control advertised settings
- *  @lp_reg: link partner's flow control settings
- *  @adv_sym: symmetric pause bit in advertisement
- *  @adv_asm: asymmetric pause bit in advertisement
- *  @lp_sym: symmetric pause bit in link partner advertisement
- *  @lp_asm: asymmetric pause bit in link partner advertisement
  *
- *  Find the intersection between advertised settings and link partner's
- *  advertised settings
+ *  Compares our advertised flow control capabilities to those advertised by
+ *  our link partner, and determines the proper flow control mode to use.
  **/
-static s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
-                              u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm)
+void ixgbe_fc_autoneg(struct ixgbe_hw *hw)
 {
-        if ((!(adv_reg)) ||  (!(lp_reg)))
-                return IXGBE_ERR_FC_NOT_NEGOTIATED;
+        s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
+        ixgbe_link_speed speed;
+        bool link_up;
 
-        if ((adv_reg & adv_sym) && (lp_reg & lp_sym)) {
-                /*
-                 * 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 == ixgbe_fc_full) {
-                        hw->fc.current_mode = ixgbe_fc_full;
-                        DEBUGOUT("Flow Control = FULL.\n");
-                } else {
-                        hw->fc.current_mode = ixgbe_fc_rx_pause;
-                        DEBUGOUT("Flow Control=RX PAUSE frames only\n");
-                }
-        } else if (!(adv_reg & adv_sym) && (adv_reg & adv_asm) &&
-                   (lp_reg & lp_sym) && (lp_reg & lp_asm)) {
-                hw->fc.current_mode = ixgbe_fc_tx_pause;
-                DEBUGOUT("Flow Control = TX PAUSE frames only.\n");
-        } else if ((adv_reg & adv_sym) && (adv_reg & adv_asm) &&
-                   !(lp_reg & lp_sym) && (lp_reg & lp_asm)) {
-                hw->fc.current_mode = ixgbe_fc_rx_pause;
-                DEBUGOUT("Flow Control = RX PAUSE frames only.\n");
-        } else {
-                hw->fc.current_mode = ixgbe_fc_none;
-                DEBUGOUT("Flow Control = NONE.\n");
-        }
-        return IXGBE_SUCCESS;
-}
+        DEBUGFUNC("ixgbe_fc_autoneg");
 
-/**
- *  ixgbe_setup_fc - Set up flow control
- *  @hw: pointer to hardware structure
- *
- *  Called at init time to set up flow control.
- **/
-s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
-{
-        s32 ret_val = IXGBE_SUCCESS;
-        u32 reg = 0, reg_bp = 0;
-        u16 reg_cu = 0;
-
-        DEBUGFUNC("ixgbe_setup_fc");
-
-        /* Validate the packetbuf configuration */
-        if (packetbuf_num < 0 || packetbuf_num > 7) {
-                DEBUGOUT1("Invalid packet buffer number [%d], expected range is"
-                          " 0-7\n", packetbuf_num);
-                ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
-                goto out;
-        }
-
         /*
-         * Validate the water mark configuration.  Zero water marks are invalid
-         * because it causes the controller to just blast out fc packets.
+         * AN should have completed when the cable was plugged in.
+         * Look for reasons to bail out.  Bail out if:
+         * - FC autoneg is disabled, or if
+         * - link is not up.
          */
-        if (!hw->fc.low_water || !hw->fc.high_water || !hw->fc.pause_time) {
-                DEBUGOUT("Invalid water mark configuration\n");
-                ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
+        if (hw->fc.disable_fc_autoneg)
                 goto out;
-        }
 
-        /*
-         * Validate the requested mode.  Strict IEEE mode does not allow
-         * ixgbe_fc_rx_pause because it will cause us to fail at UNH.
-         */
-        if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
-                DEBUGOUT("ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
-                ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
+        hw->mac.ops.check_link(hw, &speed, &link_up, FALSE);
+        if (!link_up)
                 goto out;
-        }
 
-        /*
-         * 10gig parts do not have a word in the EEPROM to determine the
-         * default flow control setting, so we explicitly set it to full.
-         */
-        if (hw->fc.requested_mode == ixgbe_fc_default)
-                hw->fc.requested_mode = ixgbe_fc_full;
-
-        /*
-         * Set up the 1G and 10G flow control advertisement registers so the
-         * HW will be able to do fc autoneg once the cable is plugged in.  If
-         * we link at 10G, the 1G advertisement is harmless and vice versa.
-         */
-
         switch (hw->phy.media_type) {
+        /* Autoneg flow control on fiber adapters */
         case ixgbe_media_type_fiber:
+                if (speed == IXGBE_LINK_SPEED_1GB_FULL)
+                        ret_val = ixgbe_fc_autoneg_fiber(hw);
+                break;
+
+        /* Autoneg flow control on backplane adapters */
         case ixgbe_media_type_backplane:
-                reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
-                reg_bp = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+                ret_val = ixgbe_fc_autoneg_backplane(hw);
                 break;
 
+        /* Autoneg flow control on copper adapters */
         case ixgbe_media_type_copper:
-                hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT,
-                                        IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®_cu);
+                if (ixgbe_device_supports_autoneg_fc(hw) == IXGBE_SUCCESS)
+                        ret_val = ixgbe_fc_autoneg_copper(hw);
                 break;
 
         default:
-                ;
-        }
-
-        /*
-         * The possible values of fc.requested_mode 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.
-         * other: Invalid.
-         */
-        switch (hw->fc.requested_mode) {
-        case ixgbe_fc_none:
-                /* Flow control completely disabled by software override. */
-                reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
-                if (hw->phy.media_type == ixgbe_media_type_backplane)
-                        reg_bp &= ~(IXGBE_AUTOC_SYM_PAUSE |
-                                    IXGBE_AUTOC_ASM_PAUSE);
-                else if (hw->phy.media_type == ixgbe_media_type_copper)
-                        reg_cu &= ~(IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE);
                 break;
-        case ixgbe_fc_rx_pause:
-                /*
-                 * Rx Flow control is enabled and Tx Flow control is
-                 * disabled by software override. 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.
-                 */
-                reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
-                if (hw->phy.media_type == ixgbe_media_type_backplane)
-                        reg_bp |= (IXGBE_AUTOC_SYM_PAUSE |
-                                   IXGBE_AUTOC_ASM_PAUSE);
-                else if (hw->phy.media_type == ixgbe_media_type_copper)
-                        reg_cu |= (IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE);
-                break;
-        case ixgbe_fc_tx_pause:
-                /*
-                 * Tx Flow control is enabled, and Rx Flow control is
-                 * disabled by software override.
-                 */
-                reg |= (IXGBE_PCS1GANA_ASM_PAUSE);
-                reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE);
-                if (hw->phy.media_type == ixgbe_media_type_backplane) {
-                        reg_bp |= (IXGBE_AUTOC_ASM_PAUSE);
-                        reg_bp &= ~(IXGBE_AUTOC_SYM_PAUSE);
-                } else if (hw->phy.media_type == ixgbe_media_type_copper) {
-                        reg_cu |= (IXGBE_TAF_ASM_PAUSE);
-                        reg_cu &= ~(IXGBE_TAF_SYM_PAUSE);
                 }
-                break;
-        case ixgbe_fc_full:
-                /* Flow control (both Rx and Tx) is enabled by SW override. */
-                reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
-                if (hw->phy.media_type == ixgbe_media_type_backplane)
-                        reg_bp |= (IXGBE_AUTOC_SYM_PAUSE |
-                                   IXGBE_AUTOC_ASM_PAUSE);
-                else if (hw->phy.media_type == ixgbe_media_type_copper)
-                        reg_cu |= (IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE);
-                break;
-        default:
-                DEBUGOUT("Flow control param set incorrectly\n");
-                ret_val = IXGBE_ERR_CONFIG;
-                goto out;
-        }
 
-        /*
-         * Enable auto-negotiation between the MAC & PHY;
-         * the MAC will advertise clause 37 flow control.
-         */
-        IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg);
-        reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL);
-
-        /* Disable AN timeout */
-        if (hw->fc.strict_ieee)
-                reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN;
-
-        IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg);
-        DEBUGOUT1("Set up FC; PCS1GLCTL = 0x%08X\n", reg);
-
-        /*
-         * AUTOC restart handles negotiation of 1G and 10G on backplane
-         * and copper. There is no need to set the PCS1GCTL register.
-         *
-         */
-        if (hw->phy.media_type == ixgbe_media_type_backplane) {
-                reg_bp |= IXGBE_AUTOC_AN_RESTART;
-                IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_bp);
-        } else if ((hw->phy.media_type == ixgbe_media_type_copper) &&
-                    (ixgbe_device_supports_autoneg_fc(hw) == IXGBE_SUCCESS)) {
-                hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT,
-                                      IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg_cu);
-        }
-
-        DEBUGOUT1("Set up FC; IXGBE_AUTOC = 0x%08X\n", reg);
 out:
-        return ret_val;
+        if (ret_val == IXGBE_SUCCESS) {
+                hw->fc.fc_was_autonegged = TRUE;
+        } else {
+                hw->fc.fc_was_autonegged = FALSE;
+                hw->fc.current_mode = hw->fc.requested_mode;
+        }
 }
 
 /**
  *  ixgbe_disable_pcie_master - Disable PCI-express master access
  *  @hw: pointer to hardware structure
@@ -2497,82 +2755,64 @@
  *  bit hasn't caused the master requests to be disabled, else IXGBE_SUCCESS
  *  is returned signifying master requests disabled.
  **/
 s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
 {
-        u32 i;
-        u32 reg_val;
-        u32 number_of_queues;
         s32 status = IXGBE_SUCCESS;
+        u32 i;
 
         DEBUGFUNC("ixgbe_disable_pcie_master");
 
-        /* Just jump out if bus mastering is already disabled */
+        /* Always set this bit to ensure any future transactions are blocked */
+        IXGBE_WRITE_REG(hw, IXGBE_CTRL, IXGBE_CTRL_GIO_DIS);
+
+        /* Exit if master requets are blocked */
         if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO))
                 goto out;
 
-        /* Disable the receive unit by stopping each queue */
-        number_of_queues = hw->mac.max_rx_queues;
-        for (i = 0; i < number_of_queues; i++) {
-                reg_val = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i));
-                if (reg_val & IXGBE_RXDCTL_ENABLE) {
-                        reg_val &= ~IXGBE_RXDCTL_ENABLE;
-                        IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(i), reg_val);
-                }
-        }
-
-        reg_val = IXGBE_READ_REG(hw, IXGBE_CTRL);
-        reg_val |= IXGBE_CTRL_GIO_DIS;
-        IXGBE_WRITE_REG(hw, IXGBE_CTRL, reg_val);
-
+        /* Poll for master request bit to clear */
         for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) {
-                if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO))
-                        goto check_device_status;
                 usec_delay(100);
+                if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO))
+                        goto out;
         }
 
+        /*
+         * Two consecutive resets are required via CTRL.RST per datasheet
+         * 5.2.5.3.2 Master Disable.  We set a flag to inform the reset routine
+         * of this need.  The first reset prevents new master requests from
+         * being issued by our device.  We then must wait 1usec or more for any
+         * remaining completions from the PCIe bus to trickle in, and then reset
+         * again to clear out any effects they may have had on our device.
+         */
         DEBUGOUT("GIO Master Disable bit didn't clear - requesting resets\n");
-        status = IXGBE_ERR_MASTER_REQUESTS_PENDING;
+        hw->mac.flags |= IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
 
         /*
          * Before proceeding, make sure that the PCIe block does not have
          * transactions pending.
          */
-check_device_status:
         for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) {
+                usec_delay(100);
                 if (!(IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_STATUS) &
                         IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING))
-                        break;
-                usec_delay(100);
+                        goto out;
         }
 
-        if (i == IXGBE_PCI_MASTER_DISABLE_TIMEOUT)
                 DEBUGOUT("PCIe transaction pending bit also did not clear.\n");
-        else
-                goto out;
+        status = IXGBE_ERR_MASTER_REQUESTS_PENDING;
 
-        /*
-         * Two consecutive resets are required via CTRL.RST per datasheet
-         * 5.2.5.3.2 Master Disable.  We set a flag to inform the reset routine
-         * of this need.  The first reset prevents new master requests from
-         * being issued by our device.  We then must wait 1usec for any
-         * remaining completions from the PCIe bus to trickle in, and then reset
-         * again to clear out any effects they may have had on our device.
-         */
-         hw->mac.flags |= IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
-
 out:
         return status;
 }
 
-
 /**
  *  ixgbe_acquire_swfw_sync - Acquire SWFW semaphore
  *  @hw: pointer to hardware structure
  *  @mask: Mask to specify which semaphore to acquire
  *
- *  Acquires the SWFW semaphore thought the GSSR register for the specified
+ *  Acquires the SWFW semaphore through the GSSR register for the specified
  *  function (CSR, PHY0, PHY1, EEPROM, Flash)
  **/
 s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask)
 {
         u32 gssr;
@@ -2618,30 +2858,87 @@
 /**
  *  ixgbe_release_swfw_sync - Release SWFW semaphore
  *  @hw: pointer to hardware structure
  *  @mask: Mask to specify which semaphore to release
  *
- *  Releases the SWFW semaphore thought the GSSR register for the specified
+ *  Releases the SWFW semaphore through the GSSR register for the specified
  *  function (CSR, PHY0, PHY1, EEPROM, Flash)
  **/
 void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask)
 {
         u32 gssr;
         u32 swmask = mask;
 
         DEBUGFUNC("ixgbe_release_swfw_sync");
 
-        (void) ixgbe_get_eeprom_semaphore(hw);
+        ixgbe_get_eeprom_semaphore(hw);
 
         gssr = IXGBE_READ_REG(hw, IXGBE_GSSR);
         gssr &= ~swmask;
         IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr);
 
         ixgbe_release_eeprom_semaphore(hw);
 }
 
 /**
+ *  ixgbe_disable_sec_rx_path_generic - Stops the receive data path
+ *  @hw: pointer to hardware structure
+ *
+ *  Stops the receive data path and waits for the HW to internally empty
+ *  the Rx security block
+ **/
+s32 ixgbe_disable_sec_rx_path_generic(struct ixgbe_hw *hw)
+{
+#define IXGBE_MAX_SECRX_POLL 40
+
+        int i;
+        int secrxreg;
+
+        DEBUGFUNC("ixgbe_disable_sec_rx_path_generic");
+
+
+        secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL);
+        secrxreg |= IXGBE_SECRXCTRL_RX_DIS;
+        IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, secrxreg);
+        for (i = 0; i < IXGBE_MAX_SECRX_POLL; i++) {
+                secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXSTAT);
+                if (secrxreg & IXGBE_SECRXSTAT_SECRX_RDY)
+                        break;
+                else
+                        /* Use interrupt-safe sleep just in case */
+                        usec_delay(1000);
+        }
+
+        /* For informational purposes only */
+        if (i >= IXGBE_MAX_SECRX_POLL)
+                DEBUGOUT("Rx unit being enabled before security "
+                         "path fully disabled.  Continuing with init.\n");
+
+        return IXGBE_SUCCESS;
+}
+
+/**
+ *  ixgbe_enable_sec_rx_path_generic - Enables the receive data path
+ *  @hw: pointer to hardware structure
+ *
+ *  Enables the receive data path.
+ **/
+s32 ixgbe_enable_sec_rx_path_generic(struct ixgbe_hw *hw)
+{
+        int secrxreg;
+
+        DEBUGFUNC("ixgbe_enable_sec_rx_path_generic");
+
+        secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL);
+        secrxreg &= ~IXGBE_SECRXCTRL_RX_DIS;
+        IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, secrxreg);
+        IXGBE_WRITE_FLUSH(hw);
+
+        return IXGBE_SUCCESS;
+}
+
+/**
  *  ixgbe_enable_rx_dma_generic - Enable the Rx DMA unit
  *  @hw: pointer to hardware structure
  *  @regval: register value to write to RXCTRL
  *
  *  Enables the Rx DMA unit
@@ -2677,10 +2974,11 @@
 
         if (!link_up) {
                 autoc_reg |= IXGBE_AUTOC_AN_RESTART;
                 autoc_reg |= IXGBE_AUTOC_FLU;
                 IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
+                IXGBE_WRITE_FLUSH(hw);
                 msec_delay(10);
         }
 
         led_reg &= ~IXGBE_LED_MODE_MASK(index);
         led_reg |= IXGBE_LED_BLINK(index);
@@ -2758,11 +3056,11 @@
 
         /*
          * First read the EEPROM pointer to see if the MAC addresses are
          * available.  If they're not, no point in calling set_lan_id() here.
          */
-        (void) ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset);
+        ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset);
 
         if ((san_mac_offset == 0) || (san_mac_offset == 0xFFFF)) {
                 /*
                  * No addresses available in this EEPROM.  It's not an
                  * error though, so just wipe the local address and return.
@@ -2803,11 +3101,11 @@
         u8 i;
 
         DEBUGFUNC("ixgbe_set_san_mac_addr_generic");
 
         /* Look for SAN mac address pointer.  If not defined, return */
-        (void) ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset);
+        ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset);
 
         if ((san_mac_offset == 0) || (san_mac_offset == 0xFFFF)) {
                 status = IXGBE_ERR_NO_SAN_ADDR_PTR;
                 goto san_mac_addr_out;
         }
@@ -2834,25 +3132,40 @@
  *  @hw: pointer to hardware structure
  *
  *  Read PCIe configuration space, and get the MSI-X vector count from
  *  the capabilities table.
  **/
-u32 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw)
+u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw)
 {
-        u32 msix_count = 64;
+        u16 msix_count = 1;
+        u16 max_msix_count;
+        u16 pcie_offset;
 
+        switch (hw->mac.type) {
+        case ixgbe_mac_82598EB:
+                pcie_offset = IXGBE_PCIE_MSIX_82598_CAPS;
+                max_msix_count = IXGBE_MAX_MSIX_VECTORS_82598;
+                break;
+        case ixgbe_mac_82599EB:
+        case ixgbe_mac_X540:
+                pcie_offset = IXGBE_PCIE_MSIX_82599_CAPS;
+                max_msix_count = IXGBE_MAX_MSIX_VECTORS_82599;
+                break;
+        default:
+                return msix_count;
+        }
+
         DEBUGFUNC("ixgbe_get_pcie_msix_count_generic");
-        if (hw->mac.msix_vectors_from_pcie) {
-                msix_count = IXGBE_READ_PCIE_WORD(hw,
-                                                  IXGBE_PCIE_MSIX_82599_CAPS);
+        msix_count = IXGBE_READ_PCIE_WORD(hw, pcie_offset);
                 msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK;
 
-                /* MSI-X count is zero-based in HW, so increment to give
-                 * proper value */
+        /* MSI-X count is zero-based in HW */
                 msix_count++;
-        }
 
+        if (msix_count > max_msix_count)
+                msix_count = max_msix_count;
+
         return msix_count;
 }
 
 /**
  *  ixgbe_insert_mac_addr_generic - Find a RAR for this mac address
@@ -2898,18 +3211,18 @@
                 }
         }
 
         if (rar < hw->mac.rar_highwater) {
                 /* already there so just add to the pool bits */
-                (void) ixgbe_set_vmdq(hw, rar, vmdq);
+                ixgbe_set_vmdq(hw, rar, vmdq);
         } else if (first_empty_rar != NO_EMPTY_RAR_FOUND) {
                 /* stick it into first empty RAR slot we found */
                 rar = first_empty_rar;
-                (void) ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV);
+                ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV);
         } else if (rar == hw->mac.rar_highwater) {
                 /* add it to the top of the list and inc the highwater mark */
-                (void) ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV);
+                ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV);
                 hw->mac.rar_highwater++;
         } else if (rar >= hw->mac.num_rar_entries) {
                 return IXGBE_ERR_INVALID_MAC_ADDR;
         }
 
@@ -2916,11 +3229,11 @@
         /*
          * If we found rar[0], make sure the default pool bit (we use pool 0)
          * remains cleared to be sure default pool packets will get delivered
          */
         if (rar == 0)
-                (void) ixgbe_clear_vmdq(hw, rar, 0);
+                ixgbe_clear_vmdq(hw, rar, 0);
 
         return rar;
 }
 
 /**
@@ -3002,10 +3315,37 @@
         }
         return IXGBE_SUCCESS;
 }
 
 /**
+ *  This function should only be involved in the IOV mode.
+ *  In IOV mode, Default pool is next pool after the number of
+ *  VFs advertized and not 0.
+ *  MPSAR table needs to be updated for SAN_MAC RAR [hw->mac.san_mac_rar_index]
+ *
+ *  ixgbe_set_vmdq_san_mac - Associate default VMDq pool index with a rx address
+ *  @hw: pointer to hardware struct
+ *  @vmdq: VMDq pool index
+ **/
+s32 ixgbe_set_vmdq_san_mac_generic(struct ixgbe_hw *hw, u32 vmdq)
+{
+        u32 rar = hw->mac.san_mac_rar_index;
+
+        DEBUGFUNC("ixgbe_set_vmdq_san_mac");
+
+        if (vmdq < 32) {
+                IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 1 << vmdq);
+                IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0);
+        } else {
+                IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0);
+                IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 1 << (vmdq - 32));
+        }
+
+        return IXGBE_SUCCESS;
+}
+
+/**
  *  ixgbe_init_uta_tables_generic - Initialize the Unicast Table Array
  *  @hw: pointer to hardware structure
  **/
 s32 ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw)
 {
@@ -3080,13 +3420,12 @@
                            bool vlan_on)
 {
         s32 regindex;
         u32 bitindex;
         u32 vfta;
-        u32 bits;
-        u32 vt;
         u32 targetbit;
+        s32 ret_val = IXGBE_SUCCESS;
         bool vfta_changed = FALSE;
 
         DEBUGFUNC("ixgbe_set_vfta_generic");
 
         if (vlan > 4095)
@@ -3120,62 +3459,97 @@
                         vfta_changed = TRUE;
                 }
         }
 
         /* Part 2
-         * If VT Mode is set
+         * Call ixgbe_set_vlvf_generic to set VLVFB and VLVF
+         */
+        ret_val = ixgbe_set_vlvf_generic(hw, vlan, vind, vlan_on,
+                                         &vfta_changed);
+        if (ret_val != IXGBE_SUCCESS)
+                return ret_val;
+
+        if (vfta_changed)
+                IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), vfta);
+
+        return IXGBE_SUCCESS;
+}
+
+/**
+ *  ixgbe_set_vlvf_generic - Set VLAN Pool Filter
+ *  @hw: pointer to hardware structure
+ *  @vlan: VLAN id to write to VLAN filter
+ *  @vind: VMDq output index that maps queue to VLAN id in VFVFB
+ *  @vlan_on: boolean flag to turn on/off VLAN in VFVF
+ *  @vfta_changed: pointer to boolean flag which indicates whether VFTA
+ *                 should be changed
+ *
+ *  Turn on/off specified bit in VLVF table.
+ **/
+s32 ixgbe_set_vlvf_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind,
+                            bool vlan_on, bool *vfta_changed)
+{
+        u32 vt;
+
+        DEBUGFUNC("ixgbe_set_vlvf_generic");
+
+        if (vlan > 4095)
+                return IXGBE_ERR_PARAM;
+
+        /* If VT Mode is set
          *   Either vlan_on
          *     make sure the vlan is in VLVF
          *     set the vind bit in the matching VLVFB
          *   Or !vlan_on
          *     clear the pool bit and possibly the vind
          */
         vt = IXGBE_READ_REG(hw, IXGBE_VT_CTL);
         if (vt & IXGBE_VT_CTL_VT_ENABLE) {
                 s32 vlvf_index;
+                u32 bits;
 
                 vlvf_index = ixgbe_find_vlvf_slot(hw, vlan);
                 if (vlvf_index < 0)
                         return vlvf_index;
 
                 if (vlan_on) {
                         /* set the pool bit */
                         if (vind < 32) {
                                 bits = IXGBE_READ_REG(hw,
-                                                IXGBE_VLVFB(vlvf_index*2));
+                                                IXGBE_VLVFB(vlvf_index * 2));
                                 bits |= (1 << vind);
                                 IXGBE_WRITE_REG(hw,
-                                                IXGBE_VLVFB(vlvf_index*2),
+                                                IXGBE_VLVFB(vlvf_index * 2),
                                                 bits);
                         } else {
                                 bits = IXGBE_READ_REG(hw,
-                                                IXGBE_VLVFB((vlvf_index*2)+1));
-                                bits |= (1 << (vind-32));
+                                        IXGBE_VLVFB((vlvf_index * 2) + 1));
+                                bits |= (1 << (vind - 32));
                                 IXGBE_WRITE_REG(hw,
-                                                IXGBE_VLVFB((vlvf_index*2)+1),
+                                        IXGBE_VLVFB((vlvf_index * 2) + 1),
                                                 bits);
                         }
                 } else {
                         /* clear the pool bit */
                         if (vind < 32) {
                                 bits = IXGBE_READ_REG(hw,
-                                                IXGBE_VLVFB(vlvf_index*2));
+                                                IXGBE_VLVFB(vlvf_index * 2));
                                 bits &= ~(1 << vind);
                                 IXGBE_WRITE_REG(hw,
-                                                IXGBE_VLVFB(vlvf_index*2),
+                                                IXGBE_VLVFB(vlvf_index * 2),
                                                 bits);
                                 bits |= IXGBE_READ_REG(hw,
-                                                IXGBE_VLVFB((vlvf_index*2)+1));
+                                        IXGBE_VLVFB((vlvf_index * 2) + 1));
                         } else {
                                 bits = IXGBE_READ_REG(hw,
-                                                IXGBE_VLVFB((vlvf_index*2)+1));
-                                bits &= ~(1 << (vind-32));
+                                        IXGBE_VLVFB((vlvf_index * 2) + 1));
+                                bits &= ~(1 << (vind - 32));
                                 IXGBE_WRITE_REG(hw,
-                                                IXGBE_VLVFB((vlvf_index*2)+1),
+                                        IXGBE_VLVFB((vlvf_index * 2) + 1),
                                                 bits);
                                 bits |= IXGBE_READ_REG(hw,
-                                                IXGBE_VLVFB(vlvf_index*2));
+                                                IXGBE_VLVFB(vlvf_index * 2));
                         }
                 }
 
                 /*
                  * If there are still bits set in the VLVFB registers
@@ -3193,24 +3567,20 @@
                  * zero.
                  */
                 if (bits) {
                         IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index),
                                         (IXGBE_VLVF_VIEN | vlan));
-                        if (!vlan_on) {
+                        if ((!vlan_on) && (vfta_changed != NULL)) {
                                 /* someone wants to clear the vfta entry
                                  * but some pools/VFs are still using it.
                                  * Ignore it. */
-                                vfta_changed = FALSE;
+                                *vfta_changed = FALSE;
                         }
-                }
-                else
+                } else
                         IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), 0);
         }
 
-        if (vfta_changed)
-                IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), vfta);
-
         return IXGBE_SUCCESS;
 }
 
 /**
  *  ixgbe_clear_vfta_generic - Clear VLAN filter table
@@ -3227,12 +3597,12 @@
         for (offset = 0; offset < hw->mac.vft_size; offset++)
                 IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0);
 
         for (offset = 0; offset < IXGBE_VLVF_ENTRIES; offset++) {
                 IXGBE_WRITE_REG(hw, IXGBE_VLVF(offset), 0);
-                IXGBE_WRITE_REG(hw, IXGBE_VLVFB(offset*2), 0);
-                IXGBE_WRITE_REG(hw, IXGBE_VLVFB((offset*2)+1), 0);
+                IXGBE_WRITE_REG(hw, IXGBE_VLVFB(offset * 2), 0);
+                IXGBE_WRITE_REG(hw, IXGBE_VLVFB((offset * 2) + 1), 0);
         }
 
         return IXGBE_SUCCESS;
 }
 
@@ -3291,16 +3661,10 @@
                  IXGBE_LINKS_SPEED_100_82599)
                 *speed = IXGBE_LINK_SPEED_100_FULL;
         else
                 *speed = IXGBE_LINK_SPEED_UNKNOWN;
 
-        /* if link is down, zero out the current_mode */
-        if (*link_up == FALSE) {
-                hw->fc.current_mode = ixgbe_fc_none;
-                hw->fc.fc_was_autonegged = FALSE;
-        }
-
         return IXGBE_SUCCESS;
 }
 
 /**
  *  ixgbe_get_wwn_prefix_generic - Get alternative WWNN/WWPN prefix from
@@ -3397,32 +3761,10 @@
 out:
         return status;
 }
 
 /**
- *  ixgbe_device_supports_autoneg_fc - Check if phy supports autoneg flow
- *  control
- *  @hw: pointer to hardware structure
- *
- *  There are several phys that do not support autoneg flow control. This
- *  function check the device id to see if the associated phy supports
- *  autoneg flow control.
- **/
-static s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
-{
-
-        DEBUGFUNC("ixgbe_device_supports_autoneg_fc");
-
-        switch (hw->device_id) {
-        case IXGBE_DEV_ID_82599_T3_LOM:
-                return IXGBE_SUCCESS;
-        default:
-                return IXGBE_ERR_FC_NOT_SUPPORTED;
-        }
-}
-
-/**
  *  ixgbe_set_mac_anti_spoofing - Enable/Disable MAC anti-spoofing
  *  @hw: pointer to hardware structure
  *  @enable: enable or disable switch for anti-spoofing
  *  @pf: Physical Function pool - do not enable anti-spoofing for the PF
  *
@@ -3442,24 +3784,26 @@
 
         /*
          * PFVFSPOOF register array is size 8 with 8 bits assigned to
          * MAC anti-spoof enables in each register array element.
          */
-        for (j = 0; j < IXGBE_PFVFSPOOF_REG_COUNT; j++)
+        for (j = 0; j < pf_target_reg; j++)
                 IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(j), pfvfspoof);
 
-        /* If not enabling anti-spoofing then done */
-        if (!enable)
-                return;
-
         /*
          * The PF should be allowed to spoof so that it can support
-         * emulation mode NICs.  Reset the bit assigned to the PF
+         * emulation mode NICs.  Do not set the bits assigned to the PF
          */
-        pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(pf_target_reg));
-        pfvfspoof ^= (1 << pf_target_shift);
-        IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(pf_target_reg), pfvfspoof);
+        pfvfspoof &= (1 << pf_target_shift) - 1;
+        IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(j), pfvfspoof);
+
+        /*
+         * Remaining pools belong to the PF so they do not need to have
+         * anti-spoofing enabled.
+         */
+        for (j++; j < IXGBE_PFVFSPOOF_REG_COUNT; j++)
+                IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(j), 0);
 }
 
 /**
  *  ixgbe_set_vlan_anti_spoofing - Enable/Disable VLAN anti-spoofing
  *  @hw: pointer to hardware structure
@@ -3514,17 +3858,301 @@
         DEBUGFUNC("ixgbe_enable_relaxed_ordering_gen2");
 
         /* Enable relaxed ordering */
         for (i = 0; i < hw->mac.max_tx_queues; i++) {
                 regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i));
-                regval |= IXGBE_DCA_TXCTRL_TX_WB_RO_EN;
+                regval |= IXGBE_DCA_TXCTRL_DESC_WRO_EN;
                 IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), regval);
         }
 
         for (i = 0; i < hw->mac.max_rx_queues; i++) {
                 regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i));
-                regval |= (IXGBE_DCA_RXCTRL_DESC_WRO_EN |
-                           IXGBE_DCA_RXCTRL_DESC_HSRO_EN);
+                regval |= IXGBE_DCA_RXCTRL_DATA_WRO_EN |
+                          IXGBE_DCA_RXCTRL_HEAD_WRO_EN;
                 IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval);
         }
 
 }
+
+/**
+ *  ixgbe_calculate_checksum - Calculate checksum for buffer
+ *  @buffer: pointer to EEPROM
+ *  @length: size of EEPROM to calculate a checksum for
+ *  Calculates the checksum for some buffer on a specified length.  The
+ *  checksum calculated is returned.
+ **/
+static u8 ixgbe_calculate_checksum(u8 *buffer, u32 length)
+{
+        u32 i;
+        u8 sum = 0;
+
+        DEBUGFUNC("ixgbe_calculate_checksum");
+
+        if (!buffer)
+                return 0;
+
+        for (i = 0; i < length; i++)
+                sum += buffer[i];
+
+        return (u8) (0 - sum);
+}
+
+/**
+ *  ixgbe_host_interface_command - Issue command to manageability block
+ *  @hw: pointer to the HW structure
+ *  @buffer: contains the command to write and where the return status will
+ *   be placed
+ *  @length: length of buffer, must be multiple of 4 bytes
+ *
+ *  Communicates with the manageability block.  On success return IXGBE_SUCCESS
+ *  else return IXGBE_ERR_HOST_INTERFACE_COMMAND.
+ **/
+static s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer,
+                                        u32 length)
+{
+        u32 hicr, i, bi;
+        u32 hdr_size = sizeof(struct ixgbe_hic_hdr);
+        u8 buf_len, dword_len;
+
+        s32 ret_val = IXGBE_SUCCESS;
+
+        DEBUGFUNC("ixgbe_host_interface_command");
+
+        if (length == 0 || length & 0x3 ||
+            length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) {
+                DEBUGOUT("Buffer length failure.\n");
+                ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
+                goto out;
+        }
+
+        /* Check that the host interface is enabled. */
+        hicr = IXGBE_READ_REG(hw, IXGBE_HICR);
+        if ((hicr & IXGBE_HICR_EN) == 0) {
+                DEBUGOUT("IXGBE_HOST_EN bit disabled.\n");
+                ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
+                goto out;
+        }
+
+        /* Calculate length in DWORDs */
+        dword_len = length >> 2;
+
+        /*
+         * The device driver writes the relevant command block
+         * into the ram area.
+         */
+        for (i = 0; i < dword_len; i++)
+                IXGBE_WRITE_REG_ARRAY(hw, IXGBE_FLEX_MNG,
+                                      i, IXGBE_CPU_TO_LE32(buffer[i]));
+
+        /* Setting this bit tells the ARC that a new command is pending. */
+        IXGBE_WRITE_REG(hw, IXGBE_HICR, hicr | IXGBE_HICR_C);
+
+        for (i = 0; i < IXGBE_HI_COMMAND_TIMEOUT; i++) {
+                hicr = IXGBE_READ_REG(hw, IXGBE_HICR);
+                if (!(hicr & IXGBE_HICR_C))
+                        break;
+                msec_delay(1);
+        }
+
+        /* Check command successful completion. */
+        if (i == IXGBE_HI_COMMAND_TIMEOUT ||
+            (!(IXGBE_READ_REG(hw, IXGBE_HICR) & IXGBE_HICR_SV))) {
+                DEBUGOUT("Command has failed with no status valid.\n");
+                ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
+                goto out;
+        }
+
+        /* Calculate length in DWORDs */
+        dword_len = hdr_size >> 2;
+
+        /* first pull in the header so we know the buffer length */
+        for (bi = 0; bi < dword_len; bi++) {
+                buffer[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, bi);
+                IXGBE_LE32_TO_CPUS(&buffer[bi]);
+        }
+
+        /* If there is any thing in data position pull it in */
+        buf_len = ((struct ixgbe_hic_hdr *)buffer)->buf_len;
+        if (buf_len == 0)
+                goto out;
+
+        if (length < (buf_len + hdr_size)) {
+                DEBUGOUT("Buffer not large enough for reply message.\n");
+                ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
+                goto out;
+        }
+
+        /* Calculate length in DWORDs, add 3 for odd lengths */
+        dword_len = (buf_len + 3) >> 2;
+
+        /* Pull in the rest of the buffer (bi is where we left off)*/
+        for (; bi <= dword_len; bi++) {
+                buffer[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, bi);
+                IXGBE_LE32_TO_CPUS(&buffer[bi]);
+        }
+
+out:
+        return ret_val;
+}
+
+/**
+ *  ixgbe_set_fw_drv_ver_generic - Sends driver version to firmware
+ *  @hw: pointer to the HW structure
+ *  @maj: driver version major number
+ *  @min: driver version minor number
+ *  @build: driver version build number
+ *  @sub: driver version sub build number
+ *
+ *  Sends driver version number to firmware through the manageability
+ *  block.  On success return IXGBE_SUCCESS
+ *  else returns IXGBE_ERR_SWFW_SYNC when encountering an error acquiring
+ *  semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
+ **/
+s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min,
+                                 u8 build, u8 sub)
+{
+        struct ixgbe_hic_drv_info fw_cmd;
+        int i;
+        s32 ret_val = IXGBE_SUCCESS;
+
+        DEBUGFUNC("ixgbe_set_fw_drv_ver_generic");
+
+        if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM)
+            != IXGBE_SUCCESS) {
+                ret_val = IXGBE_ERR_SWFW_SYNC;
+                goto out;
+        }
+
+        fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO;
+        fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN;
+        fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
+        fw_cmd.port_num = (u8)hw->bus.func;
+        fw_cmd.ver_maj = maj;
+        fw_cmd.ver_min = min;
+        fw_cmd.ver_build = build;
+        fw_cmd.ver_sub = sub;
+        fw_cmd.hdr.checksum = 0;
+        fw_cmd.hdr.checksum = ixgbe_calculate_checksum((u8 *)&fw_cmd,
+                                (FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len));
+        fw_cmd.pad = 0;
+        fw_cmd.pad2 = 0;
+
+        for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
+                ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd,
+                                                       sizeof(fw_cmd));
+                if (ret_val != IXGBE_SUCCESS)
+                        continue;
+
+                if (fw_cmd.hdr.cmd_or_resp.ret_status ==
+                    FW_CEM_RESP_STATUS_SUCCESS)
+                        ret_val = IXGBE_SUCCESS;
+                else
+                        ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
+
+                break;
+        }
+
+        hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM);
+out:
+        return ret_val;
+}
+
+/**
+ * ixgbe_set_rxpba_generic - Initialize Rx packet buffer
+ * @hw: pointer to hardware structure
+ * @num_pb: number of packet buffers to allocate
+ * @headroom: reserve n KB of headroom
+ * @strategy: packet buffer allocation strategy
+ **/
+void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, int num_pb, u32 headroom,
+                             int strategy)
+{
+        u32 pbsize = hw->mac.rx_pb_size;
+        int i = 0;
+        u32 rxpktsize, txpktsize, txpbthresh;
+
+        /* Reserve headroom */
+        pbsize -= headroom;
+
+        if (!num_pb)
+                num_pb = 1;
+
+        /* Divide remaining packet buffer space amongst the number of packet
+         * buffers requested using supplied strategy.
+         */
+        switch (strategy) {
+        case PBA_STRATEGY_WEIGHTED:
+                /* ixgbe_dcb_pba_80_48 strategy weight first half of packet
+                 * buffer with 5/8 of the packet buffer space.
+                 */
+                rxpktsize = (pbsize * 5) / (num_pb * 4);
+                pbsize -= rxpktsize * (num_pb / 2);
+                rxpktsize <<= IXGBE_RXPBSIZE_SHIFT;
+                for (; i < (num_pb / 2); i++)
+                        IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize);
+                /* Fall through to configure remaining packet buffers */
+        case PBA_STRATEGY_EQUAL:
+                rxpktsize = (pbsize / (num_pb - i)) << IXGBE_RXPBSIZE_SHIFT;
+                for (; i < num_pb; i++)
+                        IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), rxpktsize);
+                break;
+        default:
+                break;
+        }
+
+        /* Only support an equally distributed Tx packet buffer strategy. */
+        txpktsize = IXGBE_TXPBSIZE_MAX / num_pb;
+        txpbthresh = (txpktsize / 1024) - IXGBE_TXPKT_SIZE_MAX;
+        for (i = 0; i < num_pb; i++) {
+                IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), txpktsize);
+                IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), txpbthresh);
+        }
+
+        /* Clear unused TCs, if any, to zero buffer size*/
+        for (; i < IXGBE_MAX_PB; i++) {
+                IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
+                IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i), 0);
+                IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), 0);
+        }
+}
+
+/**
+ * ixgbe_clear_tx_pending - Clear pending TX work from the PCIe fifo
+ * @hw: pointer to the hardware structure
+ *
+ * The 82599 and x540 MACs can experience issues if TX work is still pending
+ * when a reset occurs.  This function prevents this by flushing the PCIe
+ * buffers on the system.
+ **/
+void ixgbe_clear_tx_pending(struct ixgbe_hw *hw)
+{
+        u32 gcr_ext, hlreg0;
+
+        /*
+         * If double reset is not requested then all transactions should
+         * already be clear and as such there is no work to do
+         */
+        if (!(hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED))
+                return;
+
+        /*
+         * Set loopback enable to prevent any transmits from being sent
+         * should the link come up.  This assumes that the RXCTRL.RXEN bit
+         * has already been cleared.
+         */
+        hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
+        IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0 | IXGBE_HLREG0_LPBK);
+
+        /* initiate cleaning flow for buffers in the PCIe transaction layer */
+        gcr_ext = IXGBE_READ_REG(hw, IXGBE_GCR_EXT);
+        IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT,
+                        gcr_ext | IXGBE_GCR_EXT_BUFFERS_CLEAR);
+
+        /* Flush all writes and allow 20usec for all transactions to clear */
+        IXGBE_WRITE_FLUSH(hw);
+        usec_delay(20);
+
+        /* restore previous register values */
+        IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext);
+        IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
+}
+