From: <nshettyj@marvell.com>
To: <netdev@vger.kernel.org>, <linux-kernel@vger.kernel.org>
Cc: Rakesh Kudurumalla <rkudurumalla@marvell.com>,
Nitin Shetty J <nshettyj@marvell.com>,
Sunil Goutham <sgoutham@marvell.com>,
"Ratheesh Kannoth" <rkannoth@marvell.com>,
Geetha sowjanya <gakula@marvell.com>,
Subbaraya Sundeep <sbhatta@marvell.com>,
Andrew Lunn <andrew+netdev@lunn.ch>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@kernel.org>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
"Simon Horman" <horms@kernel.org>
Subject: [PATCH net v3] octeontx2-af: Fix BPID leak in nix_bp_enable()
Date: Mon, 28 Sep 2026 12:27:17 +0530 [thread overview]
Message-ID: <20260928065718.3378580-1-nshettyj@marvell.com> (raw)
From: Rakesh Kudurumalla <rkudurumalla@marvell.com>
For LBK interfaces, rvu_nix_get_bpid() allocates a BPID from the free
pool on every call. nix_bp_enable() called it unconditionally before
the loop, and again after the last channel was programmed, leaking a
BPID whenever that extra call's result went unused. With
req->chan_cnt == 0, the pre-loop call leaked a BPID on every call.
Move the allocation into the loop body so it runs exactly once per
channel actually programmed, and reject req->chan_cnt == 0 upfront.
Fixes: d6212d2e41a0 ("octeontx2-af: Create BPIDs free pool")
Signed-off-by: Nitin Shetty J <nshettyj@marvell.com>
Signed-off-by: Rakesh Kudurumalla <rkudurumalla@marvell.com>
---
changes in v3:
- Unwind BPID allocations and disable programmed channels on mid-loop failure in `nix_bp_enable()`.
- Report the actual BPID written per channel instead of reconstructing it arithmetically.
- Validate the BPID range in `nix_bp_disable()` before freeing it, preventing an out-of-bounds write.
changes in v2:
- Move the rvu_nix_get_bpid() call for LBK BPID allocation from before
the loop into the loop body.
- Validate req->chan_cnt before allocating BPIDs.
- updated commit message and fix tag
---
.../ethernet/marvell/octeontx2/af/rvu_nix.c | 79 ++++++++++++++++---
1 file changed, 66 insertions(+), 13 deletions(-)
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
index 153eb57bad06..1ef505009c3a 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
@@ -631,6 +631,15 @@ static int nix_bp_disable(struct rvu *rvu,
if (type == NIX_INTF_TYPE_LBK) {
bpid = cfg & GENMASK(8, 0);
+ /* Ignore channels that were never armed with an LBK
+ * free-pool bpid (e.g. never enabled, or belonging
+ * to a CGX/SDP range) - bpid - free_pool_base would
+ * underflow and corrupt an unrelated bitmap word.
+ */
+ if (bpid < bp->free_pool_base ||
+ bpid >= bp->free_pool_base + bp->bpids.max)
+ continue;
+
mutex_lock(&rvu->rsrc_lock);
rvu_free_rsrc(&bp->bpids, bpid - bp->free_pool_base);
for (bpid = 0; bpid < bp->bpids.max; bpid++) {
@@ -738,6 +747,35 @@ static int rvu_nix_get_bpid(struct rvu *rvu, struct nix_bp_cfg_req *req,
return bpid;
}
+static void nix_bp_enable_unwind(struct rvu *rvu, struct nix_bp *bp,
+ int blkaddr, u16 chan_base, int chan_cnt,
+ int type, bool cpt_link)
+{
+ u16 chan, chan_v, bpid;
+ u64 cfg;
+
+ for (chan = chan_base; chan < chan_base + chan_cnt; chan++) {
+ chan_v = nix_get_channel(chan, cpt_link);
+ cfg = rvu_read64(rvu, blkaddr, NIX_AF_RX_CHANX_CFG(chan_v));
+ rvu_write64(rvu, blkaddr, NIX_AF_RX_CHANX_CFG(chan_v),
+ cfg & ~BIT_ULL(16));
+
+ if (type != NIX_INTF_TYPE_LBK)
+ continue;
+
+ bpid = cfg & GENMASK_ULL(8, 0);
+ if (bpid < bp->free_pool_base ||
+ bpid >= bp->free_pool_base + bp->bpids.max)
+ continue;
+
+ mutex_lock(&rvu->rsrc_lock);
+ rvu_free_rsrc(&bp->bpids, bpid - bp->free_pool_base);
+ bp->fn_map[bpid - bp->free_pool_base] = 0;
+ bp->ref_cnt[bpid - bp->free_pool_base] = 0;
+ mutex_unlock(&rvu->rsrc_lock);
+ }
+}
+
static int nix_bp_enable(struct rvu *rvu,
struct nix_bp_cfg_req *req,
struct nix_bp_cfg_rsp *rsp,
@@ -747,9 +785,12 @@ static int nix_bp_enable(struct rvu *rvu,
u16 pcifunc = req->hdr.pcifunc;
struct rvu_pfvf *pfvf;
u16 chan_base, chan;
- s16 bpid, bpid_base;
+ struct nix_hw *nix_hw;
+ struct nix_bp *bp;
u16 chan_v;
+ s16 bpid;
u64 cfg;
+ int err;
pf = rvu_get_pf(rvu->pdev, pcifunc);
type = is_lbk_vf(rvu, pcifunc) ? NIX_INTF_TYPE_LBK : NIX_INTF_TYPE_CGX;
@@ -764,16 +805,27 @@ static int nix_bp_enable(struct rvu *rvu,
if (cpt_link && !rvu->hw->cpt_links)
return 0;
+ if (!req->chan_cnt)
+ return NIX_AF_ERR_INVALID_BPID_REQ;
+
pfvf = rvu_get_pfvf(rvu, pcifunc);
- blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc);
+ err = nix_get_struct_ptrs(rvu, pcifunc, &nix_hw, &blkaddr);
+ if (err)
+ return err;
- bpid_base = rvu_nix_get_bpid(rvu, req, type, chan_id);
+ bp = &nix_hw->bp;
chan_base = pfvf->rx_chan_base + req->chan_base;
- bpid = bpid_base;
for (chan = chan_base; chan < (chan_base + req->chan_cnt); chan++) {
+ bpid = rvu_nix_get_bpid(rvu, req, type, chan_id);
if (bpid < 0) {
dev_warn(rvu->dev, "Fail to enable backpressure\n");
+ /* Undo the channels already enabled/allocated for
+ * this request so their BPIDs and armed channels
+ * don't leak until an FLR.
+ */
+ nix_bp_enable_unwind(rvu, bp, blkaddr, chan_base,
+ chan_id, type, cpt_link);
return -EINVAL;
}
@@ -783,16 +835,17 @@ static int nix_bp_enable(struct rvu *rvu,
cfg &= ~GENMASK_ULL(8, 0);
rvu_write64(rvu, blkaddr, NIX_AF_RX_CHANX_CFG(chan_v),
cfg | (bpid & GENMASK_ULL(8, 0)) | BIT_ULL(16));
- chan_id++;
- bpid = rvu_nix_get_bpid(rvu, req, type, chan_id);
- }
- for (chan = 0; chan < req->chan_cnt; chan++) {
- /* Map channel and bpid assign to it */
- rsp->chan_bpid[chan] = ((req->chan_base + chan) & 0x7F) << 10 |
- (bpid_base & 0x3FF);
- if (req->bpid_per_chan)
- bpid_base++;
+ /* Report the bpid actually programmed for this channel,
+ * instead of reconstructing it arithmetically from the
+ * first channel's bpid. For LBK, each call above can
+ * return a non-contiguous bpid from the shared free pool,
+ * so that reconstruction can diverge from what's actually
+ * written into NIX_AF_RX_CHANX_CFG.
+ */
+ rsp->chan_bpid[chan_id] = ((req->chan_base + chan_id) & 0x7F) << 10 |
+ (bpid & 0x3FF);
+ chan_id++;
}
rsp->chan_cnt = req->chan_cnt;
--
2.48.1
next reply other threads:[~2026-09-28 6:57 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-28 6:57 nshettyj [this message]
2026-09-28 6:59 ` netdev-bot+sinfo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260928065718.3378580-1-nshettyj@marvell.com \
--to=nshettyj@marvell.com \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@kernel.org \
--cc=gakula@marvell.com \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=rkannoth@marvell.com \
--cc=rkudurumalla@marvell.com \
--cc=sbhatta@marvell.com \
--cc=sgoutham@marvell.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®