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/lpfc/lpfc_init.c | |
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/lpfc/lpfc_init.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 44 |
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) | |||
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: |