net/ixgbe/base: store link active LED
[dpdk.git] / drivers / net / ixgbe / base / ixgbe_common.c
index 7a8eb6b..89b4b5f 100644 (file)
@@ -69,7 +69,7 @@ s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw)
 {
        struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
        struct ixgbe_mac_info *mac = &hw->mac;
-       u32 eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+       u32 eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
 
        DEBUGFUNC("ixgbe_init_ops_generic");
 
@@ -113,6 +113,7 @@ s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw)
        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.init_led_link_act = ixgbe_init_led_link_act_generic;
 
        /* RAR, Multicast, VLAN */
        mac->ops.set_rar = ixgbe_set_rar_generic;
@@ -135,6 +136,7 @@ s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw)
        /* Flow Control */
        mac->ops.fc_enable = ixgbe_fc_enable_generic;
        mac->ops.setup_fc = ixgbe_setup_fc_generic;
+       mac->ops.fc_autoneg = ixgbe_fc_autoneg;
 
        /* Link */
        mac->ops.get_link_capabilities = NULL;
@@ -167,13 +169,24 @@ bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
        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 ?
+               /* flow control autoneg black list */
+               switch (hw->device_id) {
+               case IXGBE_DEV_ID_X550EM_A_SFP:
+               case IXGBE_DEV_ID_X550EM_A_SFP_N:
+               case IXGBE_DEV_ID_X550EM_A_QSFP:
+               case IXGBE_DEV_ID_X550EM_A_QSFP_N:
+                       supported = false;
+                       break;
+               default:
+                       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;
+                       else
+                               supported = true;
+               }
+
                break;
        case ixgbe_media_type_backplane:
                supported = true;
@@ -185,6 +198,11 @@ bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
                case IXGBE_DEV_ID_X540T:
                case IXGBE_DEV_ID_X540T1:
                case IXGBE_DEV_ID_X550T:
+               case IXGBE_DEV_ID_X550T1:
+               case IXGBE_DEV_ID_X550EM_X_10G_T:
+               case IXGBE_DEV_ID_X550EM_A_10G_T:
+               case IXGBE_DEV_ID_X550EM_A_1G_T:
+               case IXGBE_DEV_ID_X550EM_A_1G_T_L:
                        supported = true;
                        break;
                default:
@@ -194,9 +212,10 @@ bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
                break;
        }
 
-       ERROR_REPORT2(IXGBE_ERROR_UNSUPPORTED,
-                     "Device %x does not support flow control autoneg",
-                     hw->device_id);
+       if (!supported)
+               ERROR_REPORT2(IXGBE_ERROR_UNSUPPORTED,
+                             "Device %x does not support flow control autoneg",
+                             hw->device_id);
        return supported;
 }
 
@@ -368,6 +387,7 @@ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw)
 {
        s32 ret_val;
        u32 ctrl_ext;
+       u16 device_caps;
 
        DEBUGFUNC("ixgbe_start_hw_generic");
 
@@ -390,14 +410,29 @@ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw)
 
        /* Setup flow control */
        ret_val = ixgbe_setup_fc(hw);
-       if (ret_val != IXGBE_SUCCESS)
-               goto out;
+       if (ret_val != IXGBE_SUCCESS && ret_val != IXGBE_NOT_IMPLEMENTED)
+               return ret_val;
+
+       /* Cache bit indicating need for crosstalk fix */
+       switch (hw->mac.type) {
+       case ixgbe_mac_82599EB:
+       case ixgbe_mac_X550EM_x:
+       case ixgbe_mac_X550EM_a:
+               hw->mac.ops.get_device_caps(hw, &device_caps);
+               if (device_caps & IXGBE_DEVICE_CAPS_NO_CROSSTALK_WR)
+                       hw->need_crosstalk_fix = false;
+               else
+                       hw->need_crosstalk_fix = true;
+               break;
+       default:
+               hw->need_crosstalk_fix = false;
+               break;
+       }
 
        /* Clear adapter stopped flag */
        hw->adapter_stopped = false;
 
-out:
-       return ret_val;
+       return IXGBE_SUCCESS;
 }
 
 /**
@@ -463,6 +498,9 @@ s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw)
                status = hw->mac.ops.start_hw(hw);
        }
 
+       /* Initialize the LED link active for LED blink support */
+       hw->mac.ops.init_led_link_act(hw);
+
        return status;
 }
 
@@ -1018,24 +1056,33 @@ s32 ixgbe_get_bus_info_generic(struct ixgbe_hw *hw)
  *  ixgbe_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices
  *  @hw: pointer to the HW structure
  *
