ixgbe/base: fix bus type overwrite
[dpdk.git] / lib / librte_pmd_ixgbe / ixgbe / ixgbe_common.c
index 64df997..28eb3eb 100644 (file)
@@ -1,6 +1,6 @@
 /*******************************************************************************
 
-Copyright (c) 2001-2012, Intel Corporation
+Copyright (c) 2001-2014, Intel Corporation
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -36,7 +36,6 @@ POSSIBILITY OF SUCH DAMAGE.
 #include "ixgbe_dcb.h"
 #include "ixgbe_dcb_82599.h"
 #include "ixgbe_api.h"
-#ident "$Id: ixgbe_common.c,v 1.382 2013/11/22 01:02:01 jtkirshe Exp $"
 
 STATIC s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw);
 STATIC s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw);
@@ -75,69 +74,74 @@ s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw)
        DEBUGFUNC("ixgbe_init_ops_generic");
 
        /* EEPROM */
-       eeprom->ops.init_params = &ixgbe_init_eeprom_params_generic;
+       eeprom->ops.init_params = ixgbe_init_eeprom_params_generic;
        /* If EEPROM is valid (bit 8 = 1), use EERD otherwise use bit bang */
        if (eec & IXGBE_EEC_PRES) {
-               eeprom->ops.read = &ixgbe_read_eerd_generic;
-               eeprom->ops.read_buffer = &ixgbe_read_eerd_buffer_generic;
+               eeprom->ops.read = ixgbe_read_eerd_generic;
+               eeprom->ops.read_buffer = ixgbe_read_eerd_buffer_generic;
        } else {
-               eeprom->ops.read = &ixgbe_read_eeprom_bit_bang_generic;
+               eeprom->ops.read = ixgbe_read_eeprom_bit_bang_generic;
                eeprom->ops.read_buffer =
-                                &ixgbe_read_eeprom_buffer_bit_bang_generic;
+                                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.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;
+                                     ixgbe_validate_eeprom_checksum_generic;
+       eeprom->ops.update_checksum = ixgbe_update_eeprom_checksum_generic;
+       eeprom->ops.calc_checksum = ixgbe_calc_eeprom_checksum_generic;
 
        /* MAC */
-       mac->ops.init_hw = &ixgbe_init_hw_generic;
+       mac->ops.init_hw = ixgbe_init_hw_generic;
        mac->ops.reset_hw = NULL;
-       mac->ops.start_hw = &ixgbe_start_hw_generic;
-       mac->ops.clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic;
+       mac->ops.start_hw = ixgbe_start_hw_generic;
+       mac->ops.clear_hw_cntrs = ixgbe_clear_hw_cntrs_generic;
        mac->ops.get_media_type = NULL;
        mac->ops.get_supported_physical_layer = NULL;
-       mac->ops.enable_rx_dma = &ixgbe_enable_rx_dma_generic;
-       mac->ops.get_mac_addr = &ixgbe_get_mac_addr_generic;
-       mac->ops.stop_adapter = &ixgbe_stop_adapter_generic;
-       mac->ops.get_bus_info = &ixgbe_get_bus_info_generic;
-       mac->ops.set_lan_id = &ixgbe_set_lan_id_multi_port_pcie;
-       mac->ops.acquire_swfw_sync = &ixgbe_acquire_swfw_sync;
-       mac->ops.release_swfw_sync = &ixgbe_release_swfw_sync;
+       mac->ops.enable_rx_dma = ixgbe_enable_rx_dma_generic;
+       mac->ops.get_mac_addr = ixgbe_get_mac_addr_generic;
+       mac->ops.stop_adapter = ixgbe_stop_adapter_generic;
+       mac->ops.get_bus_info = ixgbe_get_bus_info_generic;
+       mac->ops.set_lan_id = ixgbe_set_lan_id_multi_port_pcie;
+       mac->ops.acquire_swfw_sync = ixgbe_acquire_swfw_sync;
+       mac->ops.release_swfw_sync = ixgbe_release_swfw_sync;
+       mac->ops.prot_autoc_read = prot_autoc_read_generic;
+       mac->ops.prot_autoc_write = prot_autoc_write_generic;
 
        /* LEDs */
-       mac->ops.led_on = &ixgbe_led_on_generic;
-       mac->ops.led_off = &ixgbe_led_off_generic;
-       mac->ops.blink_led_start = &ixgbe_blink_led_start_generic;
-       mac->ops.blink_led_stop = &ixgbe_blink_led_stop_generic;
+       mac->ops.led_on = ixgbe_led_on_generic;
+       mac->ops.led_off = ixgbe_led_off_generic;
+       mac->ops.blink_led_start = ixgbe_blink_led_start_generic;
+       mac->ops.blink_led_stop = ixgbe_blink_led_stop_generic;
 
        /* RAR, Multicast, VLAN */
-       mac->ops.set_rar = &ixgbe_set_rar_generic;
-       mac->ops.clear_rar = &ixgbe_clear_rar_generic;
+       mac->ops.set_rar = ixgbe_set_rar_generic;
+       mac->ops.clear_rar = ixgbe_clear_rar_generic;
        mac->ops.insert_mac_addr = NULL;
        mac->ops.set_vmdq = NULL;
        mac->ops.clear_vmdq = NULL;
-       mac->ops.init_rx_addrs = &ixgbe_init_rx_addrs_generic;
-       mac->ops.update_uc_addr_list = &ixgbe_update_uc_addr_list_generic;
-       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.init_rx_addrs = ixgbe_init_rx_addrs_generic;
+       mac->ops.update_uc_addr_list = ixgbe_update_uc_addr_list_generic;
+       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;
-       mac->ops.enable_rx = &ixgbe_enable_rx_generic;
-       mac->ops.disable_rx = &ixgbe_disable_rx_generic;
+       mac->ops.enable_rx = ixgbe_enable_rx_generic;
+       mac->ops.disable_rx = ixgbe_disable_rx_generic;
 
        /* Flow Control */
-       mac->ops.fc_enable = &ixgbe_fc_enable_generic;
+       mac->ops.fc_enable = ixgbe_fc_enable_generic;
 
        /* Link */
        mac->ops.get_link_capabilities = NULL;
        mac->ops.setup_link = NULL;
        mac->ops.check_link = NULL;
+       mac->ops.dmac_config = NULL;
+       mac->ops.dmac_update_tcs = NULL;
+       mac->ops.dmac_config_tcs = NULL;
 
        return IXGBE_SUCCESS;
 }
