diff options
| author | Leon Romanovsky <leonro@nvidia.com> | 2026-07-26 15:21:44 +0300 |
|---|---|---|
| committer | Leon Romanovsky <leonro@nvidia.com> | 2026-07-29 07:46:56 -0400 |
| commit | fdfb5cea4bf070cdb31d997efd87bb684df041fd (patch) | |
| tree | 45ee73df1eb6802e6cd424978b9d29ce032211f5 | |
| parent | 033a79e308e4fe832b0924347eda8c4364055174 (diff) | |
| download | linux-next-fdfb5cea4bf070cdb31d997efd87bb684df041fd.tar.gz linux-next-fdfb5cea4bf070cdb31d997efd87bb684df041fd.zip | |
RDMA/cxgb4: free STAG index when TPT entry write fails
write_tpt_entry() allocates a new STAG index with c4iw_get_resource() and
bumps stats.stag.cur before programming the entry. When
write_adapter_mem() fails, it returns the error without releasing the index
or reversing the statistic. No MR is inserted into rhp->mrs, so
deregistration never reclaims it, leaking the index until device teardown.
Record whether this call allocated the index and, on a failed write, return
it to tpt_table and decrement stats.stag.cur. Key the rollback on both the
write error and that flag, not the error alone: a non-reset update carries
a caller-owned STAG that this call did not allocate and must not free.
Fixes: ec3eead21718 ("RDMA/cxgb4: Remove kfifo usage")
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
| -rw-r--r-- | drivers/infiniband/hw/cxgb4/mem.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c index 1413bd0c0752..c28f76a32d90 100644 --- a/drivers/infiniband/hw/cxgb4/mem.c +++ b/drivers/infiniband/hw/cxgb4/mem.c @@ -254,6 +254,7 @@ static int write_tpt_entry(struct c4iw_rdev *rdev, u32 reset_tpt_entry, int err; struct fw_ri_tpte *tpt; u32 stag_idx; + bool stag_idx_allocated = false; static atomic_t key; if (c4iw_fatal_error(rdev)) { @@ -281,6 +282,7 @@ static int write_tpt_entry(struct c4iw_rdev *rdev, u32 reset_tpt_entry, return -ENOMEM; } mutex_lock(&rdev->stats.lock); + stag_idx_allocated = true; rdev->stats.stag.cur += 32; if (rdev->stats.stag.cur > rdev->stats.stag.max) rdev->stats.stag.max = rdev->stats.stag.cur; @@ -315,7 +317,7 @@ static int write_tpt_entry(struct c4iw_rdev *rdev, u32 reset_tpt_entry, (rdev->lldi.vr->stag.start >> 5), sizeof(*tpt), tpt, skb, wr_waitp); - if (reset_tpt_entry) { + if (reset_tpt_entry || (err && stag_idx_allocated)) { c4iw_put_resource(&rdev->resource.tpt_table, stag_idx); mutex_lock(&rdev->stats.lock); rdev->stats.stag.cur -= 32; |
