]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - drivers/scsi/lpfc/lpfc_sli.c
[SCSI] lpfc 8.3.16: FCoE Discovery and Failover Fixes
[mirror_ubuntu-bionic-kernel.git] / drivers / scsi / lpfc / lpfc_sli.c
index 7a61455140b626820e186467bde9306162b11d56..fb8905f893f53ffcdd2cf71c79a5d04b87d9cd9c 100644 (file)
@@ -455,6 +455,11 @@ __lpfc_sli_get_iocbq(struct lpfc_hba *phba)
        struct lpfc_iocbq * iocbq = NULL;
 
        list_remove_head(lpfc_iocb_list, iocbq, struct lpfc_iocbq, list);
+
+       if (iocbq)
+               phba->iocb_cnt++;
+       if (phba->iocb_cnt > phba->iocb_max)
+               phba->iocb_max = phba->iocb_cnt;
        return iocbq;
 }
 
@@ -575,7 +580,8 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
 {
        struct lpfc_sglq *sglq;
        size_t start_clean = offsetof(struct lpfc_iocbq, iocb);
-       unsigned long iflag;
+       unsigned long iflag = 0;
+       struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
 
        if (iocbq->sli4_xritag == NO_XRI)
                sglq = NULL;
@@ -593,6 +599,10 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
                } else {
                        sglq->state = SGL_FREED;
                        list_add(&sglq->list, &phba->sli4_hba.lpfc_sgl_list);
+
+                       /* Check if TXQ queue needs to be serviced */
+                       if (pring->txq_cnt)
+                               lpfc_worker_wake_up(phba);
                }
        }
 
@@ -605,6 +615,7 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
        list_add_tail(&iocbq->list, &phba->lpfc_iocb_list);
 }
 
+
 /**
  * __lpfc_sli_release_iocbq_s3 - Release iocb to the iocb pool
  * @phba: Pointer to HBA context object.
@@ -642,6 +653,7 @@ static void
 __lpfc_sli_release_iocbq(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
 {
        phba->__lpfc_sli_release_iocbq(phba, iocbq);
+       phba->iocb_cnt--;
 }
 
 /**
@@ -872,7 +884,11 @@ lpfc_sli_ringtxcmpl_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                        struct lpfc_iocbq *piocb)
 {
        list_add_tail(&piocb->list, &pring->txcmplq);
+       piocb->iocb_flag |= LPFC_IO_ON_Q;
        pring->txcmplq_cnt++;
+       if (pring->txcmplq_cnt > pring->txcmplq_max)
+               pring->txcmplq_max = pring->txcmplq_cnt;
+
        if ((unlikely(pring->ringno == LPFC_ELS_RING)) &&
           (piocb->iocb.ulpCommand != CMD_ABORT_XRI_CN) &&
           (piocb->iocb.ulpCommand != CMD_CLOSE_XRI_CN)) {
@@ -897,7 +913,7 @@ lpfc_sli_ringtxcmpl_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
  * the txq, the function returns first iocb in the list after
  * removing the iocb from the list, else it returns NULL.
  **/
-static struct lpfc_iocbq *
+struct lpfc_iocbq *
 lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
 {
        struct lpfc_iocbq *cmd_iocb;
@@ -1030,7 +1046,7 @@ lpfc_sli_next_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
        } else
                spin_unlock_irq(&phba->hbalock);
 
-       lpfc_printf_log(phba, KERN_ERR,LOG_SLI,
+       lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
                        "0318 Failed to allocate IOTAG.last IOTAG is %d\n",
                        psli->last_iotag);
 
