diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_scsi.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 44 |
1 files changed, 36 insertions, 8 deletions
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 25ef2b6ccc34..51ce244cf10a 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -4727,7 +4727,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) struct lpfc_scsi_buf *lpfc_cmd; IOCB_t *cmd, *icmd; int ret = SUCCESS, status = 0; - struct lpfc_sli_ring *pring_s4; + struct lpfc_sli_ring *pring_s4 = NULL; int ret_val; unsigned long flags; DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq); @@ -4757,8 +4757,25 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) } iocb = &lpfc_cmd->cur_iocbq; + if (phba->sli_rev == LPFC_SLI_REV4) { + if (!(phba->cfg_fof) || + (!(iocb->iocb_flag & LPFC_IO_FOF))) { + pring_s4 = + phba->sli4_hba.fcp_wq[iocb->hba_wqidx]->pring; + } else { + iocb->hba_wqidx = 0; + pring_s4 = phba->sli4_hba.oas_wq->pring; + } + if (!pring_s4) { + ret = FAILED; + goto out_unlock; + } + spin_lock(&pring_s4->ring_lock); + } /* the command is in process of being cancelled */ if (!(iocb->iocb_flag & LPFC_IO_ON_TXCMPLQ)) { + if (phba->sli_rev == LPFC_SLI_REV4) + spin_unlock(&pring_s4->ring_lock); spin_unlock_irqrestore(&phba->hbalock, flags); lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, "3169 SCSI Layer abort requested I/O has been " @@ -4772,6 +4789,8 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) * see the completion before the eh fired. Just return SUCCESS. */ if (lpfc_cmd->pCmd != cmnd) { + if (phba->sli_rev == LPFC_SLI_REV4) + spin_unlock(&pring_s4->ring_lock); lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, "3170 SCSI Layer abort requested I/O has been " "completed by LLD.\n"); @@ -4784,6 +4803,8 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) if (iocb->iocb_flag & LPFC_DRIVER_ABORTED) { lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, "3389 SCSI Layer I/O Abort Request is pending\n"); + if (phba->sli_rev == LPFC_SLI_REV4) + spin_unlock(&pring_s4->ring_lock); spin_unlock_irqrestore(&phba->hbalock, flags); goto wait_for_cmpl; } @@ -4791,6 +4812,8 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) abtsiocb = __lpfc_sli_get_iocbq(phba); if (abtsiocb == NULL) { ret = FAILED; + if (phba->sli_rev == LPFC_SLI_REV4) + spin_unlock(&pring_s4->ring_lock); goto out_unlock; } @@ -4828,14 +4851,9 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) abtsiocb->iocb_cmpl = lpfc_sli_abort_fcp_cmpl; abtsiocb->vport = vport; + lpfc_cmd->waitq = &waitq; if (phba->sli_rev == LPFC_SLI_REV4) { - pring_s4 = lpfc_sli4_calc_ring(phba, abtsiocb); - if (pring_s4 == NULL) { - ret = FAILED; - goto out_unlock; - } /* Note: both hbalock and ring_lock must be set here */ - spin_lock(&pring_s4->ring_lock); ret_val = __lpfc_sli_issue_iocb(phba, pring_s4->ringno, abtsiocb, 0); spin_unlock(&pring_s4->ring_lock); @@ -4848,6 +4866,17 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) if (ret_val == IOCB_ERROR) { + if (phba->sli_rev == LPFC_SLI_REV4) + spin_lock_irqsave(&pring_s4->ring_lock, flags); + else + spin_lock_irqsave(&phba->hbalock, flags); + /* Indicate the IO is not being aborted by the driver. */ + iocb->iocb_flag &= ~LPFC_DRIVER_ABORTED; + lpfc_cmd->waitq = NULL; + if (phba->sli_rev == LPFC_SLI_REV4) + spin_unlock_irqrestore(&pring_s4->ring_lock, flags); + else + spin_unlock_irqrestore(&phba->hbalock, flags); lpfc_sli_release_iocbq(phba, abtsiocb); ret = FAILED; goto out; @@ -4858,7 +4887,6 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) &phba->sli.sli3_ring[LPFC_FCP_RING], HA_R0RE_REQ); wait_for_cmpl: - lpfc_cmd->waitq = &waitq; /* Wait for abort to complete */ wait_event_timeout(waitq, (lpfc_cmd->pCmd != cmnd), |