Improve MCAM visibility and field debugging for CN20K NPC.

- Extend "mcam_layout" to show enabled (+) or disabled state per entry
  so status can be verified without parsing the full "mcam_entry" dump.
- Add "dstats" debugfs entry: reports recently hit MCAM indices with
  packet counts; stats are cleared on read so each read shows deltas.
- Add "mismatch" debugfs entry: lists MCAM entries that are enabled
  but not explicitly allocated, helping diagnose allocation/field issues.

Signed-off-by: Ratheesh Kannoth <[email protected]>
---
 .../marvell/octeontx2/af/cn20k/debugfs.c      | 157 +++++++++++++++++-
 .../ethernet/marvell/octeontx2/af/cn20k/npc.c |  16 +-
 .../ethernet/marvell/octeontx2/af/cn20k/npc.h |   7 +
 3 files changed, 169 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/debugfs.c 
b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/debugfs.c
index 6f13296303cb..9a4c2ea5b19e 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/debugfs.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/debugfs.c
@@ -13,6 +13,7 @@
 #include "struct.h"
 #include "rvu.h"
 #include "debugfs.h"
+#include "cn20k/reg.h"
 #include "cn20k/npc.h"
 
 static int npc_mcam_layout_show(struct seq_file *s, void *unused)
@@ -58,7 +59,8 @@ static int npc_mcam_layout_show(struct seq_file *s, void 
*unused)
                                                 "v:%u", vidx0);
                                }
 
-                               seq_printf(s, "\t%u(%#x) %s\n", idx0, pf1,
+                               seq_printf(s, "\t%u(%#x)%c %s\n", idx0, pf1,
+                                          test_bit(idx0, npc_priv->en_map) ? 
'+' : ' ',
                                           map ? buf0 : " ");
                        }
                        goto next;
@@ -101,9 +103,13 @@ static int npc_mcam_layout_show(struct seq_file *s, void 
*unused)
                                                 vidx1);
                                }
 
-                               seq_printf(s, "%05u(%#x) %s\t\t%05u(%#x) %s\n",
-                                          idx1, pf2, v1 ? buf1 : "       ",
-                                          idx0, pf1, v0 ? buf0 : "       ");
+                               seq_printf(s, "%05u(%#x)%c %s\t\t%05u(%#x)%c 
%s\n",
+                                          idx1, pf2,
+                                          test_bit(idx1, npc_priv->en_map) ? 
'+' : ' ',
+                                          v1 ? buf1 : "       ",
+                                          idx0, pf1,
+                                          test_bit(idx0, npc_priv->en_map) ? 
'+' : ' ',
+                                          v0 ? buf0 : "       ");
 
                                continue;
                        }
@@ -120,8 +126,9 @@ static int npc_mcam_layout_show(struct seq_file *s, void 
*unused)
                                                 vidx0);
                                }
 
-                               seq_printf(s, "\t\t   \t\t%05u(%#x) %s\n", idx0,
-                                          pf1, map ? buf0 : " ");
+                               seq_printf(s, "\t\t   \t\t%05u(%#x)%c %s\n", 
idx0, pf1,
+                                          test_bit(idx0, npc_priv->en_map) ? 
'+' : ' ',
+                                          map ? buf0 : " ");
                                continue;
                        }
 
@@ -134,7 +141,8 @@ static int npc_mcam_layout_show(struct seq_file *s, void 
*unused)
                                snprintf(buf1, sizeof(buf1), "v:%05u", vidx1);
                        }
 
-                       seq_printf(s, "%05u(%#x) %s\n", idx1, pf1,
+                       seq_printf(s, "%05u(%#x)%c %s\n", idx1, pf1,
+                                  test_bit(idx1, npc_priv->en_map) ? '+' : ' ',
                                   map ? buf1 : " ");
                }
 next:
@@ -145,6 +153,135 @@ static int npc_mcam_layout_show(struct seq_file *s, void 
*unused)
 
 DEFINE_SHOW_ATTRIBUTE(npc_mcam_layout);
 
