static union sub_crq *ibmvnic_next_scrq(struct ibmvnic_adapter *,
                                        struct ibmvnic_sub_crq_queue *);
 static int ibmvnic_poll(struct napi_struct *napi, int data);
+static int reset_sub_crq_queues(struct ibmvnic_adapter *adapter);
+static inline void reinit_init_done(struct ibmvnic_adapter *adapter);
 static void send_query_map(struct ibmvnic_adapter *adapter);
 static int send_request_map(struct ibmvnic_adapter *, dma_addr_t, u32, u8);
 static int send_request_unmap(struct ibmvnic_adapter *, u8);
 
                if (!wait_for_completion_timeout(&adapter->init_done,
                                                 timeout)) {
-                       netdev_warn(netdev, "Login timed out, retrying...\n");
-                       retry = true;
-                       adapter->init_done_rc = 0;
-                       retry_count++;
-                       continue;
+                       netdev_warn(netdev, "Login timed out\n");
+                       adapter->login_pending = false;
+                       goto partial_reset;
                }
 
                if (adapter->init_done_rc == ABORTED) {
                } else if (adapter->init_done_rc) {
                        netdev_warn(netdev, "Adapter login failed, init_done_rc = %d\n",
                                    adapter->init_done_rc);
-                       return -EIO;
+
+partial_reset:
+                       /* adapter login failed, so free any CRQs or sub-CRQs
+                        * and register again before attempting to login again.
+                        * If we don't do this then the VIOS may think that
+                        * we are already logged in and reject any subsequent
+                        * attempts
+                        */
+                       netdev_warn(netdev,
+                                   "Freeing and re-registering CRQs before attempting to login again\n");
+                       retry = true;
+                       adapter->init_done_rc = 0;
+                       retry_count++;
+                       release_sub_crqs(adapter, true);
+                       reinit_init_done(adapter);
+                       release_crq_queue(adapter);
+                       /* If we don't sleep here then we risk an unnecessary
+                        * failover event from the VIOS. This is a known VIOS
+                        * issue caused by a vnic device freeing and registering
+                        * a CRQ too quickly.
+                        */
+                       msleep(1500);
+                       rc = init_crq_queue(adapter);
+                       if (rc) {
+                               netdev_err(netdev, "login recovery: init CRQ failed %d\n",
+                                          rc);
+                               return -EIO;
+                       }
+
+                       rc = ibmvnic_reset_init(adapter, false);
+                       if (rc) {
+                               netdev_err(netdev, "login recovery: Reset init failed %d\n",
+                                          rc);
+                               return -EIO;
+                       }
                }
        } while (retry);