@@ -151,19 +155,48 @@ s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw)
  * autonegotiation, and false if it does not.
  *
  **/
-s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
+bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
 {
+       bool supported = false;
+       ixgbe_link_speed speed;
+       bool link_up;
 
        DEBUGFUNC("ixgbe_device_supports_autoneg_fc");
 
-       switch (hw->device_id) {
-       case IXGBE_DEV_ID_X540T:
-       case IXGBE_DEV_ID_X540T1:
-       case IXGBE_DEV_ID_82599_T3_LOM:
-               return IXGBE_SUCCESS;
+       switch (hw->phy.media_type) {
+       case ixgbe_media_type_fiber_qsfp:
+       case ixgbe_media_type_fiber:
+               hw->mac.ops.check_link(hw, &speed, &link_up, false);
+               /* if link is down, assume supported */
+               if (link_up)
+                       supported = speed == IXGBE_LINK_SPEED_1GB_FULL ?
+                               true : false;
+               else
+                       supported = true;
+               break;
+       case ixgbe_media_type_backplane:
+               supported = true;
+               break;
+       case ixgbe_media_type_copper:
+               /* only some copper devices support flow control autoneg */
+               switch (hw->device_id) {
+               case IXGBE_DEV_ID_82599_T3_LOM:
+               case IXGBE_DEV_ID_X540T:
+               case IXGBE_DEV_ID_X540T1:
+               case IXGBE_DEV_ID_X550T:
+                       supported = true;
+                       break;
+               default:
+                       supported = false;
+               }
        default:
-               return IXGBE_ERR_FC_NOT_SUPPORTED;
+               break;
        }
+
+       ERROR_REPORT2(IXGBE_ERROR_UNSUPPORTED,
+                     "Device %x does not support flow control autoneg",
+                     hw->device_id);
+       return supported;
 }
 
 /**
@@ -177,14 +210,11 @@ STATIC s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
        s32 ret_val = IXGBE_SUCCESS;
        u32 reg = 0, reg_bp = 0;
        u16 reg_cu = 0;
-       bool got_lock = false;
+       bool locked = false;
 
        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.
-        */
+       /* Validate the requested mode */
        if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
                ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED,
                           "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
@@ -205,10 +235,17 @@ STATIC s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
         * 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:
+               /* some MAC's need RMW protection on AUTOC */
+               ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &reg_bp);
+               if (ret_val != IXGBE_SUCCESS)
+                       goto out;
+
+               /* only backplane uses autoc so fall though */
+       case ixgbe_media_type_fiber_qsfp:
+       case ixgbe_media_type_fiber:
                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,
@@ -303,30 +340,11 @@ STATIC s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
         */
        if (hw->phy.media_type == ixgbe_media_type_backplane) {
                reg_bp |= IXGBE_AUTOC_AN_RESTART;
-               /* Need the SW/FW semaphore around AUTOC writes if 82599 and
-                * LESM is on, likewise reset_pipeline requries the lock as
-                * it also writes AUTOC.
-                */
-               if ((hw->mac.type == ixgbe_mac_82599EB) &&
-                   ixgbe_verify_lesm_fw_enabled_82599(hw)) {
-                       ret_val = hw->mac.ops.acquire_swfw_sync(hw,
-                                                       IXGBE_GSSR_MAC_CSR_SM);
-                       if (ret_val != IXGBE_SUCCESS) {
-                               ret_val = IXGBE_ERR_SWFW_SYNC;
-                               goto out;
-                       }
-                       got_lock = true;
-               }
-
-               IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_bp);
-               if (hw->mac.type == ixgbe_mac_82599EB)
-                       ixgbe_reset_pipeline_82599(hw);
-
-               if (got_lock)
-                       hw->mac.ops.release_swfw_sync(hw,
-                                                     IXGBE_GSSR_MAC_CSR_SM);
+               ret_val = hw->mac.ops.prot_autoc_write(hw, reg_bp, locked);
+               if (ret_val)
+                       goto out;
        } else if ((hw->phy.media_type == ixgbe_media_type_copper) &&
-                   (ixgbe_device_supports_autoneg_fc(hw) == IXGBE_SUCCESS)) {
+                   (ixgbe_device_supports_autoneg_fc(hw))) {
                hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_ADVT,
                                      IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg_cu);
        }
