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