|
Daniel Wagner |
de4f30 |
From: James Smart <jsmart2021@gmail.com>
|
|
Daniel Wagner |
de4f30 |
Date: Fri, 14 May 2021 12:55:57 -0700
|
|
Daniel Wagner |
de4f30 |
Subject: scsi: lpfc: Add a option to enable interlocked ABTS before job
|
|
Daniel Wagner |
de4f30 |
completion
|
|
Daniel Wagner |
de4f30 |
Patch-mainline: Queued in subsystem maintainer repository
|
|
Daniel Wagner |
de4f30 |
Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git
|
|
Daniel Wagner |
de4f30 |
Git-commit: 3e49af9393c6e59d579de13333514fc9660a0e92
|
|
Daniel Wagner |
de4f30 |
References: bsc#1186452
|
|
Daniel Wagner |
de4f30 |
|
|
Daniel Wagner |
de4f30 |
Default behavior for the driver, when aborting an I/O, is to terminate the
|
|
Daniel Wagner |
de4f30 |
I/O with the adapter. The adapter will initiate an ABTS to terminate the
|
|
Daniel Wagner |
de4f30 |
exchange on the link and mark the exchange is terminated so that no further
|
|
Daniel Wagner |
de4f30 |
use of the sgl or any traffic for the exchange is worked on. Completion on
|
|
Daniel Wagner |
de4f30 |
the Abort is then posted to the driver, which as the I/O is terminated can
|
|
Daniel Wagner |
de4f30 |
complete the I/O to the OS. This completion may occur prior to the ABTS
|
|
Daniel Wagner |
de4f30 |
handshake completing on the wire. The ABTS handshake can take a long time
|
|
Daniel Wagner |
de4f30 |
to complete with timeouts and retries reaching 60+ seconds. Note: if
|
|
Daniel Wagner |
de4f30 |
retries fail, LOGO occurs.
|
|
Daniel Wagner |
de4f30 |
|
|
Daniel Wagner |
de4f30 |
Some devices want to ensure that the ABTS handshake fully completes (this
|
|
Daniel Wagner |
de4f30 |
device has fully ack'd it) before the I/O completion is posted back to the
|
|
Daniel Wagner |
de4f30 |
OS, where a failed I/O may be retried via a different path.
|
|
Daniel Wagner |
de4f30 |
|
|
Daniel Wagner |
de4f30 |
To support this behavior, an option was added to the driver to change I/O
|
|
Daniel Wagner |
de4f30 |
completion from the Abort cmd completion to the Exchange termination (aka
|
|
Daniel Wagner |
de4f30 |
ABTS) completion.
|
|
Daniel Wagner |
de4f30 |
|
|
Daniel Wagner |
de4f30 |
Link: https://lore.kernel.org/r/20210514195559.119853-10-jsmart2021@gmail.com
|
|
Daniel Wagner |
de4f30 |
Co-developed-by: Justin Tee <justin.tee@broadcom.com>
|
|
Daniel Wagner |
de4f30 |
Signed-off-by: Justin Tee <justin.tee@broadcom.com>
|
|
Daniel Wagner |
de4f30 |
Signed-off-by: James Smart <jsmart2021@gmail.com>
|
|
Daniel Wagner |
de4f30 |
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
|
|
Daniel Wagner |
de4f30 |
Acked-by: Daniel Wagner <dwagner@suse.de>
|
|
Daniel Wagner |
de4f30 |
---
|
|
Daniel Wagner |
de4f30 |
drivers/scsi/lpfc/lpfc.h | 1
|
|
Daniel Wagner |
de4f30 |
drivers/scsi/lpfc/lpfc_attr.c | 11 ++++++++++
|
|
Daniel Wagner |
de4f30 |
drivers/scsi/lpfc/lpfc_mbox.c | 3 +-
|
|
Daniel Wagner |
de4f30 |
drivers/scsi/lpfc/lpfc_scsi.c | 45 ++++++++++++++++++++++++++++++++++++------
|
|
Daniel Wagner |
de4f30 |
4 files changed, 53 insertions(+), 7 deletions(-)
|
|
Daniel Wagner |
de4f30 |
|
|
Daniel Wagner |
de4f30 |
--- a/drivers/scsi/lpfc/lpfc.h
|
|
Daniel Wagner |
de4f30 |
+++ b/drivers/scsi/lpfc/lpfc.h
|
|
Daniel Wagner |
de4f30 |
@@ -914,6 +914,7 @@ struct lpfc_hba {
|
|
Daniel Wagner |
de4f30 |
uint32_t cfg_request_firmware_upgrade;
|
|
Daniel Wagner |
de4f30 |
uint32_t cfg_suppress_link_up;
|
|
Daniel Wagner |
de4f30 |
uint32_t cfg_rrq_xri_bitmap_sz;
|
|
Daniel Wagner |
de4f30 |
+ u32 cfg_fcp_wait_abts_rsp;
|
|
Daniel Wagner |
de4f30 |
uint32_t cfg_delay_discovery;
|
|
Daniel Wagner |
de4f30 |
uint32_t cfg_sli_mode;
|
|
Daniel Wagner |
de4f30 |
#define LPFC_INITIALIZE_LINK 0 /* do normal init_link mbox */
|
|
Daniel Wagner |
de4f30 |
--- a/drivers/scsi/lpfc/lpfc_attr.c
|
|
Daniel Wagner |
de4f30 |
+++ b/drivers/scsi/lpfc/lpfc_attr.c
|
|
Daniel Wagner |
de4f30 |
@@ -3456,6 +3456,15 @@ LPFC_ATTR_R(fcf_failover_policy, 1, 1, 2
|
|
Daniel Wagner |
de4f30 |
"FCF Fast failover=1 Priority failover=2");
|
|
Daniel Wagner |
de4f30 |
|
|
Daniel Wagner |
de4f30 |
/*
|
|
Daniel Wagner |
de4f30 |
+ * lpfc_fcp_wait_abts_rsp: Modifies criteria for reporting completion of
|
|
Daniel Wagner |
de4f30 |
+ * aborted IO.
|
|
Daniel Wagner |
de4f30 |
+ * The range is [0,1]. Default value is 0
|
|
Daniel Wagner |
de4f30 |
+ * 0, IO completes after ABTS issued (default).
|
|
Daniel Wagner |
de4f30 |
+ * 1, IO completes after receipt of ABTS response or timeout.
|
|
Daniel Wagner |
de4f30 |
+ */
|
|
Daniel Wagner |
de4f30 |
+LPFC_ATTR_R(fcp_wait_abts_rsp, 0, 0, 1, "Wait for FCP ABTS completion");
|
|
Daniel Wagner |
de4f30 |
+
|
|
Daniel Wagner |
de4f30 |
+/*
|
|
Daniel Wagner |
de4f30 |
# lpfc_enable_rrq: Track XRI/OXID reuse after IO failures
|
|
Daniel Wagner |
de4f30 |
# 0x0 = disabled, XRI/OXID use not tracked.
|
|
Daniel Wagner |
de4f30 |
# 0x1 = XRI/OXID reuse is timed with ratov, RRQ sent.
|
|
Daniel Wagner |
de4f30 |
@@ -6167,6 +6176,7 @@ struct device_attribute *lpfc_hba_attrs[
|
|
Daniel Wagner |
de4f30 |
&dev_attr_lpfc_enable_npiv,
|
|
Daniel Wagner |
de4f30 |
&dev_attr_lpfc_fcf_failover_policy,
|
|
Daniel Wagner |
de4f30 |
&dev_attr_lpfc_enable_rrq,
|
|
Daniel Wagner |
de4f30 |
+ &dev_attr_lpfc_fcp_wait_abts_rsp,
|
|
Daniel Wagner |
de4f30 |
&dev_attr_nport_evt_cnt,
|
|
Daniel Wagner |
de4f30 |
&dev_attr_board_mode,
|
|
Daniel Wagner |
de4f30 |
&dev_attr_max_vpi,
|
|
Daniel Wagner |
de4f30 |
@@ -7299,6 +7309,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
|
|
Daniel Wagner |
de4f30 |
lpfc_enable_npiv_init(phba, lpfc_enable_npiv);
|
|
Daniel Wagner |
de4f30 |
lpfc_fcf_failover_policy_init(phba, lpfc_fcf_failover_policy);
|
|
Daniel Wagner |
de4f30 |
lpfc_enable_rrq_init(phba, lpfc_enable_rrq);
|
|
Daniel Wagner |
de4f30 |
+ lpfc_fcp_wait_abts_rsp_init(phba, lpfc_fcp_wait_abts_rsp);
|
|
Daniel Wagner |
de4f30 |
lpfc_fdmi_on_init(phba, lpfc_fdmi_on);
|
|
Daniel Wagner |
de4f30 |
lpfc_enable_SmartSAN_init(phba, lpfc_enable_SmartSAN);
|
|
Daniel Wagner |
de4f30 |
lpfc_use_msi_init(phba, lpfc_use_msi);
|
|
Daniel Wagner |
de4f30 |
--- a/drivers/scsi/lpfc/lpfc_mbox.c
|
|
Daniel Wagner |
de4f30 |
+++ b/drivers/scsi/lpfc/lpfc_mbox.c
|
|
Daniel Wagner |
de4f30 |
@@ -522,7 +522,8 @@ lpfc_init_link(struct lpfc_hba * phba,
|
|
Daniel Wagner |
de4f30 |
}
|
|
Daniel Wagner |
de4f30 |
|
|
Daniel Wagner |
de4f30 |
/* Enable asynchronous ABTS responses from firmware */
|
|
Daniel Wagner |
de4f30 |
- mb->un.varInitLnk.link_flags |= FLAGS_IMED_ABORT;
|
|
Daniel Wagner |
de4f30 |
+ if (phba->sli_rev == LPFC_SLI_REV3 && !phba->cfg_fcp_wait_abts_rsp)
|
|
Daniel Wagner |
de4f30 |
+ mb->un.varInitLnk.link_flags |= FLAGS_IMED_ABORT;
|
|
Daniel Wagner |
de4f30 |
|
|
Daniel Wagner |
de4f30 |
/* NEW_FEATURE
|
|
Daniel Wagner |
de4f30 |
* Setting up the link speed
|
|
Daniel Wagner |
de4f30 |
--- a/drivers/scsi/lpfc/lpfc_scsi.c
|
|
Daniel Wagner |
de4f30 |
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
|
|
Daniel Wagner |
de4f30 |
@@ -518,6 +518,7 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba
|
|
Daniel Wagner |
de4f30 |
struct lpfc_nodelist *ndlp;
|
|
Daniel Wagner |
de4f30 |
int rrq_empty = 0;
|
|
Daniel Wagner |
de4f30 |
struct lpfc_sli_ring *pring = phba->sli4_hba.els_wq->pring;
|
|
Daniel Wagner |
de4f30 |
+ struct scsi_cmnd *cmd;
|
|
Daniel Wagner |
de4f30 |
|
|
Daniel Wagner |
de4f30 |
if (!(phba->cfg_enable_fc4_type & LPFC_ENABLE_FCP))
|
|
Daniel Wagner |
de4f30 |
return;
|
|
Daniel Wagner |
de4f30 |
@@ -553,6 +554,31 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba
|
|
Daniel Wagner |
de4f30 |
psb->cur_iocbq.sli4_lxritag, rxid, 1);
|
|
Daniel Wagner |
de4f30 |
lpfc_sli4_abts_err_handler(phba, ndlp, axri);
|
|
Daniel Wagner |
de4f30 |
}
|
|
Daniel Wagner |
de4f30 |
+
|
|
Daniel Wagner |
de4f30 |
+ if (phba->cfg_fcp_wait_abts_rsp) {
|
|
Daniel Wagner |
de4f30 |
+ spin_lock_irqsave(&psb->buf_lock, iflag);
|
|
Daniel Wagner |
de4f30 |
+ cmd = psb->pCmd;
|
|
Daniel Wagner |
de4f30 |
+ psb->pCmd = NULL;
|
|
Daniel Wagner |
de4f30 |
+ spin_unlock_irqrestore(&psb->buf_lock, iflag);
|
|
Daniel Wagner |
de4f30 |
+
|
|
Daniel Wagner |
de4f30 |
+ /* The sdev is not guaranteed to be valid post
|
|
Daniel Wagner |
de4f30 |
+ * scsi_done upcall.
|
|
Daniel Wagner |
de4f30 |
+ */
|
|
Daniel Wagner |
de4f30 |
+ if (cmd)
|
|
Daniel Wagner |
de4f30 |
+ cmd->scsi_done(cmd);
|
|
Daniel Wagner |
de4f30 |
+
|
|
Daniel Wagner |
de4f30 |
+ /*
|
|
Daniel Wagner |
de4f30 |
+ * We expect there is an abort thread waiting
|
|
Daniel Wagner |
de4f30 |
+ * for command completion wake up the thread.
|
|
Daniel Wagner |
de4f30 |
+ */
|
|
Daniel Wagner |
de4f30 |
+ spin_lock_irqsave(&psb->buf_lock, iflag);
|
|
Daniel Wagner |
de4f30 |
+ psb->cur_iocbq.iocb_flag &=
|
|
Daniel Wagner |
de4f30 |
+ ~LPFC_DRIVER_ABORTED;
|
|
Daniel Wagner |
de4f30 |
+ if (psb->waitq)
|
|
Daniel Wagner |
de4f30 |
+ wake_up(psb->waitq);
|
|
Daniel Wagner |
de4f30 |
+ spin_unlock_irqrestore(&psb->buf_lock, iflag);
|
|
Daniel Wagner |
de4f30 |
+ }
|
|
Daniel Wagner |
de4f30 |
+
|
|
Daniel Wagner |
de4f30 |
lpfc_release_scsi_buf_s4(phba, psb);
|
|
Daniel Wagner |
de4f30 |
if (rrq_empty)
|
|
Daniel Wagner |
de4f30 |
lpfc_worker_wake_up(phba);
|
|
Daniel Wagner |
de4f30 |
@@ -780,7 +806,8 @@ lpfc_release_scsi_buf_s4(struct lpfc_hba
|
|
Daniel Wagner |
de4f30 |
qp = psb->hdwq;
|
|
Daniel Wagner |
de4f30 |
if (psb->flags & LPFC_SBUF_XBUSY) {
|
|
Daniel Wagner |
de4f30 |
spin_lock_irqsave(&qp->abts_io_buf_list_lock, iflag);
|
|
Daniel Wagner |
de4f30 |
- psb->pCmd = NULL;
|
|
Daniel Wagner |
de4f30 |
+ if (!phba->cfg_fcp_wait_abts_rsp)
|
|
Daniel Wagner |
de4f30 |
+ psb->pCmd = NULL;
|
|
Daniel Wagner |
de4f30 |
list_add_tail(&psb->list, &qp->lpfc_abts_io_buf_list);
|
|
Daniel Wagner |
de4f30 |
qp->abts_scsi_io_bufs++;
|
|
Daniel Wagner |
de4f30 |
spin_unlock_irqrestore(&qp->abts_io_buf_list_lock, iflag);
|
|
Daniel Wagner |
de4f30 |
@@ -4045,6 +4072,7 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba
|
|
Daniel Wagner |
de4f30 |
u32 logit = LOG_FCP;
|
|
Daniel Wagner |
de4f30 |
u32 status, idx;
|
|
Daniel Wagner |
de4f30 |
unsigned long iflags = 0;
|
|
Daniel Wagner |
de4f30 |
+ u8 wait_xb_clr = 0;
|
|
Daniel Wagner |
de4f30 |
|
|
Daniel Wagner |
de4f30 |
/* Sanity check on return of outstanding command */
|
|
Daniel Wagner |
de4f30 |
if (!lpfc_cmd) {
|
|
Daniel Wagner |
de4f30 |
@@ -4096,8 +4124,11 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba
|
|
Daniel Wagner |
de4f30 |
lpfc_cmd->result = (wcqe->parameter & IOERR_PARAM_MASK);
|
|
Daniel Wagner |
de4f30 |
|
|
Daniel Wagner |
de4f30 |
lpfc_cmd->flags &= ~LPFC_SBUF_XBUSY;
|
|
Daniel Wagner |
de4f30 |
- if (bf_get(lpfc_wcqe_c_xb, wcqe))
|
|
Daniel Wagner |
de4f30 |
+ if (bf_get(lpfc_wcqe_c_xb, wcqe)) {
|
|
Daniel Wagner |
de4f30 |
lpfc_cmd->flags |= LPFC_SBUF_XBUSY;
|
|
Daniel Wagner |
de4f30 |
+ if (phba->cfg_fcp_wait_abts_rsp)
|
|
Daniel Wagner |
de4f30 |
+ wait_xb_clr = 1;
|
|
Daniel Wagner |
de4f30 |
+ }
|
|
Daniel Wagner |
de4f30 |
|
|
Daniel Wagner |
de4f30 |
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
|
|
Daniel Wagner |
de4f30 |
if (lpfc_cmd->prot_data_type) {
|
|
Daniel Wagner |
de4f30 |
@@ -4329,6 +4360,8 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba
|
|
Daniel Wagner |
de4f30 |
lpfc_io_ktime(phba, lpfc_cmd);
|
|
Daniel Wagner |
de4f30 |
}
|
|
Daniel Wagner |
de4f30 |
#endif
|
|
Daniel Wagner |
de4f30 |
+ if (wait_xb_clr)
|
|
Daniel Wagner |
de4f30 |
+ goto out;
|
|
Daniel Wagner |
de4f30 |
lpfc_cmd->pCmd = NULL;
|
|
Daniel Wagner |
de4f30 |
spin_unlock(&lpfc_cmd->buf_lock);
|
|
Daniel Wagner |
de4f30 |
|
|
Daniel Wagner |
de4f30 |
@@ -4343,8 +4376,8 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba
|
|
Daniel Wagner |
de4f30 |
lpfc_cmd->cur_iocbq.iocb_flag &= ~LPFC_DRIVER_ABORTED;
|
|
Daniel Wagner |
de4f30 |
if (lpfc_cmd->waitq)
|
|
Daniel Wagner |
de4f30 |
wake_up(lpfc_cmd->waitq);
|
|
Daniel Wagner |
de4f30 |
+out:
|
|
Daniel Wagner |
de4f30 |
spin_unlock(&lpfc_cmd->buf_lock);
|
|
Daniel Wagner |
de4f30 |
-
|
|
Daniel Wagner |
de4f30 |
lpfc_release_scsi_buf(phba, lpfc_cmd);
|
|
Daniel Wagner |
de4f30 |
}
|
|
Daniel Wagner |
de4f30 |
|
|
Daniel Wagner |
de4f30 |
@@ -4398,11 +4431,10 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba
|
|
Daniel Wagner |
de4f30 |
|
|
Daniel Wagner |
de4f30 |
lpfc_cmd->result = (pIocbOut->iocb.un.ulpWord[4] & IOERR_PARAM_MASK);
|
|
Daniel Wagner |
de4f30 |
lpfc_cmd->status = pIocbOut->iocb.ulpStatus;
|
|
Daniel Wagner |
de4f30 |
- /* pick up SLI4 exhange busy status from HBA */
|
|
Daniel Wagner |
de4f30 |
+ /* pick up SLI4 exchange busy status from HBA */
|
|
Daniel Wagner |
de4f30 |
+ lpfc_cmd->flags &= ~LPFC_SBUF_XBUSY;
|
|
Daniel Wagner |
de4f30 |
if (pIocbOut->iocb_flag & LPFC_EXCHANGE_BUSY)
|
|
Daniel Wagner |
de4f30 |
lpfc_cmd->flags |= LPFC_SBUF_XBUSY;
|
|
Daniel Wagner |
de4f30 |
- else
|
|
Daniel Wagner |
de4f30 |
- lpfc_cmd->flags &= ~LPFC_SBUF_XBUSY;
|
|
Daniel Wagner |
de4f30 |
|
|
Daniel Wagner |
de4f30 |
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
|
|
Daniel Wagner |
de4f30 |
if (lpfc_cmd->prot_data_type) {
|
|
Daniel Wagner |
de4f30 |
@@ -4601,6 +4633,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba
|
|
Daniel Wagner |
de4f30 |
lpfc_io_ktime(phba, lpfc_cmd);
|
|
Daniel Wagner |
de4f30 |
}
|
|
Daniel Wagner |
de4f30 |
#endif
|
|
Daniel Wagner |
de4f30 |
+
|
|
Daniel Wagner |
de4f30 |
/* The sdev is not guaranteed to be valid post scsi_done upcall. */
|
|
Daniel Wagner |
de4f30 |
cmd->scsi_done(cmd);
|
|
Daniel Wagner |
de4f30 |
|