@@ -2150,7 +2166,10 @@ lpfc_sli_iocbq_lookup(struct lpfc_hba *phba,
        if (iotag != 0 && iotag <= phba->sli.last_iotag) {
                cmd_iocb = phba->sli.iocbq_lookup[iotag];
                list_del_init(&cmd_iocb->list);
-               pring->txcmplq_cnt--;
+               if (cmd_iocb->iocb_flag & LPFC_IO_ON_Q) {
+                       pring->txcmplq_cnt--;
+                       cmd_iocb->iocb_flag &= ~LPFC_IO_ON_Q;
+               }
                return cmd_iocb;
        }
 
@@ -2183,7 +2202,10 @@ lpfc_sli_iocbq_lookup_by_tag(struct lpfc_hba *phba,
        if (iotag != 0 && iotag <= phba->sli.last_iotag) {
                cmd_iocb = phba->sli.iocbq_lookup[iotag];
                list_del_init(&cmd_iocb->list);
-               pring->txcmplq_cnt--;
+               if (cmd_iocb->iocb_flag & LPFC_IO_ON_Q) {
+                       cmd_iocb->iocb_flag &= ~LPFC_IO_ON_Q;
+                       pring->txcmplq_cnt--;
+               }
                return cmd_iocb;
        }
 
@@ -3564,13 +3586,16 @@ static int
 lpfc_sli_brdrestart_s4(struct lpfc_hba *phba)
 {
        struct lpfc_sli *psli = &phba->sli;
-
+       uint32_t hba_aer_enabled;
 
        /* Restart HBA */
        lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
                        "0296 Restart HBA Data: x%x x%x\n",
                        phba->pport->port_state, psli->sli_flag);
 
+       /* Take PCIe device Advanced Error Reporting (AER) state */
+       hba_aer_enabled = phba->hba_flag & HBA_AER_ENABLED;
+
        lpfc_sli4_brdreset(phba);
 
        spin_lock_irq(&phba->hbalock);
@@ -3582,6 +3607,10 @@ lpfc_sli_brdrestart_s4(struct lpfc_hba *phba)
        memset(&psli->lnk_stat_offsets, 0, sizeof(psli->lnk_stat_offsets));
        psli->stats_start = get_seconds();
 
+       /* Reset HBA AER if it was enabled, note hba_flag was reset above */
+       if (hba_aer_enabled)
+               pci_disable_pcie_error_reporting(phba->pcidev);
+
        lpfc_hba_down_post(phba);
 
        return 0;
@@ -3794,7 +3823,7 @@ lpfc_sli_hbq_setup(struct lpfc_hba *phba)
 
                        phba->link_state = LPFC_HBA_ERROR;
                        mempool_free(pmb, phba->mbox_mem_pool);
-                       return ENXIO;
+                       return -ENXIO;
                }
        }
        phba->hbq_count = hbq_count;
@@ -3885,8 +3914,8 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode)
                phba->sli3_options &= ~(LPFC_SLI3_NPIV_ENABLED |
                                        LPFC_SLI3_HBQ_ENABLED |
                                        LPFC_SLI3_CRP_ENABLED |
-                                       LPFC_SLI3_INB_ENABLED |
-                                       LPFC_SLI3_BG_ENABLED);
+                                       LPFC_SLI3_BG_ENABLED |
+                                       LPFC_SLI3_DSS_ENABLED);
                if (rc != MBX_SUCCESS) {
                        lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                "0442 Adapter failed to init, mbxCmd x%x "
@@ -3921,26 +3950,30 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode)
 
                } else
                        phba->max_vpi = 0;
-               if (pmb->u.mb.un.varCfgPort.gdss)
+               phba->fips_level = 0;
+               phba->fips_spec_rev = 0;
+               if (pmb->u.mb.un.varCfgPort.gdss) {
                        phba->sli3_options |= LPFC_SLI3_DSS_ENABLED;
+                       phba->fips_level = pmb->u.mb.un.varCfgPort.fips_level;
+                       phba->fips_spec_rev = pmb->u.mb.un.varCfgPort.fips_rev;
+                       lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+                                       "2850 Security Crypto Active. FIPS x%d "
+                                       "(Spec Rev: x%d)",
+                                       phba->fips_level, phba->fips_spec_rev);
+               }
+               if (pmb->u.mb.un.varCfgPort.sec_err) {
+                       lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                                       "2856 Config Port Security Crypto "
+                                       "Error: x%x ",
+                                       pmb->u.mb.un.varCfgPort.sec_err);
+               }
                if (pmb->u.mb.un.varCfgPort.gerbm)
                        phba->sli3_options |= LPFC_SLI3_HBQ_ENABLED;
                if (pmb->u.mb.un.varCfgPort.gcrp)
                        phba->sli3_options |= LPFC_SLI3_CRP_ENABLED;
-               if (pmb->u.mb.un.varCfgPort.ginb) {
-                       phba->sli3_options |= LPFC_SLI3_INB_ENABLED;
-                       phba->hbq_get = phba->mbox->us.s3_inb_pgp.hbq_get;
-                       phba->port_gp = phba->mbox->us.s3_inb_pgp.port;
-                       phba->inb_ha_copy = &phba->mbox->us.s3_inb_pgp.ha_copy;
-                       phba->inb_counter = &phba->mbox->us.s3_inb_pgp.counter;
-                       phba->inb_last_counter =
-                                       phba->mbox->us.s3_inb_pgp.counter;
-               } else {
-                       phba->hbq_get = phba->mbox->us.s3_pgp.hbq_get;
-                       phba->port_gp = phba->mbox->us.s3_pgp.port;
-                       phba->inb_ha_copy = NULL;
-                       phba->inb_counter = NULL;
-               }
+
+               phba->hbq_get = phba->mbox->us.s3_pgp.hbq_get;
+               phba->port_gp = phba->mbox->us.s3_pgp.port;
 
                if (phba->cfg_enable_bg) {
                        if (pmb->u.mb.un.varCfgPort.gbg)
@@ -3953,8 +3986,6 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode)
        } else {
                phba->hbq_get = NULL;
                phba->port_gp = phba->mbox->us.s2.port;
-               phba->inb_ha_copy = NULL;
-               phba->inb_counter = NULL;
                phba->max_vpi = 0;
        }
 do_prep_failed:
@@ -4214,7 +4245,8 @@ lpfc_sli4_read_rev(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
        if (mqe->un.read_rev.avail_vpd_len < *vpd_size)
                *vpd_size = mqe->un.read_rev.avail_vpd_len;
 
-       lpfc_sli_pcimem_bcopy(dmabuf->virt, vpd, *vpd_size);
+       memcpy(vpd, dmabuf->virt, *vpd_size);
+
        dma_free_coherent(&phba->pcidev->dev, dma_size,
                          dmabuf->virt, dmabuf->phys);
        kfree(dmabuf);
@@ -4539,6 +4571,24 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
        /* Start error attention (ERATT) polling timer */
        mod_timer(&phba->eratt_poll, jiffies + HZ * LPFC_ERATT_POLL_INTERVAL);
 
+       /* Enable PCIe device Advanced Error Reporting (AER) if configured */
+       if (phba->cfg_aer_support == 1 && !(phba->hba_flag & HBA_AER_ENABLED)) {
+               rc = pci_enable_pcie_error_reporting(phba->pcidev);
+               if (!rc) {
+                       lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+                                       "2829 This device supports "
+                                       "Advanced Error Reporting (AER)\n");
+                       spin_lock_irq(&phba->hbalock);
+                       phba->hba_flag |= HBA_AER_ENABLED;
+                       spin_unlock_irq(&phba->hbalock);
+               } else {
+                       lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+                                       "2830 This device does not support "
+                                       "Advanced Error Reporting (AER)\n");
+                       phba->cfg_aer_support = 0;
+               }
+       }
+
        /*
         * The port is ready, set the host's link state to LINK_DOWN
         * in preparation for link interrupts.
@@ -5265,7 +5315,8 @@ lpfc_sli4_post_sync_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
        if (mcqe_status != MB_CQE_STATUS_SUCCESS) {
                bf_set(lpfc_mqe_status, mb, LPFC_MBX_ERROR_RANGE | mcqe_status);
                rc = MBXERR_ERROR;
-       }
+       } else
+               lpfc_sli4_swap_str(phba, mboxq);
 
        lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
                        "(%d):0356 Mailbox cmd x%x (x%x) Status x%x "
@@ -5592,7 +5643,7 @@ lpfc_mbox_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp)
  * iocb to the txq when SLI layer cannot submit the command iocb
  * to the ring.
  **/
