summaryrefslogtreecommitdiff
path: root/drivers/scsi/lpfc/lpfc_init.c
diff options
context:
space:
mode:
authorJames Smart <james.smart@emulex.com>2010-01-26 23:08:03 -0500
committerJames Bottomley <James.Bottomley@suse.de>2010-02-08 18:38:28 -0600
commit695a814e18561c52456acf5051fac0ea4b8111da (patch)
tree3cbe747f38bbd5dae092e643de42be1a735d9552 /drivers/scsi/lpfc/lpfc_init.c
parent341af10239c4c87192bf762f53c7bcb1f3a1e767 (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/lpfc/lpfc_init.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c44
1 files changed, 41 insertions, 3 deletions
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)
if (vports[i]->load_flag & FC_UNLOADING)
continue;
vports[i]->vpi_state &= ~LPFC_VPI_REGISTERED;
+ vports[i]->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
+ vports[i]->fc_flag &= ~FC_VFI_REGISTERED;
+
shost = lpfc_shost_from_vport(vports[i]);
list_for_each_entry_safe(ndlp, next_ndlp,
&vports[i]->fc_nodes,
@@ -3007,6 +3010,9 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
struct lpfc_nodelist *ndlp;
struct Scsi_Host *shost;
uint32_t link_state;
+ int active_vlink_present;
+ struct lpfc_vport **vports;
+ int i;
phba->fc_eventTag = acqe_fcoe->event_tag;
phba->fcoe_eventtag = acqe_fcoe->event_tag;
@@ -3074,14 +3080,46 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
if (!ndlp)
break;
shost = lpfc_shost_from_vport(vport);
+ if (phba->pport->port_state <= LPFC_FLOGI)
+ break;
+ /* If virtual link is not yet instantiated ignore CVL */
+ if (vport->port_state <= LPFC_FDISC)
+ break;
+
lpfc_linkdown_port(vport);
- if (vport->port_type != LPFC_NPIV_PORT) {
+ lpfc_cleanup_pending_mbox(vport);
+ spin_lock_irq(shost->host_lock);
+ vport->fc_flag |= FC_VPORT_CVL_RCVD;
+ spin_unlock_irq(shost->host_lock);
+ active_vlink_present = 0;
+
+ vports = lpfc_create_vport_work_array(phba);
+ if (vports) {
+ for (i = 0; i <= phba->max_vports && vports[i] != NULL;
+ i++) {
+ if ((!(vports[i]->fc_flag &
+ FC_VPORT_CVL_RCVD)) &&
+ (vports[i]->port_state > LPFC_FDISC)) {
+ active_vlink_present = 1;
+ break;
+ }
+ }
+ lpfc_destroy_vport_work_array(phba, vports);
+ }
+
+ if (active_vlink_present) {
+ /*
+ * If there are other active VLinks present,
+ * re-instantiate the Vlink using FDISC.
+ */
mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_DELAY_TMO;
spin_unlock_irq(shost->host_lock);
- ndlp->nlp_last_elscmd = ELS_CMD_FLOGI;
- vport->port_state = LPFC_FLOGI;
+ ndlp->nlp_last_elscmd = ELS_CMD_FDISC;
+ vport->port_state = LPFC_FDISC;
+ } else {
+ lpfc_retry_pport_discovery(phba);
}
break;
default: