bool i40e_set_ntuple(struct i40e_pf *pf, netdev_features_t features);
 void i40e_set_ethtool_ops(struct net_device *netdev);
 struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
-                                       u8 *macaddr, s16 vlan);
-void i40e_del_filter(struct i40e_vsi *vsi, u8 *macaddr, s16 vlan);
+                                       const u8 *macaddr, s16 vlan);
+void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan);
 int i40e_sync_vsi_filters(struct i40e_vsi *vsi);
 struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,
                                u16 uplink, u32 param1);
 int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid);
 int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid);
 struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi,
-                                            u8 *macaddr);
-int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr);
+                                            const u8 *macaddr);
+int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, const u8 *macaddr);
 bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi);
-struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr);
+struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, const u8 *macaddr);
 #ifdef I40E_FCOE
 int __i40e_setup_tc(struct net_device *netdev, u32 handle, __be16 proto,
                    struct tc_to_netdev *tc);
 
  * Returns ptr to the filter object or NULL
  **/
 static struct i40e_mac_filter *i40e_find_filter(struct i40e_vsi *vsi,
-                                               u8 *macaddr, s16 vlan)
+                                               const u8 *macaddr, s16 vlan)
 {
        struct i40e_mac_filter *f;
 
  * Returns the first filter with the provided MAC address or NULL if
  * MAC address was not found
  **/
-struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr)
+struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, const u8 *macaddr)
 {
        struct i40e_mac_filter *f;
 
  *
  * Returns first filter found on success, else NULL
  **/
-struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, u8 *macaddr)
+struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi,
+                                            const u8 *macaddr)
 {
        struct i40e_mac_filter *f;
 
  *
  * Returns 0 for success, or error
  **/
-int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr)
+int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, const u8 *macaddr)
 {
        struct i40e_mac_filter *f = NULL;
        int changed = 0;
  * being held.
  **/
 struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
-                                       u8 *macaddr, s16 vlan)
+                                       const u8 *macaddr, s16 vlan)
 {
        struct i40e_mac_filter *f;
 
  * the "safe" variants of any list iterators, e.g. list_for_each_entry_safe()
  * instead of list_for_each_entry().
  **/
-void i40e_del_filter(struct i40e_vsi *vsi, u8 *macaddr, s16 vlan)
+void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan)
 {
        struct i40e_mac_filter *f;
 
        ctxt->info.valid_sections |= cpu_to_le16(sections);
 }
 
+/**
+ * i40e_addr_sync - Callback for dev_(mc|uc)_sync to add address
+ * @netdev: the netdevice
+ * @addr: address to add
+ *
+ * Called by __dev_(mc|uc)_sync when an address needs to be added. We call
+ * __dev_(uc|mc)_sync from .set_rx_mode and guarantee to hold the hash lock.
+ */
+static int i40e_addr_sync(struct net_device *netdev, const u8 *addr)
+{
+       struct i40e_netdev_priv *np = netdev_priv(netdev);
+       struct i40e_vsi *vsi = np->vsi;
+       struct i40e_mac_filter *f;
+
+       if (i40e_is_vsi_in_vlan(vsi))
+               f = i40e_put_mac_in_vlan(vsi, addr);
+       else
+               f = i40e_add_filter(vsi, addr, I40E_VLAN_ANY);
+
+       if (f)
+               return 0;
+       else
+               return -ENOMEM;
+}
+
+/**
+ * i40e_addr_unsync - Callback for dev_(mc|uc)_sync to remove address
+ * @netdev: the netdevice
+ * @addr: address to add
+ *
+ * Called by __dev_(mc|uc)_sync when an address needs to be removed. We call
+ * __dev_(uc|mc)_sync from .set_rx_mode and guarantee to hold the hash lock.
+ */
+static int i40e_addr_unsync(struct net_device *netdev, const u8 *addr)
+{
+       struct i40e_netdev_priv *np = netdev_priv(netdev);
+       struct i40e_vsi *vsi = np->vsi;
+
+       if (i40e_is_vsi_in_vlan(vsi))
+               i40e_del_mac_all_vlan(vsi, addr);
+       else
+               i40e_del_filter(vsi, addr, I40E_VLAN_ANY);
+
+       return 0;
+}
+
 /**
  * i40e_set_rx_mode - NDO callback to set the netdev filters
  * @netdev: network interface device structure
 #endif
 {
        struct i40e_netdev_priv *np = netdev_priv(netdev);
-       struct i40e_mac_filter *f, *ftmp;
        struct i40e_vsi *vsi = np->vsi;
-       struct netdev_hw_addr *uca;
-       struct netdev_hw_addr *mca;
-       struct netdev_hw_addr *ha;
 
        spin_lock_bh(&vsi->mac_filter_list_lock);
 
-       /* add addr if not already in the filter list */
-       netdev_for_each_uc_addr(uca, netdev) {
-               if (!i40e_find_mac(vsi, uca->addr)) {
-                       if (i40e_is_vsi_in_vlan(vsi))
-                               i40e_put_mac_in_vlan(vsi, uca->addr);
-                       else
-                               i40e_add_filter(vsi, uca->addr, I40E_VLAN_ANY);
-               }
-       }
-
-       netdev_for_each_mc_addr(mca, netdev) {
-               if (!i40e_find_mac(vsi, mca->addr)) {
-                       if (i40e_is_vsi_in_vlan(vsi))
-                               i40e_put_mac_in_vlan(vsi, mca->addr);
-                       else
-                               i40e_add_filter(vsi, mca->addr, I40E_VLAN_ANY);
-               }
-       }
+       __dev_uc_sync(netdev, i40e_addr_sync, i40e_addr_unsync);
+       __dev_mc_sync(netdev, i40e_addr_sync, i40e_addr_unsync);
 
-       /* remove filter if not in netdev list */
-       list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {
-
-               netdev_for_each_mc_addr(mca, netdev)
-                       if (ether_addr_equal(mca->addr, f->macaddr))
-                               goto bottom_of_search_loop;
-
-               netdev_for_each_uc_addr(uca, netdev)
-                       if (ether_addr_equal(uca->addr, f->macaddr))
-                               goto bottom_of_search_loop;
-
-               for_each_dev_addr(netdev, ha)
-                       if (ether_addr_equal(ha->addr, f->macaddr))
-                               goto bottom_of_search_loop;
-
-               /* f->macaddr wasn't found in uc, mc, or ha list so delete it */
-               i40e_del_filter(vsi, f->macaddr, I40E_VLAN_ANY);
-
-bottom_of_search_loop:
-               continue;
-       }
        spin_unlock_bh(&vsi->mac_filter_list_lock);
 
        /* check for other flag changes */
        }
 
        spin_lock_bh(&vsi->mac_filter_list_lock);
+
+       /* clear the sync flag on all filters */
+       if (vsi->netdev) {
+               __dev_uc_unsync(vsi->netdev, NULL);
+               __dev_mc_unsync(vsi->netdev, NULL);
+       }
+
+       /* make sure any remaining filters are marked for deletion */
        list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list)
                i40e_del_filter(vsi, f->macaddr, f->vlan);
+
        spin_unlock_bh(&vsi->mac_filter_list_lock);
 
        i40e_sync_vsi_filters(vsi);