diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_els.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 116 |
1 files changed, 61 insertions, 55 deletions
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 39d5b146202e..234c7c015982 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -858,6 +858,9 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, vport->fc_flag |= FC_PT2PT; spin_unlock_irq(shost->host_lock); + /* If we are pt2pt with another NPort, force NPIV off! */ + phba->sli3_options &= ~LPFC_SLI3_NPIV_ENABLED; + /* If physical FC port changed, unreg VFI and ALL VPIs / RPIs */ if ((phba->sli_rev == LPFC_SLI_REV4) && phba->fc_topology_changed) { lpfc_unregister_fcf_prep(phba); @@ -916,28 +919,29 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, spin_lock_irq(shost->host_lock); ndlp->nlp_flag |= NLP_NPR_2B_DISC; spin_unlock_irq(shost->host_lock); - } else + + mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); + if (!mbox) + goto fail; + + lpfc_config_link(phba, mbox); + + mbox->mbox_cmpl = lpfc_mbx_cmpl_local_config_link; + mbox->vport = vport; + rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); + if (rc == MBX_NOT_FINISHED) { + mempool_free(mbox, phba->mbox_mem_pool); + goto fail; + } + } else { /* This side will wait for the PLOGI, decrement ndlp reference * count indicating that ndlp can be released when other * references to it are done. */ lpfc_nlp_put(ndlp); - /* If we are pt2pt with another NPort, force NPIV off! */ - phba->sli3_options &= ~LPFC_SLI3_NPIV_ENABLED; - - mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); - if (!mbox) - goto fail; - - lpfc_config_link(phba, mbox); - - mbox->mbox_cmpl = lpfc_mbx_cmpl_local_config_link; - mbox->vport = vport; - rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); - if (rc == MBX_NOT_FINISHED) { - mempool_free(mbox, phba->mbox_mem_pool); - goto fail; + /* Start discovery - this should just do CLEAR_LA */ + lpfc_disc_start(vport); } return 0; @@ -1030,30 +1034,31 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, stop_rr_fcf_flogi: /* FLOGI failure */ - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, - "2858 FLOGI failure Status:x%x/x%x TMO:x%x " - "Data x%x x%x\n", - irsp->ulpStatus, irsp->un.ulpWord[4], - irsp->ulpTimeout, phba->hba_flag, - phba->fcf.fcf_flag); + if (!(irsp->ulpStatus == IOSTAT_LOCAL_REJECT && + ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) == + IOERR_LOOP_OPEN_FAILURE))) + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "2858 FLOGI failure Status:x%x/x%x " + "TMO:x%x Data x%x x%x\n", + irsp->ulpStatus, irsp->un.ulpWord[4], + irsp->ulpTimeout, phba->hba_flag, + phba->fcf.fcf_flag); /* Check for retry */ if (lpfc_els_retry(phba, cmdiocb, rspiocb)) goto out; - /* FLOGI failure */ - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, - "0100 FLOGI failure Status:x%x/x%x TMO:x%x\n", - irsp->ulpStatus, irsp->un.ulpWord[4], - irsp->ulpTimeout); - - /* If this is not a loop open failure, bail out */ if (!(irsp->ulpStatus == IOSTAT_LOCAL_REJECT && ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) == IOERR_LOOP_OPEN_FAILURE))) goto flogifail; + lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS, + "0150 FLOGI failure Status:x%x/x%x TMO:x%x\n", + irsp->ulpStatus, irsp->un.ulpWord[4], + irsp->ulpTimeout); + /* FLOGI failed, so there is no fabric */ spin_lock_irq(shost->host_lock); vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); @@ -1670,6 +1675,7 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, /* Two ndlps cannot have the same did on the nodelist */ ndlp->nlp_DID = keepDID; + lpfc_nlp_set_state(vport, ndlp, keep_nlp_state); if (phba->sli_rev == LPFC_SLI_REV4 && active_rrqs_xri_bitmap) memcpy(ndlp->active_rrqs_xri_bitmap, @@ -2088,6 +2094,10 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ndlp = (struct lpfc_nodelist *) cmdiocb->context1; spin_lock_irq(shost->host_lock); ndlp->nlp_flag &= ~NLP_PRLI_SND; + + /* Driver supports multiple FC4 types. Counters matter. */ + vport->fc_prli_sent--; + ndlp->fc4_prli_sent--; spin_unlock_irq(shost->host_lock); lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, @@ -2095,9 +2105,6 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, irsp->ulpStatus, irsp->un.ulpWord[4], ndlp->nlp_DID); - /* Ddriver supports multiple FC4 types. Counters matter. */ - vport->fc_prli_sent--; - /* PRLI completes to NPort <nlp_DID> */ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "0103 PRLI completes to NPort x%06x " @@ -2111,7 +2118,6 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, if (irsp->ulpStatus) { /* Check for retry */ - ndlp->fc4_prli_sent--; if (lpfc_els_retry(phba, cmdiocb, rspiocb)) { /* ELS command is being retried */ goto out; @@ -2190,6 +2196,15 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ndlp->nlp_fc4_type |= NLP_FC4_NVME; local_nlp_type = ndlp->nlp_fc4_type; + /* This routine will issue 1 or 2 PRLIs, so zero all the ndlp + * fields here before any of them can complete. + */ + ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR); + ndlp->nlp_type &= ~(NLP_NVME_TARGET | NLP_NVME_INITIATOR); + ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE; + ndlp->nlp_flag &= ~NLP_FIRSTBURST; + ndlp->nvme_fb_size = 0; + send_next_prli: if (local_nlp_type & NLP_FC4_FCP) { /* Payload is 4 + 16 = 20 x14 bytes. */ @@ -2298,6 +2313,13 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, elsiocb->iocb_cmpl = lpfc_cmpl_els_prli; spin_lock_irq(shost->host_lock); ndlp->nlp_flag |= NLP_PRLI_SND; + + /* The vport counters are used for lpfc_scan_finished, but + * the ndlp is used to track outstanding PRLIs for different + * FC4 types. + */ + vport->fc_prli_sent++; + ndlp->fc4_prli_sent++; spin_unlock_irq(shost->host_lock); if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) == IOCB_ERROR) { @@ -2308,12 +2330,6 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, return 1; } - /* The vport counters are used for lpfc_scan_finished, but - * the ndlp is used to track outstanding PRLIs for different - * FC4 types. - */ - vport->fc_prli_sent++; - ndlp->fc4_prli_sent++; /* The driver supports 2 FC4 types. Make sure * a PRLI is issued for all types before exiting. @@ -2951,8 +2967,8 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) /* This will cause the callback-function lpfc_cmpl_els_cmd to * trigger the release of node. */ - - lpfc_nlp_put(ndlp); + if (!(vport->fc_flag & FC_PT2PT)) + lpfc_nlp_put(ndlp); return 0; } @@ -6172,9 +6188,6 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); /* send RECOVERY event for ALL nodes that match RSCN payload */ lpfc_rscn_recovery_check(vport); - spin_lock_irq(shost->host_lock); - vport->fc_flag &= ~FC_RSCN_DEFERRED; - spin_unlock_irq(shost->host_lock); return 0; } lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, @@ -6849,7 +6862,7 @@ lpfc_els_rcv_rtv(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, return 1; pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); - *((uint32_t *) (pcmd)) = ELS_CMD_ACC; + *((uint32_t *) (pcmd)) = ELS_CMD_ACC; pcmd += sizeof(uint32_t); /* Skip past command */ /* use the command's xri in the response */ @@ -8060,13 +8073,6 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, rjt_exp = LSEXP_NOTHING_MORE; break; } - - /* NVMET accepts NVME PRLI only. Reject FCP PRLI */ - if (cmd == ELS_CMD_PRLI && phba->nvmet_support) { - rjt_err = LSRJT_CMD_UNSUPPORTED; - rjt_exp = LSEXP_REQ_UNSUPPORTED; - break; - } lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_PRLI); break; case ELS_CMD_LIRR: @@ -8149,9 +8155,9 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, lpfc_nlp_put(ndlp); break; case ELS_CMD_REC: - /* receive this due to exchange closed */ - rjt_err = LSRJT_UNABLE_TPC; - rjt_exp = LSEXP_INVALID_OX_RX; + /* receive this due to exchange closed */ + rjt_err = LSRJT_UNABLE_TPC; + rjt_exp = LSEXP_INVALID_OX_RX; break; default: lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, |