- *  Determines the LAN function id by reading memory-mapped registers
- *  and swaps the port value if requested.
+ *  Determines the LAN function id by reading memory-mapped registers and swaps
+ *  the port value if requested, and set MAC instance for devices that share
+ *  CS4227.
  **/
 void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw)
 {
        struct ixgbe_bus_info *bus = &hw->bus;
        u32 reg;
+       u16 ee_ctrl_4;
 
        DEBUGFUNC("ixgbe_set_lan_id_multi_port_pcie");
 
        reg = IXGBE_READ_REG(hw, IXGBE_STATUS);
        bus->func = (reg & IXGBE_STATUS_LAN_ID) >> IXGBE_STATUS_LAN_ID_SHIFT;
-       bus->lan_id = bus->func;
+       bus->lan_id = (u8)bus->func;
 
        /* check for a port swap */
-       reg = IXGBE_READ_REG(hw, IXGBE_FACTPS);
+       reg = IXGBE_READ_REG(hw, IXGBE_FACTPS_BY_MAC(hw));
        if (reg & IXGBE_FACTPS_LFS)
                bus->func ^= 0x1;
+
+       /* Get MAC instance from EEPROM for configuring CS4227 */
+       if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP) {
+               hw->eeprom.ops.read(hw, IXGBE_EEPROM_CTRL_4, &ee_ctrl_4);
+               bus->instance_id = (ee_ctrl_4 & IXGBE_EE_CTRL_4_INST_ID) >>
+                                  IXGBE_EE_CTRL_4_INST_ID_SHIFT;
+       }
 }
 
 /**
@@ -1092,6 +1139,47 @@ s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw)
        return ixgbe_disable_pcie_master(hw);
 }
 
+/**
+ *  ixgbe_init_led_link_act_generic - Store the LED index link/activity.
+ *  @hw: pointer to hardware structure
+ *
+ *  Store the index for the link active LED. This will be used to support
+ *  blinking the LED.
+ **/
+s32 ixgbe_init_led_link_act_generic(struct ixgbe_hw *hw)
+{
+       struct ixgbe_mac_info *mac = &hw->mac;
+       u32 led_reg, led_mode;
+       u16 i;
+
+       led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
+
+       /* Get LED link active from the LEDCTL register */
+       for (i = 0; i < 4; i++) {
+               led_mode = led_reg >> IXGBE_LED_MODE_SHIFT(i);
+
+               if ((led_mode & IXGBE_LED_MODE_MASK_BASE) ==
+                    IXGBE_LED_LINK_ACTIVE) {
+                       mac->led_link_act = i;
+                       return IXGBE_SUCCESS;
+               }
+       }
+
+       /*
+        * If LEDCTL register does not have the LED link active set, then use
+        * known MAC defaults.
+        */
+       switch (hw->mac.type) {
+       case ixgbe_mac_X550EM_a:
+       case ixgbe_mac_X550EM_x:
+               mac->led_link_act = 1;
+               break;
+       default:
+               mac->led_link_act = 2;
+       }
+       return IXGBE_SUCCESS;
+}
+
 /**
  *  ixgbe_led_on_generic - Turns on the software controllable LEDs.
  *  @hw: pointer to hardware structure
@@ -1103,6 +1191,9 @@ s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index)
 
        DEBUGFUNC("ixgbe_led_on_generic");
 
+       if (index > 3)
+               return IXGBE_ERR_PARAM;
+
        /* To turn on the LED, set mode to ON. */
        led_reg &= ~IXGBE_LED_MODE_MASK(index);
        led_reg |= IXGBE_LED_ON << IXGBE_LED_MODE_SHIFT(index);
@@ -1123,6 +1214,9 @@ s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index)
 
        DEBUGFUNC("ixgbe_led_off_generic");
 
+       if (index > 3)
+               return IXGBE_ERR_PARAM;
+
        /* To turn off the LED, set mode to OFF. */
        led_reg &= ~IXGBE_LED_MODE_MASK(index);
        led_reg |= IXGBE_LED_OFF << IXGBE_LED_MODE_SHIFT(index);
@@ -1159,7 +1253,7 @@ s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw)
                 * Check for EEPROM present first.
                 * If not present leave as none
                 */
-               eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+               eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
                if (eec & IXGBE_EEC_PRES) {
                        eeprom->type = ixgbe_eeprom_spi;
 
@@ -1720,14 +1814,14 @@ STATIC s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw)
                status = IXGBE_ERR_SWFW_SYNC;
 
        if (status == IXGBE_SUCCESS) {
-               eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+               eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
 
                /* Request EEPROM Access */
                eec |= IXGBE_EEC_REQ;
-               IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+               IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
 
                for (i = 0; i < IXGBE_EEPROM_GRANT_ATTEMPTS; i++) {
-                       eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+                       eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
                        if (eec & IXGBE_EEC_GNT)
                                break;
                        usec_delay(5);
@@ -1736,7 +1830,7 @@ STATIC s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw)
                /* Release if grant not acquired */
                if (!(eec & IXGBE_EEC_GNT)) {
                        eec &= ~IXGBE_EEC_REQ;
-                       IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+                       IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
                        DEBUGOUT("Could not acquire EEPROM grant\n");
 
                        hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
@@ -1747,7 +1841,7 @@ STATIC s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw)
                if (status == IXGBE_SUCCESS) {
                        /* Clear CS and SK */
                        eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK);
-                       IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+                       IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
                        IXGBE_WRITE_FLUSH(hw);
                        usec_delay(1);
                }
@@ -1777,7 +1871,7 @@ STATIC s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw)
                 * 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);
+               swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw));
                if (!(swsm & IXGBE_SWSM_SMBI)) {
                        status = IXGBE_SUCCESS;
                        break;
@@ -1802,7 +1896,7 @@ STATIC s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw)
                 * 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);
