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

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
...@@ -119,6 +119,8 @@ struct bnxt_re_dev { ...@@ -119,6 +119,8 @@ struct bnxt_re_dev {
#define BNXT_RE_FLAG_HAVE_L2_REF 3 #define BNXT_RE_FLAG_HAVE_L2_REF 3
#define BNXT_RE_FLAG_RCFW_CHANNEL_EN 4 #define BNXT_RE_FLAG_RCFW_CHANNEL_EN 4
#define BNXT_RE_FLAG_QOS_WORK_REG 5 #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 #define BNXT_RE_FLAG_ISSUE_ROCE_STATS 29
struct net_device *netdev; struct net_device *netdev;
unsigned int version, major, minor; unsigned int version, major, minor;
......
...@@ -863,10 +863,8 @@ static void bnxt_re_cleanup_res(struct bnxt_re_dev *rdev) ...@@ -863,10 +863,8 @@ static void bnxt_re_cleanup_res(struct bnxt_re_dev *rdev)
{ {
int i; int i;
if (rdev->nq[0].hwq.max_elements) { for (i = 1; i < rdev->num_msix; i++)
for (i = 1; i < rdev->num_msix; i++) bnxt_qplib_disable_nq(&rdev->nq[i - 1]);
bnxt_qplib_disable_nq(&rdev->nq[i - 1]);
}
if (rdev->qplib_res.rcfw) if (rdev->qplib_res.rcfw)
bnxt_qplib_cleanup_res(&rdev->qplib_res); bnxt_qplib_cleanup_res(&rdev->qplib_res);
...@@ -875,6 +873,7 @@ static void bnxt_re_cleanup_res(struct bnxt_re_dev *rdev) ...@@ -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) static int bnxt_re_init_res(struct bnxt_re_dev *rdev)
{ {
int rc = 0, i; int rc = 0, i;
int num_vec_enabled = 0;
bnxt_qplib_init_res(&rdev->qplib_res); bnxt_qplib_init_res(&rdev->qplib_res);
...@@ -890,9 +889,13 @@ static int bnxt_re_init_res(struct bnxt_re_dev *rdev) ...@@ -890,9 +889,13 @@ static int bnxt_re_init_res(struct bnxt_re_dev *rdev)
"Failed to enable NQ with rc = 0x%x", rc); "Failed to enable NQ with rc = 0x%x", rc);
goto fail; goto fail;
} }
num_vec_enabled++;
} }
return 0; return 0;
fail: fail:
for (i = num_vec_enabled; i >= 0; i--)
bnxt_qplib_disable_nq(&rdev->nq[i]);
return rc; return rc;
} }
...@@ -924,6 +927,7 @@ static void bnxt_re_free_res(struct bnxt_re_dev *rdev) ...@@ -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) static int bnxt_re_alloc_res(struct bnxt_re_dev *rdev)
{ {
int rc = 0, i; int rc = 0, i;
int num_vec_created = 0;
/* Configure and allocate resources for qplib */ /* Configure and allocate resources for qplib */
rdev->qplib_res.rcfw = &rdev->rcfw; rdev->qplib_res.rcfw = &rdev->rcfw;
...@@ -950,7 +954,7 @@ static int bnxt_re_alloc_res(struct bnxt_re_dev *rdev) ...@@ -950,7 +954,7 @@ static int bnxt_re_alloc_res(struct bnxt_re_dev *rdev)
if (rc) { if (rc) {
dev_err(rdev_to_dev(rdev), "Alloc Failed NQ%d rc:%#x", dev_err(rdev_to_dev(rdev), "Alloc Failed NQ%d rc:%#x",
i, rc); i, rc);
goto dealloc_dpi; goto free_nq;
} }
rc = bnxt_re_net_ring_alloc rc = bnxt_re_net_ring_alloc
(rdev, rdev->nq[i].hwq.pbl[PBL_LVL_0].pg_map_arr, (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) ...@@ -963,14 +967,17 @@ static int bnxt_re_alloc_res(struct bnxt_re_dev *rdev)
dev_err(rdev_to_dev(rdev), dev_err(rdev_to_dev(rdev),
"Failed to allocate NQ fw id with rc = 0x%x", "Failed to allocate NQ fw id with rc = 0x%x",
rc); rc);
bnxt_qplib_free_nq(&rdev->nq[i]);
goto free_nq; goto free_nq;
} }
num_vec_created++;
} }
return 0; return 0;
free_nq: 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]); bnxt_qplib_free_nq(&rdev->nq[i]);
dealloc_dpi: }
bnxt_qplib_dealloc_dpi(&rdev->qplib_res, bnxt_qplib_dealloc_dpi(&rdev->qplib_res,
&rdev->qplib_res.dpi_tbl, &rdev->qplib_res.dpi_tbl,
&rdev->dpi_privileged); &rdev->dpi_privileged);
...@@ -1205,8 +1212,11 @@ static void bnxt_re_ib_unreg(struct bnxt_re_dev *rdev) ...@@ -1205,8 +1212,11 @@ static void bnxt_re_ib_unreg(struct bnxt_re_dev *rdev)
if (test_and_clear_bit(BNXT_RE_FLAG_QOS_WORK_REG, &rdev->flags)) if (test_and_clear_bit(BNXT_RE_FLAG_QOS_WORK_REG, &rdev->flags))
cancel_delayed_work_sync(&rdev->worker); cancel_delayed_work_sync(&rdev->worker);
bnxt_re_cleanup_res(rdev); if (test_and_clear_bit(BNXT_RE_FLAG_RESOURCES_INITIALIZED,
bnxt_re_free_res(rdev); &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)) { if (test_and_clear_bit(BNXT_RE_FLAG_RCFW_CHANNEL_EN, &rdev->flags)) {
rc = bnxt_qplib_deinit_rcfw(&rdev->rcfw); rc = bnxt_qplib_deinit_rcfw(&rdev->rcfw);
...@@ -1335,12 +1345,15 @@ static int bnxt_re_ib_reg(struct bnxt_re_dev *rdev) ...@@ -1335,12 +1345,15 @@ static int bnxt_re_ib_reg(struct bnxt_re_dev *rdev)
pr_err("Failed to allocate resources: %#x\n", rc); pr_err("Failed to allocate resources: %#x\n", rc);
goto fail; goto fail;
} }
set_bit(BNXT_RE_FLAG_RESOURCES_ALLOCATED, &rdev->flags);
rc = bnxt_re_init_res(rdev); rc = bnxt_re_init_res(rdev);
if (rc) { if (rc) {
pr_err("Failed to initialize resources: %#x\n", rc); pr_err("Failed to initialize resources: %#x\n", rc);
goto fail; goto fail;
} }
set_bit(BNXT_RE_FLAG_RESOURCES_INITIALIZED, &rdev->flags);
if (!rdev->is_virtfn) { if (!rdev->is_virtfn) {
rc = bnxt_re_setup_qos(rdev); rc = bnxt_re_setup_qos(rdev);
if (rc) if (rc)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment