return err;
 }
 
-static int nfp_net_mc_cfg(struct net_device *netdev, const unsigned char *addr, const u32 cmd)
+struct nfp_mc_addr_entry {
+       u8 addr[ETH_ALEN];
+       u32 cmd;
+       struct list_head list;
+};
+
+static int nfp_net_mc_cfg(struct nfp_net *nn, const unsigned char *addr, const u32 cmd)
 {
-       struct nfp_net *nn = netdev_priv(netdev);
        int ret;
 
        ret = nfp_net_mbox_lock(nn, NFP_NET_CFG_MULTICAST_SZ);
        return nfp_net_mbox_reconfig_and_unlock(nn, cmd);
 }
 
+static int nfp_net_mc_prep(struct nfp_net *nn, const unsigned char *addr, const u32 cmd)
+{
+       struct nfp_mc_addr_entry *entry;
+
+       entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
+       if (!entry)
+               return -ENOMEM;
+
+       ether_addr_copy(entry->addr, addr);
+       entry->cmd = cmd;
+       spin_lock_bh(&nn->mc_lock);
+       list_add_tail(&entry->list, &nn->mc_addrs);
+       spin_unlock_bh(&nn->mc_lock);
+
+       schedule_work(&nn->mc_work);
+
+       return 0;
+}
+
 static int nfp_net_mc_sync(struct net_device *netdev, const unsigned char *addr)
 {
        struct nfp_net *nn = netdev_priv(netdev);
                return -EINVAL;
        }
 
-       return nfp_net_mc_cfg(netdev, addr, NFP_NET_CFG_MBOX_CMD_MULTICAST_ADD);
+       return nfp_net_mc_prep(nn, addr, NFP_NET_CFG_MBOX_CMD_MULTICAST_ADD);
 }
 
 static int nfp_net_mc_unsync(struct net_device *netdev, const unsigned char *addr)
 {
-       return nfp_net_mc_cfg(netdev, addr, NFP_NET_CFG_MBOX_CMD_MULTICAST_DEL);
+       struct nfp_net *nn = netdev_priv(netdev);
+
+       return nfp_net_mc_prep(nn, addr, NFP_NET_CFG_MBOX_CMD_MULTICAST_DEL);
+}
+
+static void nfp_net_mc_addr_config(struct work_struct *work)
+{
+       struct nfp_net *nn = container_of(work, struct nfp_net, mc_work);
+       struct nfp_mc_addr_entry *entry, *tmp;
+       struct list_head tmp_list;
+
+       INIT_LIST_HEAD(&tmp_list);
+
+       spin_lock_bh(&nn->mc_lock);
+       list_splice_init(&nn->mc_addrs, &tmp_list);
+       spin_unlock_bh(&nn->mc_lock);
+
+       list_for_each_entry_safe(entry, tmp, &tmp_list, list) {
+               if (nfp_net_mc_cfg(nn, entry->addr, entry->cmd))
+                       nn_err(nn, "Config mc address to HW failed.\n");
+
+               list_del(&entry->list);
+               kfree(entry);
+       }
 }
 
 static void nfp_net_set_rx_mode(struct net_device *netdev)
 
        if (!nn->dp.netdev)
                return 0;
+
+       spin_lock_init(&nn->mc_lock);
+       INIT_LIST_HEAD(&nn->mc_addrs);
+       INIT_WORK(&nn->mc_work, nfp_net_mc_addr_config);
+
        return register_netdev(nn->dp.netdev);
 
 err_clean_mbox:
        unregister_netdev(nn->dp.netdev);
        nfp_net_ipsec_clean(nn);
        nfp_ccm_mbox_clean(nn);
+       flush_work(&nn->mc_work);
        nfp_net_reconfig_wait_posted(nn);
 }