+               swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw));
                if (!(swsm & IXGBE_SWSM_SMBI))
                        status = IXGBE_SUCCESS;
        }
@@ -1810,17 +1904,17 @@ STATIC s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw)
        /* 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);
+                       swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw));
 
                        /* Set the SW EEPROM semaphore bit to request access */
                        swsm |= IXGBE_SWSM_SWESMBI;
-                       IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm);
+                       IXGBE_WRITE_REG(hw, IXGBE_SWSM_BY_MAC(hw), swsm);
 
                        /*
                         * If we set the bit successfully then we got the
                         * semaphore.
                         */
-                       swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
+                       swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw));
                        if (swsm & IXGBE_SWSM_SWESMBI)
                                break;
 
@@ -1917,15 +2011,15 @@ STATIC void ixgbe_standby_eeprom(struct ixgbe_hw *hw)
 
        DEBUGFUNC("ixgbe_standby_eeprom");
 
-       eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+       eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
 
        /* Toggle CS to flush commands */
        eec |= IXGBE_EEC_CS;
-       IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+       IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
        IXGBE_WRITE_FLUSH(hw);
        usec_delay(1);
        eec &= ~IXGBE_EEC_CS;
-       IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+       IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
        IXGBE_WRITE_FLUSH(hw);
        usec_delay(1);
 }
@@ -1945,7 +2039,7 @@ STATIC void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data,
 
        DEBUGFUNC("ixgbe_shift_out_eeprom_bits");
 
-       eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+       eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
 
        /*
         * Mask is used to shift "count" bits of "data" out to the EEPROM
@@ -1966,7 +2060,7 @@ STATIC void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data,
                else
                        eec &= ~IXGBE_EEC_DI;
 
-               IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+               IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
                IXGBE_WRITE_FLUSH(hw);
 
                usec_delay(1);
@@ -1983,7 +2077,7 @@ STATIC void ixgbe_shift_out_eeprom_bits(struct ixgbe_hw *hw, u16 data,
 
        /* We leave the "DI" bit set to "0" when we leave this routine. */
        eec &= ~IXGBE_EEC_DI;
-       IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+       IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
        IXGBE_WRITE_FLUSH(hw);
 }
 
@@ -2006,7 +2100,7 @@ STATIC u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count)
         * the value of the "DO" bit.  During this "shifting in" process the
         * "DI" bit should always be clear.
         */
-       eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+       eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
 
        eec &= ~(IXGBE_EEC_DO | IXGBE_EEC_DI);
 
@@ -2014,7 +2108,7 @@ STATIC u16 ixgbe_shift_in_eeprom_bits(struct ixgbe_hw *hw, u16 count)
                data = data << 1;
                ixgbe_raise_eeprom_clk(hw, &eec);
 
-               eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+               eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
 
                eec &= ~(IXGBE_EEC_DI);
                if (eec & IXGBE_EEC_DO)
@@ -2040,7 +2134,7 @@ STATIC void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec)
         * (setting the SK bit), then delay
         */
        *eec = *eec | IXGBE_EEC_SK;
-       IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec);
+       IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), *eec);
        IXGBE_WRITE_FLUSH(hw);
        usec_delay(1);
 }
@@ -2059,7 +2153,7 @@ STATIC void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec)
         * delay
         */
        *eec = *eec & ~IXGBE_EEC_SK;
-       IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec);
+       IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), *eec);
        IXGBE_WRITE_FLUSH(hw);
        usec_delay(1);
 }
@@ -2074,19 +2168,19 @@ STATIC void ixgbe_release_eeprom(struct ixgbe_hw *hw)
 
        DEBUGFUNC("ixgbe_release_eeprom");
 
-       eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+       eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
 
        eec |= IXGBE_EEC_CS;  /* Pull CS high */
        eec &= ~IXGBE_EEC_SK; /* Lower SCK */
 
-       IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+       IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
        IXGBE_WRITE_FLUSH(hw);
 
        usec_delay(1);
 
        /* Stop requesting EEPROM access */
        eec &= ~IXGBE_EEC_REQ;
-       IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+       IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
 
        hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
 
@@ -2241,7 +2335,7 @@ s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw)
  *  ixgbe_validate_mac_addr - Validate MAC address
  *  @mac_addr: pointer to MAC address.
  *
- *  Tests a MAC address to ensure it is a valid Individual Address
+ *  Tests a MAC address to ensure it is a valid Individual Address.
  **/
 s32 ixgbe_validate_mac_addr(u8 *mac_addr)
 {
@@ -2251,16 +2345,13 @@ s32 ixgbe_validate_mac_addr(u8 *mac_addr)
 
        /* Make sure it is not a multicast address */
        if (IXGBE_IS_MULTICAST(mac_addr)) {
-               DEBUGOUT("MAC address is multicast\n");
                status = IXGBE_ERR_INVALID_MAC_ADDR;
        /* Not a broadcast address */
        } else if (IXGBE_IS_BROADCAST(mac_addr)) {
-               DEBUGOUT("MAC address is broadcast\n");
                status = IXGBE_ERR_INVALID_MAC_ADDR;
        /* Reject the zero address */
        } else if (mac_addr[0] == 0 && mac_addr[1] == 0 && mac_addr[2] == 0 &&
                   mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0) {
-               DEBUGOUT("MAC address is all zeros\n");
                status = IXGBE_ERR_INVALID_MAC_ADDR;
        }
        return status;
@@ -2398,10 +2489,11 @@ s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw)
                          hw->mac.addr[4], hw->mac.addr[5]);
 
                hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
