i40e: move to drivers/net/
[dpdk.git] / lib / librte_pmd_ixgbe / ixgbe / ixgbe_x550.c
index 06d66dd..9572697 100644 (file)
@@ -54,30 +54,30 @@ s32 ixgbe_init_ops_X550(struct ixgbe_hw *hw)
        DEBUGFUNC("ixgbe_init_ops_X550");
 
        ret_val = ixgbe_init_ops_X540(hw);
-       mac->ops.dmac_config = &ixgbe_dmac_config_X550;
-       mac->ops.dmac_config_tcs = &ixgbe_dmac_config_tcs_X550;
-       mac->ops.dmac_update_tcs = &ixgbe_dmac_update_tcs_X550;
-       mac->ops.setup_eee = &ixgbe_setup_eee_X550;
+       mac->ops.dmac_config = ixgbe_dmac_config_X550;
+       mac->ops.dmac_config_tcs = ixgbe_dmac_config_tcs_X550;
+       mac->ops.dmac_update_tcs = ixgbe_dmac_update_tcs_X550;
+       mac->ops.setup_eee = ixgbe_setup_eee_X550;
        mac->ops.set_source_address_pruning =
-                       &ixgbe_set_source_address_pruning_X550;
+                       ixgbe_set_source_address_pruning_X550;
        mac->ops.set_ethertype_anti_spoofing =
-                       &ixgbe_set_ethertype_anti_spoofing_X550;
-
-       mac->ops.get_rtrup2tc = &ixgbe_dcb_get_rtrup2tc_generic;
-       eeprom->ops.init_params = &ixgbe_init_eeprom_params_X550;
-       eeprom->ops.calc_checksum = &ixgbe_calc_eeprom_checksum_X550;
-       eeprom->ops.read = &ixgbe_read_ee_hostif_X550;
-       eeprom->ops.read_buffer = &ixgbe_read_ee_hostif_buffer_X550;
-       eeprom->ops.write = &ixgbe_write_ee_hostif_X550;
-       eeprom->ops.write_buffer = &ixgbe_write_ee_hostif_buffer_X550;
-       eeprom->ops.update_checksum = &ixgbe_update_eeprom_checksum_X550;
-       eeprom->ops.validate_checksum = &ixgbe_validate_eeprom_checksum_X550;
-
-       mac->ops.disable_mdd = &ixgbe_disable_mdd_X550;
-       mac->ops.enable_mdd = &ixgbe_enable_mdd_X550;
-       mac->ops.mdd_event = &ixgbe_mdd_event_X550;
-       mac->ops.restore_mdd_vf = &ixgbe_restore_mdd_vf_X550;
-       mac->ops.disable_rx = &ixgbe_disable_rx_x550;
+                       ixgbe_set_ethertype_anti_spoofing_X550;
+
+       mac->ops.get_rtrup2tc = ixgbe_dcb_get_rtrup2tc_generic;
+       eeprom->ops.init_params = ixgbe_init_eeprom_params_X550;
+       eeprom->ops.calc_checksum = ixgbe_calc_eeprom_checksum_X550;
+       eeprom->ops.read = ixgbe_read_ee_hostif_X550;
+       eeprom->ops.read_buffer = ixgbe_read_ee_hostif_buffer_X550;
+       eeprom->ops.write = ixgbe_write_ee_hostif_X550;
+       eeprom->ops.write_buffer = ixgbe_write_ee_hostif_buffer_X550;
+       eeprom->ops.update_checksum = ixgbe_update_eeprom_checksum_X550;
+       eeprom->ops.validate_checksum = ixgbe_validate_eeprom_checksum_X550;
+
+       mac->ops.disable_mdd = ixgbe_disable_mdd_X550;
+       mac->ops.enable_mdd = ixgbe_enable_mdd_X550;
+       mac->ops.mdd_event = ixgbe_mdd_event_X550;
+       mac->ops.restore_mdd_vf = ixgbe_restore_mdd_vf_X550;
+       mac->ops.disable_rx = ixgbe_disable_rx_x550;
        return ret_val;
 }
 
