mirror of
https://github.com/opnsense/src.git
synced 2026-06-11 09:41:03 -04:00
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)
This commit is contained in:
parent
85e7e2c8e8
commit
79737136df
4 changed files with 114 additions and 63 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue