octeontx2-af: npc: cn20k: Propagate errors in defrag MCAM alloc rollback

npc_defrag_alloc_free_slots() allocates MCAM indexes in up to two passes on
bank0 then bank1. On failure it rolls back by freeing entries already
placed in save[].

__npc_subbank_alloc() can return a negative errno while only part of the
indexes are valid. The rollback loop used rc for
npc_mcam_idx_2_subbank_idx() as well, so a successful lookup stored zero in
rc and a later __npc_subbank_free() failure could still end with return 0
when the allocation path had also left rc at zero (for example shortfall
after zero return values from the alloc helpers).

Jump to the rollback path immediately when either __npc_subbank_alloc()
call fails, preserving its errno. If both calls succeed but the total
allocated count is still less than cnt, set rc to -ENOSPC before rollback.
Use a separate err variable for npc_mcam_idx_2_subbank_idx() so a
successful lookup no longer clears a non-zero rc from the allocation phase.

Cc: Dan Carpenter <error27@gmail.com>
Fixes: 645c6e3c19 ("octeontx2-af: npc: cn20k: virtual index support")
Link: https://lore.kernel.org/netdev/adjNJEpILRZATB2N@stanley.mountain/
Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
Link: https://patch.msgid.link/20260429022722.1110289-4-rkannoth@marvell.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Ratheesh Kannoth
2026-04-29 07:57:15 +05:30
committed by Jakub Kicinski
parent 1100af13fd
commit adb5ff41ef

View File

@@ -2338,6 +2338,7 @@ static int __npc_subbank_alloc(struct rvu *rvu, struct npc_subbank *sb,
__npc_subbank_mark_free(rvu, sb);
err1:
kfree(save);
*alloc_cnt = 0;
return rc;
}
@@ -3515,7 +3516,7 @@ static int npc_defrag_alloc_free_slots(struct rvu *rvu,
{
int alloc_cnt1, alloc_cnt2;
struct npc_subbank *sb;
int rc, sb_off, i;
int rc, sb_off, i, err;
bool deleted;
sb = &npc_priv.sb[f->idx];
@@ -3529,6 +3530,7 @@ static int npc_defrag_alloc_free_slots(struct rvu *rvu,
NPC_MCAM_LOWER_PRIO,
false, cnt, save, cnt, true,
&alloc_cnt1);
if (alloc_cnt1 < cnt) {
rc = __npc_subbank_alloc(rvu, sb,
NPC_MCAM_KEY_X2, sb->b1b,
@@ -3544,15 +3546,17 @@ static int npc_defrag_alloc_free_slots(struct rvu *rvu,
dev_err(rvu->dev,
"%s: Failed to alloc cnt=%u alloc_cnt1=%u alloc_cnt2=%u\n",
__func__, cnt, alloc_cnt1, alloc_cnt2);
rc = -ENOSPC;
goto fail_free_alloc;
}
return 0;
fail_free_alloc:
for (i = 0; i < alloc_cnt1 + alloc_cnt2; i++) {
rc = npc_mcam_idx_2_subbank_idx(rvu, save[i],
&sb, &sb_off);
if (rc) {
err = npc_mcam_idx_2_subbank_idx(rvu, save[i],
&sb, &sb_off);
if (err) {
dev_err(rvu->dev,
"%s: Error to find subbank for mcam idx=%u\n",
__func__, save[i]);