diff options
author | James Smart <James.Smart@Emulex.Com> | 2008-04-07 18:15:56 +0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-04-10 16:52:11 +0400 |
commit | 58da1ffb2b1234e9c6c75013a649c659cc38ebd4 (patch) | |
tree | f159b38ff5c830e10eb90918ef5b42ae71645daa /drivers/scsi/lpfc/lpfc_scsi.c | |
parent | b35c07d00751c3d554dd6e582b661ac2e8ffc162 (diff) | |
download | linux-58da1ffb2b1234e9c6c75013a649c659cc38ebd4.tar.xz |
[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_scsi.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 26 |
1 files changed, 15 insertions, 11 deletions
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 70255c11d3ad..6df8bc003a88 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -578,14 +578,14 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, lpfc_cmd->result == IOERR_NO_RESOURCES || lpfc_cmd->result == RJT_LOGIN_REQUIRED) { cmd->result = ScsiResult(DID_REQUEUE, 0); - break; - } /* else: fall through */ + break; + } /* else: fall through */ default: cmd->result = ScsiResult(DID_ERROR, 0); break; } - if ((pnode == NULL ) + if (!pnode || !NLP_CHK_NODE_ACT(pnode) || (pnode->nlp_state != NLP_STE_MAPPED_NODE)) cmd->result = ScsiResult(DID_BUS_BUSY, SAM_STAT_BUSY); } else { @@ -626,7 +626,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, if (!result) lpfc_rampup_queue_depth(vport, sdev); - if (!result && pnode != NULL && + if (!result && pnode && NLP_CHK_NODE_ACT(pnode) && ((jiffies - pnode->last_ramp_up_time) > LPFC_Q_RAMP_UP_INTERVAL * HZ) && ((jiffies - pnode->last_q_full_time) > @@ -654,7 +654,8 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, * Check for queue full. If the lun is reporting queue full, then * back off the lun queue depth to prevent target overloads. */ - if (result == SAM_STAT_TASK_SET_FULL && pnode != NULL) { + if (result == SAM_STAT_TASK_SET_FULL && pnode && + NLP_CHK_NODE_ACT(pnode)) { pnode->last_q_full_time = jiffies; shost_for_each_device(tmp_sdev, sdev->host) { @@ -704,6 +705,9 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, int datadir = scsi_cmnd->sc_data_direction; char tag[2]; + if (!pnode || !NLP_CHK_NODE_ACT(pnode)) + return; + lpfc_cmd->fcp_rsp->rspSnsLen = 0; /* clear task management bits */ lpfc_cmd->fcp_cmnd->fcpCntl2 = 0; @@ -785,9 +789,9 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport, struct lpfc_rport_data *rdata = lpfc_cmd->rdata; struct lpfc_nodelist *ndlp = rdata->pnode; - if ((ndlp == NULL) || (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) { + if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) || + ndlp->nlp_state != NLP_STE_MAPPED_NODE) return 0; - } piocbq = &(lpfc_cmd->cur_iocbq); piocbq->vport = vport; @@ -842,7 +846,7 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf *lpfc_cmd, struct lpfc_vport *vport, struct lpfc_iocbq *iocbqrsp; int ret; - if (!rdata->pnode) + if (!rdata->pnode || !NLP_CHK_NODE_ACT(rdata->pnode)) return FAILED; lpfc_cmd->rdata = rdata; @@ -959,7 +963,7 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) * Catch race where our node has transitioned, but the * transport is still transitioning. */ - if (!ndlp) { + if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { cmnd->result = ScsiResult(DID_BUS_BUSY, 0); goto out_fail_command; } @@ -1146,7 +1150,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) * target is rediscovered or devloss timeout expires. */ while (1) { - if (!pnode) + if (!pnode || !NLP_CHK_NODE_ACT(pnode)) goto out; if (pnode->nlp_state != NLP_STE_MAPPED_NODE) { @@ -1162,7 +1166,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) goto out; } pnode = rdata->pnode; - if (!pnode) + if (!pnode || !NLP_CHK_NODE_ACT(pnode)) goto out; } if (pnode->nlp_state == NLP_STE_MAPPED_NODE) |