static void qlcnic_sriov_process_bc_cmd(struct work_struct *);
 static int qlcnic_sriov_vf_shutdown(struct pci_dev *);
 static int qlcnic_sriov_vf_resume(struct qlcnic_adapter *);
+static int qlcnic_sriov_async_issue_cmd(struct qlcnic_adapter *,
+                                       struct qlcnic_cmd_args *);
 
 static struct qlcnic_hardware_ops qlcnic_sriov_vf_hw_ops = {
        .read_crb                       = qlcnic_83xx_read_crb,
                vf->adapter = adapter;
                vf->pci_func = qlcnic_sriov_virtid_fn(adapter, i);
                mutex_init(&vf->send_cmd_lock);
-               mutex_init(&vf->vlan_list_lock);
+               spin_lock_init(&vf->vlan_list_lock);
                INIT_LIST_HEAD(&vf->rcv_act.wait_list);
                INIT_LIST_HEAD(&vf->rcv_pend.wait_list);
                spin_lock_init(&vf->rcv_act.lock);
        return -EIO;
 }
 
-static int qlcnic_sriov_issue_cmd(struct qlcnic_adapter *adapter,
+static int __qlcnic_sriov_issue_cmd(struct qlcnic_adapter *adapter,
                                  struct qlcnic_cmd_args *cmd)
 {
        struct qlcnic_hardware_context *ahw = adapter->ahw;
        return rsp;
 }
 
+
+static int qlcnic_sriov_issue_cmd(struct qlcnic_adapter *adapter,
+                                 struct qlcnic_cmd_args *cmd)
+{
+       if (cmd->type == QLC_83XX_MBX_CMD_NO_WAIT)
+               return qlcnic_sriov_async_issue_cmd(adapter, cmd);
+       else
+               return __qlcnic_sriov_issue_cmd(adapter, cmd);
+}
+
 static int qlcnic_sriov_channel_cfg_cmd(struct qlcnic_adapter *adapter, u8 cmd_op)
 {
        struct qlcnic_cmd_args cmd;
        return ret;
 }
 
-static void qlcnic_vf_add_mc_list(struct net_device *netdev)
+static void qlcnic_vf_add_mc_list(struct net_device *netdev, const u8 *mac)
 {
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
        struct qlcnic_sriov *sriov = adapter->ahw->sriov;
-       struct qlcnic_mac_vlan_list *cur;
-       struct list_head *head, tmp_list;
        struct qlcnic_vf_info *vf;
        u16 vlan_id;
        int i;
 
-       static const u8 bcast_addr[ETH_ALEN] = {
-               0xff, 0xff, 0xff, 0xff, 0xff, 0xff
-       };
-
        vf = &adapter->ahw->sriov->vf_info[0];
-       INIT_LIST_HEAD(&tmp_list);
-       head = &adapter->vf_mc_list;
-       netif_addr_lock_bh(netdev);
-
-       while (!list_empty(head)) {
-               cur = list_entry(head->next, struct qlcnic_mac_vlan_list, list);
-               list_move(&cur->list, &tmp_list);
-       }
-
-       netif_addr_unlock_bh(netdev);
 
-       while (!list_empty(&tmp_list)) {
-               cur = list_entry((&tmp_list)->next,
-                                struct qlcnic_mac_vlan_list, list);
-               if (!qlcnic_sriov_check_any_vlan(vf)) {
-                       qlcnic_nic_add_mac(adapter, bcast_addr, 0);
-                       qlcnic_nic_add_mac(adapter, cur->mac_addr, 0);
-               } else {
-                       mutex_lock(&vf->vlan_list_lock);
-                       for (i = 0; i < sriov->num_allowed_vlans; i++) {
-                               vlan_id = vf->sriov_vlans[i];
-                               if (vlan_id) {
-                                       qlcnic_nic_add_mac(adapter, bcast_addr,
-                                                          vlan_id);
-                                       qlcnic_nic_add_mac(adapter,
-                                                          cur->mac_addr,
-                                                          vlan_id);
-                               }
-                       }
-                       mutex_unlock(&vf->vlan_list_lock);
-                       if (qlcnic_84xx_check(adapter)) {
-                               qlcnic_nic_add_mac(adapter, bcast_addr, 0);
-                               qlcnic_nic_add_mac(adapter, cur->mac_addr, 0);
-                       }
+       if (!qlcnic_sriov_check_any_vlan(vf)) {
+               qlcnic_nic_add_mac(adapter, mac, 0);
+       } else {
+               spin_lock(&vf->vlan_list_lock);
+               for (i = 0; i < sriov->num_allowed_vlans; i++) {
+                       vlan_id = vf->sriov_vlans[i];
+                       if (vlan_id)
+                               qlcnic_nic_add_mac(adapter, mac, vlan_id);
                }
-               list_del(&cur->list);
-               kfree(cur);
+               spin_unlock(&vf->vlan_list_lock);
+               if (qlcnic_84xx_check(adapter))
+                       qlcnic_nic_add_mac(adapter, mac, 0);
        }
 }
 
        struct list_head *head = &bc->async_list;
        struct qlcnic_async_work_list *entry;
 
+       flush_workqueue(bc->bc_async_wq);
        while (!list_empty(head)) {
                entry = list_entry(head->next, struct qlcnic_async_work_list,
                                   list);
        }
 }
 
-static void qlcnic_sriov_vf_set_multi(struct net_device *netdev)
+void qlcnic_sriov_vf_set_multi(struct net_device *netdev)
 {
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
        struct qlcnic_hardware_context *ahw = adapter->ahw;
+       static const u8 bcast_addr[ETH_ALEN] = {
+               0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+       };
+       struct netdev_hw_addr *ha;
        u32 mode = VPORT_MISS_MODE_DROP;
 
        if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state))
        } else if ((netdev->flags & IFF_ALLMULTI) ||
                   (netdev_mc_count(netdev) > ahw->max_mc_count)) {
                mode = VPORT_MISS_MODE_ACCEPT_MULTI;
+       } else {
+               qlcnic_vf_add_mc_list(netdev, bcast_addr);
+               if (!netdev_mc_empty(netdev)) {
+                       netdev_for_each_mc_addr(ha, netdev)
+                               qlcnic_vf_add_mc_list(netdev, ha->addr);
+               }
        }
 