+#define __OCTEONTX2_DEBUGFS_ATTRIBUTE_FOPS(__name)                     \
+static const struct file_operations __name ## _fops = {                        
\
+       .owner = THIS_MODULE,                                           \
+       .open = __name ## _open,                                        \
+       .read = seq_read,                                               \
+       .llseek = seq_lseek,                                            \
+       .release = single_release,                                      \
+}
+
+#define DEFINE_OCTEONTX2_DEBUGFS_ATTRIBUTE_WITH_SIZE(__name, __size)           
\
+static int __name ## _open(struct inode *inode, struct file *file)             
\
+{                                                                              
\
+       return single_open_size(file, __name ## _show, inode->i_private,        
\
+                               __size);                                        
\
+}                                                                              
\
+__OCTEONTX2_DEBUGFS_ATTRIBUTE_FOPS(__name)
+
+static DEFINE_MUTEX(stats_lock);
+
+static u64 dstats[MAX_NUM_BANKS][MAX_SUBBANK_DEPTH * MAX_NUM_SUB_BANKS] = {};
+static int npc_mcam_dstats_show(struct seq_file *s, void *unused)
+{
+       struct npc_priv_t *npc_priv;
+       int blkaddr, pf, mcam_idx;
+       u64 stats, delta;
+       struct rvu *rvu;
+       char buff[64];
+       u8 key_type;
+       void *map;
+
+       npc_priv = npc_priv_get();
+       rvu = s->private;
+       blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
+       if (blkaddr < 0)
+               return 0;
+
+       mutex_lock(&stats_lock);
+       seq_puts(s, "idx\tpfunc\tstats\n");
+       for (int bank = npc_priv->num_banks - 1; bank >= 0; bank--) {
+               for (int idx = npc_priv->bank_depth - 1; idx >= 0; idx--) {
+                       mcam_idx = bank * npc_priv->bank_depth + idx;
+
+                       npc_mcam_idx_2_key_type(rvu, mcam_idx, &key_type);
+                       if (key_type == NPC_MCAM_KEY_X4 && bank != 0)
+                               continue;
+
+                       if (!test_bit(mcam_idx, npc_priv->en_map))
+                               continue;
+
+                       stats = rvu_read64(rvu, blkaddr,
+                                          
NPC_AF_CN20K_MCAMEX_BANKX_STAT_EXT(idx, bank));
+                       if (!stats)
+                               continue;
+                       if (stats == dstats[bank][idx])
+                               continue;
+
+                       if (stats < dstats[bank][idx])
+                               dstats[bank][idx] = 0;
+
+                       pf = 0xFFFF;
+                       map = xa_load(&npc_priv->xa_idx2pf_map, mcam_idx);
+                       if (map)
+                               pf = xa_to_value(map);
+
+                       if (stats > dstats[bank][idx])
+                               delta = stats - dstats[bank][idx];
+                       else
+                               delta = stats;
+
+                       snprintf(buff, sizeof(buff), "%u\t%#04x\t%llu\n",
+                                mcam_idx, pf, delta);
+                       seq_puts(s, buff);
+
+                       dstats[bank][idx] = stats;
+               }
+       }
+
+       mutex_unlock(&stats_lock);
+       return 0;
+}
+
+/*  "%u\t%#04x\t%llu\n" needs less than 64 characters to print */
+#define TOTAL_SZ (MAX_NUM_BANKS * MAX_NUM_SUB_BANKS * MAX_SUBBANK_DEPTH * 64)
+DEFINE_OCTEONTX2_DEBUGFS_ATTRIBUTE_WITH_SIZE(npc_mcam_dstats, TOTAL_SZ);
+
+static int npc_mcam_mismatch_show(struct seq_file *s, void *unused)
+{
+       struct npc_priv_t *npc_priv;
+       struct npc_subbank *sb;
+       int mcam_idx, sb_off;
+       struct rvu *rvu;
+       char buff[64];
+       void *map;
+       int rc;
+
+       npc_priv = npc_priv_get();
+       rvu = s->private;
+
+       seq_puts(s, "index\tsb idx\tkw type\n");
+       mutex_lock(&stats_lock);
+       for (int bank = npc_priv->num_banks - 1; bank >= 0; bank--) {
+               for (int idx = npc_priv->bank_depth - 1; idx >= 0; idx--) {
+                       mcam_idx = bank * npc_priv->bank_depth + idx;
+
+                       if (!test_bit(mcam_idx, npc_priv->en_map))
+                               continue;
+
+                       map = xa_load(&npc_priv->xa_idx2pf_map, mcam_idx);
+                       if (map)
+                               continue;
+
+                       rc = npc_mcam_idx_2_subbank_idx(rvu, mcam_idx,
+                                                       &sb, &sb_off);
+                       if (rc)
+                               continue;
+
+                       snprintf(buff, sizeof(buff), "%u\t%d\t%u\n",
+                                mcam_idx, sb->idx, sb->key_type);
+
+                       seq_puts(s, buff);
+               }
+       }
+       mutex_unlock(&stats_lock);
+       return 0;
+}
+
+/* "%u\t%d\t%u\n" needs less than 64 characters to print. */
+DEFINE_OCTEONTX2_DEBUGFS_ATTRIBUTE_WITH_SIZE(npc_mcam_mismatch, TOTAL_SZ);
+
 static int npc_mcam_default_show(struct seq_file *s, void *unused)
 {
        struct npc_priv_t *npc_priv;
@@ -259,6 +396,12 @@ int npc_cn20k_debugfs_init(struct rvu *rvu)
        debugfs_create_file("vidx2idx", 0444, rvu->rvu_dbg.npc,
                            npc_priv, &npc_vidx2idx_map_fops);
 
+       debugfs_create_file("dstats", 0444, rvu->rvu_dbg.npc, rvu,
+                           &npc_mcam_dstats_fops);
+
+       debugfs_create_file("mismatch", 0444, rvu->rvu_dbg.npc, rvu,
+                           &npc_mcam_mismatch_fops);
+
        debugfs_create_file("idx2vidx", 0444, rvu->rvu_dbg.npc,
                            npc_priv, &npc_idx2vidx_map_fops);
 
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c 
b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
index 6b3f453fd500..e9aad0ad3fa6 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
@@ -824,7 +824,7 @@ npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkaddr,
                rvu_write64(rvu, blkaddr,
                            NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(mcam_idx, bank),
                            cfg);
-               return 0;
+               goto update_en_map;
        }
 
        /* For NPC_CN20K_MCAM_KEY_X4 keys, both the banks
@@ -842,6 +842,12 @@ npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkaddr,
                            cfg);
        }
 
+update_en_map:
+       if (enable)
+               set_bit(index, npc_priv.en_map);
+       else
+               clear_bit(index, npc_priv.en_map);
+
        return 0;
 }
 
@@ -1789,9 +1795,9 @@ static int npc_subbank_idx_2_mcam_idx(struct rvu *rvu, 
struct npc_subbank *sb,
        return 0;
 }
 
-static int npc_mcam_idx_2_subbank_idx(struct rvu *rvu, u16 mcam_idx,
-                                     struct npc_subbank **sb,
-                                     int *sb_off)
+int npc_mcam_idx_2_subbank_idx(struct rvu *rvu, u16 mcam_idx,
+                              struct npc_subbank **sb,
+                              int *sb_off)
 {
        int bank_off, sb_id;
 
@@ -4605,6 +4611,8 @@ void npc_cn20k_deinit(struct rvu *rvu)
         */
        kfree(npc_priv.sb);
        kfree(subbank_srch_order);