-static void
+void
 __lpfc_sli_ringtx_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                    struct lpfc_iocbq *piocb)
 {
@@ -6209,7 +6260,6 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number,
                         struct lpfc_iocbq *piocb, uint32_t flag)
 {
        struct lpfc_sglq *sglq;
-       uint16_t xritag;
        union lpfc_wqe wqe;
        struct lpfc_sli_ring *pring = &phba->sli.ring[ring_number];
 
@@ -6218,10 +6268,26 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number,
                    piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN)
                        sglq = NULL;
                else {
+                       if (pring->txq_cnt) {
+                               if (!(flag & SLI_IOCB_RET_IOCB)) {
+                                       __lpfc_sli_ringtx_put(phba,
+                                               pring, piocb);
+                                       return IOCB_SUCCESS;
+                               } else {
+                                       return IOCB_BUSY;
+                               }
+                       } else {
                        sglq = __lpfc_sli_get_sglq(phba);
-                       if (!sglq)
-                               return IOCB_ERROR;
-                       piocb->sli4_xritag = sglq->sli4_xritag;
+                               if (!sglq) {
+                                       if (!(flag & SLI_IOCB_RET_IOCB)) {
+                                               __lpfc_sli_ringtx_put(phba,
+                                                               pring,
+                                                               piocb);
+                                               return IOCB_SUCCESS;
+                                       } else
+                                               return IOCB_BUSY;
+                               }
+                       }
                }
        } else if (piocb->iocb_flag &  LPFC_IO_FCP) {
                sglq = NULL; /* These IO's already have an XRI and
@@ -6237,8 +6303,9 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number,
        }
 
        if (sglq) {
-               xritag = lpfc_sli4_bpl2sgl(phba, piocb, sglq);
-               if (xritag != sglq->sli4_xritag)
+               piocb->sli4_xritag = sglq->sli4_xritag;
+
+               if (NO_XRI == lpfc_sli4_bpl2sgl(phba, piocb, sglq))
                        return IOCB_ERROR;
        }
 
@@ -6278,7 +6345,7 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number,
  *     IOCB_SUCCESS - Success
  *     IOCB_BUSY - Busy
  **/
-static inline int
+int
 __lpfc_sli_issue_iocb(struct lpfc_hba *phba, uint32_t ring_number,
                struct lpfc_iocbq *piocb, uint32_t flag)
 {
@@ -7095,13 +7162,6 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                         */
                        abort_iocb = phba->sli.iocbq_lookup[abort_context];
 
-               lpfc_printf_log(phba, KERN_INFO, LOG_ELS | LOG_SLI,
-                               "0327 Cannot abort els iocb %p "
-                               "with tag %x context %x, abort status %x, "
-                               "abort code %x\n",
-                               abort_iocb, abort_iotag, abort_context,
-                               irsp->ulpStatus, irsp->un.ulpWord[4]);
-
                /*
                 *  If the iocb is not found in Firmware queue the iocb
                 *  might have completed already. Do not free it again.
@@ -7120,6 +7180,13 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                        if (abort_iocb && phba->sli_rev == LPFC_SLI_REV4)
                                abort_context = abort_iocb->iocb.ulpContext;
                }
+
+               lpfc_printf_log(phba, KERN_WARNING, LOG_ELS | LOG_SLI,
+                               "0327 Cannot abort els iocb %p "
+                               "with tag %x context %x, abort status %x, "
+                               "abort code %x\n",
+                               abort_iocb, abort_iotag, abort_context,
+                               irsp->ulpStatus, irsp->un.ulpWord[4]);
                /*
                 * make sure we have the right iocbq before taking it
                 * off the txcmplq and try to call completion routine.
@@ -7137,7 +7204,10 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                         * following abort XRI from the HBA.
                         */
                        list_del_init(&abort_iocb->list);
-                       pring->txcmplq_cnt--;
+                       if (abort_iocb->iocb_flag & LPFC_IO_ON_Q) {
+                               abort_iocb->iocb_flag &= ~LPFC_IO_ON_Q;
+                               pring->txcmplq_cnt--;
+                       }
 
                        /* Firmware could still be in progress of DMAing
                         * payload, so don't free data buffer till after
@@ -7269,8 +7339,9 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
        lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI,
                         "0339 Abort xri x%x, original iotag x%x, "
                         "abort cmd iotag x%x\n",
+                        iabt->un.acxri.abortIoTag,
                         iabt->un.acxri.abortContextTag,
-                        iabt->un.acxri.abortIoTag, abtsiocbp->iotag);
+                        abtsiocbp->iotag);
        retval = __lpfc_sli_issue_iocb(phba, pring->ringno, abtsiocbp, 0);
 
        if (retval)
@@ -7600,7 +7671,7 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba,
        long timeleft, timeout_req = 0;
        int retval = IOCB_SUCCESS;
        uint32_t creg_val;
-
+       struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
        /*
         * If the caller has provided a response iocbq buffer, then context2
         * is NULL or its an error.
@@ -7622,7 +7693,8 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba,
                readl(phba->HCregaddr); /* flush */
        }
 
-       retval = lpfc_sli_issue_iocb(phba, ring_number, piocb, 0);
+       retval = lpfc_sli_issue_iocb(phba, ring_number, piocb,
+                                    SLI_IOCB_RET_IOCB);
        if (retval == IOCB_SUCCESS) {
                timeout_req = timeout * HZ;
                timeleft = wait_event_timeout(done_q,
@@ -7644,6 +7716,11 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba,
                                        timeout, (timeleft / jiffies));
                        retval = IOCB_TIMEDOUT;
                }
+       } else if (retval == IOCB_BUSY) {
+               lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+                       "2818 Max IOCBs %d txq cnt %d txcmplq cnt %d\n",
+                       phba->iocb_cnt, pring->txq_cnt, pring->txcmplq_cnt);
+               return retval;
        } else {
                lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
                                "0332 IOCB wait issue failed, Data x%x\n",
@@ -7724,9 +7801,10 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq,
                 * if LPFC_MBX_WAKE flag is set the mailbox is completed
                 * else do not free the resources.
                 */
-               if (pmboxq->mbox_flag & LPFC_MBX_WAKE)
+               if (pmboxq->mbox_flag & LPFC_MBX_WAKE) {
                        retval = MBX_SUCCESS;
-               else {
+                       lpfc_sli4_swap_str(phba, pmboxq);
+               } else {
                        retval = MBX_TIMEOUT;
                        pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
                }
@@ -8789,12 +8867,17 @@ lpfc_sli4_sp_handle_els_wcqe(struct lpfc_hba *phba,
 {
        struct lpfc_iocbq *irspiocbq;
        unsigned long iflags;
+       struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_FCP_RING];
 
        /* Get an irspiocbq for later ELS response processing use */
        irspiocbq = lpfc_sli_get_iocbq(phba);
        if (!irspiocbq) {
                lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-                               "0387 Failed to allocate an iocbq\n");
+                       "0387 NO IOCBQ data: txq_cnt=%d iocb_cnt=%d "
+                       "fcp_txcmplq_cnt=%d, els_txcmplq_cnt=%d\n",
+                       pring->txq_cnt, phba->iocb_cnt,
+                       phba->sli.ring[LPFC_FCP_RING].txcmplq_cnt,
+                       phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt);
                return false;
        }
 
@@ -8973,6 +9056,7 @@ lpfc_sli4_sp_handle_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
        switch (bf_get(lpfc_cqe_code, &cqevt)) {
        case CQE_CODE_COMPL_WQE:
                /* Process the WQ/RQ complete event */
+               phba->last_completion_time = jiffies;
                workposted = lpfc_sli4_sp_handle_els_wcqe(phba,
                                (struct lpfc_wcqe_complete *)&cqevt);
                break;
@@ -8983,11 +9067,13 @@ lpfc_sli4_sp_handle_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
                break;
        case CQE_CODE_XRI_ABORTED:
                /* Process the WQ XRI abort event */
+               phba->last_completion_time = jiffies;
                workposted = lpfc_sli4_sp_handle_abort_xri_wcqe(phba, cq,
                                (struct sli4_wcqe_xri_aborted *)&cqevt);
                break;
        case CQE_CODE_RECEIVE:
                /* Process the RQ event */
+               phba->last_completion_time = jiffies;
                workposted = lpfc_sli4_sp_handle_rcqe(phba,
                                (struct lpfc_rcqe *)&cqevt);
                break;
@@ -9043,9 +9129,10 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe)
                }
        }
        if (unlikely(!cq)) {
-               lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-                               "0365 Slow-path CQ identifier (%d) does "
-                               "not exist\n", cqid);
+               if (phba->sli.sli_flag & LPFC_SLI_ACTIVE)
+                       lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+                                       "0365 Slow-path CQ identifier "
+                                       "(%d) does not exist\n", cqid);
                return;
        }
 
