diff options
author | James Smart <james.smart@emulex.com> | 2010-01-26 23:08:03 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-02-08 19:38:28 -0500 |
commit | 695a814e18561c52456acf5051fac0ea4b8111da (patch) | |
tree | 3cbe747f38bbd5dae092e643de42be1a735d9552 /drivers/scsi | |
parent | 341af10239c4c87192bf762f53c7bcb1f3a1e767 (diff) |
[SCSI] lpfc 8.3.8: BugFixes: Discovery relates changes
Discovery relates changes:
- Separated VPI_REGISTERED state of physical port into VFI_REGISTERED and
VPI_REGISTERED state so that driver can unregister physical port VPI
independent of VFI.
- Add code to unregister, re-init and re-register physical port VPI
when physical port NportID change.
- Add code to unregister and re-register VPI of a vport when its Nport
ID change.
- Add code in FDISC completion path to re-start FLOGI discovery when
a FDISC complete with LOGIN_REQUIRED reason code.
- Fix a memory leak in lpfc_init_vpi_cmpl
- Add code to start a timer for vport to retry FDISC when CVL is received
by a vport or physical port. If all Nports receive CVLs, then all timers
are cancelled and a logical link level discovery will be started after
one second.
- Flush ELS commands after killing all delayed ELS commands.
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 3 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 5 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 129 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 36 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 44 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 62 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_vport.c | 2 |
8 files changed, 265 insertions, 18 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 1cc23a69db5e..197dc3e3bdc9 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -315,6 +315,9 @@ struct lpfc_vport { | |||
315 | #define FC_VPORT_NEEDS_REG_VPI 0x80000 /* Needs to have its vpi registered */ | 315 | #define FC_VPORT_NEEDS_REG_VPI 0x80000 /* Needs to have its vpi registered */ |
316 | #define FC_RSCN_DEFERRED 0x100000 /* A deferred RSCN being processed */ | 316 | #define FC_RSCN_DEFERRED 0x100000 /* A deferred RSCN being processed */ |
317 | #define FC_VPORT_NEEDS_INIT_VPI 0x200000 /* Need to INIT_VPI before FDISC */ | 317 | #define FC_VPORT_NEEDS_INIT_VPI 0x200000 /* Need to INIT_VPI before FDISC */ |
318 | #define FC_VPORT_CVL_RCVD 0x400000 /* VLink failed due to CVL */ | ||
319 | #define FC_VFI_REGISTERED 0x800000 /* VFI is registered */ | ||
320 | #define FC_FDISC_COMPLETED 0x1000000/* FDISC completed */ | ||
318 | 321 | ||
319 | uint32_t ct_flags; | 322 | uint32_t ct_flags; |
320 | #define FC_CT_RFF_ID 0x1 /* RFF_ID accepted by switch */ | 323 | #define FC_CT_RFF_ID 0x1 /* RFF_ID accepted by switch */ |
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 14ee7d4f71ba..b9e8cd5b818a 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
@@ -44,6 +44,8 @@ int lpfc_reg_rpi(struct lpfc_hba *, uint16_t, uint32_t, uint8_t *, | |||
44 | void lpfc_unreg_login(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *); | 44 | void lpfc_unreg_login(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *); |
45 | void lpfc_unreg_did(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *); | 45 | void lpfc_unreg_did(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *); |
46 | void lpfc_reg_vpi(struct lpfc_vport *, LPFC_MBOXQ_t *); | 46 | void lpfc_reg_vpi(struct lpfc_vport *, LPFC_MBOXQ_t *); |
47 | void lpfc_register_new_vport(struct lpfc_hba *, struct lpfc_vport *, | ||
48 | struct lpfc_nodelist *); | ||
47 | void lpfc_unreg_vpi(struct lpfc_hba *, uint16_t, LPFC_MBOXQ_t *); | 49 | void lpfc_unreg_vpi(struct lpfc_hba *, uint16_t, LPFC_MBOXQ_t *); |
48 | void lpfc_init_link(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t); | 50 | void lpfc_init_link(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t); |
49 | void lpfc_request_features(struct lpfc_hba *, struct lpfcMboxq *); | 51 | void lpfc_request_features(struct lpfc_hba *, struct lpfcMboxq *); |
@@ -52,10 +54,13 @@ struct lpfc_vport *lpfc_find_vport_by_did(struct lpfc_hba *, uint32_t); | |||
52 | void lpfc_cleanup_rcv_buffers(struct lpfc_vport *); | 54 | void lpfc_cleanup_rcv_buffers(struct lpfc_vport *); |
53 | void lpfc_rcv_seq_check_edtov(struct lpfc_vport *); | 55 | void lpfc_rcv_seq_check_edtov(struct lpfc_vport *); |
54 | void lpfc_cleanup_rpis(struct lpfc_vport *, int); | 56 | void lpfc_cleanup_rpis(struct lpfc_vport *, int); |
57 | void lpfc_cleanup_pending_mbox(struct lpfc_vport *); | ||
55 | int lpfc_linkdown(struct lpfc_hba *); | 58 | int lpfc_linkdown(struct lpfc_hba *); |
56 | void lpfc_linkdown_port(struct lpfc_vport *); | 59 | void lpfc_linkdown_port(struct lpfc_vport *); |
57 | void lpfc_port_link_failure(struct lpfc_vport *); | 60 | void lpfc_port_link_failure(struct lpfc_vport *); |
58 | void lpfc_mbx_cmpl_read_la(struct lpfc_hba *, LPFC_MBOXQ_t *); | 61 | void lpfc_mbx_cmpl_read_la(struct lpfc_hba *, LPFC_MBOXQ_t *); |
62 | void lpfc_init_vpi_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *); | ||
63 | void lpfc_retry_pport_discovery(struct lpfc_hba *); | ||
59 | 64 | ||
60 | void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); | 65 | void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); |
61 | void lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *, LPFC_MBOXQ_t *); | 66 | void lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *, LPFC_MBOXQ_t *); |
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 32e3c8df22c5..2c62349a1041 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 | ||
@@ -604,10 +601,13 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
604 | } else { | 601 | } else { |
605 | ndlp->nlp_type |= NLP_FABRIC; | 602 | ndlp->nlp_type |= NLP_FABRIC; |
606 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); | 603 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); |
607 | if (vport->vpi_state & LPFC_VPI_REGISTERED) { | 604 | if ((!(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) && |
605 | (vport->vpi_state & LPFC_VPI_REGISTERED)) { | ||
608 | lpfc_start_fdiscs(phba); | 606 | lpfc_start_fdiscs(phba); |
609 | lpfc_do_scr_ns_plogi(phba, vport); | 607 | lpfc_do_scr_ns_plogi(phba, vport); |
610 | } else | 608 | } else if (vport->fc_flag & FC_VFI_REGISTERED) |
609 | lpfc_register_new_vport(phba, vport, ndlp); | ||
610 | else | ||
611 | lpfc_issue_reg_vfi(vport); | 611 | lpfc_issue_reg_vfi(vport); |
612 | } | 612 | } |
613 | return 0; | 613 | return 0; |
@@ -804,6 +804,9 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
804 | irsp->ulpTimeout); | 804 | irsp->ulpTimeout); |
805 | goto flogifail; | 805 | goto flogifail; |
806 | } | 806 | } |
807 | spin_lock_irq(shost->host_lock); | ||
808 | vport->fc_flag &= ~FC_VPORT_CVL_RCVD; | ||
809 | spin_unlock_irq(shost->host_lock); | ||
807 | 810 | ||
808 | /* | 811 | /* |
809 | * The FLogI succeeded. Sync the data for the CPU before | 812 | * The FLogI succeeded. Sync the data for the CPU before |
@@ -2720,7 +2723,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
2720 | if (did == FDMI_DID) | 2723 | if (did == FDMI_DID) |
2721 | retry = 1; | 2724 | retry = 1; |
2722 | 2725 | ||
2723 | if ((cmd == ELS_CMD_FLOGI) && | 2726 | if (((cmd == ELS_CMD_FLOGI) || (cmd == ELS_CMD_FDISC)) && |
2724 | (phba->fc_topology != TOPOLOGY_LOOP) && | 2727 | (phba->fc_topology != TOPOLOGY_LOOP) && |
2725 | !lpfc_error_lost_link(irsp)) { | 2728 | !lpfc_error_lost_link(irsp)) { |
2726 | /* FLOGI retry policy */ | 2729 | /* FLOGI retry policy */ |
@@ -5915,6 +5918,7 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
5915 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 5918 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
5916 | struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2; | 5919 | struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2; |
5917 | MAILBOX_t *mb = &pmb->u.mb; | 5920 | MAILBOX_t *mb = &pmb->u.mb; |
5921 | int rc; | ||
5918 | 5922 | ||
5919 | spin_lock_irq(shost->host_lock); | 5923 | spin_lock_irq(shost->host_lock); |
5920 | vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI; | 5924 | vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI; |
@@ -5936,6 +5940,26 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
5936 | spin_unlock_irq(shost->host_lock); | 5940 | spin_unlock_irq(shost->host_lock); |
5937 | lpfc_can_disctmo(vport); | 5941 | lpfc_can_disctmo(vport); |
5938 | break; | 5942 | break; |
5943 | /* If reg_vpi fail with invalid VPI status, re-init VPI */ | ||
5944 | case 0x20: | ||
5945 | spin_lock_irq(shost->host_lock); | ||
5946 | vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; | ||
5947 | spin_unlock_irq(shost->host_lock); | ||
5948 | lpfc_init_vpi(phba, pmb, vport->vpi); | ||
5949 | pmb->vport = vport; | ||
5950 | pmb->mbox_cmpl = lpfc_init_vpi_cmpl; | ||
5951 | rc = lpfc_sli_issue_mbox(phba, pmb, | ||
5952 | MBX_NOWAIT); | ||
5953 | if (rc == MBX_NOT_FINISHED) { | ||
5954 | lpfc_printf_vlog(vport, | ||
5955 | KERN_ERR, LOG_MBOX, | ||
5956 | "2732 Failed to issue INIT_VPI" | ||
5957 | " mailbox command\n"); | ||
5958 | } else { | ||
5959 | lpfc_nlp_put(ndlp); | ||
5960 | return; | ||
5961 | } | ||
5962 | |||
5939 | default: | 5963 | default: |
5940 | /* Try to recover from this error */ | 5964 | /* Try to recover from this error */ |
5941 | lpfc_mbx_unreg_vpi(vport); | 5965 | lpfc_mbx_unreg_vpi(vport); |
@@ -5949,13 +5973,17 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
5949 | break; | 5973 | break; |
5950 | } | 5974 | } |
5951 | } else { | 5975 | } else { |
5976 | spin_lock_irq(shost->host_lock); | ||
5952 | vport->vpi_state |= LPFC_VPI_REGISTERED; | 5977 | vport->vpi_state |= LPFC_VPI_REGISTERED; |
5953 | if (vport == phba->pport) | 5978 | spin_unlock_irq(shost->host_lock); |
5979 | if (vport == phba->pport) { | ||
5954 | if (phba->sli_rev < LPFC_SLI_REV4) | 5980 | if (phba->sli_rev < LPFC_SLI_REV4) |
5955 | lpfc_issue_fabric_reglogin(vport); | 5981 | lpfc_issue_fabric_reglogin(vport); |
5956 | else | 5982 | else { |
5957 | lpfc_issue_reg_vfi(vport); | 5983 | lpfc_start_fdiscs(phba); |
5958 | else | 5984 | lpfc_do_scr_ns_plogi(phba, vport); |
5985 | } | ||
5986 | } else | ||
5959 | lpfc_do_scr_ns_plogi(phba, vport); | 5987 | lpfc_do_scr_ns_plogi(phba, vport); |
5960 | } | 5988 | } |
5961 | 5989 | ||
@@ -5977,7 +6005,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. | 6005 | * This routine registers the @vport as a new virtual port with a HBA. |
5978 | * It is done through a registering vpi mailbox command. | 6006 | * It is done through a registering vpi mailbox command. |
5979 | **/ | 6007 | **/ |
5980 | static void | 6008 | void |
5981 | lpfc_register_new_vport(struct lpfc_hba *phba, struct lpfc_vport *vport, | 6009 | lpfc_register_new_vport(struct lpfc_hba *phba, struct lpfc_vport *vport, |
5982 | struct lpfc_nodelist *ndlp) | 6010 | struct lpfc_nodelist *ndlp) |
5983 | { | 6011 | { |
@@ -6018,6 +6046,78 @@ mbox_err_exit: | |||
6018 | } | 6046 | } |
6019 | 6047 | ||
6020 | /** | 6048 | /** |
6049 | * lpfc_retry_pport_discovery - Start timer to retry FLOGI. | ||
6050 | * @phba: pointer to lpfc hba data structure. | ||
6051 | * | ||
6052 | * This routine abort all pending discovery commands and | ||
6053 | * start a timer to retry FLOGI for the physical port | ||
6054 | * discovery. | ||
6055 | **/ | ||
6056 | void | ||
6057 | lpfc_retry_pport_discovery(struct lpfc_hba *phba) | ||
6058 | { | ||
6059 | struct lpfc_vport **vports; | ||
6060 | struct lpfc_nodelist *ndlp; | ||
6061 | struct Scsi_Host *shost; | ||
6062 | int i; | ||
6063 | uint32_t link_state; | ||
6064 | |||
6065 | /* Treat this failure as linkdown for all vports */ | ||
6066 | link_state = phba->link_state; | ||
6067 | lpfc_linkdown(phba); | ||
6068 | phba->link_state = link_state; | ||
6069 | |||
6070 | vports = lpfc_create_vport_work_array(phba); | ||
6071 | |||
6072 | if (vports) { | ||
6073 | for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) { | ||
6074 | ndlp = lpfc_findnode_did(vports[i], Fabric_DID); | ||
6075 | if (ndlp) | ||
6076 | lpfc_cancel_retry_delay_tmo(vports[i], ndlp); | ||
6077 | lpfc_els_flush_cmd(vports[i]); | ||
6078 | } | ||
6079 | lpfc_destroy_vport_work_array(phba, vports); | ||
6080 | } | ||
6081 | |||
6082 | /* If fabric require FLOGI, then re-instantiate physical login */ | ||
6083 | ndlp = lpfc_findnode_did(phba->pport, Fabric_DID); | ||
6084 | if (!ndlp) | ||
6085 | return; | ||
6086 | |||
6087 | |||
6088 | shost = lpfc_shost_from_vport(phba->pport); | ||
6089 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ); | ||
6090 | spin_lock_irq(shost->host_lock); | ||
6091 | ndlp->nlp_flag |= NLP_DELAY_TMO; | ||
6092 | spin_unlock_irq(shost->host_lock); | ||
6093 | ndlp->nlp_last_elscmd = ELS_CMD_FLOGI; | ||
6094 | phba->pport->port_state = LPFC_FLOGI; | ||
6095 | return; | ||
6096 | } | ||
6097 | |||
6098 | /** | ||
6099 | * lpfc_fabric_login_reqd - Check if FLOGI required. | ||
6100 | * @phba: pointer to lpfc hba data structure. | ||
6101 | * @cmdiocb: pointer to FDISC command iocb. | ||
6102 | * @rspiocb: pointer to FDISC response iocb. | ||
6103 | * | ||
6104 | * This routine checks if a FLOGI is reguired for FDISC | ||
6105 | * to succeed. | ||
6106 | **/ | ||
6107 | static int | ||
6108 | lpfc_fabric_login_reqd(struct lpfc_hba *phba, | ||
6109 | struct lpfc_iocbq *cmdiocb, | ||
6110 | struct lpfc_iocbq *rspiocb) | ||
6111 | { | ||
6112 | |||
6113 | if ((rspiocb->iocb.ulpStatus != IOSTAT_FABRIC_RJT) || | ||
6114 | (rspiocb->iocb.un.ulpWord[4] != RJT_LOGIN_REQUIRED)) | ||
6115 | return 0; | ||
6116 | else | ||
6117 | return 1; | ||
6118 | } | ||
6119 | |||
6120 | /** | ||
6021 | * lpfc_cmpl_els_fdisc - Completion function for fdisc iocb command | 6121 | * lpfc_cmpl_els_fdisc - Completion function for fdisc iocb command |
6022 | * @phba: pointer to lpfc hba data structure. | 6122 | * @phba: pointer to lpfc hba data structure. |
6023 | * @cmdiocb: pointer to lpfc command iocb data structure. | 6123 | * @cmdiocb: pointer to lpfc command iocb data structure. |
@@ -6066,6 +6166,12 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
6066 | irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_prevDID); | 6166 | irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_prevDID); |
6067 | 6167 | ||
6068 | if (irsp->ulpStatus) { | 6168 | if (irsp->ulpStatus) { |
6169 | |||
6170 | if (lpfc_fabric_login_reqd(phba, cmdiocb, rspiocb)) { | ||
6171 | lpfc_retry_pport_discovery(phba); | ||
6172 | goto out; | ||
6173 | } | ||
6174 | |||
6069 | /* Check for retry */ | 6175 | /* Check for retry */ |
6070 | if (lpfc_els_retry(phba, cmdiocb, rspiocb)) | 6176 | if (lpfc_els_retry(phba, cmdiocb, rspiocb)) |
6071 | goto out; | 6177 | goto out; |
@@ -6076,6 +6182,7 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
6076 | goto fdisc_failed; | 6182 | goto fdisc_failed; |
6077 | } | 6183 | } |
6078 | spin_lock_irq(shost->host_lock); | 6184 | spin_lock_irq(shost->host_lock); |
6185 | vport->fc_flag &= ~FC_VPORT_CVL_RCVD; | ||
6079 | vport->fc_flag |= FC_FABRIC; | 6186 | vport->fc_flag |= FC_FABRIC; |
6080 | if (vport->phba->fc_topology == TOPOLOGY_LOOP) | 6187 | if (vport->phba->fc_topology == TOPOLOGY_LOOP) |
6081 | vport->fc_flag |= FC_PUBLIC_LOOP; | 6188 | vport->fc_flag |= FC_PUBLIC_LOOP; |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 2445e399fd60..7143d71c501f 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -706,6 +706,8 @@ lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove) | |||
706 | void | 706 | void |
707 | lpfc_port_link_failure(struct lpfc_vport *vport) | 707 | lpfc_port_link_failure(struct lpfc_vport *vport) |
708 | { | 708 | { |
709 | lpfc_vport_set_state(vport, FC_VPORT_LINKDOWN); | ||
710 | |||
709 | /* Cleanup any outstanding received buffers */ | 711 | /* Cleanup any outstanding received buffers */ |
710 | lpfc_cleanup_rcv_buffers(vport); | 712 | lpfc_cleanup_rcv_buffers(vport); |
711 | 713 | ||
@@ -1695,10 +1697,11 @@ out: | |||
1695 | * | 1697 | * |
1696 | * This function handles completion of init vpi mailbox command. | 1698 | * This function handles completion of init vpi mailbox command. |
1697 | */ | 1699 | */ |
1698 | static void | 1700 | void |
1699 | lpfc_init_vpi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | 1701 | lpfc_init_vpi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) |
1700 | { | 1702 | { |
1701 | struct lpfc_vport *vport = mboxq->vport; | 1703 | struct lpfc_vport *vport = mboxq->vport; |
1704 | struct lpfc_nodelist *ndlp; | ||
1702 | if (mboxq->u.mb.mbxStatus) { | 1705 | if (mboxq->u.mb.mbxStatus) { |
1703 | lpfc_printf_vlog(vport, KERN_ERR, | 1706 | lpfc_printf_vlog(vport, KERN_ERR, |
1704 | LOG_MBOX, | 1707 | LOG_MBOX, |
@@ -1712,6 +1715,20 @@ lpfc_init_vpi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
1712 | vport->fc_flag &= ~FC_VPORT_NEEDS_INIT_VPI; | 1715 | vport->fc_flag &= ~FC_VPORT_NEEDS_INIT_VPI; |
1713 | spin_unlock_irq(&phba->hbalock); | 1716 | spin_unlock_irq(&phba->hbalock); |
1714 | 1717 | ||
1718 | /* If this port is physical port or FDISC is done, do reg_vpi */ | ||
1719 | if ((phba->pport == vport) || (vport->port_state == LPFC_FDISC)) { | ||
1720 | ndlp = lpfc_findnode_did(vport, Fabric_DID); | ||
1721 | if (!ndlp) | ||
1722 | lpfc_printf_vlog(vport, KERN_ERR, | ||
1723 | LOG_DISCOVERY, | ||
1724 | "2731 Cannot find fabric " | ||
1725 | "controller node\n"); | ||
1726 | else | ||
1727 | lpfc_register_new_vport(phba, vport, ndlp); | ||
1728 | mempool_free(mboxq, phba->mbox_mem_pool); | ||
1729 | return; | ||
1730 | } | ||
1731 | |||
1715 | if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) | 1732 | if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) |
1716 | lpfc_initial_fdisc(vport); | 1733 | lpfc_initial_fdisc(vport); |
1717 | else { | 1734 | else { |
@@ -1719,6 +1736,7 @@ lpfc_init_vpi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
1719 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, | 1736 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
1720 | "2606 No NPIV Fabric support\n"); | 1737 | "2606 No NPIV Fabric support\n"); |
1721 | } | 1738 | } |
1739 | mempool_free(mboxq, phba->mbox_mem_pool); | ||
1722 | return; | 1740 | return; |
1723 | } | 1741 | } |
1724 | 1742 | ||
@@ -1814,6 +1832,9 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
1814 | } | 1832 | } |
1815 | /* The VPI is implicitly registered when the VFI is registered */ | 1833 | /* The VPI is implicitly registered when the VFI is registered */ |
1816 | vport->vpi_state |= LPFC_VPI_REGISTERED; | 1834 | vport->vpi_state |= LPFC_VPI_REGISTERED; |
1835 | vport->fc_flag |= FC_VFI_REGISTERED; | ||
1836 | |||
1837 | vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI; | ||
1817 | 1838 | ||
1818 | if (vport->port_state == LPFC_FABRIC_CFG_LINK) { | 1839 | if (vport->port_state == LPFC_FABRIC_CFG_LINK) { |
1819 | lpfc_start_fdiscs(phba); | 1840 | lpfc_start_fdiscs(phba); |
@@ -2333,6 +2354,7 @@ lpfc_mbx_cmpl_reg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
2333 | } | 2354 | } |
2334 | 2355 | ||
2335 | vport->vpi_state |= LPFC_VPI_REGISTERED; | 2356 | vport->vpi_state |= LPFC_VPI_REGISTERED; |
2357 | vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI; | ||
2336 | vport->num_disc_nodes = 0; | 2358 | vport->num_disc_nodes = 0; |
2337 | /* go thru NPR list and issue ELS PLOGIs */ | 2359 | /* go thru NPR list and issue ELS PLOGIs */ |
2338 | if (vport->fc_npr_cnt) | 2360 | if (vport->fc_npr_cnt) |
@@ -4462,6 +4484,7 @@ lpfc_unregister_unused_fcf(struct lpfc_hba *phba) | |||
4462 | int rc; | 4484 | int rc; |
4463 | struct lpfc_vport **vports; | 4485 | struct lpfc_vport **vports; |
4464 | int i; | 4486 | int i; |
4487 | struct lpfc_nodelist *ndlp; | ||
4465 | 4488 | ||
4466 | spin_lock_irq(&phba->hbalock); | 4489 | spin_lock_irq(&phba->hbalock); |
4467 | /* | 4490 | /* |
@@ -4489,6 +4512,10 @@ lpfc_unregister_unused_fcf(struct lpfc_hba *phba) | |||
4489 | if (vports && | 4512 | if (vports && |
4490 | (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)) | 4513 | (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)) |
4491 | for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) { | 4514 | for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) { |
4515 | /* Stop FLOGI/FDISC retries */ | ||
4516 | ndlp = lpfc_findnode_did(vports[i], Fabric_DID); | ||
4517 | if (ndlp) | ||
4518 | lpfc_cancel_retry_delay_tmo(vports[i], ndlp); | ||
4492 | lpfc_mbx_unreg_vpi(vports[i]); | 4519 | lpfc_mbx_unreg_vpi(vports[i]); |
4493 | spin_lock_irq(&phba->hbalock); | 4520 | spin_lock_irq(&phba->hbalock); |
4494 | vports[i]->fc_flag |= FC_VPORT_NEEDS_INIT_VPI; | 4521 | vports[i]->fc_flag |= FC_VPORT_NEEDS_INIT_VPI; |
@@ -4497,6 +4524,9 @@ lpfc_unregister_unused_fcf(struct lpfc_hba *phba) | |||
4497 | } | 4524 | } |
4498 | lpfc_destroy_vport_work_array(phba, vports); | 4525 | lpfc_destroy_vport_work_array(phba, vports); |
4499 | 4526 | ||
4527 | /* Cleanup any outstanding ELS commands */ | ||
4528 | lpfc_els_flush_all_cmd(phba); | ||
4529 | |||
4500 | /* Unregister VFI */ | 4530 | /* Unregister VFI */ |
4501 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 4531 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
4502 | if (!mbox) { | 4532 | if (!mbox) { |
@@ -4521,6 +4551,10 @@ lpfc_unregister_unused_fcf(struct lpfc_hba *phba) | |||
4521 | return; | 4551 | return; |
4522 | } | 4552 | } |
4523 | 4553 | ||
4554 | spin_lock_irq(&phba->hbalock); | ||
4555 | phba->pport->fc_flag &= ~FC_VFI_REGISTERED; | ||
4556 | spin_unlock_irq(&phba->hbalock); | ||
4557 | |||
4524 | /* Unregister FCF */ | 4558 | /* Unregister FCF */ |
4525 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 4559 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
4526 | if (!mbox) { | 4560 | if (!mbox) { |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index b8eb1b6e5e77..4d20c4148fae 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -2246,6 +2246,9 @@ lpfc_offline_prep(struct lpfc_hba * phba) | |||
2246 | if (vports[i]->load_flag & FC_UNLOADING) | 2246 | if (vports[i]->load_flag & FC_UNLOADING) |
2247 | continue; | 2247 | continue; |
2248 | vports[i]->vpi_state &= ~LPFC_VPI_REGISTERED; | 2248 | vports[i]->vpi_state &= ~LPFC_VPI_REGISTERED; |
2249 | vports[i]->fc_flag |= FC_VPORT_NEEDS_REG_VPI; | ||
2250 | vports[i]->fc_flag &= ~FC_VFI_REGISTERED; | ||
2251 | |||
2249 | shost = lpfc_shost_from_vport(vports[i]); | 2252 | shost = lpfc_shost_from_vport(vports[i]); |
2250 | list_for_each_entry_safe(ndlp, next_ndlp, | 2253 | list_for_each_entry_safe(ndlp, next_ndlp, |
2251 | &vports[i]->fc_nodes, | 2254 | &vports[i]->fc_nodes, |
@@ -3007,6 +3010,9 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, | |||
3007 | struct lpfc_nodelist *ndlp; | 3010 | struct lpfc_nodelist *ndlp; |
3008 | struct Scsi_Host *shost; | 3011 | struct Scsi_Host *shost; |
3009 | uint32_t link_state; | 3012 | uint32_t link_state; |
3013 | int active_vlink_present; | ||
3014 | struct lpfc_vport **vports; | ||
3015 | int i; | ||
3010 | 3016 | ||
3011 | phba->fc_eventTag = acqe_fcoe->event_tag; | 3017 | phba->fc_eventTag = acqe_fcoe->event_tag; |
3012 | phba->fcoe_eventtag = acqe_fcoe->event_tag; | 3018 | phba->fcoe_eventtag = acqe_fcoe->event_tag; |
@@ -3074,14 +3080,46 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, | |||
3074 | if (!ndlp) | 3080 | if (!ndlp) |
3075 | break; | 3081 | break; |
3076 | shost = lpfc_shost_from_vport(vport); | 3082 | shost = lpfc_shost_from_vport(vport); |
3083 | if (phba->pport->port_state <= LPFC_FLOGI) | ||
3084 | break; | ||
3085 | /* If virtual link is not yet instantiated ignore CVL */ | ||
3086 | if (vport->port_state <= LPFC_FDISC) | ||
3087 | break; | ||
3088 | |||
3077 | lpfc_linkdown_port(vport); | 3089 | lpfc_linkdown_port(vport); |
3078 | if (vport->port_type != LPFC_NPIV_PORT) { | 3090 | lpfc_cleanup_pending_mbox(vport); |
3091 | spin_lock_irq(shost->host_lock); | ||
3092 | vport->fc_flag |= FC_VPORT_CVL_RCVD; | ||
3093 | spin_unlock_irq(shost->host_lock); | ||
3094 | active_vlink_present = 0; | ||
3095 | |||
3096 | vports = lpfc_create_vport_work_array(phba); | ||
3097 | if (vports) { | ||
3098 | for (i = 0; i <= phba->max_vports && vports[i] != NULL; | ||
3099 | i++) { | ||
3100 | if ((!(vports[i]->fc_flag & | ||
3101 | FC_VPORT_CVL_RCVD)) && | ||
3102 | (vports[i]->port_state > LPFC_FDISC)) { | ||
3103 | active_vlink_present = 1; | ||
3104 | break; | ||
3105 | } | ||
3106 | } | ||
3107 | lpfc_destroy_vport_work_array(phba, vports); | ||
3108 | } | ||
3109 | |||
3110 | if (active_vlink_present) { | ||
3111 | /* | ||
3112 | * If there are other active VLinks present, | ||
3113 | * re-instantiate the Vlink using FDISC. | ||
3114 | */ | ||
3079 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ); | 3115 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ); |
3080 | spin_lock_irq(shost->host_lock); | 3116 | spin_lock_irq(shost->host_lock); |
3081 | ndlp->nlp_flag |= NLP_DELAY_TMO; | 3117 | ndlp->nlp_flag |= NLP_DELAY_TMO; |
3082 | spin_unlock_irq(shost->host_lock); | 3118 | spin_unlock_irq(shost->host_lock); |
3083 | ndlp->nlp_last_elscmd = ELS_CMD_FLOGI; | 3119 | ndlp->nlp_last_elscmd = ELS_CMD_FDISC; |
3084 | vport->port_state = LPFC_FLOGI; | 3120 | vport->port_state = LPFC_FDISC; |
3121 | } else { | ||
3122 | lpfc_retry_pport_discovery(phba); | ||
3085 | } | 3123 | } |
3086 | break; | 3124 | break; |
3087 | default: | 3125 | default: |
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 293234a5a944..d20ae6b3b3cf 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c | |||
@@ -254,7 +254,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
254 | int rc; | 254 | int rc; |
255 | 255 | ||
256 | memset(&stat, 0, sizeof (struct ls_rjt)); | 256 | memset(&stat, 0, sizeof (struct ls_rjt)); |
257 | if (vport->port_state <= LPFC_FLOGI) { | 257 | if (vport->port_state <= LPFC_FDISC) { |
258 | /* Before responding to PLOGI, check for pt2pt mode. | 258 | /* Before responding to PLOGI, check for pt2pt mode. |
259 | * If we are pt2pt, with an outstanding FLOGI, abort | 259 | * If we are pt2pt, with an outstanding FLOGI, abort |
260 | * the FLOGI and resend it first. | 260 | * the FLOGI and resend it first. |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index dc7c5c1231df..8d666d9fabb4 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -1710,6 +1710,7 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
1710 | struct lpfc_dmabuf *mp; | 1710 | struct lpfc_dmabuf *mp; |
1711 | uint16_t rpi, vpi; | 1711 | uint16_t rpi, vpi; |
1712 | int rc; | 1712 | int rc; |
1713 | struct lpfc_vport *vport = pmb->vport; | ||
1713 | 1714 | ||
1714 | mp = (struct lpfc_dmabuf *) (pmb->context1); | 1715 | mp = (struct lpfc_dmabuf *) (pmb->context1); |
1715 | 1716 | ||
@@ -1738,6 +1739,18 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
1738 | return; | 1739 | return; |
1739 | } | 1740 | } |
1740 | 1741 | ||
1742 | /* Unreg VPI, if the REG_VPI succeed after VLink failure */ | ||
1743 | if ((pmb->u.mb.mbxCommand == MBX_REG_VPI) && | ||
1744 | !(phba->pport->load_flag & FC_UNLOADING) && | ||
1745 | !pmb->u.mb.mbxStatus) { | ||
1746 | lpfc_unreg_vpi(phba, pmb->u.mb.un.varRegVpi.vpi, pmb); | ||
1747 | pmb->vport = vport; | ||
1748 | pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | ||
1749 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); | ||
1750 | if (rc != MBX_NOT_FINISHED) | ||
1751 | return; | ||
1752 | } | ||
1753 | |||
1741 | if (bf_get(lpfc_mqe_command, &pmb->u.mqe) == MBX_SLI4_CONFIG) | 1754 | if (bf_get(lpfc_mqe_command, &pmb->u.mqe) == MBX_SLI4_CONFIG) |
1742 | lpfc_sli4_mbox_cmd_free(phba, pmb); | 1755 | lpfc_sli4_mbox_cmd_free(phba, pmb); |
1743 | else | 1756 | else |
@@ -8440,8 +8453,10 @@ lpfc_sli4_iocb_param_transfer(struct lpfc_hba *phba, | |||
8440 | wcqe->total_data_placed; | 8453 | wcqe->total_data_placed; |
8441 | else | 8454 | else |
8442 | pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter; | 8455 | pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter; |
8443 | else | 8456 | else { |
8444 | pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter; | 8457 | pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter; |
8458 | pIocbIn->iocb.un.genreq64.bdl.bdeSize = wcqe->total_data_placed; | ||
8459 | } | ||
8445 | 8460 | ||
8446 | /* Pick up HBA exchange busy condition */ | 8461 | /* Pick up HBA exchange busy condition */ |
8447 | if (bf_get(lpfc_wcqe_c_xb, wcqe)) { | 8462 | if (bf_get(lpfc_wcqe_c_xb, wcqe)) { |
@@ -12139,3 +12154,48 @@ out: | |||
12139 | kfree(rgn23_data); | 12154 | kfree(rgn23_data); |
12140 | return; | 12155 | return; |
12141 | } | 12156 | } |
12157 | |||
12158 | /** | ||
12159 | * lpfc_cleanup_pending_mbox - Free up vport discovery mailbox commands. | ||
12160 | * @vport: pointer to vport data structure. | ||
12161 | * | ||
12162 | * This function iterate through the mailboxq and clean up all REG_LOGIN | ||
12163 | * and REG_VPI mailbox commands associated with the vport. This function | ||
12164 | * is called when driver want to restart discovery of the vport due to | ||
12165 | * a Clear Virtual Link event. | ||
12166 | **/ | ||
12167 | void | ||
12168 | lpfc_cleanup_pending_mbox(struct lpfc_vport *vport) | ||
12169 | { | ||
12170 | struct lpfc_hba *phba = vport->phba; | ||
12171 | LPFC_MBOXQ_t *mb, *nextmb; | ||
12172 | struct lpfc_dmabuf *mp; | ||
12173 | |||
12174 | spin_lock_irq(&phba->hbalock); | ||
12175 | list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) { | ||
12176 | if (mb->vport != vport) | ||
12177 | continue; | ||
12178 | |||
12179 | if ((mb->u.mb.mbxCommand != MBX_REG_LOGIN64) && | ||
12180 | (mb->u.mb.mbxCommand != MBX_REG_VPI)) | ||
12181 | continue; | ||
12182 | |||
12183 | if (mb->u.mb.mbxCommand == MBX_REG_LOGIN64) { | ||
12184 | mp = (struct lpfc_dmabuf *) (mb->context1); | ||
12185 | if (mp) { | ||
12186 | __lpfc_mbuf_free(phba, mp->virt, mp->phys); | ||
12187 | kfree(mp); | ||
12188 | } | ||
12189 | } | ||
12190 | list_del(&mb->list); | ||
12191 | mempool_free(mb, phba->mbox_mem_pool); | ||
12192 | } | ||
12193 | mb = phba->sli.mbox_active; | ||
12194 | if (mb && (mb->vport == vport)) { | ||
12195 | if ((mb->u.mb.mbxCommand == MBX_REG_LOGIN64) || | ||
12196 | (mb->u.mb.mbxCommand == MBX_REG_VPI)) | ||
12197 | mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | ||
12198 | } | ||
12199 | spin_unlock_irq(&phba->hbalock); | ||
12200 | } | ||
12201 | |||
diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index e3c7fa642306..281ff033a7b2 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c | |||
@@ -389,7 +389,7 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) | |||
389 | * by the port. | 389 | * by the port. |
390 | */ | 390 | */ |
391 | if ((phba->sli_rev == LPFC_SLI_REV4) && | 391 | if ((phba->sli_rev == LPFC_SLI_REV4) && |
392 | (pport->vpi_state & LPFC_VPI_REGISTERED)) { | 392 | (pport->fc_flag & FC_VFI_REGISTERED)) { |
393 | rc = lpfc_sli4_init_vpi(phba, vpi); | 393 | rc = lpfc_sli4_init_vpi(phba, vpi); |
394 | if (rc) { | 394 | if (rc) { |
395 | lpfc_printf_log(phba, KERN_ERR, LOG_VPORT, | 395 | lpfc_printf_log(phba, KERN_ERR, LOG_VPORT, |