@@ -94,10 +94,8 @@ STATIC s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw)
        switch (hw->device_id) {
        case IXGBE_DEV_ID_X550EM_X_SFP:
                /* set up for CS4227 usage */
-               hw->phy.lan_id = IXGBE_READ_REG(hw, IXGBE_STATUS) &
-                                IXGBE_STATUS_LAN_ID_1;
                hw->phy.phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM;
-               if (hw->phy.lan_id) {
+               if (hw->bus.lan_id) {
 
                        esdp &= ~(IXGBE_ESDP_SDP1_NATIVE | IXGBE_ESDP_SDP1);
                        esdp |= IXGBE_ESDP_SDP1_DIR;
@@ -111,9 +109,11 @@ STATIC s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw)
                hw->phy.type = ixgbe_phy_x550em_kx4;
                break;
        case IXGBE_DEV_ID_X550EM_X_KR:
-       case IXGBE_DEV_ID_X550EM_X:
                hw->phy.type = ixgbe_phy_x550em_kr;
                break;
+       case IXGBE_DEV_ID_X550EM_X_1G_T:
+       case IXGBE_DEV_ID_X550EM_X_10G_T:
+               return ixgbe_identify_phy_generic(hw);
        default:
                break;
        }
@@ -173,35 +173,35 @@ s32 ixgbe_init_ops_X550EM(struct ixgbe_hw *hw)
        mac->ops.disable_sec_rx_path = NULL;
        mac->ops.enable_sec_rx_path = NULL;
 
-       /* PCIe bus info not supported in X550EM */
-       mac->ops.get_bus_info = NULL;
+       /* X550EM bus type is internal*/
+       hw->bus.type = ixgbe_bus_type_internal;
+       mac->ops.get_bus_info = ixgbe_get_bus_info_X550em;
 
        mac->ops.read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550;
        mac->ops.write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550;
-       mac->ops.get_media_type = &ixgbe_get_media_type_X550em;
-       mac->ops.setup_sfp = &ixgbe_setup_sfp_modules_X550em;
-       mac->ops.get_link_capabilities = &ixgbe_get_link_capabilities_X550em;
-       mac->ops.reset_hw = &ixgbe_reset_hw_X550em;
+       mac->ops.get_media_type = ixgbe_get_media_type_X550em;
+       mac->ops.setup_sfp = ixgbe_setup_sfp_modules_X550em;
+       mac->ops.get_link_capabilities = ixgbe_get_link_capabilities_X550em;
+       mac->ops.reset_hw = ixgbe_reset_hw_X550em;
        mac->ops.get_supported_physical_layer =
-                                   &ixgbe_get_supported_physical_layer_X550em;
+                                   ixgbe_get_supported_physical_layer_X550em;
 
        /* PHY */
-       phy->ops.init = &ixgbe_init_phy_ops_X550em;
-       phy->ops.identify = &ixgbe_identify_phy_x550em;
-       phy->ops.read_reg = ixgbe_read_phy_reg_x550em;
-       phy->ops.write_reg = ixgbe_write_phy_reg_x550em;
-       phy->ops.setup_link = ixgbe_setup_kr_x550em;
+       phy->ops.init = ixgbe_init_phy_ops_X550em;
+       phy->ops.identify = ixgbe_identify_phy_x550em;
+       if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper)
+               phy->ops.set_phy_power = NULL;
 
 
        /* EEPROM */
-       eeprom->ops.init_params = &ixgbe_init_eeprom_params_X540;
-       eeprom->ops.read = &ixgbe_read_ee_hostif_X550;
-       eeprom->ops.read_buffer = &ixgbe_read_ee_hostif_buffer_X550;
-       eeprom->ops.write = &ixgbe_write_ee_hostif_X550;
-       eeprom->ops.write_buffer = &ixgbe_write_ee_hostif_buffer_X550;
-       eeprom->ops.update_checksum = &ixgbe_update_eeprom_checksum_X550;
-       eeprom->ops.validate_checksum = &ixgbe_validate_eeprom_checksum_X550;
-       eeprom->ops.calc_checksum = &ixgbe_calc_eeprom_checksum_X550;
+       eeprom->ops.init_params = ixgbe_init_eeprom_params_X540;
+       eeprom->ops.read = ixgbe_read_ee_hostif_X550;
+       eeprom->ops.read_buffer = ixgbe_read_ee_hostif_buffer_X550;
+       eeprom->ops.write = ixgbe_write_ee_hostif_X550;
+       eeprom->ops.write_buffer = ixgbe_write_ee_hostif_buffer_X550;
+       eeprom->ops.update_checksum = ixgbe_update_eeprom_checksum_X550;
+       eeprom->ops.validate_checksum = ixgbe_validate_eeprom_checksum_X550;
+       eeprom->ops.calc_checksum = ixgbe_calc_eeprom_checksum_X550;
 
        return ret_val;
 }
@@ -403,10 +403,9 @@ s32 ixgbe_setup_eee_X550(struct ixgbe_hw *hw, bool enable_eee)
 
                        hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_EEE_ADVT,
                                IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_eee_reg);
-               } else if (hw->device_id == IXGBE_DEV_ID_X550EM_X_KR ||
-                          hw->device_id == IXGBE_DEV_ID_X550EM_X) {
+               } else if (hw->device_id == IXGBE_DEV_ID_X550EM_X_KR) {
                        status = ixgbe_read_iosf_sb_reg_x550(hw,
-                               IXGBE_KRM_LINK_CTRL_1(hw->phy.lan_id),
+                               IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
                                IXGBE_SB_IOSF_TARGET_KR_PHY, &link_reg);
                        if (status != IXGBE_SUCCESS)
                                return status;
@@ -415,7 +414,7 @@ s32 ixgbe_setup_eee_X550(struct ixgbe_hw *hw, bool enable_eee)
                                    IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KX;
 
                        status = ixgbe_write_iosf_sb_reg_x550(hw,
-                               IXGBE_KRM_LINK_CTRL_1(hw->phy.lan_id),
+                               IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
                                IXGBE_SB_IOSF_TARGET_KR_PHY, link_reg);
                        if (status != IXGBE_SUCCESS)
                                return status;
@@ -434,10 +433,9 @@ s32 ixgbe_setup_eee_X550(struct ixgbe_hw *hw, bool enable_eee)
 
                        hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_EEE_ADVT,
                                IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_eee_reg);
-               } else if (hw->device_id == IXGBE_DEV_ID_X550EM_X_KR ||
-                          hw->device_id == IXGBE_DEV_ID_X550EM_X) {
+               } else if (hw->device_id == IXGBE_DEV_ID_X550EM_X_KR) {
                        status = ixgbe_read_iosf_sb_reg_x550(hw,
-                               IXGBE_KRM_LINK_CTRL_1(hw->phy.lan_id),
+                               IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
                                IXGBE_SB_IOSF_TARGET_KR_PHY, &link_reg);
                        if (status != IXGBE_SUCCESS)
                                return status;
@@ -446,7 +444,7 @@ s32 ixgbe_setup_eee_X550(struct ixgbe_hw *hw, bool enable_eee)
                                IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KX);
 
                        status = ixgbe_write_iosf_sb_reg_x550(hw,
-                               IXGBE_KRM_LINK_CTRL_1(hw->phy.lan_id),
+                               IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
                                IXGBE_SB_IOSF_TARGET_KR_PHY, link_reg);
                        if (status != IXGBE_SUCCESS)
                                return status;
