]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
octeontx2-af: npc: cn20k: add debugfs support
authorRatheesh Kannoth <rkannoth@marvell.com>
Tue, 24 Feb 2026 08:00:08 +0000 (13:30 +0530)
committerJakub Kicinski <kuba@kernel.org>
Sat, 28 Feb 2026 18:29:27 +0000 (10:29 -0800)
CN20K silicon divides the NPC MCAM into banks and subbanks, with each
subbank configurable for x2 or x4 key widths. This patch adds debugfs
entries to expose subbank usage details and their configured key type.

A debugfs entry is also added to display the default MCAM indexes
allocated for each pcifunc.

Additionally, debugfs support is introduced to show the mapping between
virtual indexes and real MCAM indexes, and vice versa.

Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
Link: https://patch.msgid.link/20260224080009.4147301-13-rkannoth@marvell.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/marvell/octeontx2/af/cn20k/debugfs.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c

index 0ba123be6643500635d8a649e9cf59335ebdb38a..3debf2fae1a48e04e967eb0c01a10cb3738e2b64 100644 (file)
 #include "debugfs.h"
 #include "cn20k/npc.h"
 
+static int npc_mcam_layout_show(struct seq_file *s, void *unused)
+{
+       int i, j, sbd, idx0, idx1, vidx0, vidx1;
+       struct npc_priv_t *npc_priv;
+       char buf0[32], buf1[32];
+       struct npc_subbank *sb;
+       unsigned int bw0, bw1;
+       bool v0, v1;
+       int pf1, pf2;
+       bool e0, e1;
+       void *map;
+
+       npc_priv = s->private;
+
+       sbd = npc_priv->subbank_depth;
+
+       for (i = npc_priv->num_subbanks - 1; i >= 0; i--) {
+               sb = &npc_priv->sb[i];
+               mutex_lock(&sb->lock);
+
+               if (sb->flags & NPC_SUBBANK_FLAG_FREE)
+                       goto next;
+
+               bw0 = bitmap_weight(sb->b0map, npc_priv->subbank_depth);
+               if (sb->key_type == NPC_MCAM_KEY_X4) {
+                       seq_printf(s, "\n\nsubbank:%u, x4, free=%u, used=%u\n",
+                                  sb->idx, sb->free_cnt, bw0);
+
+                       for (j = sbd - 1; j >= 0; j--) {
+                               if (!test_bit(j, sb->b0map))
+                                       continue;
+
+                               idx0 = sb->b0b + j;
+                               map = xa_load(&npc_priv->xa_idx2pf_map, idx0);
+                               pf1 = xa_to_value(map);
+
+                               map = xa_load(&npc_priv->xa_idx2vidx_map, idx0);
+                               if (map) {
+                                       vidx0 = xa_to_value(map);
+                                       snprintf(buf0, sizeof(buf0),
+                                                "v:%u", vidx0);
+                               }
+
+                               seq_printf(s, "\t%u(%#x) %s\n", idx0, pf1,
+                                          map ? buf0 : " ");
+                       }
+                       goto next;
+               }
+
+               bw1 = bitmap_weight(sb->b1map, npc_priv->subbank_depth);
+               seq_printf(s, "\n\nsubbank:%u, x2, free=%u, used=%u\n",
+                          sb->idx, sb->free_cnt, bw0 + bw1);
+               seq_printf(s, "bank1(%u)\t\tbank0(%u)\n", bw1, bw0);
+
+               for (j = sbd - 1; j >= 0; j--) {
+                       e0 = test_bit(j, sb->b0map);
+                       e1 = test_bit(j, sb->b1map);
+
+                       if (!e1 && !e0)
+                               continue;
+
+                       if (e1 && e0) {
+                               idx0 = sb->b0b + j;
+                               map = xa_load(&npc_priv->xa_idx2pf_map, idx0);
+                               pf1 = xa_to_value(map);
+
+                               map = xa_load(&npc_priv->xa_idx2vidx_map, idx0);
+                               v0 = !!map;
+                               if (v0) {
+                                       vidx0 = xa_to_value(map);
+                                       snprintf(buf0, sizeof(buf0), "v:%05u",
+                                                vidx0);
+                               }
+
+                               idx1 = sb->b1b + j;
+                               map = xa_load(&npc_priv->xa_idx2pf_map, idx1);
+                               pf2 = xa_to_value(map);
+
+                               map = xa_load(&npc_priv->xa_idx2vidx_map, idx1);
+                               v1 = !!map;
+                               if (v1) {
+                                       vidx1 = xa_to_value(map);
+                                       snprintf(buf1, sizeof(buf1), "v:%05u",
+                                                vidx1);
+                               }
+
+                               seq_printf(s, "%05u(%#x) %s\t\t%05u(%#x) %s\n",
+                                          idx1, pf2, v1 ? buf1 : "       ",
+                                          idx0, pf1, v0 ? buf0 : "       ");
+
+                               continue;
+                       }
+
+                       if (e0) {
+                               idx0 = sb->b0b + j;
+                               map = xa_load(&npc_priv->xa_idx2pf_map, idx0);
+                               pf1 = xa_to_value(map);
+
+                               map = xa_load(&npc_priv->xa_idx2vidx_map, idx0);
+                               if (map) {
+                                       vidx0 = xa_to_value(map);
+                                       snprintf(buf0, sizeof(buf0), "v:%05u",
+                                                vidx0);
+                               }
+
+                               seq_printf(s, "\t\t   \t\t%05u(%#x) %s\n", idx0,
+                                          pf1, map ? buf0 : " ");
+                               continue;
+                       }
+
+                       idx1 = sb->b1b + j;
+                       map = xa_load(&npc_priv->xa_idx2pf_map, idx1);
+                       pf1 = xa_to_value(map);
+                       map = xa_load(&npc_priv->xa_idx2vidx_map, idx1);
+                       if (map) {
+                               vidx1 = xa_to_value(map);
+                               snprintf(buf1, sizeof(buf1), "v:%05u", vidx1);
+                       }
+
+                       seq_printf(s, "%05u(%#x) %s\n", idx1, pf1,
+                                  map ? buf1 : " ");
+               }
+next:
+               mutex_unlock(&sb->lock);
+       }
+       return 0;
+}
+
+DEFINE_SHOW_ATTRIBUTE(npc_mcam_layout);
+
+static int npc_mcam_default_show(struct seq_file *s, void *unused)
+{
+       struct npc_priv_t *npc_priv;
+       unsigned long index;
+       u16 ptr[4], pcifunc;
+       struct rvu *rvu;
+       int rc, i;
+       void *map;
+
+       npc_priv = npc_priv_get();
+       rvu = s->private;
+
+       seq_puts(s, "\npcifunc\tBcast\tmcast\tpromisc\tucast\n");
+
+       xa_for_each(&npc_priv->xa_pf_map, index, map) {
+               pcifunc = index;
+
+               for (i = 0; i < ARRAY_SIZE(ptr); i++)
+                       ptr[i] = USHRT_MAX;
+
+               rc = npc_cn20k_dft_rules_idx_get(rvu, pcifunc, &ptr[0],
+                                                &ptr[1], &ptr[2], &ptr[3]);
+               if (rc)
+                       continue;
+
+               seq_printf(s, "%#x\t", pcifunc);
+               for (i = 0; i < ARRAY_SIZE(ptr); i++) {
+                       if (ptr[i] != USHRT_MAX)
+                               seq_printf(s, "%u\t", ptr[i]);
+                       else
+                               seq_puts(s, "\t");
+               }
+               seq_puts(s, "\n");
+       }
+
+       return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(npc_mcam_default);
+
+static int npc_vidx2idx_map_show(struct seq_file *s, void *unused)
+{
+       struct npc_priv_t *npc_priv;
+       unsigned long index, start;
+       struct xarray *xa;
+       void *map;
+
+       npc_priv = s->private;
+       start = npc_priv->bank_depth * 2;
+       xa = &npc_priv->xa_vidx2idx_map;
+
+       seq_puts(s, "\nvidx\tmcam_idx\n");
+
+       xa_for_each_start(xa, index, map, start)
+               seq_printf(s, "%lu\t%lu\n", index, xa_to_value(map));
+       return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(npc_vidx2idx_map);
+
+static int npc_idx2vidx_map_show(struct seq_file *s, void *unused)
+{
+       struct npc_priv_t *npc_priv;
+       unsigned long index;
+       struct xarray *xa;
+       void *map;
+
+       npc_priv = s->private;
+       xa = &npc_priv->xa_idx2vidx_map;
+
+       seq_puts(s, "\nmidx\tvidx\n");
+
+       xa_for_each(xa, index, map)
+               seq_printf(s, "%lu\t%lu\n", index, xa_to_value(map));
+       return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(npc_idx2vidx_map);
+
+static int npc_defrag_show(struct seq_file *s, void *unused)
+{
+       struct npc_defrag_show_node *node;
+       struct npc_priv_t *npc_priv;
+       u16 sbd, bdm;
+
+       npc_priv = s->private;
+       bdm = npc_priv->bank_depth - 1;
+       sbd = npc_priv->subbank_depth;
+
+       seq_puts(s, "\nold(sb)   ->    new(sb)\t\tvidx\n");
+
+       mutex_lock(&npc_priv->lock);
+       list_for_each_entry(node, &npc_priv->defrag_lh, list)
+               seq_printf(s, "%u(%u)\t%u(%u)\t%u\n", node->old_midx,
+                          (node->old_midx & bdm) / sbd,
+                          node->new_midx,
+                          (node->new_midx & bdm) / sbd,
+                          node->vidx);
+       mutex_unlock(&npc_priv->lock);
+       return 0;
+}
+
+DEFINE_SHOW_ATTRIBUTE(npc_defrag);
+
 int npc_cn20k_debugfs_init(struct rvu *rvu)
 {
+       struct npc_priv_t *npc_priv = npc_priv_get();
+       struct dentry *npc_dentry;
+
+       npc_dentry = debugfs_create_file("mcam_layout", 0444, rvu->rvu_dbg.npc,
+                                        npc_priv, &npc_mcam_layout_fops);
+
+       if (!npc_dentry)
+               return -EFAULT;
+
+       npc_dentry = debugfs_create_file("mcam_default", 0444, rvu->rvu_dbg.npc,
+                                        rvu, &npc_mcam_default_fops);
+
+       if (!npc_dentry)
+               return -EFAULT;
+
+       npc_dentry = debugfs_create_file("vidx2idx", 0444, rvu->rvu_dbg.npc,
+                                        npc_priv, &npc_vidx2idx_map_fops);
+       if (!npc_dentry)
+               return -EFAULT;
+
+       npc_dentry = debugfs_create_file("idx2vidx", 0444, rvu->rvu_dbg.npc,
+                                        npc_priv, &npc_idx2vidx_map_fops);
+       if (!npc_dentry)
+               return -EFAULT;
+
+       npc_dentry = debugfs_create_file("defrag", 0444, rvu->rvu_dbg.npc,
+                                        npc_priv, &npc_defrag_fops);
+       if (!npc_dentry)
+               return -EFAULT;
+
        return 0;
 }
 
index 620724dad0936d60828d62a02ebae0957b2a02d8..413f9fa40b330426ff54b3bc779498ab38d14fbe 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "cn20k/reg.h"
 #include "cn20k/debugfs.h"
+#include "cn20k/npc.h"
 
 #define DEBUGFS_DIR_NAME "octeontx2"
 
@@ -3197,7 +3198,9 @@ static void rvu_print_npc_mcam_info(struct seq_file *s,
 static int rvu_dbg_npc_mcam_info_display(struct seq_file *filp, void *unsued)
 {
        struct rvu *rvu = filp->private;
+       int x4_free, x2_free, sb_free;
        int pf, vf, numvfs, blkaddr;
+       struct npc_priv_t *npc_priv;
        struct npc_mcam *mcam;
        u16 pcifunc, counters;
        u64 cfg;
@@ -3211,16 +3214,34 @@ static int rvu_dbg_npc_mcam_info_display(struct seq_file *filp, void *unsued)
 
        seq_puts(filp, "\nNPC MCAM info:\n");
        /* MCAM keywidth on receive and transmit sides */
-       cfg = rvu_read64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(NIX_INTF_RX));
-       cfg = (cfg >> 32) & 0x07;
-       seq_printf(filp, "\t\t RX keywidth \t: %s\n", (cfg == NPC_MCAM_KEY_X1) ?
-                  "112bits" : ((cfg == NPC_MCAM_KEY_X2) ?
-                  "224bits" : "448bits"));
-       cfg = rvu_read64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(NIX_INTF_TX));
-       cfg = (cfg >> 32) & 0x07;
-       seq_printf(filp, "\t\t TX keywidth \t: %s\n", (cfg == NPC_MCAM_KEY_X1) ?
-                  "112bits" : ((cfg == NPC_MCAM_KEY_X2) ?
-                  "224bits" : "448bits"));
+       if (is_cn20k(rvu->pdev)) {
+               npc_priv = npc_priv_get();
+               seq_printf(filp, "\t\t RX keywidth \t: %s\n",
+                          (npc_priv->kw == NPC_MCAM_KEY_X1) ?
+                          "256bits" : "512bits");
+
+               npc_cn20k_subbank_calc_free(rvu, &x2_free, &x4_free, &sb_free);
+               seq_printf(filp, "\t\t free x4 slots\t: %d\n", x4_free);
+
+               seq_printf(filp, "\t\t free x2 slots\t: %d\n", x2_free);
+
+               seq_printf(filp, "\t\t free subbanks\t: %d\n", sb_free);
+       } else {
+               cfg = rvu_read64(rvu, blkaddr,
+                                NPC_AF_INTFX_KEX_CFG(NIX_INTF_RX));
+               cfg = (cfg >> 32) & 0x07;
+               seq_printf(filp, "\t\t RX keywidth \t: %s\n",
+                          (cfg == NPC_MCAM_KEY_X1) ?
+                          "112bits" : ((cfg == NPC_MCAM_KEY_X2) ?
+                                       "224bits" : "448bits"));
+               cfg = rvu_read64(rvu, blkaddr,
+                                NPC_AF_INTFX_KEX_CFG(NIX_INTF_TX));
+               cfg = (cfg >> 32) & 0x07;
+               seq_printf(filp, "\t\t TX keywidth \t: %s\n",
+                          (cfg == NPC_MCAM_KEY_X1) ?
+                          "112bits" : ((cfg == NPC_MCAM_KEY_X2) ?
+                                       "224bits" : "448bits"));
+       }
 
        mutex_lock(&mcam->lock);
        /* MCAM entries */