diff options
author | James Smart <james.smart@emulex.com> | 2011-02-16 12:39:35 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2011-02-18 12:45:21 -0600 |
commit | 1151e3ec15c32021a8a12a123459ab5e41692898 (patch) | |
tree | 57cf6cf10dbd7e77654958987ca0f840311fcf2d /drivers/scsi/lpfc/lpfc_scsi.c | |
parent | fedd3b7b93302c7789bd3eeb190653cfb0fe7645 (diff) | |
download | talos-obmc-linux-1151e3ec15c32021a8a12a123459ab5e41692898.tar.gz talos-obmc-linux-1151e3ec15c32021a8a12a123459ab5e41692898.zip |
[SCSI] lpfc 8.3.21: RRQ Implementation fixes
RRQ Implementation fixes
- Added checks to prevent a call to findnode_did in clr_active_rrq
- Added the del_sync_timer call for the rrq_tmr to the stop_hba_timers routine.
- Added a check in __lpfc_set_active_rrq for the driver unloading to prevent
adding an rrq when the driver is being removed.
- Add code to scsi_iocb_cmpl to check for the remote stop and add the rrq.
- Added the same check to els retry.
- Added code to compare the source did in the els rrq to the vports did and
chose the right exchange ID.
- Initialize the start_cmd pointer to indicate when we have looped through
all of the scsi buffers.
- Remove the need for the lock around the clearing of the active bit in the
rrq.
- Added code to clean the els and fcp xri aborted list and remove the all of
the RRQs for a deleted vport.
Signed-off-by: Alex Iannicelli <alex.iannicelli@emulex.com>
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_scsi.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 77 |
1 files changed, 56 insertions, 21 deletions
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index af5498d735e2..d482dfc951f3 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -609,6 +609,32 @@ lpfc_new_scsi_buf_s3(struct lpfc_vport *vport, int num_to_alloc) } /** + * lpfc_sli4_vport_delete_fcp_xri_aborted -Remove all ndlp references for vport + * @vport: pointer to lpfc vport data structure. + * + * This routine is invoked by the vport cleanup for deletions and the cleanup + * for an ndlp on removal. + **/ +void +lpfc_sli4_vport_delete_fcp_xri_aborted(struct lpfc_vport *vport) +{ + struct lpfc_hba *phba = vport->phba; + struct lpfc_scsi_buf *psb, *next_psb; + unsigned long iflag = 0; + + spin_lock_irqsave(&phba->hbalock, iflag); + spin_lock(&phba->sli4_hba.abts_scsi_buf_list_lock); + list_for_each_entry_safe(psb, next_psb, + &phba->sli4_hba.lpfc_abts_scsi_buf_list, list) { + if (psb->rdata && psb->rdata->pnode + && psb->rdata->pnode->vport == vport) + psb->rdata = NULL; + } + spin_unlock(&phba->sli4_hba.abts_scsi_buf_list_lock); + spin_unlock_irqrestore(&phba->hbalock, iflag); +} + +/** * lpfc_sli4_fcp_xri_aborted - Fast-path process of fcp xri abort * @phba: pointer to lpfc hba data structure. * @axri: pointer to the fcp xri abort wcqe structure. @@ -640,7 +666,11 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba, psb->status = IOSTAT_SUCCESS; spin_unlock( &phba->sli4_hba.abts_scsi_buf_list_lock); - ndlp = psb->rdata->pnode; + if (psb->rdata && psb->rdata->pnode) + ndlp = psb->rdata->pnode; + else + ndlp = NULL; + rrq_empty = list_empty(&phba->active_rrq_list); spin_unlock_irqrestore(&phba->hbalock, iflag); if (ndlp) @@ -964,36 +994,29 @@ lpfc_get_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) static struct lpfc_scsi_buf* lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) { - struct lpfc_scsi_buf *lpfc_cmd = NULL; - struct lpfc_scsi_buf *start_lpfc_cmd = NULL; - struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list; + struct lpfc_scsi_buf *lpfc_cmd ; unsigned long iflag = 0; int found = 0; spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag); - list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list); - spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag); - while (!found && lpfc_cmd) { + list_for_each_entry(lpfc_cmd, &phba->lpfc_scsi_buf_list, + list) { if (lpfc_test_rrq_active(phba, ndlp, - lpfc_cmd->cur_iocbq.sli4_xritag)) { - lpfc_release_scsi_buf_s4(phba, lpfc_cmd); - spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag); - list_remove_head(scsi_buf_list, lpfc_cmd, - struct lpfc_scsi_buf, list); - spin_unlock_irqrestore(&phba->scsi_buf_list_lock, - iflag); - if (lpfc_cmd == start_lpfc_cmd) { - lpfc_cmd = NULL; - break; - } else - continue; - } + lpfc_cmd->cur_iocbq.sli4_xritag)) + continue; + list_del(&lpfc_cmd->list); found = 1; lpfc_cmd->seg_cnt = 0; lpfc_cmd->nonsg_phys = 0; lpfc_cmd->prot_seg_cnt = 0; + break; } - return lpfc_cmd; + spin_unlock_irqrestore(&phba->scsi_buf_list_lock, + iflag); + if (!found) + return NULL; + else + return lpfc_cmd; } /** * lpfc_get_scsi_buf - Get a scsi buffer from lpfc_scsi_buf_list of the HBA @@ -2484,6 +2507,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, lpfc_worker_wake_up(phba); break; case IOSTAT_LOCAL_REJECT: + case IOSTAT_REMOTE_STOP: if (lpfc_cmd->result == IOERR_INVALID_RPI || lpfc_cmd->result == IOERR_NO_RESOURCES || lpfc_cmd->result == IOERR_ABORT_REQUESTED || @@ -2510,6 +2534,17 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, "on unprotected cmd\n"); } } + if ((lpfc_cmd->status == IOSTAT_REMOTE_STOP) + && (phba->sli_rev == LPFC_SLI_REV4) + && (pnode && NLP_CHK_NODE_ACT(pnode))) { + /* This IO was aborted by the target, we don't + * know the rxid and because we did not send the + * ABTS we cannot generate and RRQ. + */ + lpfc_set_rrq_active(phba, pnode, + lpfc_cmd->cur_iocbq.sli4_xritag, + 0, 0); + } /* else: fall through */ default: |