@@ -543,7 +541,7 @@ s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr,
                        break;
        }
 
-       if ((command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) != 0) {
+       if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) {
                error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >>
                         IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT;
                ERROR_REPORT2(IXGBE_ERROR_POLLING,
@@ -591,7 +589,7 @@ s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr,
                        break;
        }
 
-       if ((command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) != 0) {
+       if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) {
                error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >>
                         IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT;
                ERROR_REPORT2(IXGBE_ERROR_POLLING,
@@ -766,7 +764,6 @@ enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw)
 
        /* Detect if there is a copper PHY attached. */
        switch (hw->device_id) {
-       case IXGBE_DEV_ID_X550EM_X:
        case IXGBE_DEV_ID_X550EM_X_KR:
        case IXGBE_DEV_ID_X550EM_X_KX4:
                media_type = ixgbe_media_type_backplane;
@@ -774,6 +771,10 @@ enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw)
        case IXGBE_DEV_ID_X550EM_X_SFP:
                media_type = ixgbe_media_type_fiber;
                break;
+       case IXGBE_DEV_ID_X550EM_X_1G_T:
+       case IXGBE_DEV_ID_X550EM_X_10G_T:
+               media_type = ixgbe_media_type_copper;
+               break;
        default:
                media_type = ixgbe_media_type_unknown;
                break;
@@ -789,6 +790,7 @@ s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw)
 {
        bool setup_linear;
        u16 reg_slice, edc_mode;
+       s32 ret_val;
 
        DEBUGFUNC("ixgbe_setup_sfp_modules_X550em");
 
@@ -819,9 +821,9 @@ s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw)
        hw->phy.ops.reset = NULL;
 
        /* The CS4227 slice address is the base address + the port-pair reg
-        * offset. I.e. Slice 0 = 0x0000 and slice 1 = 0x1000.
+        * offset. I.e. Slice 0 = 0x12B0 and slice 1 = 0x22B0.
         */
-       reg_slice = IXGBE_CS4227_SPARE24_LSB + (hw->phy.lan_id << 12);
+       reg_slice = IXGBE_CS4227_SPARE24_LSB + (hw->bus.lan_id << 12);
 
        if (setup_linear)
                edc_mode = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
@@ -829,8 +831,14 @@ s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw)
                edc_mode = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
 
        /* Configure CS4227 for connection type. */
-       return hw->phy.ops.write_i2c_combined(hw, IXGBE_CS4227,
-                                             reg_slice, edc_mode);
+       ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
+                                          edc_mode);
+
+       if (ret_val != IXGBE_SUCCESS)
+               ret_val = ixgbe_write_i2c_combined(hw, 0x80, reg_slice,
+                                                  edc_mode);
+
+       return ret_val;
 }
 
 /**
@@ -882,13 +890,13 @@ s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw,
 
                /* Link capabilities are based on SFP */
                if (hw->phy.multispeed_fiber)
-                       *speed |= IXGBE_LINK_SPEED_10GB_FULL |
-                                 IXGBE_LINK_SPEED_1GB_FULL;
+                       *speed = IXGBE_LINK_SPEED_10GB_FULL |
+                                IXGBE_LINK_SPEED_1GB_FULL;
                else
                        *speed = IXGBE_LINK_SPEED_10GB_FULL;
        } else {
-               *speed |= IXGBE_LINK_SPEED_10GB_FULL |
-                         IXGBE_LINK_SPEED_1GB_FULL;
+               *speed = IXGBE_LINK_SPEED_10GB_FULL |
+                        IXGBE_LINK_SPEED_1GB_FULL;
                *autoneg = true;
        }
 