@@ -9216,6 +9303,7 @@ lpfc_sli4_fp_handle_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
        switch (bf_get(lpfc_wcqe_c_code, &wcqe)) {
        case CQE_CODE_COMPL_WQE:
                /* Process the WQ complete event */
+               phba->last_completion_time = jiffies;
                lpfc_sli4_fp_handle_fcp_wcqe(phba,
                                (struct lpfc_wcqe_complete *)&wcqe);
                break;
@@ -9226,6 +9314,7 @@ lpfc_sli4_fp_handle_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
                break;
        case CQE_CODE_XRI_ABORTED:
                /* Process the WQ XRI abort event */
+               phba->last_completion_time = jiffies;
                workposted = lpfc_sli4_sp_handle_abort_xri_wcqe(phba, cq,
                                (struct sli4_wcqe_xri_aborted *)&wcqe);
                break;
@@ -9271,9 +9360,10 @@ lpfc_sli4_fp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe,
 
        cq = phba->sli4_hba.fcp_cq[fcp_cqidx];
        if (unlikely(!cq)) {
-               lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-                               "0367 Fast-path completion queue does not "
-                               "exist\n");
+               if (phba->sli.sli_flag & LPFC_SLI_ACTIVE)
+                       lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+                                       "0367 Fast-path completion queue "
+                                       "does not exist\n");
                return;
        }
 
