aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_init.c
diff options
context:
space:
mode:
authorJames Smart <james.smart@emulex.com>2010-02-26 14:15:29 -0500
committerJames Bottomley <James.Bottomley@suse.de>2010-03-03 08:39:52 -0500
commitfc2b989be9190f3311a5ae41289828e24897a20e (patch)
tree86de4a9129f003697819af1e5aa5d83eae683b4b /drivers/scsi/lpfc/lpfc_init.c
parente2aed29f29d0d289df3b0b627b122832d4dc80fe (diff)
[SCSI] lpfc 8.3.10: Fix Discovery issues
- Prevent Vport discovery after reg_new_vport completes when physical logged in using FDISC. - Remove fast FCF failover fabric name matching. Allow failover to FCFs connected to different fabrics. - Added fast FCF failover in response to FCF DEAD event on current FCF record. 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.c140
1 files changed, 111 insertions, 29 deletions
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 88e02a453e0e..ff45e336917a 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -2199,8 +2199,10 @@ lpfc_stop_vport_timers(struct lpfc_vport *vport)
2199void 2199void
2200__lpfc_sli4_stop_fcf_redisc_wait_timer(struct lpfc_hba *phba) 2200__lpfc_sli4_stop_fcf_redisc_wait_timer(struct lpfc_hba *phba)
2201{ 2201{
2202 /* Clear pending FCF rediscovery wait timer */ 2202 /* Clear pending FCF rediscovery wait and failover in progress flags */
2203 phba->fcf.fcf_flag &= ~FCF_REDISC_PEND; 2203 phba->fcf.fcf_flag &= ~(FCF_REDISC_PEND |
2204 FCF_DEAD_FOVER |
2205 FCF_CVL_FOVER);
2204 /* Now, try to stop the timer */ 2206 /* Now, try to stop the timer */
2205 del_timer(&phba->fcf.redisc_wait); 2207 del_timer(&phba->fcf.redisc_wait);
2206} 2208}
@@ -3212,6 +3214,68 @@ out_free_pmb:
3212} 3214}
3213 3215
3214/** 3216/**
3217 * lpfc_sli4_perform_vport_cvl - Perform clear virtual link on a vport
3218 * @vport: pointer to vport data structure.
3219 *
3220 * This routine is to perform Clear Virtual Link (CVL) on a vport in
3221 * response to a CVL event.
3222 *
3223 * Return the pointer to the ndlp with the vport if successful, otherwise
3224 * return NULL.
3225 **/
3226static struct lpfc_nodelist *
3227lpfc_sli4_perform_vport_cvl(struct lpfc_vport *vport)
3228{
3229 struct lpfc_nodelist *ndlp;
3230 struct Scsi_Host *shost;
3231 struct lpfc_hba *phba;
3232
3233 if (!vport)
3234 return NULL;
3235 ndlp = lpfc_findnode_did(vport, Fabric_DID);
3236 if (!ndlp)
3237 return NULL;
3238 phba = vport->phba;
3239 if (!phba)
3240 return NULL;
3241 if (phba->pport->port_state <= LPFC_FLOGI)
3242 return NULL;
3243 /* If virtual link is not yet instantiated ignore CVL */
3244 if (vport->port_state <= LPFC_FDISC)
3245 return NULL;
3246 shost = lpfc_shost_from_vport(vport);
3247 if (!shost)
3248 return NULL;
3249 lpfc_linkdown_port(vport);
3250 lpfc_cleanup_pending_mbox(vport);
3251 spin_lock_irq(shost->host_lock);
3252 vport->fc_flag |= FC_VPORT_CVL_RCVD;
3253 spin_unlock_irq(shost->host_lock);
3254
3255 return ndlp;
3256}
3257
3258/**
3259 * lpfc_sli4_perform_all_vport_cvl - Perform clear virtual link on all vports
3260 * @vport: pointer to lpfc hba data structure.
3261 *
3262 * This routine is to perform Clear Virtual Link (CVL) on all vports in
3263 * response to a FCF dead event.
3264 **/
3265static void
3266lpfc_sli4_perform_all_vport_cvl(struct lpfc_hba *phba)
3267{
3268 struct lpfc_vport **vports;
3269 int i;
3270
3271 vports = lpfc_create_vport_work_array(phba);
3272 if (vports)
3273 for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++)
3274 lpfc_sli4_perform_vport_cvl(vports[i]);
3275 lpfc_destroy_vport_work_array(phba, vports);
3276}
3277
3278/**
3215 * lpfc_sli4_async_fcoe_evt - Process the asynchronous fcoe event 3279 * lpfc_sli4_async_fcoe_evt - Process the asynchronous fcoe event
3216 * @phba: pointer to lpfc hba data structure. 3280 * @phba: pointer to lpfc hba data structure.
3217 * @acqe_link: pointer to the async fcoe completion queue entry. 3281 * @acqe_link: pointer to the async fcoe completion queue entry.
@@ -3227,7 +3291,6 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
3227 struct lpfc_vport *vport; 3291 struct lpfc_vport *vport;
3228 struct lpfc_nodelist *ndlp; 3292 struct lpfc_nodelist *ndlp;
3229 struct Scsi_Host *shost; 3293 struct Scsi_Host *shost;
3230 uint32_t link_state;
3231 int active_vlink_present; 3294 int active_vlink_present;
3232 struct lpfc_vport **vports; 3295 struct lpfc_vport **vports;
3233 int i; 3296 int i;
@@ -3284,16 +3347,35 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
3284 /* If the event is not for currently used fcf do nothing */ 3347 /* If the event is not for currently used fcf do nothing */
3285 if (phba->fcf.current_rec.fcf_indx != acqe_fcoe->index) 3348 if (phba->fcf.current_rec.fcf_indx != acqe_fcoe->index)
3286 break; 3349 break;
3287 /* 3350 /* We request port to rediscover the entire FCF table for
3288 * Currently, driver support only one FCF - so treat this as 3351 * a fast recovery from case that the current FCF record
3289 * a link down, but save the link state because we don't want 3352 * is no longer valid if the last CVL event hasn't already
3290 * it to be changed to Link Down unless it is already down. 3353 * triggered process.
3291 */ 3354 */
3292 link_state = phba->link_state; 3355 spin_lock_irq(&phba->hbalock);
3293 lpfc_linkdown(phba); 3356 if (phba->fcf.fcf_flag & FCF_CVL_FOVER) {
3294 phba->link_state = link_state; 3357 spin_unlock_irq(&phba->hbalock);
3295 /* Unregister FCF if no devices connected to it */ 3358 break;
3296 lpfc_unregister_unused_fcf(phba); 3359 }
3360 /* Mark the fast failover process in progress */
3361 phba->fcf.fcf_flag |= FCF_DEAD_FOVER;
3362 spin_unlock_irq(&phba->hbalock);
3363 rc = lpfc_sli4_redisc_fcf_table(phba);
3364 if (rc) {
3365 spin_lock_irq(&phba->hbalock);
3366 phba->fcf.fcf_flag &= ~FCF_DEAD_FOVER;
3367 spin_unlock_irq(&phba->hbalock);
3368 /*
3369 * Last resort will fail over by treating this
3370 * as a link down to FCF registration.
3371 */
3372 lpfc_sli4_fcf_dead_failthrough(phba);
3373 } else
3374 /* Handling fast FCF failover to a DEAD FCF event
3375 * is considered equalivant to receiving CVL to all
3376 * vports.
3377 */
3378 lpfc_sli4_perform_all_vport_cvl(phba);
3297 break; 3379 break;
3298 case LPFC_FCOE_EVENT_TYPE_CVL: 3380 case LPFC_FCOE_EVENT_TYPE_CVL:
3299 lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, 3381 lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
@@ -3301,23 +3383,9 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
3301 " tag 0x%x\n", acqe_fcoe->index, acqe_fcoe->event_tag); 3383 " tag 0x%x\n", acqe_fcoe->index, acqe_fcoe->event_tag);
3302 vport = lpfc_find_vport_by_vpid(phba, 3384 vport = lpfc_find_vport_by_vpid(phba,
3303 acqe_fcoe->index - phba->vpi_base); 3385 acqe_fcoe->index - phba->vpi_base);
3304 if (!vport) 3386 ndlp = lpfc_sli4_perform_vport_cvl(vport);
3305 break;
3306 ndlp = lpfc_findnode_did(vport, Fabric_DID);
3307 if (!ndlp) 3387 if (!ndlp)
3308 break; 3388 break;
3309 shost = lpfc_shost_from_vport(vport);
3310 if (phba->pport->port_state <= LPFC_FLOGI)
3311 break;
3312 /* If virtual link is not yet instantiated ignore CVL */
3313 if (vport->port_state <= LPFC_FDISC)
3314 break;
3315
3316 lpfc_linkdown_port(vport);
3317 lpfc_cleanup_pending_mbox(vport);
3318 spin_lock_irq(shost->host_lock);
3319 vport->fc_flag |= FC_VPORT_CVL_RCVD;
3320 spin_unlock_irq(shost->host_lock);
3321 active_vlink_present = 0; 3389 active_vlink_present = 0;
3322 3390
3323 vports = lpfc_create_vport_work_array(phba); 3391 vports = lpfc_create_vport_work_array(phba);
@@ -3340,6 +3408,7 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
3340 * re-instantiate the Vlink using FDISC. 3408 * re-instantiate the Vlink using FDISC.
3341 */ 3409 */
3342 mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ); 3410 mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
3411 shost = lpfc_shost_from_vport(vport);
3343 spin_lock_irq(shost->host_lock); 3412 spin_lock_irq(shost->host_lock);
3344 ndlp->nlp_flag |= NLP_DELAY_TMO; 3413 ndlp->nlp_flag |= NLP_DELAY_TMO;
3345 spin_unlock_irq(shost->host_lock); 3414 spin_unlock_irq(shost->host_lock);
@@ -3350,15 +3419,28 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
3350 * Otherwise, we request port to rediscover 3419 * Otherwise, we request port to rediscover
3351 * the entire FCF table for a fast recovery 3420 * the entire FCF table for a fast recovery
3352 * from possible case that the current FCF 3421 * from possible case that the current FCF
3353 * is no longer valid. 3422 * is no longer valid if the FCF_DEAD event
3423 * hasn't already triggered process.
3354 */ 3424 */
3425 spin_lock_irq(&phba->hbalock);
3426 if (phba->fcf.fcf_flag & FCF_DEAD_FOVER) {
3427 spin_unlock_irq(&phba->hbalock);
3428 break;
3429 }
3430 /* Mark the fast failover process in progress */
3431 phba->fcf.fcf_flag |= FCF_CVL_FOVER;
3432 spin_unlock_irq(&phba->hbalock);
3355 rc = lpfc_sli4_redisc_fcf_table(phba); 3433 rc = lpfc_sli4_redisc_fcf_table(phba);
3356 if (rc) 3434 if (rc) {
3435 spin_lock_irq(&phba->hbalock);
3436 phba->fcf.fcf_flag &= ~FCF_CVL_FOVER;
3437 spin_unlock_irq(&phba->hbalock);
3357 /* 3438 /*
3358 * Last resort will be re-try on the 3439 * Last resort will be re-try on the
3359 * the current registered FCF entry. 3440 * the current registered FCF entry.
3360 */ 3441 */
3361 lpfc_retry_pport_discovery(phba); 3442 lpfc_retry_pport_discovery(phba);
3443 }
3362 } 3444 }
3363 break; 3445 break;
3364 default: 3446 default: