diff options
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 1 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 7 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 27 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 140 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 54 | ||||
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_sli4.h | 8 |
6 files changed, 186 insertions, 51 deletions
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index e7f548281b94..39739a707ed4 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
| @@ -221,6 +221,7 @@ void lpfc_unregister_fcf_rescan(struct lpfc_hba *); | |||
| 221 | void lpfc_unregister_unused_fcf(struct lpfc_hba *); | 221 | void lpfc_unregister_unused_fcf(struct lpfc_hba *); |
| 222 | int lpfc_sli4_redisc_fcf_table(struct lpfc_hba *); | 222 | int lpfc_sli4_redisc_fcf_table(struct lpfc_hba *); |
| 223 | void lpfc_fcf_redisc_wait_start_timer(struct lpfc_hba *); | 223 | void lpfc_fcf_redisc_wait_start_timer(struct lpfc_hba *); |
| 224 | void lpfc_sli4_fcf_dead_failthrough(struct lpfc_hba *); | ||
| 224 | 225 | ||
| 225 | int lpfc_mem_alloc(struct lpfc_hba *, int align); | 226 | int lpfc_mem_alloc(struct lpfc_hba *, int align); |
| 226 | void lpfc_mem_free(struct lpfc_hba *); | 227 | void lpfc_mem_free(struct lpfc_hba *); |
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 6a2135a0d03a..a81d43306d17 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
| @@ -6004,7 +6004,12 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
| 6004 | if (phba->sli_rev < LPFC_SLI_REV4) | 6004 | if (phba->sli_rev < LPFC_SLI_REV4) |
| 6005 | lpfc_issue_fabric_reglogin(vport); | 6005 | lpfc_issue_fabric_reglogin(vport); |
| 6006 | else { | 6006 | else { |
| 6007 | lpfc_start_fdiscs(phba); | 6007 | /* |
| 6008 | * If the physical port is instantiated using | ||
| 6009 | * FDISC, do not start vport discovery. | ||
| 6010 | */ | ||
| 6011 | if (vport->port_state != LPFC_FDISC) | ||
| 6012 | lpfc_start_fdiscs(phba); | ||
| 6008 | lpfc_do_scr_ns_plogi(phba, vport); | 6013 | lpfc_do_scr_ns_plogi(phba, vport); |
| 6009 | } | 6014 | } |
| 6010 | } else | 6015 | } else |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index e58d8aeec09e..f28ce40dc349 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
| @@ -1504,7 +1504,9 @@ lpfc_check_pending_fcoe_event(struct lpfc_hba *phba, uint8_t unreg_fcf) | |||
| 1504 | */ | 1504 | */ |
| 1505 | spin_lock_irq(&phba->hbalock); | 1505 | spin_lock_irq(&phba->hbalock); |
| 1506 | phba->hba_flag &= ~FCF_DISC_INPROGRESS; | 1506 | phba->hba_flag &= ~FCF_DISC_INPROGRESS; |
| 1507 | phba->fcf.fcf_flag &= ~FCF_REDISC_FOV; | 1507 | phba->fcf.fcf_flag &= ~(FCF_REDISC_FOV | |
| 1508 | FCF_DEAD_FOVER | | ||
| 1509 | FCF_CVL_FOVER); | ||
| 1508 | spin_unlock_irq(&phba->hbalock); | 1510 | spin_unlock_irq(&phba->hbalock); |
| 1509 | } | 1511 | } |
| 1510 | 1512 | ||
| @@ -1649,7 +1651,9 @@ lpfc_mbx_cmpl_read_fcf_record(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
| 1649 | __lpfc_sli4_stop_fcf_redisc_wait_timer(phba); | 1651 | __lpfc_sli4_stop_fcf_redisc_wait_timer(phba); |
| 1650 | else if (phba->fcf.fcf_flag & FCF_REDISC_FOV) | 1652 | else if (phba->fcf.fcf_flag & FCF_REDISC_FOV) |
| 1651 | /* If in fast failover, mark it's completed */ | 1653 | /* If in fast failover, mark it's completed */ |
| 1652 | phba->fcf.fcf_flag &= ~FCF_REDISC_FOV; | 1654 | phba->fcf.fcf_flag &= ~(FCF_REDISC_FOV | |
| 1655 | FCF_DEAD_FOVER | | ||
| 1656 | FCF_CVL_FOVER); | ||
| 1653 | spin_unlock_irqrestore(&phba->hbalock, iflags); | 1657 | spin_unlock_irqrestore(&phba->hbalock, iflags); |
| 1654 | goto out; | 1658 | goto out; |
| 1655 | } | 1659 | } |
| @@ -1669,14 +1673,9 @@ lpfc_mbx_cmpl_read_fcf_record(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
| 1669 | * Update on failover FCF record only if it's in FCF fast-failover | 1673 | * Update on failover FCF record only if it's in FCF fast-failover |
| 1670 | * period; otherwise, update on current FCF record. | 1674 | * period; otherwise, update on current FCF record. |
| 1671 | */ | 1675 | */ |
| 1672 | if (phba->fcf.fcf_flag & FCF_REDISC_FOV) { | 1676 | if (phba->fcf.fcf_flag & FCF_REDISC_FOV) |
| 1673 | /* Fast FCF failover only to the same fabric name */ | 1677 | fcf_rec = &phba->fcf.failover_rec; |
| 1674 | if (lpfc_fab_name_match(phba->fcf.current_rec.fabric_name, | 1678 | else |
| 1675 | new_fcf_record)) | ||
| 1676 | fcf_rec = &phba->fcf.failover_rec; | ||
| 1677 | else | ||
| 1678 | goto read_next_fcf; | ||
| 1679 | } else | ||
| 1680 | fcf_rec = &phba->fcf.current_rec; | 1679 | fcf_rec = &phba->fcf.current_rec; |
| 1681 | 1680 | ||
| 1682 | if (phba->fcf.fcf_flag & FCF_AVAILABLE) { | 1681 | if (phba->fcf.fcf_flag & FCF_AVAILABLE) { |
| @@ -1705,8 +1704,7 @@ lpfc_mbx_cmpl_read_fcf_record(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
| 1705 | * If the new hba FCF record has lower priority value | 1704 | * If the new hba FCF record has lower priority value |
| 1706 | * than the driver FCF record, use the new record. | 1705 | * than the driver FCF record, use the new record. |
| 1707 | */ | 1706 | */ |
| 1708 | if (lpfc_fab_name_match(fcf_rec->fabric_name, new_fcf_record) && | 1707 | if (new_fcf_record->fip_priority < fcf_rec->priority) { |
| 1709 | (new_fcf_record->fip_priority < fcf_rec->priority)) { | ||
| 1710 | /* Choose this FCF record */ | 1708 | /* Choose this FCF record */ |
| 1711 | __lpfc_update_fcf_record(phba, fcf_rec, new_fcf_record, | 1709 | __lpfc_update_fcf_record(phba, fcf_rec, new_fcf_record, |
| 1712 | addr_mode, vlan_id, 0); | 1710 | addr_mode, vlan_id, 0); |
| @@ -1762,7 +1760,9 @@ read_next_fcf: | |||
| 1762 | sizeof(struct lpfc_fcf_rec)); | 1760 | sizeof(struct lpfc_fcf_rec)); |
| 1763 | /* mark the FCF fast failover completed */ | 1761 | /* mark the FCF fast failover completed */ |
| 1764 | spin_lock_irqsave(&phba->hbalock, iflags); | 1762 | spin_lock_irqsave(&phba->hbalock, iflags); |
| 1765 | phba->fcf.fcf_flag &= ~FCF_REDISC_FOV; | 1763 | phba->fcf.fcf_flag &= ~(FCF_REDISC_FOV | |
| 1764 | FCF_DEAD_FOVER | | ||
| 1765 | FCF_CVL_FOVER); | ||
| 1766 | spin_unlock_irqrestore(&phba->hbalock, iflags); | 1766 | spin_unlock_irqrestore(&phba->hbalock, iflags); |
| 1767 | /* Register to the new FCF record */ | 1767 | /* Register to the new FCF record */ |
| 1768 | lpfc_register_fcf(phba); | 1768 | lpfc_register_fcf(phba); |
| @@ -4760,6 +4760,7 @@ lpfc_unregister_fcf_rescan(struct lpfc_hba *phba) | |||
| 4760 | return; | 4760 | return; |
| 4761 | /* Reset HBA FCF states after successful unregister FCF */ | 4761 | /* Reset HBA FCF states after successful unregister FCF */ |
| 4762 | phba->fcf.fcf_flag = 0; | 4762 | phba->fcf.fcf_flag = 0; |
| 4763 | phba->fcf.current_rec.flag = 0; | ||
| 4763 | 4764 | ||
| 4764 | /* | 4765 | /* |
| 4765 | * If driver is not unloading, check if there is any other | 4766 | * If driver is not unloading, check if there is any other |
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) | |||
| 2199 | void | 2199 | void |
| 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 | **/ | ||
| 3226 | static struct lpfc_nodelist * | ||
| 3227 | lpfc_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 | **/ | ||
| 3265 | static void | ||
| 3266 | lpfc_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: |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 9feeaff47a52..bb6a4426d469 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
| @@ -4519,6 +4519,10 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) | |||
| 4519 | /* Post receive buffers to the device */ | 4519 | /* Post receive buffers to the device */ |
| 4520 | lpfc_sli4_rb_setup(phba); | 4520 | lpfc_sli4_rb_setup(phba); |
| 4521 | 4521 | ||
| 4522 | /* Reset HBA FCF states after HBA reset */ | ||
| 4523 | phba->fcf.fcf_flag = 0; | ||
| 4524 | phba->fcf.current_rec.flag = 0; | ||
| 4525 | |||
| 4522 | /* Start the ELS watchdog timer */ | 4526 | /* Start the ELS watchdog timer */ |
| 4523 | mod_timer(&vport->els_tmofunc, | 4527 | mod_timer(&vport->els_tmofunc, |
| 4524 | jiffies + HZ * (phba->fc_ratov * 2)); | 4528 | jiffies + HZ * (phba->fc_ratov * 2)); |
| @@ -12069,11 +12073,26 @@ lpfc_mbx_cmpl_redisc_fcf_table(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox) | |||
| 12069 | "2746 Requesting for FCF rediscovery failed " | 12073 | "2746 Requesting for FCF rediscovery failed " |
| 12070 | "status x%x add_status x%x\n", | 12074 | "status x%x add_status x%x\n", |
| 12071 | shdr_status, shdr_add_status); | 12075 | shdr_status, shdr_add_status); |
| 12072 | /* | 12076 | if (phba->fcf.fcf_flag & FCF_CVL_FOVER) { |
| 12073 | * Request failed, last resort to re-try current | 12077 | spin_lock_irq(&phba->hbalock); |
| 12074 | * registered FCF entry | 12078 | phba->fcf.fcf_flag &= ~FCF_CVL_FOVER; |
| 12075 | */ | 12079 | spin_unlock_irq(&phba->hbalock); |
| 12076 | lpfc_retry_pport_discovery(phba); | 12080 | /* |
| 12081 | * CVL event triggered FCF rediscover request failed, | ||
| 12082 | * last resort to re-try current registered FCF entry. | ||
| 12083 | */ | ||
| 12084 | lpfc_retry_pport_discovery(phba); | ||
| 12085 | } else { | ||
| 12086 | spin_lock_irq(&phba->hbalock); | ||
| 12087 | phba->fcf.fcf_flag &= ~FCF_DEAD_FOVER; | ||
| 12088 | spin_unlock_irq(&phba->hbalock); | ||
| 12089 | /* | ||
| 12090 | * DEAD FCF event triggered FCF rediscover request | ||
| 12091 | * failed, last resort to fail over as a link down | ||
| 12092 | * to FCF registration. | ||
| 12093 | */ | ||
| 12094 | lpfc_sli4_fcf_dead_failthrough(phba); | ||
| 12095 | } | ||
| 12077 | } else | 12096 | } else |
| 12078 | /* | 12097 | /* |
| 12079 | * Start FCF rediscovery wait timer for pending FCF | 12098 | * Start FCF rediscovery wait timer for pending FCF |
| @@ -12129,6 +12148,31 @@ lpfc_sli4_redisc_fcf_table(struct lpfc_hba *phba) | |||
| 12129 | } | 12148 | } |
| 12130 | 12149 | ||
| 12131 | /** | 12150 | /** |
| 12151 | * lpfc_sli4_fcf_dead_failthrough - Failthrough routine to fcf dead event | ||
| 12152 | * @phba: pointer to lpfc hba data structure. | ||
| 12153 | * | ||
| 12154 | * This function is the failover routine as a last resort to the FCF DEAD | ||
| 12155 | * event when driver failed to perform fast FCF failover. | ||
| 12156 | **/ | ||
| 12157 | void | ||
| 12158 | lpfc_sli4_fcf_dead_failthrough(struct lpfc_hba *phba) | ||
| 12159 | { | ||
| 12160 | uint32_t link_state; | ||
| 12161 | |||
| 12162 | /* | ||
| 12163 | * Last resort as FCF DEAD event failover will treat this as | ||
| 12164 | * a link down, but save the link state because we don't want | ||
| 12165 | * it to be changed to Link Down unless it is already down. | ||
| 12166 | */ | ||
| 12167 | link_state = phba->link_state; | ||
| 12168 | lpfc_linkdown(phba); | ||
| 12169 | phba->link_state = link_state; | ||
| 12170 | |||
| 12171 | /* Unregister FCF if no devices connected to it */ | ||
| 12172 | lpfc_unregister_unused_fcf(phba); | ||
| 12173 | } | ||
| 12174 | |||
| 12175 | /** | ||
| 12132 | * lpfc_sli_read_link_ste - Read region 23 to decide if link is disabled. | 12176 | * lpfc_sli_read_link_ste - Read region 23 to decide if link is disabled. |
| 12133 | * @phba: pointer to lpfc hba data structure. | 12177 | * @phba: pointer to lpfc hba data structure. |
| 12134 | * | 12178 | * |
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 04fd7829cf39..2169cd24d90c 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h | |||
| @@ -153,9 +153,11 @@ struct lpfc_fcf { | |||
| 153 | #define FCF_REGISTERED 0x02 /* FCF registered with FW */ | 153 | #define FCF_REGISTERED 0x02 /* FCF registered with FW */ |
| 154 | #define FCF_SCAN_DONE 0x04 /* FCF table scan done */ | 154 | #define FCF_SCAN_DONE 0x04 /* FCF table scan done */ |
| 155 | #define FCF_IN_USE 0x08 /* Atleast one discovery completed */ | 155 | #define FCF_IN_USE 0x08 /* Atleast one discovery completed */ |
| 156 | #define FCF_REDISC_PEND 0x10 /* FCF rediscovery pending */ | 156 | #define FCF_DEAD_FOVER 0x10 /* FCF DEAD triggered fast FCF failover */ |
| 157 | #define FCF_REDISC_EVT 0x20 /* FCF rediscovery event to worker thread */ | 157 | #define FCF_CVL_FOVER 0x20 /* CVL triggered fast FCF failover */ |
| 158 | #define FCF_REDISC_FOV 0x40 /* Post FCF rediscovery fast failover */ | 158 | #define FCF_REDISC_PEND 0x40 /* FCF rediscovery pending */ |
| 159 | #define FCF_REDISC_EVT 0x80 /* FCF rediscovery event to worker thread */ | ||
| 160 | #define FCF_REDISC_FOV 0x100 /* Post FCF rediscovery fast failover */ | ||
| 159 | uint32_t addr_mode; | 161 | uint32_t addr_mode; |
| 160 | struct lpfc_fcf_rec current_rec; | 162 | struct lpfc_fcf_rec current_rec; |
| 161 | struct lpfc_fcf_rec failover_rec; | 163 | struct lpfc_fcf_rec failover_rec; |