-       if (qlcnic_sriov_vf_check(adapter))
-               qlcnic_vf_add_mc_list(netdev);
-
        qlcnic_nic_set_promisc(adapter, mode);
 }
 
-static void qlcnic_sriov_handle_async_multi(struct work_struct *work)
+static void qlcnic_sriov_handle_async_issue_cmd(struct work_struct *work)
 {
        struct qlcnic_async_work_list *entry;
-       struct net_device *netdev;
+       struct qlcnic_adapter *adapter;
+       struct qlcnic_cmd_args *cmd;
 
        entry = container_of(work, struct qlcnic_async_work_list, work);
-       netdev = (struct net_device *)entry->ptr;
-
-       qlcnic_sriov_vf_set_multi(netdev);
+       adapter = entry->ptr;
+       cmd = entry->cmd;
+       __qlcnic_sriov_issue_cmd(adapter, cmd);
        return;
 }
 
        return entry;
 }
 
-static void qlcnic_sriov_schedule_bc_async_work(struct qlcnic_back_channel *bc,
-                                               work_func_t func, void *data)
+static void qlcnic_sriov_schedule_async_cmd(struct qlcnic_back_channel *bc,
+                                           work_func_t func, void *data,
+                                           struct qlcnic_cmd_args *cmd)
 {
        struct qlcnic_async_work_list *entry = NULL;
 
                return;
 
        entry->ptr = data;
+       entry->cmd = cmd;
        INIT_WORK(&entry->work, func);
        queue_work(bc->bc_async_wq, &entry->work);
 }
 
-void qlcnic_sriov_vf_schedule_multi(struct net_device *netdev)
+static int qlcnic_sriov_async_issue_cmd(struct qlcnic_adapter *adapter,
+                                       struct qlcnic_cmd_args *cmd)
 {
 
-       struct qlcnic_adapter *adapter = netdev_priv(netdev);
        struct qlcnic_back_channel *bc = &adapter->ahw->sriov->bc;
 
        if (adapter->need_fw_reset)
-               return;
+               return -EIO;
 
-       qlcnic_sriov_schedule_bc_async_work(bc, qlcnic_sriov_handle_async_multi,
-                                           netdev);
+       qlcnic_sriov_schedule_async_cmd(bc, qlcnic_sriov_handle_async_issue_cmd,
+                                       adapter, cmd);
+       return 0;
 }
 
 static int qlcnic_sriov_vf_reinit_driver(struct qlcnic_adapter *adapter)
        if (!vf->sriov_vlans)
                return err;
 
-       mutex_lock(&vf->vlan_list_lock);
+       spin_lock_bh(&vf->vlan_list_lock);
 
        for (i = 0; i < sriov->num_allowed_vlans; i++) {
                if (vf->sriov_vlans[i] == vlan_id) {
                }
        }
 
-       mutex_unlock(&vf->vlan_list_lock);
+       spin_unlock_bh(&vf->vlan_list_lock);
        return err;
 }
 
 {
        int err = 0;
 
-       mutex_lock(&vf->vlan_list_lock);
+       spin_lock_bh(&vf->vlan_list_lock);
 
        if (vf->num_vlan >= sriov->num_allowed_vlans)
                err = -EINVAL;
 
-       mutex_unlock(&vf->vlan_list_lock);
+       spin_unlock_bh(&vf->vlan_list_lock);
        return err;
 }
 
        if (!vf->sriov_vlans)
                return;
 