@@ -11890,6 +11980,22 @@ lpfc_sli4_alloc_rpi(struct lpfc_hba *phba)
        return rpi;
 }
 
+/**
+ * lpfc_sli4_free_rpi - Release an rpi for reuse.
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine is invoked to release an rpi to the pool of
+ * available rpis maintained by the driver.
+ **/
+void
+__lpfc_sli4_free_rpi(struct lpfc_hba *phba, int rpi)
+{
+       if (test_and_clear_bit(rpi, phba->sli4_hba.rpi_bmask)) {
+               phba->sli4_hba.rpi_count--;
+               phba->sli4_hba.max_cfg_param.rpi_used--;
+       }
+}
+
 /**
  * lpfc_sli4_free_rpi - Release an rpi for reuse.
  * @phba: pointer to lpfc hba data structure.
@@ -11901,9 +12007,7 @@ void
 lpfc_sli4_free_rpi(struct lpfc_hba *phba, int rpi)
 {
        spin_lock_irq(&phba->hbalock);
-       clear_bit(rpi, phba->sli4_hba.rpi_bmask);
-       phba->sli4_hba.rpi_count--;
-       phba->sli4_hba.max_cfg_param.rpi_used--;
+       __lpfc_sli4_free_rpi(phba, rpi);
        spin_unlock_irq(&phba->hbalock);
 }
 
@@ -12191,12 +12295,9 @@ lpfc_sli4_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, uint16_t fcf_index)
                spin_lock_irq(&phba->hbalock);
                phba->hba_flag |= FCF_DISC_INPROGRESS;
                spin_unlock_irq(&phba->hbalock);
-               /* Reset FCF round robin index bmask for new scan */
-               if (fcf_index == LPFC_FCOE_FCF_GET_FIRST) {
-                       memset(phba->fcf.fcf_rr_bmask, 0,
-                              sizeof(*phba->fcf.fcf_rr_bmask));
+               /* Reset eligible FCF count for new scan */
+               if (fcf_index == LPFC_FCOE_FCF_GET_FIRST)
                        phba->fcf.eligible_fcf_cnt = 0;
-               }
                error = 0;
        }
 fail_fcf_scan:
@@ -12318,18 +12419,47 @@ lpfc_sli4_fcf_rr_next_index_get(struct lpfc_hba *phba)
 {
        uint16_t next_fcf_index;
 
-       /* Search from the currently registered FCF index */
+       /* Search start from next bit of currently registered FCF index */
+       next_fcf_index = (phba->fcf.current_rec.fcf_indx + 1) %
+                                       LPFC_SLI4_FCF_TBL_INDX_MAX;
        next_fcf_index = find_next_bit(phba->fcf.fcf_rr_bmask,
                                       LPFC_SLI4_FCF_TBL_INDX_MAX,
-                                      phba->fcf.current_rec.fcf_indx);
+                                      next_fcf_index);
+
        /* Wrap around condition on phba->fcf.fcf_rr_bmask */
        if (next_fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX)
                next_fcf_index = find_next_bit(phba->fcf.fcf_rr_bmask,
                                               LPFC_SLI4_FCF_TBL_INDX_MAX, 0);
-       /* Round robin failover stop condition */
-       if (next_fcf_index == phba->fcf.fcf_rr_init_indx)
+
+       /* Check roundrobin failover list empty condition */
+       if (next_fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX) {
+               lpfc_printf_log(phba, KERN_WARNING, LOG_FIP,
+                               "2844 No roundrobin failover FCF available\n");
                return LPFC_FCOE_FCF_NEXT_NONE;
+       }
 