@@ -545,7 +563,7 @@ s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw)
                }
        }
 
-       if (hw->mac.type == ixgbe_mac_X540) {
+       if (hw->mac.type == ixgbe_mac_X550 || hw->mac.type == ixgbe_mac_X540) {
                if (hw->phy.id == 0)
                        ixgbe_identify_phy(hw);
                hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECL,
@@ -763,7 +781,7 @@ s32 ixgbe_read_pba_raw(struct ixgbe_hw *hw, u16 *eeprom_buf,
                                return ret_val;
                } else {
                        if (eeprom_buf_size > (u32)(pba->word[1] +
-                                             pba->pba_block[0])) {
+                                             pba_block_size)) {
                                memcpy(pba->pba_block,
                                       &eeprom_buf[pba->word[1]],
                                       pba_block_size * sizeof(u16));
@@ -925,22 +943,18 @@ s32 ixgbe_get_mac_addr_generic(struct ixgbe_hw *hw, u8 *mac_addr)
 }
 
 /**
- *  ixgbe_get_bus_info_generic - Generic set PCI bus info
+ *  ixgbe_set_pci_config_data_generic - Generic store PCI bus info
  *  @hw: pointer to hardware structure
+ *  @link_status: the link status returned by the PCI config space
  *
- *  Sets the PCI bus info (speed, width, type) within the ixgbe_hw structure
+ *  Stores the PCI bus info (speed, width, type) within the ixgbe_hw structure
  **/
-s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw)
+void ixgbe_set_pci_config_data_generic(struct ixgbe_hw *hw, u16 link_status)
 {
        struct ixgbe_mac_info *mac = &hw->mac;
-       u16 link_status;
-
-       DEBUGFUNC("ixgbe_get_bus_info_generic");
 
-       hw->bus.type = ixgbe_bus_type_pci_express;
-
-       /* Get the negotiated link width and speed from PCI config space */
-       link_status = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_LINK_STATUS);
+       if (hw->bus.type == ixgbe_bus_type_unknown)
+               hw->bus.type = ixgbe_bus_type_pci_express;
 
        switch (link_status & IXGBE_PCI_LINK_WIDTH) {
        case IXGBE_PCI_LINK_WIDTH_1:
@@ -976,6 +990,25 @@ s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw)
        }
 
        mac->ops.set_lan_id(hw);
+}
+
+/**
+ *  ixgbe_get_bus_info_generic - Generic set PCI bus info
+ *  @hw: pointer to hardware structure
+ *
+ *  Gets the PCI bus info (speed, width, type) then calls helper function to
+ *  store this data within the ixgbe_hw structure.
+ **/
+s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw)
+{
+       u16 link_status;
+
+       DEBUGFUNC("ixgbe_get_bus_info_generic");
+
+       /* Get the negotiated link width and speed from PCI config space */
+       link_status = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_LINK_STATUS);
+
+       ixgbe_set_pci_config_data_generic(hw, link_status);
 
        return IXGBE_SUCCESS;
 }
@@ -1027,7 +1060,7 @@ s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw)
        hw->adapter_stopped = true;
 
        /* Disable the receive unit */
-       IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, 0);
+       ixgbe_disable_rx(hw);
 
        /* Clear interrupt mask to stop interrupts from being generated */
        IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK);
@@ -2063,8 +2096,10 @@ STATIC void ixgbe_release_eeprom(struct ixgbe_hw *hw)
 /**
  *  ixgbe_calc_eeprom_checksum_generic - Calculates and returns the checksum
  *  @hw: pointer to hardware structure
+ *
+ *  Returns a negative error code on error, or the 16-bit checksum
  **/
-u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw)
+s32 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw)
 {
        u16 i;
        u16 j;
@@ -2077,33 +2112,44 @@ u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw)
 
        /* Include 0x0-0x3F in the checksum */
        for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) {
-               if (hw->eeprom.ops.read(hw, i, &word) != IXGBE_SUCCESS) {
+               if (hw->eeprom.ops.read(hw, i, &word)) {
                        DEBUGOUT("EEPROM read failed\n");
-                       break;
+                       return IXGBE_ERR_EEPROM;
                }
                checksum += word;
        }
 
        /* Include all data from pointers except for the fw pointer */
        for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) {
-               hw->eeprom.ops.read(hw, i, &pointer);
+               if (hw->eeprom.ops.read(hw, i, &pointer)) {
+                       DEBUGOUT("EEPROM read failed\n");
+                       return IXGBE_ERR_EEPROM;
+               }
+
+               /* If the pointer seems invalid */
+               if (pointer == 0xFFFF || pointer == 0)
+                       continue;
 
-               /* Make sure the pointer seems valid */
-               if (pointer != 0xFFFF && pointer != 0) {
-                       hw->eeprom.ops.read(hw, pointer, &length);
+               if (hw->eeprom.ops.read(hw, pointer, &length)) {
+                       DEBUGOUT("EEPROM read failed\n");
+                       return IXGBE_ERR_EEPROM;
+               }
 
-                       if (length != 0xFFFF && length != 0) {
-                               for (j = pointer+1; j <= pointer+length; j++) {
-                                       hw->eeprom.ops.read(hw, j, &word);
-                                       checksum += word;
-                               }
+               if (length == 0xFFFF || length == 0)
+                       continue;
+
+               for (j = pointer + 1; j <= pointer + length; j++) {
+                       if (hw->eeprom.ops.read(hw, j, &word)) {
+                               DEBUGOUT("EEPROM read failed\n");
+                               return IXGBE_ERR_EEPROM;
                        }
+                       checksum += word;
                }
        }
 
        checksum = (u16)IXGBE_EEPROM_SUM - checksum;
 
-       return checksum;
+       return (s32)checksum;
 }
 
 /**
@@ -2123,32 +2169,38 @@ s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw,
 
        DEBUGFUNC("ixgbe_validate_eeprom_checksum_generic");
 
-       /*
-        * Read the first word from the EEPROM. If this times out or fails, do
+       /* Read the first word from the EEPROM. If this times out or fails, do
         * not continue or we could be in for a very long wait while every
         * EEPROM read fails
         */
        status = hw->eeprom.ops.read(hw, 0, &checksum);
+       if (status) {
+               DEBUGOUT("EEPROM read failed\n");
+               return status;
+       }
 
-       if (status == IXGBE_SUCCESS) {
-               checksum = hw->eeprom.ops.calc_checksum(hw);
+       status = hw->eeprom.ops.calc_checksum(hw);
+       if (status < 0)
+               return status;
 
-               hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum);
+       checksum = (u16)(status & 0xffff);
 
-               /*
-                * Verify read checksum from EEPROM is the same as
-                * calculated checksum
-                */
-               if (read_checksum != checksum)
-                       status = IXGBE_ERR_EEPROM_CHECKSUM;
-
-               /* If the user cares, return the calculated checksum */
-               if (checksum_val)
-                       *checksum_val = checksum;
-       } else {
+       status = hw->eeprom.ops.read(hw, IXGBE_EEPROM_CHECKSUM, &read_checksum);
+       if (status) {
                DEBUGOUT("EEPROM read failed\n");
+               return status;
        }
 
+       /* Verify read checksum from EEPROM is the same as
+        * calculated checksum
+        */
+       if (read_checksum != checksum)
+               status = IXGBE_ERR_EEPROM_CHECKSUM;
+
+       /* If the user cares, return the calculated checksum */
+       if (checksum_val)
+               *checksum_val = checksum;
+
        return status;
 }
 
@@ -2163,21 +2215,24 @@ s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw)
 
        DEBUGFUNC("ixgbe_update_eeprom_checksum_generic");
 
-       /*
-        * Read the first word from the EEPROM. If this times out or fails, do
+       /* Read the first word from the EEPROM. If this times out or fails, do
         * not continue or we could be in for a very long wait while every
         * EEPROM read fails
         */
        status = hw->eeprom.ops.read(hw, 0, &checksum);
-
-       if (status == IXGBE_SUCCESS) {
-               checksum = hw->eeprom.ops.calc_checksum(hw);
-               status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM,
-                                             checksum);
-       } else {
+       if (status) {
                DEBUGOUT("EEPROM read failed\n");
+               return status;
        }
 
+       status = hw->eeprom.ops.calc_checksum(hw);
+       if (status < 0)
+               return status;
+
+       checksum = (u16)(status & 0xffff);
+
+       status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM, checksum);
+
        return status;
 }
 
@@ -2749,10 +2804,11 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw)
                        /*
                         * 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.
+                        * to the Rx packet buffer size - 24KB.  This allows
+                        * the Tx switch to function even under heavy Rx
+                        * workloads.
                         */
-                       fcrth = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 32;
+                       fcrth = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 24576;
                }
 
                IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), fcrth);
@@ -2844,8 +2900,7 @@ STATIC s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw)
        linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
        if ((!!(linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) ||
            (!!(linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) {
-               ERROR_REPORT1(IXGBE_ERROR_POLLING,
-                            "Auto-Negotiation did not complete or timed out");
+               DEBUGOUT("Auto-Negotiation did not complete or timed out\n");
                goto out;
        }
 
@@ -2880,16 +2935,14 @@ STATIC s32 ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw)
         */
        links = IXGBE_READ_REG(hw, IXGBE_LINKS);
        if ((links & IXGBE_LINKS_KX_AN_COMP) == 0) {
-               ERROR_REPORT1(IXGBE_ERROR_POLLING,
-                            "Auto-Negotiation did not complete");
+               DEBUGOUT("Auto-Negotiation did not complete\n");
                goto out;
        }
 
        if (hw->mac.type == ixgbe_mac_82599EB) {
                links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2);
                if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0) {
-                       ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED,
-                                    "Link partner is not AN enabled");
+                       DEBUGOUT("Link partner is not AN enabled\n");
                        goto out;
                }
        }
@@ -2967,6 +3020,7 @@ void ixgbe_fc_autoneg(struct ixgbe_hw *hw)
 
        switch (hw->phy.media_type) {
        /* Autoneg flow control on fiber adapters */
+       case ixgbe_media_type_fiber_qsfp:
        case ixgbe_media_type_fiber:
                if (speed == IXGBE_LINK_SPEED_1GB_FULL)
                        ret_val = ixgbe_fc_autoneg_fiber(hw);
@@ -2979,7 +3033,7 @@ void ixgbe_fc_autoneg(struct ixgbe_hw *hw)
 
        /* Autoneg flow control on copper adapters */
        case ixgbe_media_type_copper:
-               if (ixgbe_device_supports_autoneg_fc(hw) == IXGBE_SUCCESS)
+               if (ixgbe_device_supports_autoneg_fc(hw))
                        ret_val = ixgbe_fc_autoneg_copper(hw);
                break;
 
@@ -3116,46 +3170,43 @@ out:
  *  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)
