return err;
 }
 
-/*
- * Add a Multicast address to slaves
- * according to mode
- */
-static void bond_mc_add(struct bonding *bond, void *addr)
-{
-       if (USES_PRIMARY(bond->params.mode)) {
-               /* write lock already acquired */
-               if (bond->curr_active_slave)
-                       dev_mc_add(bond->curr_active_slave->dev, addr);
-       } else {
-               struct slave *slave;
-               int i;
-
-               bond_for_each_slave(bond, slave, i)
-                       dev_mc_add(slave->dev, addr);
-       }
-}
-
-/*
- * Remove a multicast address from slave
- * according to mode
- */
-static void bond_mc_del(struct bonding *bond, void *addr)
-{
-       if (USES_PRIMARY(bond->params.mode)) {
-               /* write lock already acquired */
-               if (bond->curr_active_slave)
-                       dev_mc_del(bond->curr_active_slave->dev, addr);
-       } else {
-               struct slave *slave;
-               int i;
-               bond_for_each_slave(bond, slave, i) {
-                       dev_mc_del(slave->dev, addr);
-               }
-       }
-}
-
-
 static void __bond_resend_igmp_join_requests(struct net_device *dev)
 {
        struct in_device *in_dev;
        bond_resend_igmp_join_requests(bond);
 }
 
-/*
- * flush all members of flush->mc_list from device dev->mc_list
+/* Flush bond's hardware addresses from slave
  */
-static void bond_mc_list_flush(struct net_device *bond_dev,
+static void bond_hw_addr_flush(struct net_device *bond_dev,
                               struct net_device *slave_dev)
 {
        struct bonding *bond = netdev_priv(bond_dev);
-       struct netdev_hw_addr *ha;
 
-       netdev_for_each_mc_addr(ha, bond_dev)
-               dev_mc_del(slave_dev, ha->addr);
+       dev_uc_unsync(slave_dev, bond_dev);
+       dev_mc_unsync(slave_dev, bond_dev);
 
        if (bond->params.mode == BOND_MODE_8023AD) {
                /* del lacpdu mc addr from mc list */
 
 /*--------------------------- Active slave change ---------------------------*/
 
-/*
- * Update the mc list and multicast-related flags for the new and
- * old active slaves (if any) according to the multicast mode, and
- * promiscuous flags unconditionally.
+/* Update the hardware address list and promisc/allmulti for the new and
+ * old active slaves (if any).  Modes that are !USES_PRIMARY keep all
+ * slaves up date at all times; only the USES_PRIMARY modes need to call
+ * this function to swap these settings during a failover.
  */
-static void bond_mc_swap(struct bonding *bond, struct slave *new_active,
-                        struct slave *old_active)
+static void bond_hw_addr_swap(struct bonding *bond, struct slave *new_active,
+                             struct slave *old_active)
 {
-       struct netdev_hw_addr *ha;
-
-       if (!USES_PRIMARY(bond->params.mode))
-               /* nothing to do -  mc list is already up-to-date on
-                * all slaves
-                */
-               return;
-
        if (old_active) {
                if (bond->dev->flags & IFF_PROMISC)
                        dev_set_promiscuity(old_active->dev, -1);
                if (bond->dev->flags & IFF_ALLMULTI)
                        dev_set_allmulti(old_active->dev, -1);
 
-               netif_addr_lock_bh(bond->dev);
-               netdev_for_each_mc_addr(ha, bond->dev)
-                       dev_mc_del(old_active->dev, ha->addr);
-               netif_addr_unlock_bh(bond->dev);
+               bond_hw_addr_flush(bond->dev, old_active->dev);
        }
 
        if (new_active) {
                        dev_set_allmulti(new_active->dev, 1);
 
                netif_addr_lock_bh(bond->dev);
-               netdev_for_each_mc_addr(ha, bond->dev)
-                       dev_mc_add(new_active->dev, ha->addr);
+               dev_uc_sync(new_active->dev, bond->dev);
+               dev_mc_sync(new_active->dev, bond->dev);
                netif_addr_unlock_bh(bond->dev);
        }
 }
        }
 
        if (USES_PRIMARY(bond->params.mode))
-               bond_mc_swap(bond, new_active, old_active);
+               bond_hw_addr_swap(bond, new_active, old_active);
 
        if (bond_is_lb(bond)) {
                bond_alb_handle_active_change(bond, new_active);
        struct bonding *bond = netdev_priv(bond_dev);
        const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
        struct slave *new_slave = NULL;
-       struct netdev_hw_addr *ha;
        struct sockaddr addr;
        int link_reporting;
        int res = 0;
                        goto err_close;
        }
 
-       /* If the mode USES_PRIMARY, then the new slave gets the
-        * master's promisc (and mc) settings only if it becomes the
-        * curr_active_slave, and that is taken care of later when calling
-        * bond_change_active()
+       /* If the mode USES_PRIMARY, then the following is handled by
+        * bond_change_active_slave().
         */
        if (!USES_PRIMARY(bond->params.mode)) {
                /* set promiscuity level to new slave */
                }
 
                netif_addr_lock_bh(bond_dev);
-               /* upload master's mc_list to new slave */
-               netdev_for_each_mc_addr(ha, bond_dev)
-                       dev_mc_add(slave_dev, ha->addr);
+
+               dev_mc_sync_multiple(slave_dev, bond_dev);
+               dev_uc_sync_multiple(slave_dev, bond_dev);
+
                netif_addr_unlock_bh(bond_dev);
        }
 
        bond_destroy_slave_symlinks(bond_dev, slave_dev);
 
 err_detach:
-       if (!USES_PRIMARY(bond->params.mode)) {
-               netif_addr_lock_bh(bond_dev);
-               bond_mc_list_flush(bond_dev, slave_dev);
-               netif_addr_unlock_bh(bond_dev);
-       }
+       if (!USES_PRIMARY(bond->params.mode))
+               bond_hw_addr_flush(bond_dev, slave_dev);
+
        bond_del_vlans_from_slave(bond, slave_dev);
        write_lock_bh(&bond->lock);
        bond_detach_slave(bond, new_slave);
 
        bond_del_vlans_from_slave(bond, slave_dev);
 
-       /* If the mode USES_PRIMARY, then we should only remove its
-        * promisc and mc settings if it was the curr_active_slave, but that was
-        * already taken care of above when we detached the slave
+       /* If the mode USES_PRIMARY, then this cases was handled above by
+        * bond_change_active_slave(..., NULL)
         */
        if (!USES_PRIMARY(bond->params.mode)) {
                /* unset promiscuity level from slave */
                if (bond_dev->flags & IFF_ALLMULTI)
                        dev_set_allmulti(slave_dev, -1);
 
-               /* flush master's mc_list from slave */
-               netif_addr_lock_bh(bond_dev);
-               bond_mc_list_flush(bond_dev, slave_dev);
-               netif_addr_unlock_bh(bond_dev);
+               bond_hw_addr_flush(bond_dev, slave_dev);
        }
 
        bond_upper_dev_unlink(bond_dev, slave_dev);
        return res;
 }
 
-static bool bond_addr_in_mc_list(unsigned char *addr,
-                                struct netdev_hw_addr_list *list,
-                                int addrlen)
-{
-       struct netdev_hw_addr *ha;
-
-       netdev_hw_addr_list_for_each(ha, list)
-               if (!memcmp(ha->addr, addr, addrlen))
-                       return true;
-
-       return false;
-}
-
 static void bond_change_rx_flags(struct net_device *bond_dev, int change)
 {
        struct bonding *bond = netdev_priv(bond_dev);
                                  bond_dev->flags & IFF_ALLMULTI ? 1 : -1);
 }
 
-static void bond_set_multicast_list(struct net_device *bond_dev)
+static void bond_set_rx_mode(struct net_device *bond_dev)
 {
        struct bonding *bond = netdev_priv(bond_dev);
-       struct netdev_hw_addr *ha;
-       bool found;
+       struct slave *slave;
+       int i;
 
        read_lock(&bond->lock);
 
-       /* looking for addresses to add to slaves' mc list */
-       netdev_for_each_mc_addr(ha, bond_dev) {
-               found = bond_addr_in_mc_list(ha->addr, &bond->mc_list,
-                                            bond_dev->addr_len);
-               if (!found)
-                       bond_mc_add(bond, ha->addr);
-       }
-
-       /* looking for addresses to delete from slaves' list */
-       netdev_hw_addr_list_for_each(ha, &bond->mc_list) {
-               found = bond_addr_in_mc_list(ha->addr, &bond_dev->mc,
-                                            bond_dev->addr_len);
-               if (!found)
-                       bond_mc_del(bond, ha->addr);
+       if (USES_PRIMARY(bond->params.mode)) {
+               read_lock(&bond->curr_slave_lock);
+               slave = bond->curr_active_slave;
+               if (slave) {
+                       dev_uc_sync(slave->dev, bond_dev);
+                       dev_mc_sync(slave->dev, bond_dev);
+               }
+               read_unlock(&bond->curr_slave_lock);
+       } else {
+               bond_for_each_slave(bond, slave, i) {
+                       dev_uc_sync_multiple(slave->dev, bond_dev);
+                       dev_mc_sync_multiple(slave->dev, bond_dev);
+               }
        }
 
-       /* save master's multicast list */
-       __hw_addr_flush(&bond->mc_list);
-       __hw_addr_add_multiple(&bond->mc_list, &bond_dev->mc,
-                              bond_dev->addr_len, NETDEV_HW_ADDR_T_MULTICAST);
-
        read_unlock(&bond->lock);
 }
 
        .ndo_get_stats64        = bond_get_stats,
        .ndo_do_ioctl           = bond_do_ioctl,
        .ndo_change_rx_flags    = bond_change_rx_flags,
-       .ndo_set_rx_mode        = bond_set_multicast_list,
+       .ndo_set_rx_mode        = bond_set_rx_mode,
        .ndo_change_mtu         = bond_change_mtu,
        .ndo_set_mac_address    = bond_set_mac_address,
        .ndo_neigh_setup        = bond_neigh_setup,
 
        bond_debug_unregister(bond);
 
-       __hw_addr_flush(&bond->mc_list);
-
        list_for_each_entry_safe(vlan, tmp, &bond->vlan_list, vlan_list) {
                list_del(&vlan->vlan_list);
                kfree(vlan);
                bond->dev_addr_from_first = true;
        }
 
-       __hw_addr_init(&bond->mc_list);
        return 0;
 }