Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 10 Dec 2025 17:38:59 +0000
From:      Krzysztof Galazka <kgalazka@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Cc:        Bartosz Sobczak <bartosz.sobczak@intel.com>
Subject:   git: bb69c090b5b2 - stable/15 - irdma(4): fix potential memory leak on qhash cqp operation
Message-ID:  <6939b033.a199.33fb60e6@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help

The branch stable/15 has been updated by kgalazka:

URL: https://cgit.FreeBSD.org/src/commit/?id=bb69c090b5b21ac243c5be2c5679114473c73b12

commit bb69c090b5b21ac243c5be2c5679114473c73b12
Author:     Bartosz Sobczak <bartosz.sobczak@intel.com>
AuthorDate: 2025-11-24 18:41:41 +0000
Commit:     Krzysztof Galazka <kgalazka@FreeBSD.org>
CommitDate: 2025-12-10 17:20:56 +0000

    irdma(4): fix potential memory leak on qhash cqp operation
    
    It was found that in some circumstances when launching
    non-waiting create qhash cqp operation the refcount on
    the cqp_request may be not properly decremented leading to a memory
    leak.
    
    Signed-off-by: Bartosz Sobczak <bartosz.sobczak@intel.com>
    
    Reviewed by:    anzhu_netapp.com
    Tested by:      mateusz.moga_intel.com
    Approved by:    kbowling (mentor)
    Sponsored by:   Intel Corporation
    Differential Revision:  https://reviews.freebsd.org/D53732
    
    (cherry picked from commit 7b6644e160ed63b633e7c68a3cacf2c71d216cd5)
---
 sys/dev/irdma/icrdma.c     |   4 +-
 sys/dev/irdma/irdma_cm.c   |  38 +------------
 sys/dev/irdma/irdma_hw.c   | 132 ++++++++++++++++++++++++++++++++++++---------
 sys/dev/irdma/irdma_main.h |   3 +-
 4 files changed, 114 insertions(+), 63 deletions(-)

diff --git a/sys/dev/irdma/icrdma.c b/sys/dev/irdma/icrdma.c
index 576a185b013f..a4f3904a820c 100644
--- a/sys/dev/irdma/icrdma.c
+++ b/sys/dev/irdma/icrdma.c
@@ -1,7 +1,7 @@
 /*-
  * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB
  *
- * Copyright (c) 2021 - 2023 Intel Corporation
+ * Copyright (c) 2021 - 2025 Intel Corporation
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -52,7 +52,7 @@
 /**
  *  Driver version
  */