@@ -913,10 +921,9 @@ s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw)
 
        if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP) {
                esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
-               phy->lan_id = IXGBE_READ_REG(hw, IXGBE_STATUS) &
-                             IXGBE_STATUS_LAN_ID_1;
                phy->phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM;
-               if (phy->lan_id) {
+
+               if (hw->bus.lan_id) {
                        esdp &= ~(IXGBE_ESDP_SDP1_NATIVE | IXGBE_ESDP_SDP1);
                        esdp |= IXGBE_ESDP_SDP1_DIR;
                }
@@ -936,8 +943,18 @@ s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw)
 
        /* Set functions pointers based on phy type */
        switch (hw->phy.type) {
+       case ixgbe_phy_x550em_kx4:
+               phy->ops.setup_link = ixgbe_setup_kx4_x550em;
+               phy->ops.read_reg = ixgbe_read_phy_reg_x550em;
+               phy->ops.write_reg = ixgbe_write_phy_reg_x550em;
+               break;
        case ixgbe_phy_x550em_kr:
                phy->ops.setup_link = ixgbe_setup_kr_x550em;
+               phy->ops.read_reg = ixgbe_read_phy_reg_x550em;
+               phy->ops.write_reg = ixgbe_write_phy_reg_x550em;
+               break;
+       case ixgbe_phy_x550em_ext_t:
+               phy->ops.setup_internal_link = ixgbe_setup_internal_phy_x550em;
                break;
        default:
                break;
@@ -979,6 +996,13 @@ s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw)
        if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
                return status;
 
+       /* start the external PHY */
+       if (hw->phy.type == ixgbe_phy_x550em_ext_t) {
+               status = ixgbe_init_ext_t_x550em(hw);
+               if (status)
+                       return status;
+       }
+
        /* Setup SFP module if there is one present. */
        if (hw->phy.sfp_setup_needed) {
                status = hw->mac.ops.setup_sfp(hw);
@@ -1043,6 +1067,97 @@ mac_reset_top:
        hw->mac.num_rar_entries = 128;
        hw->mac.ops.init_rx_addrs(hw);
 
+
+       return status;
+}
+
+/**
+ * ixgbe_init_ext_t_x550em - Start (unstall) the external Base T PHY.
+ * @hw: pointer to hardware structure
+ */
+s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw)
+{
+       u32 status;
+       u16 reg;
+       u32 retries = 1;
+
+       /* TODO: The number of attempts and delay between attempts is undefined */
+       do {
+               /* decrement retries counter and exit if we hit 0 */
+               if (retries < 1) {
+                       ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE,
+                                     "External PHY not yet finished resetting.");
+                       return IXGBE_ERR_PHY;
+               }
+               retries--;
+
+               usec_delay(0);
+
+               status = hw->phy.ops.read_reg(hw,
+                                             IXGBE_MDIO_TX_VENDOR_ALARMS_3,
+                                             IXGBE_MDIO_PMA_PMD_DEV_TYPE,
+                                             &reg);
+
+               if (status != IXGBE_SUCCESS)
+                       return status;
+
+               /* Verify PHY FW reset has completed */
+       } while ((reg & IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK) != 1);
+
+       /* Set port to low power mode */
+       status = hw->phy.ops.read_reg(hw,
+                                     IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL,
+                                     IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+                                     &reg);
+
+       if (status != IXGBE_SUCCESS)
+               return status;
+
+       reg |= IXGBE_MDIO_PHY_SET_LOW_POWER_MODE;
+
+       status = hw->phy.ops.write_reg(hw,
+                                      IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL,
+                                      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+                                      reg);
+
+       if (status != IXGBE_SUCCESS)
+               return status;
+
+       /* Enable the transmitter */
+       status = hw->phy.ops.read_reg(hw,
+                                     IXGBE_MDIO_PMD_STD_TX_DISABLE_CNTR,
+                                     IXGBE_MDIO_PMA_PMD_DEV_TYPE,
+                                     &reg);
+
+       if (status != IXGBE_SUCCESS)
+               return status;
+
+       reg &= ~IXGBE_MDIO_PMD_GLOBAL_TX_DISABLE;
+
+       status = hw->phy.ops.write_reg(hw,
+                                      IXGBE_MDIO_PMD_STD_TX_DISABLE_CNTR,
+                                      IXGBE_MDIO_PMA_PMD_DEV_TYPE,
+                                      reg);
+
+       if (status != IXGBE_SUCCESS)
+               return status;
+
+       /* Un-stall the PHY FW */
+       status = hw->phy.ops.read_reg(hw,
+                                     IXGBE_MDIO_GLOBAL_RES_PR_10,
+                                     IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+                                     &reg);
+
+       if (status != IXGBE_SUCCESS)
+               return status;
+
+       reg &= ~IXGBE_MDIO_POWER_UP_STALL;
+
+       status = hw->phy.ops.write_reg(hw,
+                                      IXGBE_MDIO_GLOBAL_RES_PR_10,
+                                      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+                                      reg);
+
        return status;
 }
 
@@ -1058,8 +1173,10 @@ s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw)
        u32 reg_val;
 
        status = ixgbe_read_iosf_sb_reg_x550(hw,
-               IXGBE_KRM_LINK_CTRL_1(hw->phy.lan_id),
+               IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
                IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
+       if (status)
+               return status;
 
        reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
        reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_FEC_REQ;
@@ -1078,54 +1195,107 @@ s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw)
        /* Restart auto-negotiation. */
        reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART;
        status = ixgbe_write_iosf_sb_reg_x550(hw,
-               IXGBE_KRM_LINK_CTRL_1(hw->phy.lan_id),
+               IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
                IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
 
        return status;
 }
 
 /**
- *  ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI.
+ *  ixgbe_setup_kx4_x550em - Configure the KX4 PHY.
+ *  @hw: pointer to hardware structure
+ *
+ *  Configures the integrated KX4 PHY.
+ **/
+s32 ixgbe_setup_kx4_x550em(struct ixgbe_hw *hw)
+{
+       s32 status;
+       u32 reg_val;
+
+       status = ixgbe_read_iosf_sb_reg_x550(hw, IXGBE_KX4_LINK_CNTL_1,
+               IXGBE_SB_IOSF_TARGET_KX4_PCS0 + hw->bus.lan_id, &reg_val);
+       if (status)
+               return status;
+
+       reg_val &= ~(IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4 |
+                       IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX);
+
+       reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_ENABLE;
+
+       /* Advertise 10G support. */
+       if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL)
+               reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4;
+
+       /* Advertise 1G support. */
+       if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL)
+               reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX;
+
+       /* Restart auto-negotiation. */
+       reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_RESTART;
+       status = ixgbe_write_iosf_sb_reg_x550(hw, IXGBE_KX4_LINK_CNTL_1,
+               IXGBE_SB_IOSF_TARGET_KX4_PCS0 + hw->bus.lan_id, reg_val);
+
+       return status;
+}
+
+/**
+ *  ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode.
  *  @hw: pointer to hardware structure
+ *  @speed: the link speed to force
  *
- *  Configures the integrated KR PHY to use iXFI mode.
+ *  Configures the integrated KR PHY to use iXFI mode. Used to connect an
+ *  internal and external PHY at a specific speed, without autonegotiation.
  **/