-
-               /* clear VMDq pool/queue selection for RAR 0 */
-               hw->mac.ops.clear_vmdq(hw, 0, IXGBE_CLEAR_VMDQ_ALL);
        }
+
+       /* clear VMDq pool/queue selection for RAR 0 */
+       hw->mac.ops.clear_vmdq(hw, 0, IXGBE_CLEAR_VMDQ_ALL);
+
        hw->addr_ctrl.overflow_promisc = 0;
 
        hw->addr_ctrl.rar_used_count = 1;
@@ -2730,7 +2822,7 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw)
        }
 
        /* Negotiate the fc mode to use */
-       ixgbe_fc_autoneg(hw);
+       hw->mac.ops.fc_autoneg(hw);
 
        /* Disable any previous flow control settings */
        mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN);
@@ -2840,8 +2932,8 @@ out:
  *  Find the intersection between advertised settings and link partner's
  *  advertised settings
  **/
-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 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)
 {
        if ((!(adv_reg)) ||  (!(lp_reg))) {
                ERROR_REPORT3(IXGBE_ERROR_UNSUPPORTED,
@@ -3141,6 +3233,9 @@ s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
        DEBUGOUT("GIO Master Disable bit didn't clear - requesting resets\n");
        hw->mac.flags |= IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
 
+       if (hw->mac.type >= ixgbe_mac_X550)
+               goto out;
+
        /*
         * Before proceeding, make sure that the PCIe block does not have
         * transactions pending.
@@ -3310,7 +3405,7 @@ s32 prot_autoc_write_generic(struct ixgbe_hw *hw, u32 reg_val, bool locked)
  **/
 s32 ixgbe_enable_sec_rx_path_generic(struct ixgbe_hw *hw)
 {
-       int secrxreg;
+       u32 secrxreg;
 
        DEBUGFUNC("ixgbe_enable_sec_rx_path_generic");
 
@@ -3357,6 +3452,9 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
 
        DEBUGFUNC("ixgbe_blink_led_start_generic");
 
+       if (index > 3)
+               return IXGBE_ERR_PARAM;
+
        /*
         * Link must be up to auto-blink the LEDs;
         * Force it if link is down.
@@ -3402,6 +3500,10 @@ s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index)
 
        DEBUGFUNC("ixgbe_blink_led_stop_generic");
 
+       if (index > 3)
+               return IXGBE_ERR_PARAM;
+
+
        ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg);
        if (ret_val != IXGBE_SUCCESS)
                goto out;
@@ -3568,6 +3670,7 @@ u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw)
        case ixgbe_mac_X540:
        case ixgbe_mac_X550:
        case ixgbe_mac_X550EM_x:
+       case ixgbe_mac_X550EM_a:
                pcie_offset = IXGBE_PCIE_MSIX_82599_CAPS;
                max_msix_count = IXGBE_MAX_MSIX_VECTORS_82599;
                break;
@@ -3706,7 +3809,8 @@ s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
        }
 
        /* was that the last pool using this rar? */
-       if (mpsar_lo == 0 && mpsar_hi == 0 && rar != 0)
+       if (mpsar_lo == 0 && mpsar_hi == 0 &&
+           rar != 0 && rar != hw->mac.san_mac_rar_index)
                hw->mac.ops.clear_rar(hw, rar);
 done:
        return IXGBE_SUCCESS;
@@ -3796,68 +3900,65 @@ s32 ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw)
  *  return the VLVF index where this VLAN id should be placed
  *
  **/
-s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan)
+s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan, bool vlvf_bypass)
 {
-       u32 bits = 0;
-       u32 first_empty_slot = 0;
-       s32 regindex;
+       s32 regindex, first_empty_slot;
+       u32 bits;
 
        /* short cut the special case */
        if (vlan == 0)
                return 0;
 
-       /*
-         * Search for the vlan id in the VLVF entries. Save off the first empty
-         * slot found along the way
-         */
-       for (regindex = 1; regindex < IXGBE_VLVF_ENTRIES; regindex++) {
+       /* if vlvf_bypass is set we don't want to use an empty slot, we
+        * will simply bypass the VLVF if there are no entries present in the
+        * VLVF that contain our VLAN
+        */
+       first_empty_slot = vlvf_bypass ? IXGBE_ERR_NO_SPACE : 0;
+
+       /* add VLAN enable bit for comparison */
+       vlan |= IXGBE_VLVF_VIEN;
+
+       /* Search for the vlan id in the VLVF entries. Save off the first empty
+        * slot found along the way.
+        *
+        * pre-decrement loop covering (IXGBE_VLVF_ENTRIES - 1) .. 1
+        */
+       for (regindex = IXGBE_VLVF_ENTRIES; --regindex;) {
                bits = IXGBE_READ_REG(hw, IXGBE_VLVF(regindex));
-               if (!bits && !(first_empty_slot))
+               if (bits == vlan)
+                       return regindex;
+               if (!first_empty_slot && !bits)
                        first_empty_slot = regindex;
-               else if ((bits & 0x0FFF) == vlan)
-                       break;
        }
 
-       /*
-         * If regindex is less than IXGBE_VLVF_ENTRIES, then we found the vlan
-         * in the VLVF. Else use the first empty VLVF register for this
-         * vlan id.
-         */
-       if (regindex >= IXGBE_VLVF_ENTRIES) {
-               if (first_empty_slot)
-                       regindex = first_empty_slot;
-               else {
-                       ERROR_REPORT1(IXGBE_ERROR_SOFTWARE,
-                                    "No space in VLVF.\n");
-                       regindex = IXGBE_ERR_NO_SPACE;
-               }
-       }
+       /* If we are here then we didn't find the VLAN.  Return first empty
+        * slot we found during our search, else error.
+        */
+       if (!first_empty_slot)
+               ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "No space in VLVF.\n");
 
-       return regindex;
+       return first_empty_slot ? first_empty_slot : IXGBE_ERR_NO_SPACE;
 }
 
 /**
  *  ixgbe_set_vfta_generic - Set VLAN filter table
  *  @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
+ *  @vind: VMDq output index that maps queue to VLAN id in VLVFB
+ *  @vlan_on: boolean flag to turn on/off VLAN
+ *  @vlvf_bypass: boolean flag indicating updating default pool is okay
  *
  *  Turn on/off specified VLAN in the VLAN filter table.
  **/
 s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind,
-                          bool vlan_on)
+                          bool vlan_on, bool vlvf_bypass)
 {
-       s32 regindex;
-       u32 bitindex;
-       u32 vfta;
-       u32 targetbit;
-       s32 ret_val = IXGBE_SUCCESS;
-       bool vfta_changed = false;
+       u32 regidx, vfta_delta, vfta;
+       s32 ret_val;
 
        DEBUGFUNC("ixgbe_set_vfta_generic");
 
-       if (vlan > 4095)
+       if (vlan > 4095 || vind > 63)
                return IXGBE_ERR_PARAM;
 
        /*
@@ -3872,33 +3973,33 @@ s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind,
         *    bits[11-5]: which register
         *    bits[4-0]:  which bit in the register
         */
-       regindex = (vlan >> 5) & 0x7F;
-       bitindex = vlan & 0x1F;
-       targetbit = (1 << bitindex);
-       vfta = IXGBE_READ_REG(hw, IXGBE_VFTA(regindex));
-
-       if (vlan_on) {
-               if (!(vfta & targetbit)) {
-                       vfta |= targetbit;
-                       vfta_changed = true;
-               }
-       } else {
-               if ((vfta & targetbit)) {
-                       vfta &= ~targetbit;
-                       vfta_changed = true;
-               }
-       }
+       regidx = vlan / 32;
+       vfta_delta = 1 << (vlan % 32);
+       vfta = IXGBE_READ_REG(hw, IXGBE_VFTA(regidx));
+
+       /*
+        * vfta_delta represents the difference between the current value
+        * of vfta and the value we want in the register.  Since the diff
+        * is an XOR mask we can just update the vfta using an XOR
+        */
+       vfta_delta &= vlan_on ? ~vfta : vfta;
+       vfta ^= vfta_delta;
 
        /* Part 2
         * 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)
+       ret_val = ixgbe_set_vlvf_generic(hw, vlan, vind, vlan_on, &vfta_delta,
+                                        vfta, vlvf_bypass);
+       if (ret_val != IXGBE_SUCCESS) {
+               if (vlvf_bypass)
+                       goto vfta_update;
                return ret_val;
+       }
 
-       if (vfta_changed)
-               IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), vfta);
+vfta_update:
+       /* Update VFTA now that we are ready for traffic */
+       if (vfta_delta)
+               IXGBE_WRITE_REG(hw, IXGBE_VFTA(regidx), vfta);
 
        return IXGBE_SUCCESS;
 }