+       bitmap_clear(npc_priv.en_map, 0, MAX_NUM_BANKS * MAX_NUM_SUB_BANKS *
+                    MAX_SUBBANK_DEPTH);
 }
 
 static int npc_setup_mcam_section(struct rvu *rvu, int key_type)
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h 
b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h
index 3d5eb952cc07..9567a2d80b58 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h
@@ -170,6 +170,7 @@ struct npc_defrag_show_node {
  * @num_banks:         Number of banks.
  * @num_subbanks:      Number of subbanks.
  * @subbank_depth:     Depth of subbank.
+ * @en_map:            Enable/disable status.
  * @kw:                        Kex configured key type.
  * @sb:                        Subbank array.
  * @xa_sb_used:                Array of used subbanks.
@@ -193,6 +194,9 @@ struct npc_priv_t {
        const int num_banks;
        int num_subbanks;
        int subbank_depth;
+       DECLARE_BITMAP(en_map, MAX_NUM_BANKS *
+                      MAX_NUM_SUB_BANKS *
+                      MAX_SUBBANK_DEPTH);
        u8 kw;
        struct npc_subbank *sb;
        struct xarray xa_sb_used;
@@ -336,5 +340,8 @@ u16 npc_cn20k_vidx2idx(u16 index);
 u16 npc_cn20k_idx2vidx(u16 idx);
 int npc_cn20k_defrag(struct rvu *rvu);
 bool npc_is_cgx_or_lbk(struct rvu *rvu, u16 pcifunc);
+int npc_mcam_idx_2_subbank_idx(struct rvu *rvu, u16 mcam_idx,
+                              struct npc_subbank **sb,
+                              int *sb_off);
 
 #endif /* NPC_CN20K_H */
-- 
2.43.0

Reply via email to