diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_els.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 145 |
1 files changed, 132 insertions, 13 deletions
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 2cc39684ce97..08b6634cb994 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -50,9 +50,6 @@ static int lpfc_issue_els_fdisc(struct lpfc_vport *vport, | |||
50 | struct lpfc_nodelist *ndlp, uint8_t retry); | 50 | struct lpfc_nodelist *ndlp, uint8_t retry); |
51 | static int lpfc_issue_fabric_iocb(struct lpfc_hba *phba, | 51 | static int lpfc_issue_fabric_iocb(struct lpfc_hba *phba, |
52 | struct lpfc_iocbq *iocb); | 52 | struct lpfc_iocbq *iocb); |
53 | static void lpfc_register_new_vport(struct lpfc_hba *phba, | ||
54 | struct lpfc_vport *vport, | ||
55 | struct lpfc_nodelist *ndlp); | ||
56 | 53 | ||
57 | static int lpfc_max_els_tries = 3; | 54 | static int lpfc_max_els_tries = 3; |
58 | 55 | ||
@@ -592,6 +589,15 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
592 | vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; | 589 | vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; |
593 | spin_unlock_irq(shost->host_lock); | 590 | spin_unlock_irq(shost->host_lock); |
594 | } | 591 | } |
592 | /* | ||
593 | * If VPI is unreged, driver need to do INIT_VPI | ||
594 | * before re-registering | ||
595 | */ | ||
596 | if (phba->sli_rev == LPFC_SLI_REV4) { | ||
597 | spin_lock_irq(shost->host_lock); | ||
598 | vport->fc_flag |= FC_VPORT_NEEDS_INIT_VPI; | ||
599 | spin_unlock_irq(shost->host_lock); | ||
600 | } | ||
595 | } | 601 | } |
596 | 602 | ||
597 | if (phba->sli_rev < LPFC_SLI_REV4) { | 603 | if (phba->sli_rev < LPFC_SLI_REV4) { |
@@ -604,10 +610,13 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
604 | } else { | 610 | } else { |
605 | ndlp->nlp_type |= NLP_FABRIC; | 611 | ndlp->nlp_type |= NLP_FABRIC; |
606 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); | 612 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); |
607 | if (vport->vpi_state & LPFC_VPI_REGISTERED) { | 613 | if ((!(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) && |
614 | (vport->vpi_state & LPFC_VPI_REGISTERED)) { | ||
608 | lpfc_start_fdiscs(phba); | 615 | lpfc_start_fdiscs(phba); |
609 | lpfc_do_scr_ns_plogi(phba, vport); | 616 | lpfc_do_scr_ns_plogi(phba, vport); |
610 | } else | 617 | } else if (vport->fc_flag & FC_VFI_REGISTERED) |
618 | lpfc_issue_init_vpi(vport); | ||
619 | else | ||
611 | lpfc_issue_reg_vfi(vport); | 620 | lpfc_issue_reg_vfi(vport); |
612 | } | 621 | } |
613 | return 0; | 622 | return 0; |
@@ -804,6 +813,9 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
804 | irsp->ulpTimeout); | 813 | irsp->ulpTimeout); |
805 | goto flogifail; | 814 | goto flogifail; |
806 | } | 815 | } |
816 | spin_lock_irq(shost->host_lock); | ||
817 | vport->fc_flag &= ~FC_VPORT_CVL_RCVD; | ||
818 | spin_unlock_irq(shost->host_lock); | ||
807 | 819 | ||
808 | /* | 820 | /* |
809 | * The FLogI succeeded. Sync the data for the CPU before | 821 | * The FLogI succeeded. Sync the data for the CPU before |
@@ -2720,7 +2732,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
2720 | if (did == FDMI_DID) | 2732 | if (did == FDMI_DID) |
2721 | retry = 1; | 2733 | retry = 1; |
2722 | 2734 | ||
2723 | if ((cmd == ELS_CMD_FLOGI) && | 2735 | if (((cmd == ELS_CMD_FLOGI) || (cmd == ELS_CMD_FDISC)) && |
2724 | (phba->fc_topology != TOPOLOGY_LOOP) && | 2736 | (phba->fc_topology != TOPOLOGY_LOOP) && |
2725 | !lpfc_error_lost_link(irsp)) { | 2737 | !lpfc_error_lost_link(irsp)) { |
2726 | /* FLOGI retry policy */ | 2738 | /* FLOGI retry policy */ |
@@ -4385,7 +4397,7 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
4385 | 4397 | ||
4386 | did = Fabric_DID; | 4398 | did = Fabric_DID; |
4387 | 4399 | ||
4388 | if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3))) { | 4400 | if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3, 1))) { |
4389 | /* For a FLOGI we accept, then if our portname is greater | 4401 | /* For a FLOGI we accept, then if our portname is greater |
4390 | * then the remote portname we initiate Nport login. | 4402 | * then the remote portname we initiate Nport login. |
4391 | */ | 4403 | */ |
@@ -5915,6 +5927,7 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
5915 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 5927 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
5916 | struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2; | 5928 | struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2; |
5917 | MAILBOX_t *mb = &pmb->u.mb; | 5929 | MAILBOX_t *mb = &pmb->u.mb; |
5930 | int rc; | ||
5918 | 5931 | ||
5919 | spin_lock_irq(shost->host_lock); | 5932 | spin_lock_irq(shost->host_lock); |
5920 | vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI; | 5933 | vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI; |
@@ -5936,6 +5949,26 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
5936 | spin_unlock_irq(shost->host_lock); | 5949 | spin_unlock_irq(shost->host_lock); |
5937 | lpfc_can_disctmo(vport); | 5950 | lpfc_can_disctmo(vport); |
5938 | break; | 5951 | break; |
5952 | /* If reg_vpi fail with invalid VPI status, re-init VPI */ | ||
5953 | case 0x20: | ||
5954 | spin_lock_irq(shost->host_lock); | ||
5955 | vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; | ||
5956 | spin_unlock_irq(shost->host_lock); | ||
5957 | lpfc_init_vpi(phba, pmb, vport->vpi); | ||
5958 | pmb->vport = vport; | ||
5959 | pmb->mbox_cmpl = lpfc_init_vpi_cmpl; | ||
5960 | rc = lpfc_sli_issue_mbox(phba, pmb, | ||
5961 | MBX_NOWAIT); | ||
5962 | if (rc == MBX_NOT_FINISHED) { | ||
5963 | lpfc_printf_vlog(vport, | ||
5964 | KERN_ERR, LOG_MBOX, | ||
5965 | "2732 Failed to issue INIT_VPI" | ||
5966 | " mailbox command\n"); | ||
5967 | } else { | ||
5968 | lpfc_nlp_put(ndlp); | ||
5969 | return; | ||
5970 | } | ||
5971 | |||
5939 | default: | 5972 | default: |
5940 | /* Try to recover from this error */ | 5973 | /* Try to recover from this error */ |
5941 | lpfc_mbx_unreg_vpi(vport); | 5974 | lpfc_mbx_unreg_vpi(vport); |
@@ -5949,13 +5982,17 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
5949 | break; | 5982 | break; |
5950 | } | 5983 | } |
5951 | } else { | 5984 | } else { |
5985 | spin_lock_irq(shost->host_lock); | ||
5952 | vport->vpi_state |= LPFC_VPI_REGISTERED; | 5986 | vport->vpi_state |= LPFC_VPI_REGISTERED; |
5953 | if (vport == phba->pport) | 5987 | spin_unlock_irq(shost->host_lock); |
5988 | if (vport == phba->pport) { | ||
5954 | if (phba->sli_rev < LPFC_SLI_REV4) | 5989 | if (phba->sli_rev < LPFC_SLI_REV4) |
5955 | lpfc_issue_fabric_reglogin(vport); | 5990 | lpfc_issue_fabric_reglogin(vport); |
5956 | else | 5991 | else { |
5957 | lpfc_issue_reg_vfi(vport); | 5992 | lpfc_start_fdiscs(phba); |
5958 | else | 5993 | lpfc_do_scr_ns_plogi(phba, vport); |
5994 | } | ||
5995 | } else | ||
5959 | lpfc_do_scr_ns_plogi(phba, vport); | 5996 | lpfc_do_scr_ns_plogi(phba, vport); |
5960 | } | 5997 | } |
5961 | 5998 | ||
@@ -5977,7 +6014,7 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
5977 | * This routine registers the @vport as a new virtual port with a HBA. | 6014 | * This routine registers the @vport as a new virtual port with a HBA. |
5978 | * It is done through a registering vpi mailbox command. | 6015 | * It is done through a registering vpi mailbox command. |
5979 | **/ | 6016 | **/ |
5980 | static void | 6017 | void |
5981 | lpfc_register_new_vport(struct lpfc_hba *phba, struct lpfc_vport *vport, | 6018 | lpfc_register_new_vport(struct lpfc_hba *phba, struct lpfc_vport *vport, |
5982 | struct lpfc_nodelist *ndlp) | 6019 | struct lpfc_nodelist *ndlp) |
5983 | { | 6020 | { |
@@ -6018,6 +6055,78 @@ mbox_err_exit: | |||
6018 | } | 6055 | } |
6019 | 6056 | ||
6020 | /** | 6057 | /** |
6058 | * lpfc_retry_pport_discovery - Start timer to retry FLOGI. | ||
6059 | * @phba: pointer to lpfc hba data structure. | ||
6060 | * | ||
6061 | * This routine abort all pending discovery commands and | ||
6062 | * start a timer to retry FLOGI for the physical port | ||
6063 | * discovery. | ||
6064 | **/ | ||
6065 | void | ||
6066 | lpfc_retry_pport_discovery(struct lpfc_hba *phba) | ||
6067 | { | ||
6068 | struct lpfc_vport **vports; | ||
6069 | struct lpfc_nodelist *ndlp; | ||
6070 | struct Scsi_Host *shost; | ||
6071 | int i; | ||
6072 | uint32_t link_state; | ||
6073 | |||
6074 | /* Treat this failure as linkdown for all vports */ | ||
6075 | link_state = phba->link_state; | ||
6076 | lpfc_linkdown(phba); | ||
6077 | phba->link_state = link_state; | ||
6078 | |||
6079 | vports = lpfc_create_vport_work_array(phba); | ||
6080 | |||
6081 | if (vports) { | ||
6082 | for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) { | ||
6083 | ndlp = lpfc_findnode_did(vports[i], Fabric_DID); | ||
6084 | if (ndlp) | ||
6085 | lpfc_cancel_retry_delay_tmo(vports[i], ndlp); | ||
6086 | lpfc_els_flush_cmd(vports[i]); | ||
6087 | } | ||
6088 | lpfc_destroy_vport_work_array(phba, vports); | ||
6089 | } | ||
6090 | |||
6091 | /* If fabric require FLOGI, then re-instantiate physical login */ | ||
6092 | ndlp = lpfc_findnode_did(phba->pport, Fabric_DID); | ||
6093 | if (!ndlp) | ||
6094 | return; | ||
6095 | |||
6096 | |||
6097 | shost = lpfc_shost_from_vport(phba->pport); | ||
6098 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ); | ||
6099 | spin_lock_irq(shost->host_lock); | ||
6100 | ndlp->nlp_flag |= NLP_DELAY_TMO; | ||
6101 | spin_unlock_irq(shost->host_lock); | ||
6102 | ndlp->nlp_last_elscmd = ELS_CMD_FLOGI; | ||
6103 | phba->pport->port_state = LPFC_FLOGI; | ||
6104 | return; | ||
6105 | } | ||
6106 | |||
6107 | /** | ||
6108 | * lpfc_fabric_login_reqd - Check if FLOGI required. | ||
6109 | * @phba: pointer to lpfc hba data structure. | ||
6110 | * @cmdiocb: pointer to FDISC command iocb. | ||
6111 | * @rspiocb: pointer to FDISC response iocb. | ||
6112 | * | ||
6113 | * This routine checks if a FLOGI is reguired for FDISC | ||
6114 | * to succeed. | ||
6115 | **/ | ||
6116 | static int | ||
6117 | lpfc_fabric_login_reqd(struct lpfc_hba *phba, | ||
6118 | struct lpfc_iocbq *cmdiocb, | ||
6119 | struct lpfc_iocbq *rspiocb) | ||
6120 | { | ||
6121 | |||
6122 | if ((rspiocb->iocb.ulpStatus != IOSTAT_FABRIC_RJT) || | ||
6123 | (rspiocb->iocb.un.ulpWord[4] != RJT_LOGIN_REQUIRED)) | ||
6124 | return 0; | ||
6125 | else | ||
6126 | return 1; | ||
6127 | } | ||
6128 | |||
6129 | /** | ||
6021 | * lpfc_cmpl_els_fdisc - Completion function for fdisc iocb command | 6130 | * lpfc_cmpl_els_fdisc - Completion function for fdisc iocb command |
6022 | * @phba: pointer to lpfc hba data structure. | 6131 | * @phba: pointer to lpfc hba data structure. |
6023 | * @cmdiocb: pointer to lpfc command iocb data structure. | 6132 | * @cmdiocb: pointer to lpfc command iocb data structure. |
@@ -6066,6 +6175,12 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
6066 | irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_prevDID); | 6175 | irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_prevDID); |
6067 | 6176 | ||
6068 | if (irsp->ulpStatus) { | 6177 | if (irsp->ulpStatus) { |
6178 | |||
6179 | if (lpfc_fabric_login_reqd(phba, cmdiocb, rspiocb)) { | ||
6180 | lpfc_retry_pport_discovery(phba); | ||
6181 | goto out; | ||
6182 | } | ||
6183 | |||
6069 | /* Check for retry */ | 6184 | /* Check for retry */ |
6070 | if (lpfc_els_retry(phba, cmdiocb, rspiocb)) | 6185 | if (lpfc_els_retry(phba, cmdiocb, rspiocb)) |
6071 | goto out; | 6186 | goto out; |
@@ -6076,6 +6191,7 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
6076 | goto fdisc_failed; | 6191 | goto fdisc_failed; |
6077 | } | 6192 | } |
6078 | spin_lock_irq(shost->host_lock); | 6193 | spin_lock_irq(shost->host_lock); |
6194 | vport->fc_flag &= ~FC_VPORT_CVL_RCVD; | ||
6079 | vport->fc_flag |= FC_FABRIC; | 6195 | vport->fc_flag |= FC_FABRIC; |
6080 | if (vport->phba->fc_topology == TOPOLOGY_LOOP) | 6196 | if (vport->phba->fc_topology == TOPOLOGY_LOOP) |
6081 | vport->fc_flag |= FC_PUBLIC_LOOP; | 6197 | vport->fc_flag |= FC_PUBLIC_LOOP; |
@@ -6103,10 +6219,13 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
6103 | lpfc_mbx_unreg_vpi(vport); | 6219 | lpfc_mbx_unreg_vpi(vport); |
6104 | spin_lock_irq(shost->host_lock); | 6220 | spin_lock_irq(shost->host_lock); |
6105 | vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; | 6221 | vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; |
6222 | vport->fc_flag |= FC_VPORT_NEEDS_INIT_VPI; | ||
6106 | spin_unlock_irq(shost->host_lock); | 6223 | spin_unlock_irq(shost->host_lock); |
6107 | } | 6224 | } |
6108 | 6225 | ||
6109 | if (vport->fc_flag & FC_VPORT_NEEDS_REG_VPI) | 6226 | if (vport->fc_flag & FC_VPORT_NEEDS_INIT_VPI) |
6227 | lpfc_issue_init_vpi(vport); | ||
6228 | else if (vport->fc_flag & FC_VPORT_NEEDS_REG_VPI) | ||
6110 | lpfc_register_new_vport(phba, vport, ndlp); | 6229 | lpfc_register_new_vport(phba, vport, ndlp); |
6111 | else | 6230 | else |
6112 | lpfc_do_scr_ns_plogi(phba, vport); | 6231 | lpfc_do_scr_ns_plogi(phba, vport); |