Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5df95099 authored by Selvin Xavier's avatar Selvin Xavier Committed by Jason Gunthorpe
Browse files

RDMA/bnxt_re: Avoid resource leak in case the NQ registration fails



In case the NQ alloc/enable fails, free up the already allocated/enabled
NQ before reporting failure. Also, track the alloc/enable using proper
state checking.

Signed-off-by: default avatarSelvin Xavier <selvin.xavier@broadcom.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
parent a08b9e9a
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -119,6 +119,8 @@ struct bnxt_re_dev {
#define BNXT_RE_FLAG_HAVE_L2_REF		3
#define BNXT_RE_FLAG_RCFW_CHANNEL_EN		4
#define BNXT_RE_FLAG_QOS_WORK_REG		5
#define BNXT_RE_FLAG_RESOURCES_ALLOCATED	7
#define BNXT_RE_FLAG_RESOURCES_INITIALIZED	8
#define BNXT_RE_FLAG_ISSUE_ROCE_STATS          29
	struct net_device		*netdev;
	unsigned int			version, major, minor;
+22 −9
Original line number Diff line number Diff line
@@ -863,10 +863,8 @@ static void bnxt_re_cleanup_res(struct bnxt_re_dev *rdev)
{
	int i;

	if (rdev->nq[0].hwq.max_elements) {
	for (i = 1; i < rdev->num_msix; i++)
		bnxt_qplib_disable_nq(&rdev->nq[i - 1]);
	}

	if (rdev->qplib_res.rcfw)
		bnxt_qplib_cleanup_res(&rdev->qplib_res);
@@ -875,6 +873,7 @@ static void bnxt_re_cleanup_res(struct bnxt_re_dev *rdev)
static int bnxt_re_init_res(struct bnxt_re_dev *rdev)
{
	int rc = 0, i;
	int num_vec_enabled = 0;

	bnxt_qplib_init_res(&rdev->qplib_res);

@@ -890,9 +889,13 @@ static int bnxt_re_init_res(struct bnxt_re_dev *rdev)
				"Failed to enable NQ with rc = 0x%x", rc);
			goto fail;
		}
		num_vec_enabled++;
	}
	return 0;
fail:
	for (i = num_vec_enabled; i >= 0; i--)
		bnxt_qplib_disable_nq(&rdev->nq[i]);

	return rc;
}

@@ -924,6 +927,7 @@ static void bnxt_re_free_res(struct bnxt_re_dev *rdev)
static int bnxt_re_alloc_res(struct bnxt_re_dev *rdev)
{
	int rc = 0, i;
	int num_vec_created = 0;

	/* Configure and allocate resources for qplib */
	rdev->qplib_res.rcfw = &rdev->rcfw;
@@ -950,7 +954,7 @@ static int bnxt_re_alloc_res(struct bnxt_re_dev *rdev)
		if (rc) {
			dev_err(rdev_to_dev(rdev), "Alloc Failed NQ%d rc:%#x",
				i, rc);
			goto dealloc_dpi;
			goto free_nq;
		}
		rc = bnxt_re_net_ring_alloc
			(rdev, rdev->nq[i].hwq.pbl[PBL_LVL_0].pg_map_arr,
@@ -963,14 +967,17 @@ static int bnxt_re_alloc_res(struct bnxt_re_dev *rdev)
			dev_err(rdev_to_dev(rdev),
				"Failed to allocate NQ fw id with rc = 0x%x",
				rc);
			bnxt_qplib_free_nq(&rdev->nq[i]);
			goto free_nq;
		}
		num_vec_created++;
	}
	return 0;
free_nq:
	for (i = 0; i < rdev->num_msix - 1; i++)
	for (i = num_vec_created; i >= 0; i--) {
		bnxt_re_net_ring_free(rdev, rdev->nq[i].ring_id);
		bnxt_qplib_free_nq(&rdev->nq[i]);
dealloc_dpi:
	}
	bnxt_qplib_dealloc_dpi(&rdev->qplib_res,
			       &rdev->qplib_res.dpi_tbl,
			       &rdev->dpi_privileged);
@@ -1205,7 +1212,10 @@ static void bnxt_re_ib_unreg(struct bnxt_re_dev *rdev)
	if (test_and_clear_bit(BNXT_RE_FLAG_QOS_WORK_REG, &rdev->flags))
		cancel_delayed_work_sync(&rdev->worker);

	if (test_and_clear_bit(BNXT_RE_FLAG_RESOURCES_INITIALIZED,
			       &rdev->flags))
		bnxt_re_cleanup_res(rdev);
	if (test_and_clear_bit(BNXT_RE_FLAG_RESOURCES_ALLOCATED, &rdev->flags))
		bnxt_re_free_res(rdev);

	if (test_and_clear_bit(BNXT_RE_FLAG_RCFW_CHANNEL_EN, &rdev->flags)) {
@@ -1335,12 +1345,15 @@ static int bnxt_re_ib_reg(struct bnxt_re_dev *rdev)
		pr_err("Failed to allocate resources: %#x\n", rc);
		goto fail;
	}
	set_bit(BNXT_RE_FLAG_RESOURCES_ALLOCATED, &rdev->flags);
	rc = bnxt_re_init_res(rdev);
	if (rc) {
		pr_err("Failed to initialize resources: %#x\n", rc);
		goto fail;
	}

	set_bit(BNXT_RE_FLAG_RESOURCES_INITIALIZED, &rdev->flags);

	if (!rdev->is_virtfn) {
		rc = bnxt_re_setup_qos(rdev);
		if (rc)