summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_scsi.c
diff options
context:
space:
mode:
authorJames Smart <james.smart@emulex.com>2011-02-16 12:39:35 -0500
committerJames Bottomley <James.Bottomley@suse.de>2011-02-18 12:45:21 -0600
commit1151e3ec15c32021a8a12a123459ab5e41692898 (patch)
tree57cf6cf10dbd7e77654958987ca0f840311fcf2d /drivers/scsi/lpfc/lpfc_scsi.c
parentfedd3b7b93302c7789bd3eeb190653cfb0fe7645 (diff)
downloadtalos-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.c77
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:
OpenPOWER on IntegriCloud