struct octeon_device *oct = lio->oct_dev;
        u8 *mac;
 
+       if (nctrl->completion && nctrl->response_code) {
+               /* Signal whoever is interested that the response code from the
+                * firmware has arrived.
+                */
+               WRITE_ONCE(*nctrl->response_code, nctrl->status);
+               complete(nctrl->completion);
+       }
+
+       if (nctrl->status)
+               return;
+
        switch (nctrl->ncmd.s.cmd) {
        case OCTNET_CMD_CHANGE_DEVFLAGS:
        case OCTNET_CMD_SET_MULTI_LIST:
 
        struct octnic_ctrl_pkt nctrl;
        int ret = 0;
 
+       memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
+
        nctrl.ncmd.u64 = 0;
        nctrl.ncmd.s.cmd = command;
        nctrl.ncmd.s.param1 = rx_cmd;
        struct octnic_ctrl_pkt nctrl;
        int ret = 0;
 
+       memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
+
        nctrl.ncmd.u64 = 0;
        nctrl.ncmd.s.cmd = command;
        nctrl.ncmd.s.more = vxlan_cmd_bit;
 
        struct lio *lio = GET_LIO(netdev);
        struct octeon_device *oct = lio->oct_dev;
        struct octnic_ctrl_pkt nctrl;
+       struct completion compl;
+       u16 response_code;
        int ret = 0;
 
        memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
        nctrl.wait_time = 100;
        nctrl.netpndev = (u64)netdev;
        nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
+       init_completion(&compl);
+       nctrl.completion = &compl;
+       nctrl.response_code = &response_code;
 
        ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
        if (ret < 0) {
                dev_err(&oct->pci_dev->dev, "Add VLAN filter failed in core (ret: 0x%x)\n",
                        ret);
+               return -EIO;
        }
 
-       return ret;
+       if (!wait_for_completion_timeout(&compl,
+                                        msecs_to_jiffies(nctrl.wait_time)))
+               return -EPERM;
+
+       if (READ_ONCE(response_code))
+               return -EPERM;
+
+       return 0;
 }
 
 static int
        struct octnic_ctrl_pkt nctrl;
        int ret = 0;
 
+       memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
+
        nctrl.ncmd.u64 = 0;
        nctrl.ncmd.s.cmd = command;
        nctrl.ncmd.s.param1 = rx_cmd;
        struct octnic_ctrl_pkt nctrl;
        int ret = 0;
 
+       memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
+
        nctrl.ncmd.u64 = 0;
        nctrl.ncmd.s.cmd = command;
        nctrl.ncmd.s.more = vxlan_cmd_bit;
 
 
        nctrl = (struct octnic_ctrl_pkt *)sc->ctxptr;
 
-       /* Call the callback function if status is OK.
-        * Status is OK only if a response was expected and core returned
-        * success.
+       /* Call the callback function if status is zero (meaning OK) or status
+        * contains a firmware status code bigger than zero (meaning the
+        * firmware is reporting an error).
         * If no response was expected, status is OK if the command was posted
         * successfully.
         */
-       if (!status && nctrl->cb_fn)
+       if ((!status || status > FIRMWARE_STATUS_CODE(0)) && nctrl->cb_fn) {
+               nctrl->status = status;
                nctrl->cb_fn(nctrl);
+       }
 
        octeon_free_soft_command(oct, sc);
 }
 
 
        /** Callback function called when the command has been fetched */
        octnic_ctrl_pkt_cb_fn_t cb_fn;
+
+       u32 status;
+       u16 *response_code;
+       struct completion *completion;
 };
 
 #define MAX_UDD_SIZE(nctrl) (sizeof((nctrl)->udd))