@@ -3907,21 +4008,25 @@ s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind,
  *  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
+ *  @vind: VMDq output index that maps queue to VLAN id in VLVFB
+ *  @vlan_on: boolean flag to turn on/off VLAN in VLVF
+ *  @vfta_delta: pointer to the difference between the current value of VFTA
+ *              and the desired value
+ *  @vfta: the desired value of the VFTA
+ *  @vlvf_bypass: boolean flag indicating updating default pool is okay
  *
  *  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)
+                          bool vlan_on, u32 *vfta_delta, u32 vfta,
+                          bool vlvf_bypass)
 {
-       u32 vt;
+       u32 bits;
+       s32 vlvf_index;
 
        DEBUGFUNC("ixgbe_set_vlvf_generic");
 
-       if (vlan > 4095)
+       if (vlan > 4095 || vind > 63)
                return IXGBE_ERR_PARAM;
 
        /* If VT Mode is set
@@ -3931,83 +4036,60 @@ s32 ixgbe_set_vlvf_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind,
         *   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));
-                               bits |= (1 << vind);
-                               IXGBE_WRITE_REG(hw,
-                                               IXGBE_VLVFB(vlvf_index * 2),
-                                               bits);
-                       } else {
-                               bits = IXGBE_READ_REG(hw,
-                                       IXGBE_VLVFB((vlvf_index * 2) + 1));
-                               bits |= (1 << (vind - 32));
-                               IXGBE_WRITE_REG(hw,
-                                       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));
-                               bits &= ~(1 << vind);
-                               IXGBE_WRITE_REG(hw,
-                                               IXGBE_VLVFB(vlvf_index * 2),
-                                               bits);
-                               bits |= IXGBE_READ_REG(hw,
-                                       IXGBE_VLVFB((vlvf_index * 2) + 1));
-                       } else {
-                               bits = IXGBE_READ_REG(hw,
-                                       IXGBE_VLVFB((vlvf_index * 2) + 1));
-                               bits &= ~(1 << (vind - 32));
-                               IXGBE_WRITE_REG(hw,
-                                       IXGBE_VLVFB((vlvf_index * 2) + 1),
-                                       bits);
-                               bits |= IXGBE_READ_REG(hw,
-                                               IXGBE_VLVFB(vlvf_index * 2));
-                       }
-               }
+       if (!(IXGBE_READ_REG(hw, IXGBE_VT_CTL) & IXGBE_VT_CTL_VT_ENABLE))
+               return IXGBE_SUCCESS;
 
-               /*
-                * If there are still bits set in the VLVFB registers
-                * for the VLAN ID indicated we need to see if the
-                * caller is requesting that we clear the VFTA entry bit.
-                * If the caller has requested that we clear the VFTA
-                * entry bit but there are still pools/VFs using this VLAN
-                * ID entry then ignore the request.  We're not worried
-                * about the case where we're turning the VFTA VLAN ID
-                * entry bit on, only when requested to turn it off as
-                * there may be multiple pools and/or VFs using the
-                * VLAN ID entry.  In that case we cannot clear the
-                * VFTA bit until all pools/VFs using that VLAN ID have also
-                * been cleared.  This will be indicated by "bits" being
-                * zero.
+       vlvf_index = ixgbe_find_vlvf_slot(hw, vlan, vlvf_bypass);
+       if (vlvf_index < 0)
+               return vlvf_index;
+
+       bits = IXGBE_READ_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32));
+
+       /* set the pool bit */
+       bits |= 1 << (vind % 32);
+       if (vlan_on)
+               goto vlvf_update;
+
+       /* clear the pool bit */
+       bits ^= 1 << (vind % 32);
+
+       if (!bits &&
+           !IXGBE_READ_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + 1 - vind / 32))) {
+               /* Clear VFTA first, then disable VLVF.  Otherwise
+                * we run the risk of stray packets leaking into
+                * the PF via the default pool
                 */
-               if (bits) {
-                       IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index),
-                                       (IXGBE_VLVF_VIEN | vlan));
-                       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;
-                       }
-               } else
-                       IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), 0);
+               if (*vfta_delta)
+                       IXGBE_WRITE_REG(hw, IXGBE_VFTA(vlan / 32), vfta);
+
+               /* disable VLVF and clear remaining bit from pool */
+               IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), 0);
+               IXGBE_WRITE_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32), 0);
+
+               return IXGBE_SUCCESS;
        }
 