+       /* Check roundrobin failover index bmask stop condition */
+       if (next_fcf_index == phba->fcf.fcf_rr_init_indx) {
+               if (!(phba->fcf.fcf_flag & FCF_REDISC_RRU)) {
+                       lpfc_printf_log(phba, KERN_WARNING, LOG_FIP,
+                                       "2847 Round robin failover FCF index "
+                                       "search hit stop condition:x%x\n",
+                                       next_fcf_index);
+                       return LPFC_FCOE_FCF_NEXT_NONE;
+               }
+               /* The roundrobin failover index bmask updated, start over */
+               lpfc_printf_log(phba, KERN_INFO, LOG_FIP,
+                               "2848 Round robin failover FCF index bmask "
+                               "updated, start over\n");
+               spin_lock_irq(&phba->hbalock);
+               phba->fcf.fcf_flag &= ~FCF_REDISC_RRU;
+               spin_unlock_irq(&phba->hbalock);
+               return phba->fcf.fcf_rr_init_indx;
+       }
+
+       lpfc_printf_log(phba, KERN_INFO, LOG_FIP,
+                       "2845 Get next round robin failover "
+                       "FCF index x%x\n", next_fcf_index);
        return next_fcf_index;
 }
 
@@ -12359,11 +12489,20 @@ lpfc_sli4_fcf_rr_index_set(struct lpfc_hba *phba, uint16_t fcf_index)
        /* Set the eligible FCF record index bmask */
        set_bit(fcf_index, phba->fcf.fcf_rr_bmask);
 
+       /* Set the roundrobin index bmask updated */
+       spin_lock_irq(&phba->hbalock);
+       phba->fcf.fcf_flag |= FCF_REDISC_RRU;
+       spin_unlock_irq(&phba->hbalock);
+
+       lpfc_printf_log(phba, KERN_INFO, LOG_FIP,
+                       "2790 Set FCF index x%x to round robin failover "
+                       "bmask\n", fcf_index);
+
        return 0;
 }
 
 /**
- * lpfc_sli4_fcf_rr_index_set - Clear bmask from eligible fcf record index
+ * lpfc_sli4_fcf_rr_index_clear - Clear bmask from eligible fcf record index
  * @phba: pointer to lpfc hba data structure.
  *
  * This routine clears the FCF record index from the eligible bmask for
@@ -12384,6 +12523,10 @@ lpfc_sli4_fcf_rr_index_clear(struct lpfc_hba *phba, uint16_t fcf_index)
        }
        /* Clear the eligible FCF record index bmask */
        clear_bit(fcf_index, phba->fcf.fcf_rr_bmask);
