]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
octeontx2-af: npc: cn20k: Fix subbank free list indexing for search order
authorRatheesh Kannoth <rkannoth@marvell.com>
Fri, 19 Jun 2026 09:51:00 +0000 (15:21 +0530)
committerJakub Kicinski <kuba@kernel.org>
Thu, 25 Jun 2026 01:39:45 +0000 (18:39 -0700)
subbank_srch_order[i] is the physical subbank at search-order slot i,
so each subbank's arr_idx must be i (its slot), not
subbank_srch_order[sb->idx].  The old logic mis-keyed xa_sb_free
and broke allocation traversal order.

Populate arr_idx and xa_sb_free in a single pass over the search
order after subbank structs are initialized.

Fixes: 7ac9d4c4075c ("octeontx2-af: npc: cn20k: add subbank search order control")
Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260619095100.1864440-1-rkannoth@marvell.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c

index 9052b88f36851d64f1ad0dd68727b150cf03c0a4..3070700b952bfa8bfe9a1ca67e183ff82c7e80a4 100644 (file)
@@ -3423,6 +3423,36 @@ static int npc_create_srch_order(int cnt)
        return 0;
 }
 
+static int npc_subbanks_srch_order_init(struct rvu *rvu)
+{
+       struct npc_subbank *sb;
+       int sb_idx;
+       int i, j;
+       int rc;
+
+       for (i = 0; i < npc_priv->num_subbanks; i++) {
+               sb_idx = subbank_srch_order[i];
+               sb = &npc_priv->sb[sb_idx];
+               sb->arr_idx = i;
+
+               dev_dbg(rvu->dev, "%s: sb->idx=%u sb->arr_idx=%u\n",
+                       __func__, sb->idx, sb->arr_idx);
+
+               rc = xa_err(xa_store(&npc_priv->xa_sb_free, sb->arr_idx,
+                                    xa_mk_value(sb->idx), GFP_KERNEL));
+               if (rc) {
+                       dev_err(rvu->dev,
+                               "%s: xa_store(xa_sb_free) failed at slot %d (sb=%d): %d\n",
+                               __func__, i, sb_idx, rc);
+                       for (j = 0; j < i; j++)
+                               xa_erase(&npc_priv->xa_sb_free, j);
+                       return rc;
+               }
+       }
+
+       return 0;
+}
+
 static void npc_subbank_init(struct rvu *rvu, struct npc_subbank *sb, int idx)
 {
        mutex_init(&sb->lock);
@@ -3435,16 +3465,6 @@ static void npc_subbank_init(struct rvu *rvu, struct npc_subbank *sb, int idx)
 
        sb->flags = NPC_SUBBANK_FLAG_FREE;
        sb->idx = idx;
-       sb->arr_idx = subbank_srch_order[idx];
-
-       dev_dbg(rvu->dev, "%s: sb->idx=%u sb->arr_idx=%u\n",
-               __func__, sb->idx, sb->arr_idx);
-
-       /* Keep first and last subbank at end of free array; so that
-        * it will be used at last
-        */
-       xa_store(&npc_priv->xa_sb_free, sb->arr_idx,
-                xa_mk_value(sb->idx), GFP_KERNEL);
 }
 
 static int npc_pcifunc_map_create(struct rvu *rvu)
@@ -4638,6 +4658,7 @@ static int npc_priv_init(struct rvu *rvu)
        int num_subbanks, subbank_depth;
        u64 npc_const1, npc_const2 = 0;
        struct npc_subbank *sb;
+       int ret = -ENOMEM;
        u64 cfg;
        int i;
 
@@ -4730,13 +4751,19 @@ static int npc_priv_init(struct rvu *rvu)
        for (i = 0, sb = npc_priv->sb; i < num_subbanks; i++, sb++)
                npc_subbank_init(rvu, sb, i);
 
+       ret = npc_subbanks_srch_order_init(rvu);
+       if (ret)
+               goto fail3;
+
        /* Get number of pcifuncs in the system */
        npc_priv->pf_cnt = npc_pcifunc_map_create(rvu);
        npc_priv->xa_pf2idx_map = kcalloc(npc_priv->pf_cnt,
                                          sizeof(struct xarray),
                                          GFP_KERNEL);
-       if (!npc_priv->xa_pf2idx_map)
+       if (!npc_priv->xa_pf2idx_map) {
+               ret = -ENOMEM;
                goto fail3;
+       }
 
        for (i = 0; i < npc_priv->pf_cnt; i++)
                xa_init_flags(&npc_priv->xa_pf2idx_map[i], XA_FLAGS_ALLOC);
@@ -4763,7 +4790,7 @@ fail2:
 fail1:
        kfree(npc_priv);
        npc_priv = NULL;
-       return -ENOMEM;
+       return ret;
 }
 
 void npc_cn20k_deinit(struct rvu *rvu)