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: Selvin Xavier <selvin.xavier@broadcom.com> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
This commit is contained in:
parent
a08b9e9a70
commit
5df9509949
|
@ -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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
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)
|
||||||
"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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
|
|
Loading…
Reference in New Issue