+s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u32 mask)
 {
-       u32 gssr;
+       u32 gssr = 0;
        u32 swmask = mask;
        u32 fwmask = mask << 5;
-       s32 timeout = 200;
+       u32 timeout = 200;
+       u32 i;
 
        DEBUGFUNC("ixgbe_acquire_swfw_sync");
 
-       while (timeout) {
+       for (i = 0; i < timeout; i++) {
                /*
-                * SW EEPROM semaphore bit is used for access to all
-                * SW_FW_SYNC/GSSR bits (not just EEPROM)
+                * SW NVM semaphore bit is used for access to all
+                * SW_FW_SYNC bits (not just NVM)
                 */
                if (ixgbe_get_eeprom_semaphore(hw))
                        return IXGBE_ERR_SWFW_SYNC;
 
                gssr = IXGBE_READ_REG(hw, IXGBE_GSSR);
-               if (!(gssr & (fwmask | swmask)))
-                       break;
-
-               /*
-                * Firmware currently using resource (fwmask) or other software
-                * thread currently using resource (swmask)
-                */
-               ixgbe_release_eeprom_semaphore(hw);
-               msec_delay(5);
-               timeout--;
-       }
-
-       if (!timeout) {
-               DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n");
-               return IXGBE_ERR_SWFW_SYNC;
+               if (!(gssr & (fwmask | swmask))) {
+                       gssr |= swmask;
+                       IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr);
+                       ixgbe_release_eeprom_semaphore(hw);
+                       return IXGBE_SUCCESS;
+               } else {
+                       /* Resource is currently in use by FW or SW */
+                       ixgbe_release_eeprom_semaphore(hw);
+                       msec_delay(5);
+               }
        }
 
-       gssr |= swmask;
-       IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr);
+       /* If time expired clear the bits holding the lock and retry */
+       if (gssr & (fwmask | swmask))
+               ixgbe_release_swfw_sync(hw, gssr & (fwmask | swmask));
 
-       ixgbe_release_eeprom_semaphore(hw);
-       return IXGBE_SUCCESS;
+       msec_delay(5);
+       return IXGBE_ERR_SWFW_SYNC;
 }
 
 /**
@@ -3166,7 +3217,7 @@ s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask)
  *  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)
+void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u32 mask)
 {
        u32 gssr;
        u32 swmask = mask;
@@ -3219,6 +3270,37 @@ s32 ixgbe_disable_sec_rx_path_generic(struct ixgbe_hw *hw)
        return IXGBE_SUCCESS;
 }
 
+/**
+ *  prot_autoc_read_generic - Hides MAC differences needed for AUTOC read
+ *  @hw: pointer to hardware structure
+ *  @reg_val: Value we read from AUTOC
+ *
+ *  The default case requires no protection so just to the register read.
+ */
+s32 prot_autoc_read_generic(struct ixgbe_hw *hw, bool *locked, u32 *reg_val)
+{
+       *locked = false;
+       *reg_val = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+       return IXGBE_SUCCESS;
+}
+
+/**
+ * prot_autoc_write_generic - Hides MAC differences needed for AUTOC write
+ * @hw: pointer to hardware structure
+ * @reg_val: value to write to AUTOC
+ * @locked: bool to indicate whether the SW/FW lock was already taken by
+ *           previous read.
+ *
+ * The default case requires no protection so just to the register write.
+ */
+s32 prot_autoc_write_generic(struct ixgbe_hw *hw, u32 reg_val, bool locked)
+{
+       UNREFERENCED_1PARAMETER(locked);
+
+       IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_val);
+       return IXGBE_SUCCESS;
+}
+
 /**
  *  ixgbe_enable_sec_rx_path_generic - Enables the receive data path
  *  @hw: pointer to hardware structure
@@ -3267,9 +3349,10 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
 {
        ixgbe_link_speed speed = 0;
        bool link_up = 0;
-       u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+       u32 autoc_reg = 0;
        u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
        s32 ret_val = IXGBE_SUCCESS;
+       bool locked = false;
 
        DEBUGFUNC("ixgbe_blink_led_start_generic");
 
@@ -3280,29 +3363,18 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
        hw->mac.ops.check_link(hw, &speed, &link_up, false);
 
        if (!link_up) {
-               /* Need the SW/FW semaphore around AUTOC writes if 82599 and
-                * LESM is on.
-                */
-               bool got_lock = false;
-               if ((hw->mac.type == ixgbe_mac_82599EB) &&
-                   ixgbe_verify_lesm_fw_enabled_82599(hw)) {
-                       ret_val = hw->mac.ops.acquire_swfw_sync(hw,
-                                                       IXGBE_GSSR_MAC_CSR_SM);
-                       if (ret_val != IXGBE_SUCCESS) {
-                               ret_val = IXGBE_ERR_SWFW_SYNC;
-                               goto out;
-                       }
-                       got_lock = true;
-               }
+               ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg);
+               if (ret_val != IXGBE_SUCCESS)
+                       goto out;
 
                autoc_reg |= IXGBE_AUTOC_AN_RESTART;
                autoc_reg |= IXGBE_AUTOC_FLU;
-               IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
-               IXGBE_WRITE_FLUSH(hw);
 