+
+       lpfc_printf_log(phba, KERN_INFO, LOG_FIP,
+                       "2791 Clear FCF index x%x from round robin failover "
+                       "bmask\n", fcf_index);
 }
 
 /**
@@ -12446,7 +12589,7 @@ lpfc_mbx_cmpl_redisc_fcf_table(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox)
 }
 
 /**
- * lpfc_sli4_redisc_all_fcf - Request to rediscover entire FCF table by port.
+ * lpfc_sli4_redisc_fcf_table - Request to rediscover entire FCF table by port.
  * @phba: pointer to lpfc hba data structure.
  *
  * This routine is invoked to request for rediscovery of the entire FCF table
@@ -12662,6 +12805,7 @@ lpfc_cleanup_pending_mbox(struct lpfc_vport *vport)
        LPFC_MBOXQ_t *mb, *nextmb;
        struct lpfc_dmabuf *mp;
        struct lpfc_nodelist *ndlp;
+       struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
 
        spin_lock_irq(&phba->hbalock);
        list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) {
@@ -12673,6 +12817,9 @@ lpfc_cleanup_pending_mbox(struct lpfc_vport *vport)
                        continue;
 
                if (mb->u.mb.mbxCommand == MBX_REG_LOGIN64) {
+                       if (phba->sli_rev == LPFC_SLI_REV4)
+                               __lpfc_sli4_free_rpi(phba,
+                                               mb->u.mb.un.varRegLogin.rpi);
                        mp = (struct lpfc_dmabuf *) (mb->context1);
                        if (mp) {
                                __lpfc_mbuf_free(phba, mp->virt, mp->phys);
@@ -12680,6 +12827,9 @@ lpfc_cleanup_pending_mbox(struct lpfc_vport *vport)
                        }
                        ndlp = (struct lpfc_nodelist *) mb->context2;
                        if (ndlp) {
+                               spin_lock_irq(shost->host_lock);
+                               ndlp->nlp_flag &= ~NLP_IGNR_REG_CMPL;
+                               spin_unlock_irq(shost->host_lock);
                                lpfc_nlp_put(ndlp);
                                mb->context2 = NULL;
                        }
@@ -12695,6 +12845,9 @@ lpfc_cleanup_pending_mbox(struct lpfc_vport *vport)
                if (mb->u.mb.mbxCommand == MBX_REG_LOGIN64) {
                        ndlp = (struct lpfc_nodelist *) mb->context2;
                        if (ndlp) {
+                               spin_lock_irq(shost->host_lock);
+                               ndlp->nlp_flag &= ~NLP_IGNR_REG_CMPL;
+                               spin_unlock_irq(shost->host_lock);
                                lpfc_nlp_put(ndlp);
                                mb->context2 = NULL;
                        }
@@ -12705,3 +12858,85 @@ lpfc_cleanup_pending_mbox(struct lpfc_vport *vport)
        spin_unlock_irq(&phba->hbalock);
 }
 
+/**
+ * lpfc_drain_txq - Drain the txq
+ * @phba: Pointer to HBA context object.
+ *
+ * This function attempt to submit IOCBs on the txq
+ * to the adapter.  For SLI4 adapters, the txq contains
+ * ELS IOCBs that have been deferred because the there
+ * are no SGLs.  This congestion can occur with large
+ * vport counts during node discovery.
+ **/
+
+uint32_t
+lpfc_drain_txq(struct lpfc_hba *phba)
+{
+       LIST_HEAD(completions);
+       struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
+       struct lpfc_iocbq *piocbq = 0;
+       unsigned long iflags = 0;
+       char *fail_msg = NULL;
+       struct lpfc_sglq *sglq;
+       union lpfc_wqe wqe;
+
+       spin_lock_irqsave(&phba->hbalock, iflags);
+       if (pring->txq_cnt > pring->txq_max)
+               pring->txq_max = pring->txq_cnt;
+
+       spin_unlock_irqrestore(&phba->hbalock, iflags);
+
+       while (pring->txq_cnt) {
+               spin_lock_irqsave(&phba->hbalock, iflags);
+
+               sglq = __lpfc_sli_get_sglq(phba);
+               if (!sglq) {
+                       spin_unlock_irqrestore(&phba->hbalock, iflags);
+                       break;
+               } else {
+                       piocbq = lpfc_sli_ringtx_get(phba, pring);
+                       if (!piocbq) {
+                               /* The txq_cnt out of sync. This should
+                                * never happen
+                                */
+                               sglq = __lpfc_clear_active_sglq(phba,
+                                                sglq->sli4_xritag);
+                               spin_unlock_irqrestore(&phba->hbalock, iflags);
+                               lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+                                       "2823 txq empty and txq_cnt is %d\n ",
+                                       pring->txq_cnt);
+                               break;
+                       }
+               }
+
+               /* The xri and iocb resources secured,
+                * attempt to issue request
+                */
+               piocbq->sli4_xritag = sglq->sli4_xritag;
+               if (NO_XRI == lpfc_sli4_bpl2sgl(phba, piocbq, sglq))
+                       fail_msg = "to convert bpl to sgl";
+               else if (lpfc_sli4_iocb2wqe(phba, piocbq, &wqe))
+                       fail_msg = "to convert iocb to wqe";
+               else if (lpfc_sli4_wq_put(phba->sli4_hba.els_wq, &wqe))
+                       fail_msg = " - Wq is full";
+               else
+                       lpfc_sli_ringtxcmpl_put(phba, pring, piocbq);
+
+               if (fail_msg) {
+                       /* Failed means we can't issue and need to cancel */
+                       lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+                                       "2822 IOCB failed %s iotag 0x%x "
+                                       "xri 0x%x\n",
+                                       fail_msg,
+                                       piocbq->iotag, piocbq->sli4_xritag);
+                       list_add_tail(&piocbq->list, &completions);
+               }
+               spin_unlock_irqrestore(&phba->hbalock, iflags);
+       }
+
+       /* Cancel all the IOCBs that cannot be issued */
+       lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
+                               IOERR_SLI_ABORTED);
+
+       return pring->txq_cnt;
+}