diff options
author | James Smart <james.smart@emulex.com> | 2010-02-26 14:15:29 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-03-03 08:39:52 -0500 |
commit | fc2b989be9190f3311a5ae41289828e24897a20e (patch) | |
tree | 86de4a9129f003697819af1e5aa5d83eae683b4b /drivers/scsi | |
parent | e2aed29f29d0d289df3b0b627b122832d4dc80fe (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')
-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; |