Daniel Wagner d56cdd
From: James Smart <jsmart2021@gmail.com>
Daniel Wagner d56cdd
Date: Fri, 3 Dec 2021 16:26:36 -0800
Daniel Wagner d56cdd
Subject: scsi: lpfc: Fix leaked lpfc_dmabuf mbox allocations with NPIV
Daniel Wagner d56cdd
Patch-mainline: Queued in subsystem maintainer repository
Daniel Wagner d56cdd
Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git
Daniel Wagner d56cdd
Git-commit: f0d3919697492950f57a26a1093aee53880d669d
Daniel Wagner d56cdd
References: bsc1192145
Daniel Wagner d56cdd
Daniel Wagner d56cdd
During rmmod testing, messages appeared indicating lpfc_mbuf_pool entries
Daniel Wagner d56cdd
were still busy. This situation was only seen doing rmmod after at least 1
Daniel Wagner d56cdd
vport (NPIV) instance was created and destroyed. The number of messages
Daniel Wagner d56cdd
scaled with the number of vports created.
Daniel Wagner d56cdd
Daniel Wagner d56cdd
When a vport is created, it can receive a PLOGI from another initiator
Daniel Wagner d56cdd
Nport.  When this happens, the driver prepares to ack the PLOGI and
Daniel Wagner d56cdd
prepares an RPI for registration (via mbx cmd) which includes an mbuf
Daniel Wagner d56cdd
allocation. During the unsolicited PLOGI processing and after the RPI
Daniel Wagner d56cdd
preparation, the driver recognizes it is one of the vport instances and
Daniel Wagner d56cdd
decides to reject the PLOGI. During the LS_RJT preparation for the PLOGI,
Daniel Wagner d56cdd
the mailbox struct allocated for RPI registration is freed, but the mbuf
Daniel Wagner d56cdd
that was also allocated is not released.
Daniel Wagner d56cdd
Daniel Wagner d56cdd
Fix by freeing the mbuf with the mailbox struct in the LS_RJT path.
Daniel Wagner d56cdd
Daniel Wagner d56cdd
As part of the code review to figure the issue out a couple of other areas
Daniel Wagner d56cdd
where found that also would not have released the mbuf. Those are cleaned
Daniel Wagner d56cdd
up as well.
Daniel Wagner d56cdd
Daniel Wagner d56cdd
Link: https://lore.kernel.org/r/20211204002644.116455-2-jsmart2021@gmail.com
Daniel Wagner d56cdd
Co-developed-by: Justin Tee <justin.tee@broadcom.com>
Daniel Wagner d56cdd
Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Daniel Wagner d56cdd
Signed-off-by: James Smart <jsmart2021@gmail.com>
Daniel Wagner d56cdd
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Daniel Wagner d56cdd
Acked-by: Daniel Wagner <dwagner@suse.de>
Daniel Wagner d56cdd
---
Daniel Wagner d56cdd
 drivers/scsi/lpfc/lpfc_els.c       |    6 +++++-
Daniel Wagner d56cdd
 drivers/scsi/lpfc/lpfc_init.c      |    8 ++++++--
Daniel Wagner d56cdd
 drivers/scsi/lpfc/lpfc_nportdisc.c |    6 ++++++
Daniel Wagner d56cdd
 3 files changed, 17 insertions(+), 3 deletions(-)
Daniel Wagner d56cdd
Daniel Wagner d56cdd
--- a/drivers/scsi/lpfc/lpfc_els.c
Daniel Wagner d56cdd
+++ b/drivers/scsi/lpfc/lpfc_els.c
Daniel Wagner d56cdd
@@ -6851,6 +6851,7 @@ static int
Daniel Wagner d56cdd
 lpfc_get_rdp_info(struct lpfc_hba *phba, struct lpfc_rdp_context *rdp_context)
Daniel Wagner d56cdd
 {
Daniel Wagner d56cdd
 	LPFC_MBOXQ_t *mbox = NULL;
Daniel Wagner d56cdd
+	struct lpfc_dmabuf *mp;
Daniel Wagner d56cdd
 	int rc;
Daniel Wagner d56cdd
 
Daniel Wagner d56cdd
 	mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
Daniel Wagner d56cdd
@@ -6866,8 +6867,11 @@ lpfc_get_rdp_info(struct lpfc_hba *phba,
Daniel Wagner d56cdd
 	mbox->mbox_cmpl = lpfc_mbx_cmpl_rdp_page_a0;
Daniel Wagner d56cdd
 	mbox->ctx_ndlp = (struct lpfc_rdp_context *)rdp_context;
Daniel Wagner d56cdd
 	rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
Daniel Wagner d56cdd
-	if (rc == MBX_NOT_FINISHED)
Daniel Wagner d56cdd
+	if (rc == MBX_NOT_FINISHED) {
Daniel Wagner d56cdd
+		mp = (struct lpfc_dmabuf *)mbox->ctx_buf;
Daniel Wagner d56cdd
+		lpfc_mbuf_free(phba, mp->virt, mp->phys);
Daniel Wagner d56cdd
 		goto issue_mbox_fail;
Daniel Wagner d56cdd
+	}
Daniel Wagner d56cdd
 
Daniel Wagner d56cdd
 	return 0;
Daniel Wagner d56cdd
 
Daniel Wagner d56cdd
--- a/drivers/scsi/lpfc/lpfc_init.c
Daniel Wagner d56cdd
+++ b/drivers/scsi/lpfc/lpfc_init.c
Daniel Wagner d56cdd
@@ -5278,8 +5278,10 @@ lpfc_sli4_async_link_evt(struct lpfc_hba
Daniel Wagner d56cdd
 	 */
Daniel Wagner d56cdd
 	if (!(phba->hba_flag & HBA_FCOE_MODE)) {
Daniel Wagner d56cdd
 		rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
Daniel Wagner d56cdd
-		if (rc == MBX_NOT_FINISHED)
Daniel Wagner d56cdd
+		if (rc == MBX_NOT_FINISHED) {
Daniel Wagner d56cdd
+			lpfc_mbuf_free(phba, mp->virt, mp->phys);
Daniel Wagner d56cdd
 			goto out_free_dmabuf;
Daniel Wagner d56cdd
+		}
Daniel Wagner d56cdd
 		return;
Daniel Wagner d56cdd
 	}
Daniel Wagner d56cdd
 	/*
Daniel Wagner d56cdd
@@ -6242,8 +6244,10 @@ lpfc_sli4_async_fc_evt(struct lpfc_hba *
Daniel Wagner d56cdd
 	}
Daniel Wagner d56cdd
 
Daniel Wagner d56cdd
 	rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
Daniel Wagner d56cdd
-	if (rc == MBX_NOT_FINISHED)
Daniel Wagner d56cdd
+	if (rc == MBX_NOT_FINISHED) {
Daniel Wagner d56cdd
+		lpfc_mbuf_free(phba, mp->virt, mp->phys);
Daniel Wagner d56cdd
 		goto out_free_dmabuf;
Daniel Wagner d56cdd
+	}
Daniel Wagner d56cdd
 	return;
Daniel Wagner d56cdd
 
Daniel Wagner d56cdd
 out_free_dmabuf:
Daniel Wagner d56cdd
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
Daniel Wagner d56cdd
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
Daniel Wagner d56cdd
@@ -324,6 +324,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport,
Daniel Wagner d56cdd
 {
Daniel Wagner d56cdd
 	struct lpfc_hba    *phba = vport->phba;
Daniel Wagner d56cdd
 	struct lpfc_dmabuf *pcmd;
Daniel Wagner d56cdd
+	struct lpfc_dmabuf *mp;
Daniel Wagner d56cdd
 	uint64_t nlp_portwwn = 0;
Daniel Wagner d56cdd
 	uint32_t *lp;
Daniel Wagner d56cdd
 	IOCB_t *icmd;
Daniel Wagner d56cdd
@@ -568,6 +569,11 @@ lpfc_rcv_plogi(struct lpfc_vport *vport,
Daniel Wagner d56cdd
 		 * a default RPI.
Daniel Wagner d56cdd
 		 */
Daniel Wagner d56cdd
 		if (phba->sli_rev == LPFC_SLI_REV4) {
Daniel Wagner d56cdd
+			mp = (struct lpfc_dmabuf *)login_mbox->ctx_buf;
Daniel Wagner d56cdd
+			if (mp) {
Daniel Wagner d56cdd
+				lpfc_mbuf_free(phba, mp->virt, mp->phys);
Daniel Wagner d56cdd
+				kfree(mp);
Daniel Wagner d56cdd
+			}
Daniel Wagner d56cdd
 			mempool_free(login_mbox, phba->mbox_mem_pool);
Daniel Wagner d56cdd
 			login_mbox = NULL;
Daniel Wagner d56cdd
 		} else {