-char irdma_driver_version[] = "1.2.36-k";
+char irdma_driver_version[] = "1.2.37-k";
 
 /**
  * irdma_init_tunable - prepare tunables
diff --git a/sys/dev/irdma/irdma_cm.c b/sys/dev/irdma/irdma_cm.c
index d4d4f328fb43..f3ca761b32f6 100644
--- a/sys/dev/irdma/irdma_cm.c
+++ b/sys/dev/irdma/irdma_cm.c
@@ -1,7 +1,7 @@
 /*-
  * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB
  *
- * Copyright (c) 2015 - 2023 Intel Corporation
+ * Copyright (c) 2015 - 2025 Intel Corporation
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -1683,31 +1683,6 @@ irdma_get_vlan_ipv4(struct iw_cm_id *cm_id, u32 *addr)
 	return vlan_id;
 }
 
-static int
-irdma_manage_qhash_wait(struct irdma_pci_f *rf, struct irdma_cm_info *cm_info)
-{
-	struct irdma_cqp_request *cqp_request = cm_info->cqp_request;
-	int cnt = rf->sc_dev.hw_attrs.max_cqp_compl_wait_time_ms * CQP_TIMEOUT_THRESHOLD;
-	u32 ret_val;
-
-	if (!cqp_request)
-		return -ENOMEM;
-	do {
-		irdma_cqp_ce_handler(rf, &rf->ccq.sc_cq);
-		mdelay(1);
-	} while (!READ_ONCE(cqp_request->request_done) && --cnt);
-
-	ret_val = cqp_request->compl_info.op_ret_val;
-	irdma_put_cqp_request(&rf->cqp, cqp_request);
-	if (cnt) {
-		if (!ret_val)
-			return 0;
-		return -EINVAL;
-	}
-
-	return -ETIMEDOUT;
-}
-
 /**
  * irdma_add_mqh_ifa_cb - Adds multiple qhashes for IPv4/IPv6
  * @arg: Calback argument structure from irdma_add_mqh
@@ -1771,16 +1746,7 @@ irdma_add_mqh_ifa_cb(void *arg, struct ifaddr *ifa, u_int count)
 		    irdma_iw_get_vlan_prio(child_listen_node->loc_addr,
 					   cm_info->user_pri,
 					   cm_info->ipv4);
-	ret = irdma_manage_qhash(iwdev, cm_info,
-				 IRDMA_QHASH_TYPE_TCP_SYN,
-				 IRDMA_QHASH_MANAGE_TYPE_ADD,
-				 NULL, false);
-	if (ret) {
-		kfree(child_listen_node);
-		return ret;
-	}
-	/* wait for qhash finish */
-	ret = irdma_manage_qhash_wait(iwdev->rf, cm_info);
+	ret = irdma_add_qhash_wait_no_lock(iwdev, cm_info);
 	if (ret) {
 		kfree(child_listen_node);
 		return ret;
diff --git a/sys/dev/irdma/irdma_hw.c b/sys/dev/irdma/irdma_hw.c
index 05004b1ccc83..64c05b8663e0 100644
--- a/sys/dev/irdma/irdma_hw.c
+++ b/sys/dev/irdma/irdma_hw.c
@@ -1,7 +1,7 @@
 /*-
  * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB
  *
- * Copyright (c) 2015 - 2023 Intel Corporation
+ * Copyright (c) 2015 - 2025 Intel Corporation
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -2581,35 +2581,22 @@ irdma_send_syn_cqp_callback(struct irdma_cqp_request *cqp_request)
 }
 
 /**
- * irdma_manage_qhash - add or modify qhash
+ * irdma_qhash_info_prepare - fill info for qhash op
  * @iwdev: irdma device
+ * @cqp_info: cqp info
  * @cminfo: cm info for qhash
  * @etype: type (syn or quad)
  * @mtype: type of qhash
- * @cmnode: cmnode associated with connection
- * @wait: wait for completion
  */
-int
-irdma_manage_qhash(struct irdma_device *iwdev, struct irdma_cm_info *cminfo,
-		   enum irdma_quad_entry_type etype,
-		   enum irdma_quad_hash_manage_type mtype, void *cmnode,
-		   bool wait)
+static void
+irdma_qhash_info_prepare(struct irdma_device *iwdev,
+			 struct cqp_cmds_info *cqp_info,
+			 struct irdma_cm_info *cminfo,
+			 enum irdma_quad_entry_type etype,
+			 enum irdma_quad_hash_manage_type mtype)
 {
 	struct irdma_qhash_table_info *info;
-	struct irdma_cqp *iwcqp = &iwdev->rf->cqp;
-	struct irdma_cqp_request *cqp_request;
-	struct cqp_cmds_info *cqp_info;
-	struct irdma_cm_node *cm_node = cmnode;
-	int status;
-
-	cqp_request = irdma_alloc_and_get_cqp_request(iwcqp, wait);
-	if (!cqp_request)
-		return -ENOMEM;
 
-	cminfo->cqp_request = cqp_request;
-	if (!wait)
-		atomic_inc(&cqp_request->refcnt);
-	cqp_info = &cqp_request->info;
 	info = &cqp_info->in.u.manage_qhash_table_entry.info;
 	memset(info, 0, sizeof(*info));
 	info->vsi = &iwdev->vsi;
@@ -2641,6 +2628,105 @@ irdma_manage_qhash(struct irdma_device *iwdev, struct irdma_cm_info *cminfo,
 		info->src_ip[2] = cminfo->rem_addr[2];
 		info->src_ip[3] = cminfo->rem_addr[3];
 	}
+	cqp_info->cqp_cmd = IRDMA_OP_MANAGE_QHASH_TABLE_ENTRY;
+	cqp_info->post_sq = 1;
+}
+
+/**
+ * irdma_add_qhash_wait_no_lock - add qhash, blocking w/o lock
+ * @iwdev: irdma device
+ * @cminfo: cm info for qhash
+ */
+int
+irdma_add_qhash_wait_no_lock(struct irdma_device *iwdev,
+			     struct irdma_cm_info *cminfo)
+{
+	struct irdma_qhash_table_info *info;
+	struct irdma_cqp *iwcqp = &iwdev->rf->cqp;
+	struct irdma_cqp_request *cqp_request;
+	struct cqp_cmds_info *cqp_info;
+	int cnt = iwdev->rf->sc_dev.hw_attrs.max_cqp_compl_wait_time_ms * CQP_TIMEOUT_THRESHOLD;
+	int status;
+	int ret_val;
+
+	cqp_request = irdma_alloc_and_get_cqp_request(iwcqp, false);
+	if (!cqp_request)
+		return -ENOMEM;
+
+	cqp_info = &cqp_request->info;
+	info = &cqp_info->in.u.manage_qhash_table_entry.info;
+	irdma_qhash_info_prepare(iwdev, cqp_info, cminfo, IRDMA_QHASH_TYPE_TCP_SYN,
+				 IRDMA_QHASH_MANAGE_TYPE_ADD);
+	if (info->ipv4_valid)
+		irdma_debug(&iwdev->rf->sc_dev, IRDMA_DEBUG_CM,
+			    "ADD caller: %pS loc_port=0x%04x rem_port=0x%04x loc_addr=%x rem_addr=%x mac=%x:%x:%x:%x:%x:%x, vlan_id=%d\n",
+			    __builtin_return_address(0), info->src_port,
+			    info->dest_port, info->src_ip[0], info->dest_ip[0],
+			    info->mac_addr[0], info->mac_addr[1],
+			    info->mac_addr[2], info->mac_addr[3],
+			    info->mac_addr[4], info->mac_addr[5],
+			    cminfo->vlan_id);
+	else
+		irdma_debug(&iwdev->rf->sc_dev, IRDMA_DEBUG_CM,
+			    "ADD caller: %pS loc_port=0x%04x rem_port=0x%04x loc_addr=%x:%x:%x:%x rem_addr=%x:%x:%x:%x mac=%x:%x:%x:%x:%x:%x, vlan_id=%d\n",
+			    __builtin_return_address(0), info->src_port,
+			    info->dest_port, IRDMA_PRINT_IP6(info->src_ip),
+			    IRDMA_PRINT_IP6(info->dest_ip), info->mac_addr[0],
+			    info->mac_addr[1], info->mac_addr[2],
+			    info->mac_addr[3], info->mac_addr[4],
+			    info->mac_addr[5], cminfo->vlan_id);
+
+	cqp_info->in.u.manage_qhash_table_entry.cqp = &iwdev->rf->cqp.sc_cqp;
+	cqp_info->in.u.manage_qhash_table_entry.scratch = (uintptr_t)cqp_request;
+	status = irdma_handle_cqp_op(iwdev->rf, cqp_request);
+	if (status) {
+		irdma_put_cqp_request(iwcqp, cqp_request);
+		irdma_dev_warn(&iwdev->ibdev, "manage_qhash cqp op failure %d\n", status);
+		return status;
+	}
+
+	do {
+		irdma_cqp_ce_handler(iwdev->rf, &iwdev->rf->ccq.sc_cq);
+		mdelay(1);
+	} while (!READ_ONCE(cqp_request->request_done) && --cnt);
+
+	ret_val = cqp_request->compl_info.op_ret_val;
+	status = (cnt) ? ret_val : -ETIMEDOUT;
+
+	irdma_put_cqp_request(iwcqp, cqp_request);
+
+	return status;
+}
+
+/**
+ * irdma_manage_qhash - add or modify qhash
+ * @iwdev: irdma device
+ * @cminfo: cm info for qhash
+ * @etype: type (syn or quad)
+ * @mtype: type of qhash
+ * @cmnode: cmnode associated with connection
+ * @wait: wait for completion
+ */
+int
+irdma_manage_qhash(struct irdma_device *iwdev, struct irdma_cm_info *cminfo,
+		   enum irdma_quad_entry_type etype,
+		   enum irdma_quad_hash_manage_type mtype, void *cmnode,
+		   bool wait)
+{
+	struct irdma_qhash_table_info *info;
+	struct irdma_cqp *iwcqp = &iwdev->rf->cqp;
+	struct irdma_cqp_request *cqp_request;
+	struct cqp_cmds_info *cqp_info;
+	struct irdma_cm_node *cm_node = cmnode;
+	int status;
+
+	cqp_request = irdma_alloc_and_get_cqp_request(iwcqp, wait);
+	if (!cqp_request)
+		return -ENOMEM;
+
+	cqp_info = &cqp_request->info;
+	info = &cqp_info->in.u.manage_qhash_table_entry.info;
+	irdma_qhash_info_prepare(iwdev, cqp_info, cminfo, etype, mtype);
 	if (cmnode) {
 		cqp_request->callback_fcn = irdma_send_syn_cqp_callback;
 		cqp_request->param = cmnode;
@@ -2671,8 +2757,6 @@ irdma_manage_qhash(struct irdma_device *iwdev, struct irdma_cm_info *cminfo,
 
 	cqp_info->in.u.manage_qhash_table_entry.cqp = &iwdev->rf->cqp.sc_cqp;
 	cqp_info->in.u.manage_qhash_table_entry.scratch = (uintptr_t)cqp_request;
-	cqp_info->cqp_cmd = IRDMA_OP_MANAGE_QHASH_TABLE_ENTRY;
-	cqp_info->post_sq = 1;
 	status = irdma_handle_cqp_op(iwdev->rf, cqp_request);
 	if (status && cm_node && !wait)
 		irdma_rem_ref_cm_node(cm_node);
diff --git a/sys/dev/irdma/irdma_main.h b/sys/dev/irdma/irdma_main.h
index 5b292ceafea8..9181f3b70463 100644
--- a/sys/dev/irdma/irdma_main.h
+++ b/sys/dev/irdma/irdma_main.h
@@ -1,7 +1,7 @@
 /*-
  * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB
  *
- * Copyright (c) 2015 - 2023 Intel Corporation
+ * Copyright (c) 2015 - 2025 Intel Corporation
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -563,6 +563,7 @@ int irdma_manage_qhash(struct irdma_device *iwdev, struct irdma_cm_info *cminfo,
 		       enum irdma_quad_entry_type etype,
 		       enum irdma_quad_hash_manage_type mtype, void *cmnode,
 		       bool wait);
+int irdma_add_qhash_wait_no_lock(struct irdma_device *iwdev, struct irdma_cm_info *cminfo);
 void irdma_receive_ilq(struct irdma_sc_vsi *vsi, struct irdma_puda_buf *rbuf);
 void irdma_free_sqbuf(struct irdma_sc_vsi *vsi, void *bufp);
 void irdma_free_qp_rsrc(struct irdma_qp *iwqp);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6939b033.a199.33fb60e6>