diff options
author | James Smart <james.smart@broadcom.com> | 2020-11-15 20:26:44 +0100 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2020-11-17 06:43:56 +0100 |
commit | db7531d2b3775c662466e4eeda774986472c6d18 (patch) | |
tree | d36019635b7116043f89feea135f9789272563a6 /drivers/scsi/lpfc/lpfc_scsi.c | |
parent | scsi: lpfc: Convert SCSI I/O completions to SLI-3 and SLI-4 handlers (diff) | |
download | linux-db7531d2b3775c662466e4eeda774986472c6d18.tar.xz linux-db7531d2b3775c662466e4eeda774986472c6d18.zip |
scsi: lpfc: Convert abort handling to SLI-3 and SLI-4 handlers
This patch reworks the abort interfaces such that SLI-3 retains the
iocb-based formatting and completions and SLI-4 now uses native WQEs and
completion routines.
The following changes are made:
- The code is refactored from a confusing 2 routine sequence of
xx_abort_iotag_issue(), which creates/formats and abort cmd, and
xx_issue_abort_tag(), which then issues and handles the completion of
the abort cmd - into a single interface of xx_issue_abort_iotag(). The
new interface will determine whether SLI-3 or SLI-4 and then call the
appropriate handler. A completion handler can now be specified to
address the differences in completion handling. Note: original code is
all iocb based, with SLI-4 converting to SLI-3 for the SCSI/ELS path,
and NVMe natively using wqes.
- The SLI-3 side is refactored:
The older iocb-base lpfc_sli_issue_abort_iotag() routine is combined
with the logic of lpfc_sli_abort_iotag_issue() as well as the
iocb-specific code in lpfc_abort_handler() and lpfc_sli_abort_iocb() to
create the new single SLI-3 abort routine that formats and issues the
iocb.
- The SLI-4 side is refactored and added to:
The native WQE abort code in NVMe is moved to the new SLI-4
issue_abort_iotag() routine. Items in SCSI that set fields not set by
NVMe is migrated into the new routine. Thus the routine supports NVMe
and SCSI initiators. The nvmet block (target) formats the abort slightly
different (like the old NVMe initiator) thus it has its own prep routine
stolen from NVMe initiator and it retains the current code it has for
issuing the WQE (does not use the commonized routine the initiators
do). SLI-4 completion handlers were also added.
- lpfc_abort_handler now becomes a wrapper that determines whether
SLI-3 or SLI-4 and calls the proper abort handler.
Link: https://lore.kernel.org/r/20201115192646.12977-16-james.smart@broadcom.com
Co-developed-by: Dick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: James Smart <james.smart@broadcom.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_scsi.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 62 |
1 files changed, 11 insertions, 51 deletions
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 63c1ea3fd359..f989490359a5 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -5385,11 +5385,10 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; struct lpfc_hba *phba = vport->phba; struct lpfc_iocbq *iocb; - struct lpfc_iocbq *abtsiocb; struct lpfc_io_buf *lpfc_cmd; - IOCB_t *cmd, *icmd; int ret = SUCCESS, status = 0; struct lpfc_sli_ring *pring_s4 = NULL; + struct lpfc_sli_ring *pring = NULL; int ret_val; unsigned long flags; DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq); @@ -5466,64 +5465,22 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) goto wait_for_cmpl; } - abtsiocb = __lpfc_sli_get_iocbq(phba); - if (abtsiocb == NULL) { - ret = FAILED; - goto out_unlock_ring; - } - - /* Indicate the IO is being aborted by the driver. */ - iocb->iocb_flag |= LPFC_DRIVER_ABORTED; - - /* - * The scsi command can not be in txq and it is in flight because the - * pCmd is still pointig at the SCSI command we have to abort. There - * is no need to search the txcmplq. Just send an abort to the FW. - */ - - cmd = &iocb->iocb; - icmd = &abtsiocb->iocb; - icmd->un.acxri.abortType = ABORT_TYPE_ABTS; - icmd->un.acxri.abortContextTag = cmd->ulpContext; - if (phba->sli_rev == LPFC_SLI_REV4) - icmd->un.acxri.abortIoTag = iocb->sli4_xritag; - else - icmd->un.acxri.abortIoTag = cmd->ulpIoTag; - - icmd->ulpLe = 1; - icmd->ulpClass = cmd->ulpClass; - - /* ABTS WQE must go to the same WQ as the WQE to be aborted */ - abtsiocb->hba_wqidx = iocb->hba_wqidx; - abtsiocb->iocb_flag |= LPFC_USE_FCPWQIDX; - if (iocb->iocb_flag & LPFC_IO_FOF) - abtsiocb->iocb_flag |= LPFC_IO_FOF; - - if (lpfc_is_link_up(phba)) - icmd->ulpCommand = CMD_ABORT_XRI_CN; - else - icmd->ulpCommand = CMD_CLOSE_XRI_CN; - - abtsiocb->iocb_cmpl = lpfc_sli_abort_fcp_cmpl; - abtsiocb->vport = vport; lpfc_cmd->waitq = &waitq; if (phba->sli_rev == LPFC_SLI_REV4) { - /* Note: both hbalock and ring_lock must be set here */ - ret_val = __lpfc_sli_issue_iocb(phba, pring_s4->ringno, - abtsiocb, 0); spin_unlock(&pring_s4->ring_lock); + ret_val = lpfc_sli4_issue_abort_iotag(phba, iocb, + lpfc_sli4_abort_fcp_cmpl); } else { - ret_val = __lpfc_sli_issue_iocb(phba, LPFC_FCP_RING, - abtsiocb, 0); + pring = &phba->sli.sli3_ring[LPFC_FCP_RING]; + ret_val = lpfc_sli_issue_abort_iotag(phba, pring, iocb, + lpfc_sli_abort_fcp_cmpl); } - if (ret_val == IOCB_ERROR) { + if (ret_val != IOCB_SUCCESS) { /* Indicate the IO is not being aborted by the driver. */ - iocb->iocb_flag &= ~LPFC_DRIVER_ABORTED; lpfc_cmd->waitq = NULL; spin_unlock(&lpfc_cmd->buf_lock); spin_unlock_irqrestore(&phba->hbalock, flags); - lpfc_sli_release_iocbq(phba, abtsiocb); ret = FAILED; goto out; } @@ -5537,7 +5494,10 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) &phba->sli.sli3_ring[LPFC_FCP_RING], HA_R0RE_REQ); wait_for_cmpl: - /* Wait for abort to complete */ + /* + * iocb_flag is set to LPFC_DRIVER_ABORTED before we wait + * for abort to complete. + */ wait_event_timeout(waitq, (lpfc_cmd->pCmd != cmnd), msecs_to_jiffies(2*vport->cfg_devloss_tmo*1000)); |