-s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw)
+STATIC s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed)
 {
        s32 status;
        u32 reg_val;
 
        /* Disable AN and force speed to 10G Serial. */
        status = ixgbe_read_iosf_sb_reg_x550(hw,
-                                       IXGBE_KRM_LINK_CTRL_1(hw->phy.lan_id),
+                                       IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
                                        IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
        if (status != IXGBE_SUCCESS)
                return status;
+
        reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
        reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
-       reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G;
+
+       /* Select forced link speed for internal PHY. */
+       switch (*speed) {
+       case IXGBE_LINK_SPEED_10GB_FULL:
+               reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G;
+               break;
+       case IXGBE_LINK_SPEED_1GB_FULL:
+               reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G;
+               break;
+       default:
+               /* Other link speeds are not supported by internal KR PHY. */
+               return IXGBE_ERR_LINK_SETUP;
+       }
+
        status = ixgbe_write_iosf_sb_reg_x550(hw,
-                                       IXGBE_KRM_LINK_CTRL_1(hw->phy.lan_id),
+                                       IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
                                        IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
        if (status != IXGBE_SUCCESS)
                return status;
 
        /* Disable training protocol FSM. */
        status = ixgbe_read_iosf_sb_reg_x550(hw,
-                               IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->phy.lan_id),
+                               IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
                                IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
        if (status != IXGBE_SUCCESS)
                return status;
        reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_CONV_WO_PROTOCOL;
        status = ixgbe_write_iosf_sb_reg_x550(hw,
-                               IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->phy.lan_id),
+                               IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
                                IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
        if (status != IXGBE_SUCCESS)
                return status;
 
        /* Disable Flex from training TXFFE. */
        status = ixgbe_read_iosf_sb_reg_x550(hw,
-                               IXGBE_KRM_DSP_TXFFE_STATE_4(hw->phy.lan_id),
+                               IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id),
                                IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
        if (status != IXGBE_SUCCESS)
                return status;
@@ -1133,12 +1303,12 @@ s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw)
        reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN;
        reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN;
        status = ixgbe_write_iosf_sb_reg_x550(hw,
-                               IXGBE_KRM_DSP_TXFFE_STATE_4(hw->phy.lan_id),
+                               IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id),
                                IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
        if (status != IXGBE_SUCCESS)
                return status;
        status = ixgbe_read_iosf_sb_reg_x550(hw,
-                               IXGBE_KRM_DSP_TXFFE_STATE_5(hw->phy.lan_id),
+                               IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id),
                                IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
        if (status != IXGBE_SUCCESS)
                return status;
@@ -1146,14 +1316,14 @@ s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw)
        reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN;
        reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN;
        status = ixgbe_write_iosf_sb_reg_x550(hw,
-                               IXGBE_KRM_DSP_TXFFE_STATE_5(hw->phy.lan_id),
+                               IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id),
                                IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
        if (status != IXGBE_SUCCESS)
                return status;
 
        /* Enable override for coefficients. */
        status = ixgbe_read_iosf_sb_reg_x550(hw,
-                               IXGBE_KRM_TX_COEFF_CTRL_1(hw->phy.lan_id),
+                               IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id),
                                IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
        if (status != IXGBE_SUCCESS)
                return status;
@@ -1162,25 +1332,93 @@ s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw)
        reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CPLUS1_OVRRD_EN;
        reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CMINUS1_OVRRD_EN;
        status = ixgbe_write_iosf_sb_reg_x550(hw,
-                               IXGBE_KRM_TX_COEFF_CTRL_1(hw->phy.lan_id),
+                               IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id),
                                IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
        if (status != IXGBE_SUCCESS)
                return status;
 
        /* Toggle port SW reset by AN reset. */
        status = ixgbe_read_iosf_sb_reg_x550(hw,
-                                       IXGBE_KRM_LINK_CTRL_1(hw->phy.lan_id),
+                                       IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
                                        IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
        if (status != IXGBE_SUCCESS)
                return status;
        reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART;
        status = ixgbe_write_iosf_sb_reg_x550(hw,
-                                       IXGBE_KRM_LINK_CTRL_1(hw->phy.lan_id),
+                                       IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
                                        IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
 
        return status;
 }
 
+/**
+ * ixgbe_setup_internal_phy_x550em - Configure integrated KR PHY
+ * @hw: point to hardware structure
+ *
+ * Configures the integrated KR PHY to talk to the external PHY. The base
+ * driver will call this function when it gets notification via interrupt from
+ * the external PHY. This function forces the internal PHY into iXFI mode at
+ * the correct speed.
+ *
+ * A return of a non-zero value indicates an error, and the base driver should
+ * not report link up.
+ */
+s32 ixgbe_setup_internal_phy_x550em(struct ixgbe_hw *hw)
+{
+       u32 status;
+       u16 lasi, autoneg_status, speed;
+       ixgbe_link_speed force_speed;
+
+       /* Verify that the external link status has changed */
+       status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_XENPAK_LASI_STATUS,
+                                     IXGBE_MDIO_PMA_PMD_DEV_TYPE,
+                                     &lasi);
+       if (status != IXGBE_SUCCESS)
+               return status;
+
+       /* If there was no change in link status, we can just exit */
+       if (!(lasi & IXGBE_XENPAK_LASI_LINK_STATUS_ALARM))
+               return IXGBE_SUCCESS;
+
+       /* we read this twice back to back to indicate current status */
+       status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
+                                     IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+                                     &autoneg_status);
+       if (status != IXGBE_SUCCESS)
+               return status;
+
+       status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
+                                     IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+                                     &autoneg_status);
+       if (status != IXGBE_SUCCESS)
+               return status;
+
+       /* If link is not up return an error indicating treat link as down */
+       if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS))
+               return IXGBE_ERR_INVALID_LINK_SETTINGS;
+
+       status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT,
+                                     IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+                                     &speed);
+
+       /* clear everything but the speed and duplex bits */
+       speed &= IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK;
+
+       switch (speed) {
+       case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_FULL:
+               force_speed = IXGBE_LINK_SPEED_10GB_FULL;
+               break;
+       case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB_FULL:
+               force_speed = IXGBE_LINK_SPEED_1GB_FULL;
+               break;
+       default:
+               /* Internal PHY does not support anything else */
+               return IXGBE_ERR_INVALID_LINK_SETTINGS;
+       }
+
+       return ixgbe_setup_ixfi_x550em(hw, &force_speed);
+}
+
 /**
  *  ixgbe_setup_phy_loopback_x550em - Configure the KR PHY for loopback.
  *  @hw: pointer to hardware structure
@@ -1194,7 +1432,7 @@ s32 ixgbe_setup_phy_loopback_x550em(struct ixgbe_hw *hw)
 
        /* Disable AN and force speed to 10G Serial. */
        status = ixgbe_read_iosf_sb_reg_x550(hw,
-               IXGBE_KRM_LINK_CTRL_1(hw->phy.lan_id),
+               IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
                IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
        if (status != IXGBE_SUCCESS)
                return status;
@@ -1202,47 +1440,47 @@ s32 ixgbe_setup_phy_loopback_x550em(struct ixgbe_hw *hw)
        reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
        reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G;
        status = ixgbe_write_iosf_sb_reg_x550(hw,
-               IXGBE_KRM_LINK_CTRL_1(hw->phy.lan_id),
+               IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
                IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
        if (status != IXGBE_SUCCESS)
                return status;
 
        /* Set near-end loopback clocks. */
        status = ixgbe_read_iosf_sb_reg_x550(hw,
-               IXGBE_KRM_PORT_CAR_GEN_CTRL(hw->phy.lan_id),
+               IXGBE_KRM_PORT_CAR_GEN_CTRL(hw->bus.lan_id),
                IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
        if (status != IXGBE_SUCCESS)
                return status;
        reg_val |= IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_32B;
        reg_val |= IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_KRPCS;
        status = ixgbe_write_iosf_sb_reg_x550(hw,
-               IXGBE_KRM_PORT_CAR_GEN_CTRL(hw->phy.lan_id),
+               IXGBE_KRM_PORT_CAR_GEN_CTRL(hw->bus.lan_id),
                IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
        if (status != IXGBE_SUCCESS)
                return status;
 
        /* Set loopback enable. */
        status = ixgbe_read_iosf_sb_reg_x550(hw,
-               IXGBE_KRM_PMD_DFX_BURNIN(hw->phy.lan_id),
+               IXGBE_KRM_PMD_DFX_BURNIN(hw->bus.lan_id),
                IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
        if (status != IXGBE_SUCCESS)
                return status;
        reg_val |= IXGBE_KRM_PMD_DFX_BURNIN_TX_RX_KR_LB_MASK;
        status = ixgbe_write_iosf_sb_reg_x550(hw,
-               IXGBE_KRM_PMD_DFX_BURNIN(hw->phy.lan_id),
+               IXGBE_KRM_PMD_DFX_BURNIN(hw->bus.lan_id),
                IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
        if (status != IXGBE_SUCCESS)
                return status;
 
        /* Training bypass. */
        status = ixgbe_read_iosf_sb_reg_x550(hw,
-               IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->phy.lan_id),
+               IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
                IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
        if (status != IXGBE_SUCCESS)
                return status;
        reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_PROTOCOL_BYPASS;
        status = ixgbe_write_iosf_sb_reg_x550(hw,
-               IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->phy.lan_id),
+               IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
                IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
 
        return status;
@@ -1264,10 +1502,10 @@ s32 ixgbe_read_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset,
        struct ixgbe_hic_read_shadow_ram buffer;
 
        DEBUGFUNC("ixgbe_read_ee_hostif_data_X550");
-       buffer.hdr.cmd = FW_READ_SHADOW_RAM_CMD;
-       buffer.hdr.buf_len1 = 0;
-       buffer.hdr.buf_len2 = FW_READ_SHADOW_RAM_LEN;
-       buffer.hdr.checksum = FW_DEFAULT_CHECKSUM;
+       buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD;
+       buffer.hdr.req.buf_lenh = 0;
+       buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN;
+       buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
 
        /* convert offset from words to bytes */
        buffer.address = IXGBE_CPU_TO_BE32(offset * 2);
@@ -1275,7 +1513,8 @@ s32 ixgbe_read_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset,
        buffer.length = IXGBE_CPU_TO_BE16(sizeof(u16));
 
        status = ixgbe_host_interface_command(hw, (u32 *)&buffer,
-                                             sizeof(buffer), false);
+                                             sizeof(buffer),
+                                             IXGBE_HI_COMMAND_TIMEOUT, false);
 
        if (status)
                return status;
@@ -1344,17 +1583,19 @@ s32 ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw,
                else
                        words_to_read = words;
 
-               buffer.hdr.cmd = FW_READ_SHADOW_RAM_CMD;
-               buffer.hdr.buf_len1 = 0;
-               buffer.hdr.buf_len2 = FW_READ_SHADOW_RAM_LEN;
-               buffer.hdr.checksum = FW_DEFAULT_CHECKSUM;
+               buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD;
+               buffer.hdr.req.buf_lenh = 0;
+               buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN;
+               buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
 
                /* convert offset from words to bytes */
                buffer.address = IXGBE_CPU_TO_BE32((offset + current_word) * 2);
                buffer.length = IXGBE_CPU_TO_BE16(words_to_read * 2);
 
                status = ixgbe_host_interface_command(hw, (u32 *)&buffer,
-                                                     sizeof(buffer), false);
+                                                     sizeof(buffer),
+                                                     IXGBE_HI_COMMAND_TIMEOUT,
+                                                     false);
 
                if (status) {
                        DEBUGOUT("Host interface command failed\n");
@@ -1399,10 +1640,10 @@ s32 ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset,
 
        DEBUGFUNC("ixgbe_write_ee_hostif_data_X550");
 
-       buffer.hdr.cmd = FW_WRITE_SHADOW_RAM_CMD;
-       buffer.hdr.buf_len1 = 0;
-       buffer.hdr.buf_len2 = FW_WRITE_SHADOW_RAM_LEN;
-       buffer.hdr.checksum = FW_DEFAULT_CHECKSUM;
+       buffer.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD;
+       buffer.hdr.req.buf_lenh = 0;
+       buffer.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN;
+       buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
 
         /* one word */
        buffer.length = IXGBE_CPU_TO_BE16(sizeof(u16));
@@ -1410,7 +1651,8 @@ s32 ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset,
        buffer.address = IXGBE_CPU_TO_BE32(offset * 2);
 
        status = ixgbe_host_interface_command(hw, (u32 *)&buffer,
-                                             sizeof(buffer), false);
+                                             sizeof(buffer),
+                                             IXGBE_HI_COMMAND_TIMEOUT, false);
 
        return status;
 }
@@ -1492,19 +1734,28 @@ out:
  * Returns error status for any failure
  */
 STATIC s32 ixgbe_checksum_ptr_x550(struct ixgbe_hw *hw, u16 ptr,
-                                  u16 size, u16 *csum)
+                                  u16 size, u16 *csum, u16 *buffer,
+                                  u32 buffer_size)
 {
        u16 buf[256];
        s32 status;
        u16 length, bufsz, i, start;
+       u16 *local_buffer;
 
        bufsz = sizeof(buf) / sizeof(buf[0]);
 
        /* Read a chunk at the pointer location */
-       status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, bufsz, buf);
-       if (status) {
-               DEBUGOUT("Failed to read EEPROM image\n");
-               return status;
+       if (!buffer) {
+               status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, bufsz, buf);
+               if (status) {
+                       DEBUGOUT("Failed to read EEPROM image\n");
+                       return status;
+               }
+               local_buffer = buf;
+       } else {
+               if (buffer_size < ptr)
+                       return  IXGBE_ERR_PARAM;
+               local_buffer = &buffer[ptr];
        }
 
        if (size) {
@@ -1512,7 +1763,7 @@ STATIC s32 ixgbe_checksum_ptr_x550(struct ixgbe_hw *hw, u16 ptr,
                length = size;
        } else {
                start = 1;
-               length = buf[0];
+               length = local_buffer[0];
 
                /* Skip pointer section if length is invalid. */
                if (length == 0xFFFF || length == 0 ||
@@ -1520,8 +1771,11 @@ STATIC s32 ixgbe_checksum_ptr_x550(struct ixgbe_hw *hw, u16 ptr,
                        return IXGBE_SUCCESS;
        }
 
+       if (buffer && ((u32)start + (u32)length > buffer_size))
+               return IXGBE_ERR_PARAM;
+
        for (i = start; length; i++, length--) {
-               if (i == bufsz) {
+               if (i == bufsz && !buffer) {
                        ptr += bufsz;
                        i = 0;
                        if (length < bufsz)
@@ -1535,20 +1789,23 @@ STATIC s32 ixgbe_checksum_ptr_x550(struct ixgbe_hw *hw, u16 ptr,
                                return status;
                        }
                }
-               *csum += buf[i];
+               *csum += local_buffer[i];
        }
        return IXGBE_SUCCESS;
 }
 
 /**
- *  ixgbe_calc_eeprom_checksum_X550 - Calculates and returns the checksum
+ *  ixgbe_calc_checksum_X550 - Calculates and returns the checksum
  *  @hw: pointer to hardware structure
+ *  @buffer: pointer to buffer containing calculated checksum
+ *  @buffer_size: size of buffer
  *
  *  Returns a negative error code on error, or the 16-bit checksum
  **/
-s32 ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw)
+s32 ixgbe_calc_checksum_X550(struct ixgbe_hw *hw, u16 *buffer, u32 buffer_size)
 {
        u16 eeprom_ptrs[IXGBE_EEPROM_LAST_WORD + 1];
+       u16 *local_buffer;
        s32 status;
        u16 checksum = 0;
        u16 pointer, i, size;
@@ -1557,13 +1814,20 @@ s32 ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw)
 
        hw->eeprom.ops.init_params(hw);
 
-       /* Read pointer area */
-       status = ixgbe_read_ee_hostif_buffer_X550(hw, 0,
-                                                 IXGBE_EEPROM_LAST_WORD + 1,
-                                                 eeprom_ptrs);
-       if (status) {
-               DEBUGOUT("Failed to read EEPROM image\n");
-               return status;
+       if (!buffer) {
+               /* Read pointer area */
+               status = ixgbe_read_ee_hostif_buffer_X550(hw, 0,
+                                                    IXGBE_EEPROM_LAST_WORD + 1,
+                                                    eeprom_ptrs);
+               if (status) {
+                       DEBUGOUT("Failed to read EEPROM image\n");
+                       return status;
+               }
+               local_buffer = eeprom_ptrs;
+       } else {
+               if (buffer_size < IXGBE_EEPROM_LAST_WORD)
+                       return IXGBE_ERR_PARAM;
+               local_buffer = buffer;
        }
 
        /*
@@ -1572,7 +1836,7 @@ s32 ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw)
         */
        for (i = 0; i <= IXGBE_EEPROM_LAST_WORD; i++)
                if (i != IXGBE_EEPROM_CHECKSUM)
-                       checksum += eeprom_ptrs[i];
+                       checksum += local_buffer[i];
 
        /*
         * Include all data from pointers 0x3, 0x6-0xE.  This excludes the
@@ -1582,7 +1846,7 @@ s32 ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw)
                if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR)
                        continue;
 
-               pointer = eeprom_ptrs[i];
+               pointer = local_buffer[i];
 
                /* Skip pointer section if the pointer is invalid. */
                if (pointer == 0xFFFF || pointer == 0 ||
@@ -1602,7 +1866,8 @@ s32 ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw)
                        break;
                }
 
-               status = ixgbe_checksum_ptr_x550(hw, pointer, size, &checksum);
+               status = ixgbe_checksum_ptr_x550(hw, pointer, size, &checksum,
+                                               buffer, buffer_size);
                if (status)
                        return status;
        }
@@ -1612,6 +1877,17 @@ s32 ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw)
        return (s32)checksum;
 }
 
+/**
+ *  ixgbe_calc_eeprom_checksum_X550 - Calculates and returns the checksum
+ *  @hw: pointer to hardware structure
+ *
+ *  Returns a negative error code on error, or the 16-bit checksum
+ **/
+s32 ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw)
+{
+       return ixgbe_calc_checksum_X550(hw, NULL, 0);
+}
+
 /**
  *  ixgbe_validate_eeprom_checksum_X550 - Validate EEPROM checksum
  *  @hw: pointer to hardware structure
@@ -1620,8 +1896,7 @@ s32 ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw)
  *  Performs checksum calculation and validates the EEPROM checksum.  If the
  *  caller does not need checksum_val, the value can be NULL.
  **/
