int wait)
 {
        struct devcmd2_controller *dc2c = vdev->devcmd2;
-       struct devcmd2_result *result = dc2c->result + dc2c->next_result;
+       struct devcmd2_result *result = NULL;
        unsigned int i;
        int delay;
        int err;
        u32 posted;
+       u32 fetch_idx;
        u32 new_posted;
+       u8 color;
+
+       fetch_idx = ioread32(&dc2c->wq_ctrl->fetch_index);
+       if (fetch_idx == 0xFFFFFFFF) { /* check for hardware gone  */
+               /* Hardware surprise removal: return error */
+               return -ENODEV;
+       }
 
        posted = ioread32(&dc2c->wq_ctrl->posted_index);
 
        }
 
        new_posted = (posted + 1) % DEVCMD2_RING_SIZE;
+       if (new_posted == fetch_idx) {
+               pr_err("%s: wq is full while issuing devcmd2 command %d, fetch index: %u, posted index: %u\n",
+                       pci_name(vdev->pdev), _CMD_N(cmd), fetch_idx, posted);
+
+               return -EBUSY;
+       }
+
        dc2c->cmd_ring[posted].cmd = cmd;
        dc2c->cmd_ring[posted].flags = 0;
 
        if (dc2c->cmd_ring[posted].flags & DEVCMD2_FNORESULT)
                return 0;
 
+       result = dc2c->result + dc2c->next_result;
+       color = dc2c->color;
+
+       /*
+        * Increment next_result, after posting the devcmd, irrespective of
+        * devcmd result, and it should be done only once.
+        */
+       dc2c->next_result++;
+       if (dc2c->next_result == dc2c->result_size) {
+               dc2c->next_result = 0;
+               dc2c->color = dc2c->color ? 0 : 1;
+       }
+
        for (delay = 0; delay < wait; delay++) {
                udelay(100);
-               if (result->color == dc2c->color) {
-                       dc2c->next_result++;
-                       if (dc2c->next_result == dc2c->result_size) {
-                               dc2c->next_result = 0;
-                               dc2c->color = dc2c->color ? 0 : 1;
-                       }
+               if (result->color == color) {
                        if (result->error) {
                                err = (int) result->error;
                                if (err != ERR_ECMDUNKNOWN ||
                                return err;
                        }
                        if (_CMD_DIR(cmd) & _CMD_DIR_READ) {
-                               /*
-                                * Adding the rmb() prevents the compiler
-                                * and/or CPU from reordering the reads which
-                                * would potentially result in reading stale
-                                * values.
-                                */
-                               rmb();
                                for (i = 0; i < VNIC_DEVCMD_NARGS; i++)
                                        vdev->args[i] = result->results[i];
                        }