-               if (got_lock)
-                       hw->mac.ops.release_swfw_sync(hw,
-                                                     IXGBE_GSSR_MAC_CSR_SM);
+               ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked);
+               if (ret_val != IXGBE_SUCCESS)
+                       goto out;
+
+               IXGBE_WRITE_FLUSH(hw);
                msec_delay(10);
        }
 
@@ -3322,36 +3394,23 @@ out:
  **/
 s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index)
 {
-       u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+       u32 autoc_reg = 0;
        u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
        s32 ret_val = IXGBE_SUCCESS;
-       bool got_lock = false;
+       bool locked = false;
 
        DEBUGFUNC("ixgbe_blink_led_stop_generic");
-       /* Need the SW/FW semaphore around AUTOC writes if 82599 and
-        * LESM is on.
-        */
-       if ((hw->mac.type == ixgbe_mac_82599EB) &&
-           ixgbe_verify_lesm_fw_enabled_82599(hw)) {
-               ret_val = hw->mac.ops.acquire_swfw_sync(hw,
-                                               IXGBE_GSSR_MAC_CSR_SM);
-               if (ret_val != IXGBE_SUCCESS) {
-                       ret_val = IXGBE_ERR_SWFW_SYNC;
-                       goto out;
-               }
-               got_lock = true;
-       }
 
+       ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg);
+       if (ret_val != IXGBE_SUCCESS)
+               goto out;
 
        autoc_reg &= ~IXGBE_AUTOC_FLU;
        autoc_reg |= IXGBE_AUTOC_AN_RESTART;
-       IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
-
-       if (hw->mac.type == ixgbe_mac_82599EB)
-               ixgbe_reset_pipeline_82599(hw);
 
-       if (got_lock)
-               hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
+       ret_val = hw->mac.ops.prot_autoc_write(hw, autoc_reg, locked);
+       if (ret_val != IXGBE_SUCCESS)
+               goto out;
 
        led_reg &= ~IXGBE_LED_MODE_MASK(index);
        led_reg &= ~IXGBE_LED_BLINK(index);
@@ -3506,6 +3565,8 @@ u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw)
                break;
        case ixgbe_mac_82599EB:
        case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
                pcie_offset = IXGBE_PCIE_MSIX_82599_CAPS;
                max_msix_count = IXGBE_MAX_MSIX_VECTORS_82599;
                break;
@@ -4019,8 +4080,13 @@ s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
        }
 
        if ((links_reg & IXGBE_LINKS_SPEED_82599) ==
-           IXGBE_LINKS_SPEED_10G_82599)
+           IXGBE_LINKS_SPEED_10G_82599) {
                *speed = IXGBE_LINK_SPEED_10GB_FULL;
+               if (hw->mac.type > ixgbe_mac_X550) {
+                       if (links_reg & IXGBE_LINKS_SPEED_NON_STD)
+                               *speed = IXGBE_LINK_SPEED_2_5GB_FULL;
+               }
+       }
        else if ((links_reg & IXGBE_LINKS_SPEED_82599) ==
                 IXGBE_LINKS_SPEED_1G_82599)
                *speed = IXGBE_LINK_SPEED_1GB_FULL;
@@ -4186,7 +4252,7 @@ void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int pf)
  *  ixgbe_set_vlan_anti_spoofing - Enable/Disable VLAN anti-spoofing
  *  @hw: pointer to hardware structure
  *  @enable: enable or disable switch for VLAN anti-spoofing
- *  @pf: Virtual Function pool - VF Pool to set for VLAN anti-spoofing
+ *  @vf: Virtual Function pool - VF Pool to set for VLAN anti-spoofing
  *
  **/
 void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf)
@@ -4280,41 +4346,50 @@ u8 ixgbe_calculate_checksum(u8 *buffer, u32 length)
  *  @buffer: contains the command to write and where the return status will
  *   be placed
  *  @length: length of buffer, must be multiple of 4 bytes
+ *  @return_data: read and return data from the buffer (true) or not (false)
+ *   Needed because FW structures are big endian and decoding of
+ *   these fields can be 8 bit or 16 bit based on command. Decoding
+ *   is not easily understood without making a table of commands.
+ *   So we will leave this up to the caller to read back the data
+ *   in these cases.
  *
  *  Communicates with the manageability block.  On success return IXGBE_SUCCESS
  *  else return IXGBE_ERR_HOST_INTERFACE_COMMAND.
  **/
 s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer,
-                                u32 length)
+                                u32 length, bool return_data)
 {
-       u32 hicr, i, bi;
+       u32 hicr, i, bi, fwsts;
        u32 hdr_size = sizeof(struct ixgbe_hic_hdr);
-       u8 buf_len, dword_len;
-
-       s32 ret_val = IXGBE_SUCCESS;
+       u16 buf_len;
+       u8 dword_len;
 
        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;
+       if (length == 0 || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) {
+               DEBUGOUT1("Buffer length failure buffersize=%d.\n", length);
+               return IXGBE_ERR_HOST_INTERFACE_COMMAND;
        }
+       /* Set bit 9 of FWSTS clearing FW reset indication */
+       fwsts = IXGBE_READ_REG(hw, IXGBE_FWSTS);
+       IXGBE_WRITE_REG(hw, IXGBE_FWSTS, fwsts | IXGBE_FWSTS_FWRI);
 
        /* 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;
+               return IXGBE_ERR_HOST_INTERFACE_COMMAND;
+       }
+
+       /* Calculate length in DWORDs. We must be DWORD aligned */
+       if ((length % (sizeof(u32))) != 0) {
+               DEBUGOUT("Buffer length failure, not aligned to dword");
+               return IXGBE_ERR_INVALID_ARGUMENT;
        }
 
-       /* Calculate length in DWORDs */
        dword_len = length >> 2;
 
-       /*
-        * The device driver writes the relevant command block
+       /* The device driver writes the relevant command block
         * into the ram area.
         */
        for (i = 0; i < dword_len; i++)
@@ -4331,14 +4406,17 @@ s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer,
                msec_delay(1);
        }
 