-s32 ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw *hw,
-                                       u16 *checksum_val)
+s32 ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw *hw, u16 *checksum_val)
 {
        s32 status;
        u16 checksum;
@@ -1716,17 +1991,18 @@ s32 ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw *hw)
 s32 ixgbe_update_flash_X550(struct ixgbe_hw *hw)
 {
        s32 status = IXGBE_SUCCESS;
-       struct ixgbe_hic_hdr2 buffer;
+       union ixgbe_hic_hdr2 buffer;
 
        DEBUGFUNC("ixgbe_update_flash_X550");
 
-       buffer.cmd = FW_SHADOW_RAM_DUMP_CMD;
-       buffer.buf_len1 = 0;
-       buffer.buf_len2 = FW_SHADOW_RAM_DUMP_LEN;
-       buffer.checksum = FW_DEFAULT_CHECKSUM;
+       buffer.req.cmd = FW_SHADOW_RAM_DUMP_CMD;
+       buffer.req.buf_lenh = 0;
+       buffer.req.buf_lenl = FW_SHADOW_RAM_DUMP_LEN;
+       buffer.req.checksum = FW_DEFAULT_CHECKSUM;
 
        status = ixgbe_host_interface_command(hw, (u32 *)&buffer,
-                                             sizeof(buffer), false);
+                                             sizeof(buffer),
+                                             IXGBE_HI_COMMAND_TIMEOUT, false);
 
        return status;
 }
@@ -1740,6 +2016,7 @@ s32 ixgbe_update_flash_X550(struct ixgbe_hw *hw)
 u32 ixgbe_get_supported_physical_layer_X550em(struct ixgbe_hw *hw)
 {
        u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
+       u16 ext_ability = 0;
 
        DEBUGFUNC("ixgbe_get_supported_physical_layer_X550em");
 
@@ -1754,6 +2031,15 @@ u32 ixgbe_get_supported_physical_layer_X550em(struct ixgbe_hw *hw)
                physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KX4 |
                                 IXGBE_PHYSICAL_LAYER_1000BASE_KX;
                break;
+       case ixgbe_phy_x550em_ext_t:
+               hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY,
+                                    IXGBE_MDIO_PMA_PMD_DEV_TYPE,
+                                    &ext_ability);
+               if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY)
+                       physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T;
+               if (ext_ability & IXGBE_MDIO_PHY_1000BASET_ABILITY)
+                       physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
+               break;
        default:
                break;
        }
@@ -1764,6 +2050,24 @@ u32 ixgbe_get_supported_physical_layer_X550em(struct ixgbe_hw *hw)
        return physical_layer;
 }
 
+/**
+ * ixgbe_get_bus_info_x550em - Set PCI bus info
+ * @hw: pointer to hardware structure
+ *
+ * Sets bus link width and speed to unknown because X550em is
+ * not a PCI device.
+ **/
+s32 ixgbe_get_bus_info_X550em(struct ixgbe_hw *hw)
+{
+
+       DEBUGFUNC("ixgbe_get_bus_info_x550em");
+
+       hw->bus.width = ixgbe_bus_width_unknown;
+       hw->bus.speed = ixgbe_bus_speed_unknown;
+
+       return IXGBE_SUCCESS;
+}
+
 /**
  * ixgbe_disable_rx_x550 - Disable RX unit
  *
@@ -1791,11 +2095,11 @@ void ixgbe_disable_rx_x550(struct ixgbe_hw *hw)
                fw_cmd.hdr.cmd = FW_DISABLE_RXEN_CMD;
                fw_cmd.hdr.buf_len = FW_DISABLE_RXEN_LEN;
                fw_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM;
-               fw_cmd.port_number = hw->phy.lan_id;
+               fw_cmd.port_number = (u8)hw->bus.lan_id;
 
                status = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd,
                                        sizeof(struct ixgbe_hic_disable_rxen),
-                                       true);
+                                       IXGBE_HI_COMMAND_TIMEOUT, true);
 
                /* If we fail - disable RX using register write */
                if (status) {