/* Map PF MAC address in RAR Entry 0 to first pool following VFs */
        hw->mac.ops.set_vmdq(hw, 0, VMDQ_P(0));
 
+       /* clear VLAN promisc flag so VFTA will be updated if necessary */
+       adapter->flags2 &= ~IXGBE_FLAG2_VLAN_PROMISC;
+
        /*
         * Set up VF register offsets for selected VT Mode,
         * i.e. 32 or 64 VFs for SR-IOV
        }
 }
 
+static void ixgbe_vlan_promisc_enable(struct ixgbe_adapter *adapter)
+{
+       struct ixgbe_hw *hw = &adapter->hw;
+       u32 vlnctrl, i;
+
+       switch (hw->mac.type) {
+       case ixgbe_mac_82599EB:
+       case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
+       default:
+               if (adapter->flags & IXGBE_FLAG_VMDQ_ENABLED)
+                       break;
+               /* fall through */
+       case ixgbe_mac_82598EB:
+               /* legacy case, we can just disable VLAN filtering */
+               vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
+               vlnctrl &= ~(IXGBE_VLNCTRL_VFE | IXGBE_VLNCTRL_CFIEN);
+               IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
+               return;
+       }
+
+       /* We are already in VLAN promisc, nothing to do */
+       if (adapter->flags2 & IXGBE_FLAG2_VLAN_PROMISC)
+               return;
+
+       /* Set flag so we don't redo unnecessary work */
+       adapter->flags2 |= IXGBE_FLAG2_VLAN_PROMISC;
+
+       /* Add PF to all active pools */
+       for (i = IXGBE_VLVF_ENTRIES; --i;) {
+               u32 reg_offset = IXGBE_VLVFB(i * 2 + VMDQ_P(0) / 32);
+               u32 vlvfb = IXGBE_READ_REG(hw, reg_offset);
+
+               vlvfb |= 1 << (VMDQ_P(0) % 32);
+               IXGBE_WRITE_REG(hw, reg_offset, vlvfb);
+       }
+
+       /* Set all bits in the VLAN filter table array */
+       for (i = hw->mac.vft_size; i--;)
+               IXGBE_WRITE_REG(hw, IXGBE_VFTA(i), ~0U);
+}
+
+#define VFTA_BLOCK_SIZE 8
+static void ixgbe_scrub_vfta(struct ixgbe_adapter *adapter, u32 vfta_offset)
+{
+       struct ixgbe_hw *hw = &adapter->hw;
+       u32 vfta[VFTA_BLOCK_SIZE] = { 0 };
+       u32 vid_start = vfta_offset * 32;
+       u32 vid_end = vid_start + (VFTA_BLOCK_SIZE * 32);
+       u32 i, vid, word, bits;
+
+       for (i = IXGBE_VLVF_ENTRIES; --i;) {
+               u32 vlvf = IXGBE_READ_REG(hw, IXGBE_VLVF(i));
+
+               /* pull VLAN ID from VLVF */
+               vid = vlvf & VLAN_VID_MASK;
+
+               /* only concern outselves with a certain range */
+               if (vid < vid_start || vid >= vid_end)
+                       continue;
+
+               if (vlvf) {
+                       /* record VLAN ID in VFTA */
+                       vfta[(vid - vid_start) / 32] |= 1 << (vid % 32);
+
+                       /* if PF is part of this then continue */
+                       if (test_bit(vid, adapter->active_vlans))
+                               continue;
+               }
+
+               /* remove PF from the pool */
+               word = i * 2 + VMDQ_P(0) / 32;
+               bits = ~(1 << (VMDQ_P(0) % 32));
+               bits &= IXGBE_READ_REG(hw, IXGBE_VLVFB(word));
+               IXGBE_WRITE_REG(hw, IXGBE_VLVFB(word), bits);
+       }
+
+       /* extract values from active_vlans and write back to VFTA */
+       for (i = VFTA_BLOCK_SIZE; i--;) {
+               vid = (vfta_offset + i) * 32;
+               word = vid / BITS_PER_LONG;
+               bits = vid % BITS_PER_LONG;
+
+               vfta[i] |= adapter->active_vlans[word] >> bits;
+
+               IXGBE_WRITE_REG(hw, IXGBE_VFTA(vfta_offset + i), vfta[i]);
+       }
+}
+
+static void ixgbe_vlan_promisc_disable(struct ixgbe_adapter *adapter)
+{
+       struct ixgbe_hw *hw = &adapter->hw;
+       u32 vlnctrl, i;
+
+       switch (hw->mac.type) {
+       case ixgbe_mac_82599EB:
+       case ixgbe_mac_X540:
+       case ixgbe_mac_X550:
+       case ixgbe_mac_X550EM_x:
+       default:
+               if (adapter->flags & IXGBE_FLAG_VMDQ_ENABLED)
+                       break;
+               /* fall through */
+       case ixgbe_mac_82598EB:
+               vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
+               vlnctrl &= ~IXGBE_VLNCTRL_CFIEN;
+               vlnctrl |= IXGBE_VLNCTRL_VFE;
+               IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
+               return;
+       }
+
+       /* We are not in VLAN promisc, nothing to do */
+       if (!(adapter->flags2 & IXGBE_FLAG2_VLAN_PROMISC))
+               return;
+
+       /* Set flag so we don't redo unnecessary work */
+       adapter->flags2 &= ~IXGBE_FLAG2_VLAN_PROMISC;
+
+       for (i = 0; i < hw->mac.vft_size; i += VFTA_BLOCK_SIZE)
+               ixgbe_scrub_vfta(adapter, i);
+}
+
 static void ixgbe_restore_vlan(struct ixgbe_adapter *adapter)
 {
        u16 vid;
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
        struct ixgbe_hw *hw = &adapter->hw;
        u32 fctrl, vmolr = IXGBE_VMOLR_BAM | IXGBE_VMOLR_AUPE;
-       u32 vlnctrl;
        int count;
 
        /* Check for Promiscuous and All Multicast modes */
        fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
-       vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
 
        /* set all bits that we expect to always be set */
        fctrl &= ~IXGBE_FCTRL_SBP; /* disable store-bad-packets */
 
        /* clear the bits we are changing the status of */
        fctrl &= ~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
-       vlnctrl &= ~(IXGBE_VLNCTRL_VFE | IXGBE_VLNCTRL_CFIEN);
        if (netdev->flags & IFF_PROMISC) {
                hw->addr_ctrl.user_set_promisc = true;
                fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
                vmolr |= IXGBE_VMOLR_MPE;
-               /* Only disable hardware filter vlans in promiscuous mode
-                * if SR-IOV and VMDQ are disabled - otherwise ensure
-                * that hardware VLAN filters remain enabled.
-                */
-               if (adapter->flags & (IXGBE_FLAG_VMDQ_ENABLED |
-                                     IXGBE_FLAG_SRIOV_ENABLED))
-                       vlnctrl |= (IXGBE_VLNCTRL_VFE | IXGBE_VLNCTRL_CFIEN);
+               ixgbe_vlan_promisc_enable(adapter);
        } else {
                if (netdev->flags & IFF_ALLMULTI) {
                        fctrl |= IXGBE_FCTRL_MPE;
                        vmolr |= IXGBE_VMOLR_MPE;
                }
-               vlnctrl |= IXGBE_VLNCTRL_VFE;
                hw->addr_ctrl.user_set_promisc = false;
+               ixgbe_vlan_promisc_disable(adapter);
        }
 
        /*
                /* NOTE:  VLAN filtering is disabled by setting PROMISC */
        }
 
-       IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
        IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
 
        if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX)