Hannes Reinecke 16a9e5
From: James Smart <jsmart2021@gmail.com>
Hannes Reinecke 16a9e5
Date: Tue, 31 Mar 2020 09:50:07 -0700
Hannes Reinecke 16a9e5
Subject: [PATCH] lpfc: Refactor Send LS Abort support
Hannes Reinecke 16a9e5
Git-commit: 2cd0363b234f8557d0ec3fa9a099854ce7940aa3
Hannes Reinecke 16a9e5
Git-repo: git://git.infradead.org/nvme.git
Hannes Reinecke 16a9e5
Patch-mainline: Queued in subsystem maintainer repository
Hannes Reinecke 16a9e5
References: bsc#1169045
Hannes Reinecke 16a9e5
Hannes Reinecke 16a9e5
Send LS Abort support is needed when Send LS Request is supported.
Hannes Reinecke 16a9e5
Hannes Reinecke 16a9e5
Currently, the ability to abort an NVME LS request is limited to the nvme
Hannes Reinecke 16a9e5
(host) side of the driver.  In preparation of both the nvme and nvmet sides
Hannes Reinecke 16a9e5
supporting Send LS Abort, rework the existing ls_req abort routines such
Hannes Reinecke 16a9e5
that there is common code that can be used by both sides.
Hannes Reinecke 16a9e5
Hannes Reinecke 16a9e5
While refactoring it was seen the logic in the abort routine was incorrect.
Hannes Reinecke 16a9e5
It attempted to abort all NVME LS's on the indicated port. As such, the
Hannes Reinecke 16a9e5
routine was reworked to abort only the NVME LS request that was specified.
Hannes Reinecke 16a9e5
Hannes Reinecke 16a9e5
Signed-off-by: Paul Ely <paul.ely@broadcom.com>
Hannes Reinecke 16a9e5
Signed-off-by: James Smart <jsmart2021@gmail.com>
Hannes Reinecke 16a9e5
Reviewed-by: Hannes Reinecke <hare@suse.de>
Hannes Reinecke 16a9e5
Signed-off-by: Christoph Hellwig <hch@lst.de>
Hannes Reinecke 16a9e5
Acked-by: Hannes Reinecke <hare@suse.com>
Hannes Reinecke 16a9e5
---
Hannes Reinecke 16a9e5
 drivers/scsi/lpfc/lpfc_nvme.c | 125 +++++++++++++++++++++++++-----------------
Hannes Reinecke 16a9e5
 drivers/scsi/lpfc/lpfc_nvme.h |   2 +
Hannes Reinecke 16a9e5
 2 files changed, 77 insertions(+), 50 deletions(-)
Hannes Reinecke 16a9e5
Hannes Reinecke 16a9e5
diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
Hannes Reinecke 16a9e5
index 2fa48d0049bd..776ee547740a 100644
Hannes Reinecke 16a9e5
--- a/drivers/scsi/lpfc/lpfc_nvme.c
Hannes Reinecke 16a9e5
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
Hannes Reinecke 16a9e5
@@ -790,83 +790,108 @@ lpfc_nvme_ls_req(struct nvme_fc_local_port *pnvme_lport,
Hannes Reinecke 16a9e5
 }
Hannes Reinecke 16a9e5
 
Hannes Reinecke 16a9e5
 /**
Hannes Reinecke 16a9e5
- * lpfc_nvme_ls_abort - Issue an Link Service request
Hannes Reinecke 16a9e5
- * @lpfc_pnvme: Pointer to the driver's nvme instance data
Hannes Reinecke 16a9e5
- * @lpfc_nvme_lport: Pointer to the driver's local port data
Hannes Reinecke 16a9e5
- * @lpfc_nvme_rport: Pointer to the rport getting the @lpfc_nvme_ereq
Hannes Reinecke 16a9e5
+ * __lpfc_nvme_ls_abort - Generic service routine to abort a prior
Hannes Reinecke 16a9e5
+ *         NVME LS request
Hannes Reinecke 16a9e5
+ * @vport: The local port that issued the LS
Hannes Reinecke 16a9e5
+ * @ndlp: The remote port the LS was sent to
Hannes Reinecke 16a9e5
+ * @pnvme_lsreq: Pointer to LS request structure from the transport
Hannes Reinecke 16a9e5
  *
Hannes Reinecke 16a9e5
- * Driver registers this routine to handle any link service request
Hannes Reinecke 16a9e5
- * from the nvme_fc transport to a remote nvme-aware port.
Hannes Reinecke 16a9e5
+ * The driver validates the ndlp, looks for the LS, and aborts the
Hannes Reinecke 16a9e5
+ * LS if found.
Hannes Reinecke 16a9e5
  *
Hannes Reinecke 16a9e5
- * Return value :
Hannes Reinecke 16a9e5
- *   0 - Success
Hannes Reinecke 16a9e5
- *   TODO: What are the failure codes.
Hannes Reinecke 16a9e5
+ * Returns:
Hannes Reinecke 16a9e5
+ * 0 : if LS found and aborted
Hannes Reinecke 16a9e5
+ * non-zero: various error conditions in form -Exxx
Hannes Reinecke 16a9e5
  **/
Hannes Reinecke 16a9e5
-static void
Hannes Reinecke 16a9e5
-lpfc_nvme_ls_abort(struct nvme_fc_local_port *pnvme_lport,
Hannes Reinecke 16a9e5
-		   struct nvme_fc_remote_port *pnvme_rport,
Hannes Reinecke 16a9e5
-		   struct nvmefc_ls_req *pnvme_lsreq)
Hannes Reinecke 16a9e5
+int
Hannes Reinecke 16a9e5
+__lpfc_nvme_ls_abort(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
Hannes Reinecke 16a9e5
+			struct nvmefc_ls_req *pnvme_lsreq)
Hannes Reinecke 16a9e5
 {
Hannes Reinecke 16a9e5
-	struct lpfc_nvme_lport *lport;
Hannes Reinecke 16a9e5
-	struct lpfc_vport *vport;
Hannes Reinecke 16a9e5
-	struct lpfc_hba *phba;
Hannes Reinecke 16a9e5
-	struct lpfc_nodelist *ndlp;
Hannes Reinecke 16a9e5
-	LIST_HEAD(abort_list);
Hannes Reinecke 16a9e5
+	struct lpfc_hba *phba = vport->phba;
Hannes Reinecke 16a9e5
 	struct lpfc_sli_ring *pring;
Hannes Reinecke 16a9e5
 	struct lpfc_iocbq *wqe, *next_wqe;
Hannes Reinecke 16a9e5
+	bool foundit = false;
Hannes Reinecke 16a9e5
 
Hannes Reinecke 16a9e5
-	lport = (struct lpfc_nvme_lport *)pnvme_lport->private;
Hannes Reinecke 16a9e5
-	if (unlikely(!lport))
Hannes Reinecke 16a9e5
-		return;
Hannes Reinecke 16a9e5
-	vport = lport->vport;
Hannes Reinecke 16a9e5
-	phba = vport->phba;
Hannes Reinecke 16a9e5
-
Hannes Reinecke 16a9e5
-	if (vport->load_flag & FC_UNLOADING)
Hannes Reinecke 16a9e5
-		return;
Hannes Reinecke 16a9e5
-
Hannes Reinecke 16a9e5
-	ndlp = lpfc_findnode_did(vport, pnvme_rport->port_id);
Hannes Reinecke 16a9e5
 	if (!ndlp) {
Hannes Reinecke 16a9e5
-		lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_ABTS,
Hannes Reinecke 16a9e5
-				 "6049 Could not find node for DID %x\n",
Hannes Reinecke 16a9e5
-				 pnvme_rport->port_id);
Hannes Reinecke 16a9e5
-		return;
Hannes Reinecke 16a9e5
+		lpfc_printf_log(phba, KERN_ERR,
Hannes Reinecke 16a9e5
+				LOG_NVME_DISC | LOG_NODE |
Hannes Reinecke 16a9e5
+					LOG_NVME_IOERR | LOG_NVME_ABTS,
Hannes Reinecke 16a9e5
+				"6049 NVMEx LS REQ Abort: Bad NDLP x%px DID "
Hannes Reinecke 16a9e5
+				"x%06x, Failing LS Req\n",
Hannes Reinecke 16a9e5
+				ndlp, ndlp ? ndlp->nlp_DID : 0);
Hannes Reinecke 16a9e5
+		return -EINVAL;
Hannes Reinecke 16a9e5
 	}
Hannes Reinecke 16a9e5
 
Hannes Reinecke 16a9e5
-	/* Expand print to include key fields. */
Hannes Reinecke 16a9e5
-	lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_ABTS,
Hannes Reinecke 16a9e5
-			 "6040 ENTER.  lport x%px, rport x%px lsreq x%px rqstlen:%d "
Hannes Reinecke 16a9e5
-			 "rsplen:%d %pad %pad\n",
Hannes Reinecke 16a9e5
-			 pnvme_lport, pnvme_rport,
Hannes Reinecke 16a9e5
+	lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC | LOG_NVME_ABTS,
Hannes Reinecke 16a9e5
+			 "6040 NVMEx LS REQ Abort: Issue LS_ABORT for lsreq "
Hannes Reinecke 16a9e5
+			 "x%p rqstlen:%d rsplen:%d %pad %pad\n",
Hannes Reinecke 16a9e5
 			 pnvme_lsreq, pnvme_lsreq->rqstlen,
Hannes Reinecke 16a9e5
 			 pnvme_lsreq->rsplen, &pnvme_lsreq->rqstdma,
Hannes Reinecke 16a9e5
 			 &pnvme_lsreq->rspdma);
Hannes Reinecke 16a9e5
 
Hannes Reinecke 16a9e5
 	/*
Hannes Reinecke 16a9e5
-	 * Lock the ELS ring txcmplq and build a local list of all ELS IOs
Hannes Reinecke 16a9e5
-	 * that need an ABTS.  The IOs need to stay on the txcmplq so that
Hannes Reinecke 16a9e5
-	 * the abort operation completes them successfully.
Hannes Reinecke 16a9e5
+	 * Lock the ELS ring txcmplq and look for the wqe that matches
Hannes Reinecke 16a9e5
+	 * this ELS. If found, issue an abort on the wqe.
Hannes Reinecke 16a9e5
 	 */
Hannes Reinecke 16a9e5
 	pring = phba->sli4_hba.nvmels_wq->pring;
Hannes Reinecke 16a9e5
 	spin_lock_irq(&phba->hbalock);
Hannes Reinecke 16a9e5
 	spin_lock(&pring->ring_lock);
Hannes Reinecke 16a9e5
 	list_for_each_entry_safe(wqe, next_wqe, &pring->txcmplq, list) {
Hannes Reinecke 16a9e5
-		/* Add to abort_list on on NDLP match. */
Hannes Reinecke 16a9e5
-		if (lpfc_check_sli_ndlp(phba, pring, wqe, ndlp)) {
Hannes Reinecke 16a9e5
+		if (wqe->context2 == pnvme_lsreq) {
Hannes Reinecke 16a9e5
 			wqe->iocb_flag |= LPFC_DRIVER_ABORTED;
Hannes Reinecke 16a9e5
-			list_add_tail(&wqe->dlist, &abort_list);
Hannes Reinecke 16a9e5
+			foundit = true;
Hannes Reinecke 16a9e5
+			break;
Hannes Reinecke 16a9e5
 		}
Hannes Reinecke 16a9e5
 	}
Hannes Reinecke 16a9e5
 	spin_unlock(&pring->ring_lock);
Hannes Reinecke 16a9e5
+
Hannes Reinecke 16a9e5
+	if (foundit)
Hannes Reinecke 16a9e5
+		lpfc_sli_issue_abort_iotag(phba, pring, wqe);
Hannes Reinecke 16a9e5
 	spin_unlock_irq(&phba->hbalock);
Hannes Reinecke 16a9e5
 
Hannes Reinecke 16a9e5
-	/* Abort the targeted IOs and remove them from the abort list. */
Hannes Reinecke 16a9e5
-	list_for_each_entry_safe(wqe, next_wqe, &abort_list, dlist) {
Hannes Reinecke 16a9e5
+	if (foundit)
Hannes Reinecke 16a9e5
+		return 0;
Hannes Reinecke 16a9e5
+
Hannes Reinecke 16a9e5
+	lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC | LOG_NVME_ABTS,
Hannes Reinecke 16a9e5
+			 "6213 NVMEx LS REQ Abort: Unable to locate req x%p\n",
Hannes Reinecke 16a9e5
+			 pnvme_lsreq);
Hannes Reinecke 16a9e5
+	return 1;
Hannes Reinecke 16a9e5
+}
Hannes Reinecke 16a9e5
+
Hannes Reinecke 16a9e5
+/**
Hannes Reinecke 16a9e5
+ * lpfc_nvme_ls_abort - Abort a prior NVME LS request
Hannes Reinecke 16a9e5
+ * @lpfc_nvme_lport: Transport localport that LS is to be issued from.
Hannes Reinecke 16a9e5
+ * @lpfc_nvme_rport: Transport remoteport that LS is to be sent to.
Hannes Reinecke 16a9e5
+ * @pnvme_lsreq - the transport nvme_ls_req structure for the LS
Hannes Reinecke 16a9e5
+ *
Hannes Reinecke 16a9e5
+ * Driver registers this routine to abort a NVME LS request that is
Hannes Reinecke 16a9e5
+ * in progress (from the transports perspective).
Hannes Reinecke 16a9e5
+ **/
Hannes Reinecke 16a9e5
+static void
Hannes Reinecke 16a9e5
+lpfc_nvme_ls_abort(struct nvme_fc_local_port *pnvme_lport,
Hannes Reinecke 16a9e5
+		   struct nvme_fc_remote_port *pnvme_rport,
Hannes Reinecke 16a9e5
+		   struct nvmefc_ls_req *pnvme_lsreq)
Hannes Reinecke 16a9e5
+{
Hannes Reinecke 16a9e5
+	struct lpfc_nvme_lport *lport;
Hannes Reinecke 16a9e5
+	struct lpfc_vport *vport;
Hannes Reinecke 16a9e5
+	struct lpfc_hba *phba;
Hannes Reinecke 16a9e5
+	struct lpfc_nodelist *ndlp;
Hannes Reinecke 16a9e5
+	int ret;
Hannes Reinecke 16a9e5
+
Hannes Reinecke 16a9e5
+	lport = (struct lpfc_nvme_lport *)pnvme_lport->private;
Hannes Reinecke 16a9e5
+	if (unlikely(!lport))
Hannes Reinecke 16a9e5
+		return;
Hannes Reinecke 16a9e5
+	vport = lport->vport;
Hannes Reinecke 16a9e5
+	phba = vport->phba;
Hannes Reinecke 16a9e5
+
Hannes Reinecke 16a9e5
+	if (vport->load_flag & FC_UNLOADING)
Hannes Reinecke 16a9e5
+		return;
Hannes Reinecke 16a9e5
+
Hannes Reinecke 16a9e5
+	ndlp = lpfc_findnode_did(vport, pnvme_rport->port_id);
Hannes Reinecke 16a9e5
+
Hannes Reinecke 16a9e5
+	ret = __lpfc_nvme_ls_abort(vport, ndlp, pnvme_lsreq);
Hannes Reinecke 16a9e5
+	if (!ret)
Hannes Reinecke 16a9e5
 		atomic_inc(&lport->xmt_ls_abort);
Hannes Reinecke 16a9e5
-		spin_lock_irq(&phba->hbalock);
Hannes Reinecke 16a9e5
-		list_del_init(&wqe->dlist);
Hannes Reinecke 16a9e5
-		lpfc_sli_issue_abort_iotag(phba, pring, wqe);
Hannes Reinecke 16a9e5
-		spin_unlock_irq(&phba->hbalock);
Hannes Reinecke 16a9e5
-	}
Hannes Reinecke 16a9e5
 }
Hannes Reinecke 16a9e5
 
Hannes Reinecke 16a9e5
 /* Fix up the existing sgls for NVME IO. */
Hannes Reinecke 16a9e5
diff --git a/drivers/scsi/lpfc/lpfc_nvme.h b/drivers/scsi/lpfc/lpfc_nvme.h
Hannes Reinecke 16a9e5
index 6f8d44aa47b2..a9ad81d0c182 100644
Hannes Reinecke 16a9e5
--- a/drivers/scsi/lpfc/lpfc_nvme.h
Hannes Reinecke 16a9e5
+++ b/drivers/scsi/lpfc/lpfc_nvme.h
Hannes Reinecke 16a9e5
@@ -237,6 +237,8 @@ int __lpfc_nvme_ls_req(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
Hannes Reinecke 16a9e5
 				struct lpfc_wcqe_complete *wcqe));
Hannes Reinecke 16a9e5
 void __lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba,  struct lpfc_vport *vport,
Hannes Reinecke 16a9e5
 		struct lpfc_iocbq *cmdwqe, struct lpfc_wcqe_complete *wcqe);
Hannes Reinecke 16a9e5
+int __lpfc_nvme_ls_abort(struct lpfc_vport *vport,
Hannes Reinecke 16a9e5
+		struct lpfc_nodelist *ndlp, struct nvmefc_ls_req *pnvme_lsreq);
Hannes Reinecke 16a9e5
 
Hannes Reinecke 16a9e5
 /* routines found in lpfc_nvmet.c */
Hannes Reinecke 16a9e5
 int lpfc_nvme_unsol_ls_issue_abort(struct lpfc_hba *phba,
Hannes Reinecke 16a9e5
-- 
Hannes Reinecke 16a9e5
2.16.4
Hannes Reinecke 16a9e5