-       /* Check command successful completion. */
+       /* Check command 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;
+           !(IXGBE_READ_REG(hw, IXGBE_HICR) & IXGBE_HICR_SV)) {
+               ERROR_REPORT1(IXGBE_ERROR_CAUTION,
+                            "Command has failed with no status valid.\n");
+               return IXGBE_ERR_HOST_INTERFACE_COMMAND;
        }
 
+       if (!return_data)
+               return 0;
+
        /* Calculate length in DWORDs */
        dword_len = hdr_size >> 2;
 
@@ -4351,25 +4429,23 @@ s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer,
        /* 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;
+               return 0;
 
-       if (length < (buf_len + hdr_size)) {
+       if (length < buf_len + hdr_size) {
                DEBUGOUT("Buffer not large enough for reply message.\n");
-               ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
-               goto out;
+               return IXGBE_ERR_HOST_INTERFACE_COMMAND;
        }
 
        /* 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)*/
+       /* 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;
+       return 0;
 }
 
 /**
@@ -4416,7 +4492,7 @@ s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min,
 
        for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
                ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd,
-                                                      sizeof(fw_cmd));
+                                                      sizeof(fw_cmd), true);
                if (ret_val != IXGBE_SUCCESS)
                        continue;
 
@@ -4534,6 +4610,175 @@ void ixgbe_clear_tx_pending(struct ixgbe_hw *hw)
        IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
 }
 
+STATIC const u8 ixgbe_emc_temp_data[4] = {
+       IXGBE_EMC_INTERNAL_DATA,
+       IXGBE_EMC_DIODE1_DATA,
+       IXGBE_EMC_DIODE2_DATA,
+       IXGBE_EMC_DIODE3_DATA
+};
+STATIC const u8 ixgbe_emc_therm_limit[4] = {
+       IXGBE_EMC_INTERNAL_THERM_LIMIT,
+       IXGBE_EMC_DIODE1_THERM_LIMIT,
+       IXGBE_EMC_DIODE2_THERM_LIMIT,
+       IXGBE_EMC_DIODE3_THERM_LIMIT
+};
+
+/**
+ *  ixgbe_get_thermal_sensor_data - Gathers thermal sensor data
+ *  @hw: pointer to hardware structure
+ *  @data: pointer to the thermal sensor data structure
+ *
+ *  Returns the thermal sensor data structure
+ **/
+s32 ixgbe_get_thermal_sensor_data_generic(struct ixgbe_hw *hw)
+{
+       s32 status = IXGBE_SUCCESS;
+       u16 ets_offset;
+       u16 ets_cfg;
+       u16 ets_sensor;
+       u8  num_sensors;
+       u8  sensor_index;
+       u8  sensor_location;
+       u8  i;
+       struct ixgbe_thermal_sensor_data *data = &hw->mac.thermal_sensor_data;
+
+       DEBUGFUNC("ixgbe_get_thermal_sensor_data_generic");
+
+       /* Only support thermal sensors attached to 82599 physical port 0 */
+       if ((hw->mac.type != ixgbe_mac_82599EB) ||
+           (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)) {
+               status = IXGBE_NOT_IMPLEMENTED;
+               goto out;
+       }
+
+       status = hw->eeprom.ops.read(hw, IXGBE_ETS_CFG, &ets_offset);
+       if (status)
+               goto out;
+
+       if ((ets_offset == 0x0000) || (ets_offset == 0xFFFF)) {
+               status = IXGBE_NOT_IMPLEMENTED;
+               goto out;
+       }
+
+       status = hw->eeprom.ops.read(hw, ets_offset, &ets_cfg);
+       if (status)
+               goto out;
+
+       if (((ets_cfg & IXGBE_ETS_TYPE_MASK) >> IXGBE_ETS_TYPE_SHIFT)
+               != IXGBE_ETS_TYPE_EMC) {
+               status = IXGBE_NOT_IMPLEMENTED;
+               goto out;
+       }
+
+       num_sensors = (ets_cfg & IXGBE_ETS_NUM_SENSORS_MASK);
+       if (num_sensors > IXGBE_MAX_SENSORS)
+               num_sensors = IXGBE_MAX_SENSORS;
+
+       for (i = 0; i < num_sensors; i++) {
+               status = hw->eeprom.ops.read(hw, (ets_offset + 1 + i),
+                                            &ets_sensor);
+               if (status)
+                       goto out;
+
+               sensor_index = ((ets_sensor & IXGBE_ETS_DATA_INDEX_MASK) >>
+                               IXGBE_ETS_DATA_INDEX_SHIFT);
+               sensor_location = ((ets_sensor & IXGBE_ETS_DATA_LOC_MASK) >>
+                                  IXGBE_ETS_DATA_LOC_SHIFT);
+
+               if (sensor_location != 0) {
+                       status = hw->phy.ops.read_i2c_byte(hw,
+                                       ixgbe_emc_temp_data[sensor_index],
+                                       IXGBE_I2C_THERMAL_SENSOR_ADDR,
+                                       &data->sensor[i].temp);
+                       if (status)
+                               goto out;
+               }
+       }
+out:
+       return status;
+}
+
+/**
+ *  ixgbe_init_thermal_sensor_thresh_generic - Inits thermal sensor thresholds
+ *  @hw: pointer to hardware structure
+ *
+ *  Inits the thermal sensor thresholds according to the NVM map
+ *  and save off the threshold and location values into mac.thermal_sensor_data
+ **/
+s32 ixgbe_init_thermal_sensor_thresh_generic(struct ixgbe_hw *hw)
+{
+       s32 status = IXGBE_SUCCESS;
+       u16 offset;
+       u16 ets_offset;
+       u16 ets_cfg;
+       u16 ets_sensor;
+       u8  low_thresh_delta;
+       u8  num_sensors;
+       u8  sensor_index;
+       u8  sensor_location;
+       u8  therm_limit;
+       u8  i;
+       struct ixgbe_thermal_sensor_data *data = &hw->mac.thermal_sensor_data;
+
+       DEBUGFUNC("ixgbe_init_thermal_sensor_thresh_generic");
+
+       memset(data, 0, sizeof(struct ixgbe_thermal_sensor_data));
+
+       /* Only support thermal sensors attached to 82599 physical port 0 */
+       if ((hw->mac.type != ixgbe_mac_82599EB) ||
+           (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1))
+               return IXGBE_NOT_IMPLEMENTED;
+
+       offset = IXGBE_ETS_CFG;
+       if (hw->eeprom.ops.read(hw, offset, &ets_offset))
+               goto eeprom_err;
+       if ((ets_offset == 0x0000) || (ets_offset == 0xFFFF))
+               return IXGBE_NOT_IMPLEMENTED;
+
+       offset = ets_offset;
+       if (hw->eeprom.ops.read(hw, offset, &ets_cfg))
+               goto eeprom_err;
+       if (((ets_cfg & IXGBE_ETS_TYPE_MASK) >> IXGBE_ETS_TYPE_SHIFT)
+               != IXGBE_ETS_TYPE_EMC)
+               return IXGBE_NOT_IMPLEMENTED;
+
+       low_thresh_delta = ((ets_cfg & IXGBE_ETS_LTHRES_DELTA_MASK) >>
+                            IXGBE_ETS_LTHRES_DELTA_SHIFT);
+       num_sensors = (ets_cfg & IXGBE_ETS_NUM_SENSORS_MASK);
+
+       for (i = 0; i < num_sensors; i++) {
+               offset = ets_offset + 1 + i;
+               if (hw->eeprom.ops.read(hw, offset, &ets_sensor)) {
+                       ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE,
+                                     "eeprom read at offset %d failed",
+                                     offset);
+                       continue;
+               }
+               sensor_index = ((ets_sensor & IXGBE_ETS_DATA_INDEX_MASK) >>
+                               IXGBE_ETS_DATA_INDEX_SHIFT);
+               sensor_location = ((ets_sensor & IXGBE_ETS_DATA_LOC_MASK) >>
+                                  IXGBE_ETS_DATA_LOC_SHIFT);
+               therm_limit = ets_sensor & IXGBE_ETS_DATA_HTHRESH_MASK;
+
+               hw->phy.ops.write_i2c_byte(hw,
+                       ixgbe_emc_therm_limit[sensor_index],
+                       IXGBE_I2C_THERMAL_SENSOR_ADDR, therm_limit);
+
+               if ((i < IXGBE_MAX_SENSORS) && (sensor_location != 0)) {
+                       data->sensor[i].location = sensor_location;
+                       data->sensor[i].caution_thresh = therm_limit;
+                       data->sensor[i].max_op_thresh = therm_limit -
+                                                       low_thresh_delta;
+               }
+       }
+       return status;
+
+eeprom_err:
+       ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE,
+                     "eeprom read at offset %d failed", offset);
+       return IXGBE_NOT_IMPLEMENTED;
+}
+
 
 /**
  * ixgbe_dcb_get_rtrup2tc_generic - read rtrup2tc reg
@@ -4592,3 +4837,30 @@ void ixgbe_enable_rx_generic(struct ixgbe_hw *hw)
                }
        }
 }
+
+/**
+ * ixgbe_mng_enabled - Is the manageability engine enabled?
+ * @hw: pointer to hardware structure
+ *
+ * Returns true if the manageability engine is enabled.
+ **/
+bool ixgbe_mng_enabled(struct ixgbe_hw *hw)
+{
+       u32 fwsm, manc, factps;
+
+       fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM);
+       if ((fwsm & IXGBE_FWSM_MODE_MASK) != IXGBE_FWSM_FW_MODE_PT)
+               return false;
+
+       manc = IXGBE_READ_REG(hw, IXGBE_MANC);
+       if (!(manc & IXGBE_MANC_RCV_TCO_EN))
+               return false;
+
+       if (hw->mac.type <= ixgbe_mac_X540) {
+               factps = IXGBE_READ_REG(hw, IXGBE_FACTPS);
+               if (factps & IXGBE_FACTPS_MNGCG)
+                       return false;
+       }
+
+       return true;
+}