net/ixgbe/base: simplify VLAN management
[dpdk.git] / drivers / net / ixgbe / base / ixgbe_common.c
index 3758df1..4551a2a 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");
 
@@ -134,6 +134,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;
 
        /* Link */
        mac->ops.get_link_capabilities = NULL;
@@ -184,6 +185,8 @@ 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:
                        supported = true;
                        break;
                default:
@@ -200,19 +203,19 @@ bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
 }
 
 /**
- *  ixgbe_setup_fc - Set up flow control
+ *  ixgbe_setup_fc_generic - Set up flow control
  *  @hw: pointer to hardware structure
  *
  *  Called at init time to set up flow control.
  **/
-STATIC s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
+s32 ixgbe_setup_fc_generic(struct ixgbe_hw *hw)
 {
        s32 ret_val = IXGBE_SUCCESS;
        u32 reg = 0, reg_bp = 0;
        u16 reg_cu = 0;
        bool locked = false;
 
-       DEBUGFUNC("ixgbe_setup_fc");
+       DEBUGFUNC("ixgbe_setup_fc_generic");
 
        /* Validate the requested mode */
        if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
@@ -1017,13 +1020,15 @@ 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");
 
@@ -1032,9 +1037,16 @@ void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw)
        bus->lan_id = 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;
+       }
 }
 
 /**
@@ -1158,7 +1170,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;
 
@@ -1719,14 +1731,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);
@@ -1735,7 +1747,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);
@@ -1746,7 +1758,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);
                }
@@ -1776,7 +1788,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;
@@ -1801,7 +1813,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;
        }
@@ -1809,17 +1821,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;
 
@@ -1916,15 +1928,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);
 }
@@ -1944,7 +1956,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
@@ -1965,7 +1977,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);
@@ -1982,7 +1994,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);
 }
 
@@ -2005,7 +2017,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);
 
@@ -2013,7 +2025,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)
@@ -2039,7 +2051,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);
 }
@@ -2058,7 +2070,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);
 }
@@ -2073,19 +2085,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);
 
@@ -2240,7 +2252,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)
 {
@@ -2250,16 +2262,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;
@@ -2397,10 +2406,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;
@@ -3140,6 +3150,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.
@@ -3567,6 +3580,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;
@@ -3839,24 +3853,20 @@ s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan)
  *  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
  *
  *  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)
 {
-       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;
 
        /*
@@ -3871,33 +3881,28 @@ 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);
+       ret_val = ixgbe_set_vlvf_generic(hw, vlan, vind, vlan_on, &vfta_delta,
+                                        vfta);
        if (ret_val != IXGBE_SUCCESS)
                return ret_val;
 
-       if (vfta_changed)
-               IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), vfta);
+       /* Update VFTA now that we are ready for traffic */
+       if (vfta_delta)
+               IXGBE_WRITE_REG(hw, IXGBE_VFTA(regidx), vfta);
 
        return IXGBE_SUCCESS;
 }
@@ -3906,21 +3911,23 @@ 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
  *
  *  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)
 {
-       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
@@ -3930,82 +3937,57 @@ 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;
+       vlvf_index = ixgbe_find_vlvf_slot(hw, vlan);
+       if (vlvf_index < 0)
+               return vlvf_index;
 
-               /*
-                * 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.
+       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;
 }
@@ -4028,7 +4010,7 @@ 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;
@@ -4062,7 +4044,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;
@@ -4359,8 +4341,9 @@ u8 ixgbe_calculate_checksum(u8 *buffer, u32 length)
  *   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.
  **/
 s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer,
                                 u32 length, u32 timeout, bool return_data)
@@ -4369,6 +4352,7 @@ s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer,
        u32 hdr_size = sizeof(struct ixgbe_hic_hdr);
        u16 buf_len;
        u16 dword_len;
+       s32 status;
 
        DEBUGFUNC("ixgbe_host_interface_command");
 
@@ -4376,6 +4360,12 @@ s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer,
                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;
+
        /* 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);
@@ -4384,13 +4374,15 @@ s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer,
        hicr = IXGBE_READ_REG(hw, IXGBE_HICR);
        if ((hicr & IXGBE_HICR_EN) == 0) {
                DEBUGOUT("IXGBE_HOST_EN bit disabled.\n");
-               return IXGBE_ERR_HOST_INTERFACE_COMMAND;
+               status = IXGBE_ERR_HOST_INTERFACE_COMMAND;
+               goto rel_out;
        }
 
        /* Calculate length in DWORDs. We must be DWORD aligned */
        if ((length % (sizeof(u32))) != 0) {
                DEBUGOUT("Buffer length failure, not aligned to dword");
-               return IXGBE_ERR_INVALID_ARGUMENT;
+               status = IXGBE_ERR_INVALID_ARGUMENT;
+               goto rel_out;
        }
 
        dword_len = length >> 2;
@@ -4417,11 +4409,12 @@ s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer,
            !(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;
+               status = IXGBE_ERR_HOST_INTERFACE_COMMAND;
+               goto rel_out;
        }
 
        if (!return_data)
-               return 0;
+               goto rel_out;
 
        /* Calculate length in DWORDs */
        dword_len = hdr_size >> 2;
@@ -4435,11 +4428,12 @@ 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;
+               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 */
@@ -4451,7 +4445,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;
 }
 
 /**
@@ -4476,12 +4473,6 @@ s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min,
 
        DEBUGFUNC("ixgbe_set_fw_drv_ver_generic");
 
-       if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM)
-           != IXGBE_SUCCESS) {
-               ret_val = IXGBE_ERR_SWFW_SYNC;
-               goto out;
-       }
-
        fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO;
        fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN;
        fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
@@ -4513,8 +4504,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;
 }
 
@@ -4877,7 +4866,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;
 }
@@ -4892,7 +4881,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;
 
@@ -4901,7 +4890,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;
        }