-       mutex_lock(&vf->vlan_list_lock);
+       spin_lock_bh(&vf->vlan_list_lock);
 
        switch (opcode) {
        case QLC_VLAN_ADD:
                netdev_err(adapter->netdev, "Invalid VLAN operation\n");
        }
 
-       mutex_unlock(&vf->vlan_list_lock);
+       spin_unlock_bh(&vf->vlan_list_lock);
        return;
 }
 
                                   u16 vid, u8 enable)
 {
        struct qlcnic_sriov *sriov = adapter->ahw->sriov;
+       struct net_device *netdev = adapter->netdev;
        struct qlcnic_vf_info *vf;
        struct qlcnic_cmd_args cmd;
        int ret;
                dev_err(&adapter->pdev->dev,
                        "Failed to configure guest VLAN, err=%d\n", ret);
        } else {
+               netif_addr_lock_bh(netdev);
                qlcnic_free_mac_list(adapter);
+               netif_addr_unlock_bh(netdev);
 
                if (enable)
                        qlcnic_sriov_vlan_operation(vf, vid, QLC_VLAN_ADD);
                else
                        qlcnic_sriov_vlan_operation(vf, vid, QLC_VLAN_DELETE);
 
-               qlcnic_set_multi(adapter->netdev);
+               netif_addr_lock_bh(netdev);
+               qlcnic_set_multi(netdev);
+               netif_addr_unlock_bh(netdev);
        }
 
        qlcnic_free_mbx_args(&cmd);
 {
        bool err = false;
 
-       mutex_lock(&vf->vlan_list_lock);
+       spin_lock_bh(&vf->vlan_list_lock);
 
        if (vf->num_vlan)
                err = true;
 
-       mutex_unlock(&vf->vlan_list_lock);
+       spin_unlock_bh(&vf->vlan_list_lock);
        return err;
 }
 
                                       struct qlcnic_vf_info *vf,
                                       u16 vlan, u8 op)
 {
-       struct qlcnic_cmd_args cmd;
+       struct qlcnic_cmd_args *cmd;
        struct qlcnic_macvlan_mbx mv;
        struct qlcnic_vport *vp;
        u8 *addr;
 
        vp = vf->vp;
 
-       if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_MAC_VLAN))
+       cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
+       if (!cmd)
                return -ENOMEM;
 
+       err = qlcnic_alloc_mbx_args(cmd, adapter, QLCNIC_CMD_CONFIG_MAC_VLAN);
+       if (err)
+               goto free_cmd;
+
+       cmd->type = QLC_83XX_MBX_CMD_NO_WAIT;
        vpid = qlcnic_sriov_pf_get_vport_handle(adapter, vf->pci_func);
        if (vpid < 0) {
                err = -EINVAL;
-               goto out;
+               goto free_args;
        }
 
        if (vlan)
                op = ((op == QLCNIC_MAC_ADD || op == QLCNIC_MAC_VLAN_ADD) ?
                      QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_VLAN_DEL);
 
-       cmd.req.arg[1] = op | (1 << 8) | (3 << 6);
-       cmd.req.arg[1] |= ((vpid & 0xffff) << 16) | BIT_31;
+       cmd->req.arg[1] = op | (1 << 8) | (3 << 6);
+       cmd->req.arg[1] |= ((vpid & 0xffff) << 16) | BIT_31;
 
        addr = vp->mac;
        mv.vlan = vlan;
        mv.mac_addr3 = addr[3];
        mv.mac_addr4 = addr[4];
        mv.mac_addr5 = addr[5];
-       buf = &cmd.req.arg[2];
+       buf = &cmd->req.arg[2];
        memcpy(buf, &mv, sizeof(struct qlcnic_macvlan_mbx));
 
-       err = qlcnic_issue_cmd(adapter, &cmd);
+       err = qlcnic_issue_cmd(adapter, cmd);
 
-       if (err)
-               dev_err(&adapter->pdev->dev,
-                       "MAC-VLAN %s to CAM failed, err=%d.\n",
-                       ((op == 1) ? "add " : "delete "), err);
+       if (!err)
+               return err;
 
-out:
-       qlcnic_free_mbx_args(&cmd);
+free_args:
+       qlcnic_free_mbx_args(cmd);
+free_cmd:
+       kfree(cmd);
        return err;
 }
 
 
        sriov = adapter->ahw->sriov;
 
-       mutex_lock(&vf->vlan_list_lock);
+       spin_lock_bh(&vf->vlan_list_lock);
        if (vf->num_vlan) {
                for (i = 0; i < sriov->num_allowed_vlans; i++) {
                        vlan = vf->sriov_vlans[i];
                                                            opcode);
                }
        }
-       mutex_unlock(&vf->vlan_list_lock);
+       spin_unlock_bh(&vf->vlan_list_lock);
 
        if (vf->vp->vlan_mode != QLC_PVID_MODE) {
                if (qlcnic_83xx_pf_check(adapter) &&