diff options
author | James Smart <James.Smart@Emulex.Com> | 2008-04-07 10:15:56 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-04-10 08:52:11 -0400 |
commit | 58da1ffb2b1234e9c6c75013a649c659cc38ebd4 (patch) | |
tree | f159b38ff5c830e10eb90918ef5b42ae71645daa /drivers/scsi/lpfc/lpfc_hbadisc.c | |
parent | b35c07d00751c3d554dd6e582b661ac2e8ffc162 (diff) |
[SCSI] lpfc 8.2.6 : Multiple discovery fixes
Multiple Discovery Fixes:
- Fix race on discovery due to link events coinciding with vport_delete.
- Use NLP_FABRIC state to filter out switch-based pseudo initiators that
reuse the same WWNs.
- Correct erroneous setting of DID=0 in lpfc_matchdid()
- Correct extra reference count that was in the lookup path for the
remoteid from an unsolicited ELS.
- Correct double-free bug in els abort path.
- Correct FDMI server discovery logic for switch that return a WWN of 0.
- Fix bugs in ndlp mgmt when a node changes address
- Correct bug that did not delete RSCNs for vports upon link transitions
- Fix "0216 Link event during NS query" error which pops up when vports
are swapped to different switch ports.
- Add sanity checks on ndlp structures
- Fix devloss log message to dump WWN correctly
- Hold off mgmt commands that were interferring with discovery mailbox cmds
- Remove unnecessary FC_ESTABLISH_LINK logic.
- Correct some race conditions in the worker thread, resulting in devloss:
- Clear the work_port_events field before handling the work port events
- Clear the deferred ring event before handling a deferred ring event
- Hold the hba lock when waking up the work thread
- Send an acc for the rscn even when we aren't going to handle it
- Fix locking behavior that was not properly protecting the ACTIVE flag,
thus allowing mailbox command order to shift.
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_hbadisc.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 41 |
1 files changed, 21 insertions, 20 deletions
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 976653440fba..7c8c3e6f399d 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -69,7 +69,7 @@ lpfc_terminate_rport_io(struct fc_rport *rport) | |||
69 | rdata = rport->dd_data; | 69 | rdata = rport->dd_data; |
70 | ndlp = rdata->pnode; | 70 | ndlp = rdata->pnode; |
71 | 71 | ||
72 | if (!ndlp) { | 72 | if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { |
73 | if (rport->roles & FC_RPORT_ROLE_FCP_TARGET) | 73 | if (rport->roles & FC_RPORT_ROLE_FCP_TARGET) |
74 | printk(KERN_ERR "Cannot find remote node" | 74 | printk(KERN_ERR "Cannot find remote node" |
75 | " to terminate I/O Data x%x\n", | 75 | " to terminate I/O Data x%x\n", |
@@ -114,7 +114,7 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
114 | 114 | ||
115 | rdata = rport->dd_data; | 115 | rdata = rport->dd_data; |
116 | ndlp = rdata->pnode; | 116 | ndlp = rdata->pnode; |
117 | if (!ndlp) | 117 | if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) |
118 | return; | 118 | return; |
119 | 119 | ||
120 | vport = ndlp->vport; | 120 | vport = ndlp->vport; |
@@ -243,8 +243,8 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) | |||
243 | if (warn_on) { | 243 | if (warn_on) { |
244 | lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, | 244 | lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, |
245 | "0203 Devloss timeout on " | 245 | "0203 Devloss timeout on " |
246 | "WWPN %x:%x:%x:%x:%x:%x:%x:%x " | 246 | "WWPN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x " |
247 | "NPort x%x Data: x%x x%x x%x\n", | 247 | "NPort x%06x Data: x%x x%x x%x\n", |
248 | *name, *(name+1), *(name+2), *(name+3), | 248 | *name, *(name+1), *(name+2), *(name+3), |
249 | *(name+4), *(name+5), *(name+6), *(name+7), | 249 | *(name+4), *(name+5), *(name+6), *(name+7), |
250 | ndlp->nlp_DID, ndlp->nlp_flag, | 250 | ndlp->nlp_DID, ndlp->nlp_flag, |
@@ -252,8 +252,8 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) | |||
252 | } else { | 252 | } else { |
253 | lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, | 253 | lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, |
254 | "0204 Devloss timeout on " | 254 | "0204 Devloss timeout on " |
255 | "WWPN %x:%x:%x:%x:%x:%x:%x:%x " | 255 | "WWPN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x " |
256 | "NPort x%x Data: x%x x%x x%x\n", | 256 | "NPort x%06x Data: x%x x%x x%x\n", |
257 | *name, *(name+1), *(name+2), *(name+3), | 257 | *name, *(name+1), *(name+2), *(name+3), |
258 | *(name+4), *(name+5), *(name+6), *(name+7), | 258 | *(name+4), *(name+5), *(name+6), *(name+7), |
259 | ndlp->nlp_DID, ndlp->nlp_flag, | 259 | ndlp->nlp_DID, ndlp->nlp_flag, |
@@ -399,7 +399,10 @@ lpfc_work_done(struct lpfc_hba *phba) | |||
399 | vport = vports[i]; | 399 | vport = vports[i]; |
400 | if (vport == NULL) | 400 | if (vport == NULL) |
401 | break; | 401 | break; |
402 | spin_lock_irq(&vport->work_port_lock); | ||
402 | work_port_events = vport->work_port_events; | 403 | work_port_events = vport->work_port_events; |
404 | vport->work_port_events &= ~work_port_events; | ||
405 | spin_unlock_irq(&vport->work_port_lock); | ||
403 | if (work_port_events & WORKER_DISC_TMO) | 406 | if (work_port_events & WORKER_DISC_TMO) |
404 | lpfc_disc_timeout_handler(vport); | 407 | lpfc_disc_timeout_handler(vport); |
405 | if (work_port_events & WORKER_ELS_TMO) | 408 | if (work_port_events & WORKER_ELS_TMO) |
@@ -416,9 +419,6 @@ lpfc_work_done(struct lpfc_hba *phba) | |||
416 | lpfc_ramp_down_queue_handler(phba); | 419 | lpfc_ramp_down_queue_handler(phba); |
417 | if (work_port_events & WORKER_RAMP_UP_QUEUE) | 420 | if (work_port_events & WORKER_RAMP_UP_QUEUE) |
418 | lpfc_ramp_up_queue_handler(phba); | 421 | lpfc_ramp_up_queue_handler(phba); |
419 | spin_lock_irq(&vport->work_port_lock); | ||
420 | vport->work_port_events &= ~work_port_events; | ||
421 | spin_unlock_irq(&vport->work_port_lock); | ||
422 | } | 422 | } |
423 | lpfc_destroy_vport_work_array(phba, vports); | 423 | lpfc_destroy_vport_work_array(phba, vports); |
424 | 424 | ||
@@ -430,10 +430,10 @@ lpfc_work_done(struct lpfc_hba *phba) | |||
430 | if (pring->flag & LPFC_STOP_IOCB_EVENT) { | 430 | if (pring->flag & LPFC_STOP_IOCB_EVENT) { |
431 | pring->flag |= LPFC_DEFERRED_RING_EVENT; | 431 | pring->flag |= LPFC_DEFERRED_RING_EVENT; |
432 | } else { | 432 | } else { |
433 | pring->flag &= ~LPFC_DEFERRED_RING_EVENT; | ||
433 | lpfc_sli_handle_slow_ring_event(phba, pring, | 434 | lpfc_sli_handle_slow_ring_event(phba, pring, |
434 | (status & | 435 | (status & |
435 | HA_RXMASK)); | 436 | HA_RXMASK)); |
436 | pring->flag &= ~LPFC_DEFERRED_RING_EVENT; | ||
437 | } | 437 | } |
438 | /* | 438 | /* |
439 | * Turn on Ring interrupts | 439 | * Turn on Ring interrupts |
@@ -519,7 +519,9 @@ lpfc_do_work(void *p) | |||
519 | schedule(); | 519 | schedule(); |
520 | } | 520 | } |
521 | } | 521 | } |
522 | spin_lock_irq(&phba->hbalock); | ||
522 | phba->work_wait = NULL; | 523 | phba->work_wait = NULL; |
524 | spin_unlock_irq(&phba->hbalock); | ||
523 | return 0; | 525 | return 0; |
524 | } | 526 | } |
525 | 527 | ||
@@ -809,11 +811,9 @@ out: | |||
809 | mempool_free(pmb, phba->mbox_mem_pool); | 811 | mempool_free(pmb, phba->mbox_mem_pool); |
810 | 812 | ||
811 | spin_lock_irq(shost->host_lock); | 813 | spin_lock_irq(shost->host_lock); |
812 | vport->fc_flag &= ~(FC_ABORT_DISCOVERY | FC_ESTABLISH_LINK); | 814 | vport->fc_flag &= ~FC_ABORT_DISCOVERY; |
813 | spin_unlock_irq(shost->host_lock); | 815 | spin_unlock_irq(shost->host_lock); |
814 | 816 | ||
815 | del_timer_sync(&phba->fc_estabtmo); | ||
816 | |||
817 | lpfc_can_disctmo(vport); | 817 | lpfc_can_disctmo(vport); |
818 | 818 | ||
819 | /* turn on Link Attention interrupts */ | 819 | /* turn on Link Attention interrupts */ |
@@ -1340,10 +1340,14 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
1340 | i++) { | 1340 | i++) { |
1341 | if (vports[i]->port_type == LPFC_PHYSICAL_PORT) | 1341 | if (vports[i]->port_type == LPFC_PHYSICAL_PORT) |
1342 | continue; | 1342 | continue; |
1343 | if (phba->fc_topology == TOPOLOGY_LOOP) { | ||
1344 | lpfc_vport_set_state(vports[i], | ||
1345 | FC_VPORT_LINKDOWN); | ||
1346 | continue; | ||
1347 | } | ||
1343 | if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) | 1348 | if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) |
1344 | lpfc_initial_fdisc(vports[i]); | 1349 | lpfc_initial_fdisc(vports[i]); |
1345 | else if (phba->sli3_options & | 1350 | else { |
1346 | LPFC_SLI3_NPIV_ENABLED) { | ||
1347 | lpfc_vport_set_state(vports[i], | 1351 | lpfc_vport_set_state(vports[i], |
1348 | FC_VPORT_NO_FABRIC_SUPP); | 1352 | FC_VPORT_NO_FABRIC_SUPP); |
1349 | lpfc_printf_vlog(vport, KERN_ERR, | 1353 | lpfc_printf_vlog(vport, KERN_ERR, |
@@ -2190,10 +2194,6 @@ lpfc_matchdid(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
2190 | if (did == Bcast_DID) | 2194 | if (did == Bcast_DID) |
2191 | return 0; | 2195 | return 0; |
2192 | 2196 | ||
2193 | if (ndlp->nlp_DID == 0) { | ||
2194 | return 0; | ||
2195 | } | ||
2196 | |||
2197 | /* First check for Direct match */ | 2197 | /* First check for Direct match */ |
2198 | if (ndlp->nlp_DID == did) | 2198 | if (ndlp->nlp_DID == did) |
2199 | return 1; | 2199 | return 1; |
@@ -2301,7 +2301,8 @@ lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did) | |||
2301 | return ndlp; | 2301 | return ndlp; |
2302 | } | 2302 | } |
2303 | 2303 | ||
2304 | if (vport->fc_flag & FC_RSCN_MODE) { | 2304 | if ((vport->fc_flag & FC_RSCN_MODE) && |
2305 | !(vport->fc_flag & FC_NDISC_ACTIVE)) { | ||
2305 | if (lpfc_rscn_payload_check(vport, did)) { | 2306 | if (lpfc_rscn_payload_check(vport, did)) { |
2306 | /* If we've already recieved a PLOGI from this NPort | 2307 | /* If we've already recieved a PLOGI from this NPort |
2307 | * we don't need to try to discover it again. | 2308 | * we don't need to try to discover it again. |