+       /* If there are still bits set in the VLVFB registers
+        * for the VLAN ID indicated we need to see if the
+        * caller is requesting that we clear the VFTA entry bit.
+        * If the caller has requested that we clear the VFTA
+        * entry bit but there are still pools/VFs using this VLAN
+        * ID entry then ignore the request.  We're not worried
+        * about the case where we're turning the VFTA VLAN ID
+        * entry bit on, only when requested to turn it off as
+        * there may be multiple pools and/or VFs using the
+        * VLAN ID entry.  In that case we cannot clear the
+        * VFTA bit until all pools/VFs using that VLAN ID have also
+        * been cleared.  This will be indicated by "bits" being
+        * zero.
+        */
+       *vfta_delta = 0;
+
+vlvf_update:
+       /* record pool change and enable VLAN ID if not already enabled */
+       IXGBE_WRITE_REG(hw, IXGBE_VLVFB(vlvf_index * 2 + vind / 32), bits);
+       IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), IXGBE_VLVF_VIEN | vlan);
+
        return IXGBE_SUCCESS;
 }
 
@@ -4029,12 +4111,38 @@ s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw)
        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 + 1), 0);
        }
 
        return IXGBE_SUCCESS;
 }
 
+/**
+ *  ixgbe_need_crosstalk_fix - Determine if we need to do cross talk fix
+ *  @hw: pointer to hardware structure
+ *
+ *  Contains the logic to identify if we need to verify link for the
+ *  crosstalk fix
+ **/
+static bool ixgbe_need_crosstalk_fix(struct ixgbe_hw *hw)
+{
+
+       /* Does FW say we need the fix */
+       if (!hw->need_crosstalk_fix)
+               return false;
+
+       /* Only consider SFP+ PHYs i.e. media type fiber */
+       switch (hw->mac.ops.get_media_type(hw)) {
+       case ixgbe_media_type_fiber:
+       case ixgbe_media_type_fiber_qsfp:
+               break;
+       default:
+               return false;
+       }
+
+       return true;
+}
+
 /**
  *  ixgbe_check_mac_link_generic - Determine link and speed status
  *  @hw: pointer to hardware structure
@@ -4052,6 +4160,35 @@ s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
 
        DEBUGFUNC("ixgbe_check_mac_link_generic");
 
+       /* If Crosstalk fix enabled do the sanity check of making sure
+        * the SFP+ cage is full.
+        */
+       if (ixgbe_need_crosstalk_fix(hw)) {
+               u32 sfp_cage_full;
+
+               switch (hw->mac.type) {
+               case ixgbe_mac_82599EB:
+                       sfp_cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) &
+                                       IXGBE_ESDP_SDP2;
+                       break;
+               case ixgbe_mac_X550EM_x:
+               case ixgbe_mac_X550EM_a:
+                       sfp_cage_full = IXGBE_READ_REG(hw, IXGBE_ESDP) &
+                                       IXGBE_ESDP_SDP0;
+                       break;
+               default:
+                       /* sanity check - No SFP+ devices here */
+                       sfp_cage_full = false;
+                       break;
+               }
+
+               if (!sfp_cage_full) {
+                       *link_up = false;
+                       *speed = IXGBE_LINK_SPEED_UNKNOWN;
+                       return IXGBE_SUCCESS;
+               }
+       }
+
        /* clear the old state */
        links_orig = IXGBE_READ_REG(hw, IXGBE_LINKS);
 
