diff options
author | James Smart <James.Smart@Emulex.Com> | 2007-08-02 11:10:31 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.localdomain> | 2007-08-01 13:24:10 -0400 |
commit | 51ef4c26891a734bc8416b639ad460a8162926bc (patch) | |
tree | 8279e11bf1a0a3200e8aa9bb3d956345ef73533c /drivers/scsi/lpfc/lpfc_hbadisc.c | |
parent | 78b2d852a88cd2a55e3ab632109de045d58b83e3 (diff) |
[SCSI] lpfc 8.2.2 : Miscellaneous Bug Fixes
- Fix vport ndlp ref counting errors
- Fix use after free of ndlp structure
- Use the correct flag to check for LOADING setting.
- Fix driver unload bugs (related to shost references) after link down or rscn
- Fix up HBQ initialization
- Fix port_list locking around driver unload.
- Fix references to hostdata as a phba
- Fix GFFID type offset to work correctly with big endian structure.
- Only call pci_disable_msi if the pci_enable_msi succeeded
- Fix vport_delete wait/fail if in discovery
- Put a reference on the nameservers ndlp when performing CT traffic.
- Remove unbalanced hba unlock.
- Fix up HBQ processing
- Fix lpfc debugfs discovery trace output for ELS rsp cmpl
- Send ADISC when rpi is 0
- Stop FDISC retrying forever
- Unable to retrieve correct config parameter for vport
- Fix sli_validate_fcp_iocb, sli_sum_iocb, sli_abort_iocb to be vport-aware.
- Fix index-out-of-range error in iocb. Spotted by Coverity.
Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_hbadisc.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 53 |
1 files changed, 31 insertions, 22 deletions
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index f96ab75ba637..8788f14b1dec 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -83,10 +83,17 @@ lpfc_terminate_rport_io(struct fc_rport *rport) | |||
83 | ndlp->nlp_sid, ndlp->nlp_DID, ndlp->nlp_flag); | 83 | ndlp->nlp_sid, ndlp->nlp_DID, ndlp->nlp_flag); |
84 | 84 | ||
85 | if (ndlp->nlp_sid != NLP_NO_SID) { | 85 | if (ndlp->nlp_sid != NLP_NO_SID) { |
86 | lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], | 86 | lpfc_sli_abort_iocb(ndlp->vport, |
87 | ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT); | 87 | &phba->sli.ring[phba->sli.fcp_ring], |
88 | ndlp->nlp_sid, 0, LPFC_CTX_TGT); | ||
88 | } | 89 | } |
89 | 90 | ||
91 | /* | ||
92 | * A device is normally blocked for rediscovery and unblocked when | ||
93 | * devloss timeout happens. In case a vport is removed or driver | ||
94 | * unloaded before devloss timeout happens, we need to unblock here. | ||
95 | */ | ||
96 | scsi_target_unblock(&rport->dev); | ||
90 | return; | 97 | return; |
91 | } | 98 | } |
92 | 99 | ||
@@ -194,8 +201,8 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) | |||
194 | if (ndlp->nlp_sid != NLP_NO_SID) { | 201 | if (ndlp->nlp_sid != NLP_NO_SID) { |
195 | warn_on = 1; | 202 | warn_on = 1; |
196 | /* flush the target */ | 203 | /* flush the target */ |
197 | lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], | 204 | lpfc_sli_abort_iocb(vport, &phba->sli.ring[phba->sli.fcp_ring], |
198 | ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT); | 205 | ndlp->nlp_sid, 0, LPFC_CTX_TGT); |
199 | } | 206 | } |
200 | if (vport->load_flag & FC_UNLOADING) | 207 | if (vport->load_flag & FC_UNLOADING) |
201 | warn_on = 0; | 208 | warn_on = 0; |
@@ -348,6 +355,7 @@ lpfc_work_done(struct lpfc_hba *phba) | |||
348 | struct lpfc_sli_ring *pring; | 355 | struct lpfc_sli_ring *pring; |
349 | uint32_t ha_copy, status, control, work_port_events; | 356 | uint32_t ha_copy, status, control, work_port_events; |
350 | struct lpfc_vport **vports; | 357 | struct lpfc_vport **vports; |
358 | struct lpfc_vport *vport; | ||
351 | int i; | 359 | int i; |
352 | 360 | ||
353 | spin_lock_irq(&phba->hbalock); | 361 | spin_lock_irq(&phba->hbalock); |
@@ -365,12 +373,22 @@ lpfc_work_done(struct lpfc_hba *phba) | |||
365 | lpfc_handle_latt(phba); | 373 | lpfc_handle_latt(phba); |
366 | vports = lpfc_create_vport_work_array(phba); | 374 | vports = lpfc_create_vport_work_array(phba); |
367 | if (vports != NULL) | 375 | if (vports != NULL) |
368 | for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) { | 376 | for(i = 0; i < LPFC_MAX_VPORTS; i++) { |
369 | work_port_events = vports[i]->work_port_events; | 377 | /* |
378 | * We could have no vports in array if unloading, so if | ||
379 | * this happens then just use the pport | ||
380 | */ | ||
381 | if (vports[i] == NULL && i == 0) | ||
382 | vport = phba->pport; | ||
383 | else | ||
384 | vport = vports[i]; | ||
385 | if (vport == NULL) | ||
386 | break; | ||
387 | work_port_events = vport->work_port_events; | ||
370 | if (work_port_events & WORKER_DISC_TMO) | 388 | if (work_port_events & WORKER_DISC_TMO) |
371 | lpfc_disc_timeout_handler(vports[i]); | 389 | lpfc_disc_timeout_handler(vport); |
372 | if (work_port_events & WORKER_ELS_TMO) | 390 | if (work_port_events & WORKER_ELS_TMO) |
373 | lpfc_els_timeout_handler(vports[i]); | 391 | lpfc_els_timeout_handler(vport); |
374 | if (work_port_events & WORKER_HB_TMO) | 392 | if (work_port_events & WORKER_HB_TMO) |
375 | lpfc_hb_timeout_handler(phba); | 393 | lpfc_hb_timeout_handler(phba); |
376 | if (work_port_events & WORKER_MBOX_TMO) | 394 | if (work_port_events & WORKER_MBOX_TMO) |
@@ -378,14 +396,14 @@ lpfc_work_done(struct lpfc_hba *phba) | |||
378 | if (work_port_events & WORKER_FABRIC_BLOCK_TMO) | 396 | if (work_port_events & WORKER_FABRIC_BLOCK_TMO) |
379 | lpfc_unblock_fabric_iocbs(phba); | 397 | lpfc_unblock_fabric_iocbs(phba); |
380 | if (work_port_events & WORKER_FDMI_TMO) | 398 | if (work_port_events & WORKER_FDMI_TMO) |
381 | lpfc_fdmi_timeout_handler(vports[i]); | 399 | lpfc_fdmi_timeout_handler(vport); |
382 | if (work_port_events & WORKER_RAMP_DOWN_QUEUE) | 400 | if (work_port_events & WORKER_RAMP_DOWN_QUEUE) |
383 | lpfc_ramp_down_queue_handler(phba); | 401 | lpfc_ramp_down_queue_handler(phba); |
384 | if (work_port_events & WORKER_RAMP_UP_QUEUE) | 402 | if (work_port_events & WORKER_RAMP_UP_QUEUE) |
385 | lpfc_ramp_up_queue_handler(phba); | 403 | lpfc_ramp_up_queue_handler(phba); |
386 | spin_lock_irq(&vports[i]->work_port_lock); | 404 | spin_lock_irq(&vport->work_port_lock); |
387 | vports[i]->work_port_events &= ~work_port_events; | 405 | vport->work_port_events &= ~work_port_events; |
388 | spin_unlock_irq(&vports[i]->work_port_lock); | 406 | spin_unlock_irq(&vport->work_port_lock); |
389 | } | 407 | } |
390 | lpfc_destroy_vport_work_array(vports); | 408 | lpfc_destroy_vport_work_array(vports); |
391 | 409 | ||
@@ -1638,16 +1656,7 @@ lpfc_dequeue_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
1638 | void | 1656 | void |
1639 | lpfc_drop_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | 1657 | lpfc_drop_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) |
1640 | { | 1658 | { |
1641 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 1659 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); |
1642 | |||
1643 | if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0) | ||
1644 | lpfc_cancel_retry_delay_tmo(vport, ndlp); | ||
1645 | if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp)) | ||
1646 | lpfc_nlp_counters(vport, ndlp->nlp_state, -1); | ||
1647 | spin_lock_irq(shost->host_lock); | ||
1648 | list_del_init(&ndlp->nlp_listp); | ||
1649 | ndlp->nlp_flag &= ~NLP_TARGET_REMOVE; | ||
1650 | spin_unlock_irq(shost->host_lock); | ||
1651 | lpfc_nlp_put(ndlp); | 1660 | lpfc_nlp_put(ndlp); |
1652 | } | 1661 | } |
1653 | 1662 | ||