@@ -4063,7 +4200,7 @@ s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
        }
 
        if (link_up_wait_to_complete) {
-               for (i = 0; i < IXGBE_LINK_UP_TIME; i++) {
+               for (i = 0; i < hw->mac.max_link_up_time; i++) {
                        if (links_reg & IXGBE_LINKS_UP) {
                                *link_up = true;
                                break;
@@ -4098,6 +4235,13 @@ s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
                                *speed = IXGBE_LINK_SPEED_5GB_FULL;
                }
                break;
+       case IXGBE_LINKS_SPEED_10_X550EM_A:
+               *speed = IXGBE_LINK_SPEED_UNKNOWN;
+               if (hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T ||
+                   hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L) {
+                       *speed = IXGBE_LINK_SPEED_10_FULL;
+               }
+               break;
        default:
                *speed = IXGBE_LINK_SPEED_UNKNOWN;
        }
@@ -4215,43 +4359,25 @@ out:
 /**
  *  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
+ *  @enable: enable or disable switch for MAC anti-spoofing
+ *  @vf: Virtual Function pool - VF Pool to set for MAC anti-spoofing
  *
  **/
-void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int pf)
+void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf)
 {
-       int j;
-       int pf_target_reg = pf >> 3;
-       int pf_target_shift = pf % 8;
-       u32 pfvfspoof = 0;
+       int vf_target_reg = vf >> 3;
+       int vf_target_shift = vf % 8;
+       u32 pfvfspoof;
 
        if (hw->mac.type == ixgbe_mac_82598EB)
                return;
 
+       pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg));
        if (enable)
-               pfvfspoof = IXGBE_SPOOF_MACAS_MASK;
-
-       /*
-        * PFVFSPOOF register array is size 8 with 8 bits assigned to
-        * MAC anti-spoof enables in each register array element.
-        */
-       for (j = 0; j < pf_target_reg; j++)
-               IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(j), pfvfspoof);
-
-       /*
-        * The PF should be allowed to spoof so that it can support
-        * emulation mode NICs.  Do not set the bits assigned to the PF
-        */
-       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);
+               pfvfspoof |= (1 << vf_target_shift);
+       else
+               pfvfspoof &= ~(1 << vf_target_shift);
+       IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof);
 }
 
 /**
@@ -4347,49 +4473,45 @@ u8 ixgbe_calculate_checksum(u8 *buffer, u32 length)
 }
 
 /**
- *  ixgbe_host_interface_command - Issue command to manageability block
+ *  ixgbe_hic_unlocked - Issue command to manageability block unlocked
  *  @hw: pointer to the HW structure
- *  @buffer: contains the command to write and where the return status will
- *   be placed
+ *  @buffer: command to write and where the return status will be placed
  *  @length: length of buffer, must be multiple of 4 bytes
  *  @timeout: time in ms to wait for command completion
- *  @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.
+ *  Communicates with the manageability block. On success return IXGBE_SUCCESS
+ *  else returns semaphore error when encountering an error acquiring
+ *  semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
+ *
+ *  This function assumes that the IXGBE_GSSR_SW_MNG_SM semaphore is held
+ *  by the caller.
  **/
-s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer,
-                                u32 length, u32 timeout, bool return_data)
+s32 ixgbe_hic_unlocked(struct ixgbe_hw *hw, u32 *buffer, u32 length,
+                      u32 timeout)
 {
-       u32 hicr, i, bi, fwsts;
-       u32 hdr_size = sizeof(struct ixgbe_hic_hdr);
-       u16 buf_len;
+       u32 hicr, i, fwsts;
        u16 dword_len;
 
-       DEBUGFUNC("ixgbe_host_interface_command");
+       DEBUGFUNC("ixgbe_hic_unlocked");
 
-       if (length == 0 || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) {
+       if (!length || 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) {
+       if (!(hicr & IXGBE_HICR_EN)) {
                DEBUGOUT("IXGBE_HOST_EN bit disabled.\n");
                return IXGBE_ERR_HOST_INTERFACE_COMMAND;
        }
 
        /* Calculate length in DWORDs. We must be DWORD aligned */
-       if ((length % (sizeof(u32))) != 0) {
+       if (length % sizeof(u32)) {
                DEBUGOUT("Buffer length failure, not aligned to dword");
                return IXGBE_ERR_INVALID_ARGUMENT;
        }
@@ -4414,15 +4536,61 @@ s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer,
        }
 
        /* Check command completion */
-       if ((timeout != 0 && i == timeout) ||
+       if ((timeout && i == timeout) ||
            !(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;
        }
 
+       return IXGBE_SUCCESS;
+}
+
+/**
+ *  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
+ *  @timeout: time in ms to wait for command completion
+ *  @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 returns semaphore error when encountering an error acquiring
+ *  semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
+ **/
+s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer,
+                                u32 length, u32 timeout, bool return_data)
+{
+       u32 hdr_size = sizeof(struct ixgbe_hic_hdr);
+       u16 dword_len;
+       u16 buf_len;
+       s32 status;
+       u32 bi;
+
+       DEBUGFUNC("ixgbe_host_interface_command");
+
+       if (length == 0 || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) {
+               DEBUGOUT1("Buffer length failure buffersize=%d.\n", length);
+               return IXGBE_ERR_HOST_INTERFACE_COMMAND;
+       }
+
+       /* Take management host interface semaphore */
+       status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM);
+       if (status)
+               return status;
+
+       status = ixgbe_hic_unlocked(hw, buffer, length, timeout);
+       if (status)
+               goto rel_out;
+
        if (!return_data)
-               return 0;
+               goto rel_out;
 
        /* Calculate length in DWORDs */
        dword_len = hdr_size >> 2;
@@ -4435,12 +4603,13 @@ 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)
-               return 0;
+       if (!buf_len)
+               goto rel_out;
 
        if (length < buf_len + hdr_size) {
                DEBUGOUT("Buffer not large enough for reply message.\n");
-               return IXGBE_ERR_HOST_INTERFACE_COMMAND;
+               status = IXGBE_ERR_HOST_INTERFACE_COMMAND;
+               goto rel_out;
        }
 
        /* Calculate length in DWORDs, add 3 for odd lengths */
@@ -4452,7 +4621,10 @@ s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer,
                IXGBE_LE32_TO_CPUS(&buffer[bi]);
        }
 
-       return 0;
+rel_out:
+       hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM);
+
+       return status;
 }
 
 /**
@@ -4469,19 +4641,15 @@ s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer,
  *  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)
+                                u8 build, u8 sub, u16 len,
+                                const char *driver_ver)
 {
        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;
-       }
+       UNREFERENCED_2PARAMETER(len, driver_ver);
 
        fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO;
        fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN;
@@ -4514,8 +4682,6 @@ s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min,
                break;
        }
 
-       hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM);
-out:
        return ret_val;
 }
 
@@ -4878,7 +5044,7 @@ bool ixgbe_mng_present(struct ixgbe_hw *hw)
        if (hw->mac.type < ixgbe_mac_82599EB)
                return false;
 
-       fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM);
+       fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw));
        fwsm &= IXGBE_FWSM_MODE_MASK;
        return fwsm == IXGBE_FWSM_FW_MODE_PT;
 }
@@ -4893,7 +5059,7 @@ bool ixgbe_mng_enabled(struct ixgbe_hw *hw)
 {
        u32 fwsm, manc, factps;
 
-       fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM);
+       fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw));
        if ((fwsm & IXGBE_FWSM_MODE_MASK) != IXGBE_FWSM_FW_MODE_PT)
                return false;
 
@@ -4902,7 +5068,7 @@ bool ixgbe_mng_enabled(struct ixgbe_hw *hw)
                return false;
 
        if (hw->mac.type <= ixgbe_mac_X540) {
-               factps = IXGBE_READ_REG(hw, IXGBE_FACTPS);
+               factps = IXGBE_READ_REG(hw, IXGBE_FACTPS_BY_MAC(hw));
                if (factps & IXGBE_FACTPS_MNGCG)
                        return false;
        }
@@ -4945,14 +5111,6 @@ s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
                speedcnt++;
                highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL;
 
-               /* If we already have link at this speed, just jump out */
-               status = ixgbe_check_link(hw, &link_speed, &link_up, false);
-               if (status != IXGBE_SUCCESS)
-                       return status;
-
-               if ((link_speed == IXGBE_LINK_SPEED_10GB_FULL) && link_up)
-                       goto out;
-
                /* Set the module link speed */
                switch (hw->phy.media_type) {
                case ixgbe_media_type_fiber:
@@ -5003,14 +5161,6 @@ s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
                if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN)
                        highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL;
 
-               /* If we already have link at this speed, just jump out */
-               status = ixgbe_check_link(hw, &link_speed, &link_up, false);
-               if (status != IXGBE_SUCCESS)
-                       return status;
-
-               if ((link_speed == IXGBE_LINK_SPEED_1GB_FULL) && link_up)
-                       goto out;
-
                /* Set the module link speed */
                switch (hw->phy.media_type) {
                case ixgbe_media_type_fiber: