--- /dev/null
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) Meta Platforms, Inc. and affiliates. */
+
+#include "fbnic.h"
+
+#define FBNIC_BOUNDS(section) { \
+       .start = FBNIC_CSR_START_##section, \
+       .end = FBNIC_CSR_END_##section + 1, \
+}
+
+struct fbnic_csr_bounds {
+       u32     start;
+       u32     end;
+};
+
+static const struct fbnic_csr_bounds fbnic_csr_sects[] = {
+       FBNIC_BOUNDS(INTR),
+       FBNIC_BOUNDS(INTR_CQ),
+       FBNIC_BOUNDS(QM_TX),
+       FBNIC_BOUNDS(QM_RX),
+       FBNIC_BOUNDS(TCE),
+       FBNIC_BOUNDS(TCE_RAM),
+       FBNIC_BOUNDS(TMI),
+       FBNIC_BOUNDS(PTP),
+       FBNIC_BOUNDS(RXB),
+       FBNIC_BOUNDS(RPC),
+       FBNIC_BOUNDS(FAB),
+       FBNIC_BOUNDS(MASTER),
+       FBNIC_BOUNDS(PCS),
+       FBNIC_BOUNDS(RSFEC),
+       FBNIC_BOUNDS(MAC_MAC),
+       FBNIC_BOUNDS(SIG),
+       FBNIC_BOUNDS(PUL_USER),
+       FBNIC_BOUNDS(QUEUE),
+       FBNIC_BOUNDS(RPC_RAM),
+};
+
+#define FBNIC_RPC_TCAM_ACT_DW_PER_ENTRY                        14
+#define FBNIC_RPC_TCAM_ACT_NUM_ENTRIES                 64
+
+#define FBNIC_RPC_TCAM_MACDA_DW_PER_ENTRY              4
+#define FBNIC_RPC_TCAM_MACDA_NUM_ENTRIES               32
+
+#define FBNIC_RPC_TCAM_OUTER_IPSRC_DW_PER_ENTRY                9
+#define FBNIC_RPC_TCAM_OUTER_IPSRC_NUM_ENTRIES         8
+
+#define FBNIC_RPC_TCAM_OUTER_IPDST_DW_PER_ENTRY                9
+#define FBNIC_RPC_TCAM_OUTER_IPDST_NUM_ENTRIES         8
+
+#define FBNIC_RPC_TCAM_IPSRC_DW_PER_ENTRY              9
+#define FBNIC_RPC_TCAM_IPSRC_NUM_ENTRIES               8
+
+#define FBNIC_RPC_TCAM_IPDST_DW_PER_ENTRY              9
+#define FBNIC_RPC_TCAM_IPDST_NUM_ENTRIES               8
+
+#define FBNIC_RPC_RSS_TBL_DW_PER_ENTRY                 2
+#define FBNIC_RPC_RSS_TBL_NUM_ENTRIES                  256
+
+static void fbnic_csr_get_regs_rpc_ram(struct fbnic_dev *fbd, u32 **data_p)
+{
+       u32 start = FBNIC_CSR_START_RPC_RAM;
+       u32 end = FBNIC_CSR_END_RPC_RAM;
+       u32 *data = *data_p;
+       u32 i, j;
+
+       *(data++) = start;
+       *(data++) = end - 1;
+
+       /* FBNIC_RPC_TCAM_ACT */
+       for (i = 0; i < FBNIC_RPC_TCAM_ACT_NUM_ENTRIES; i++) {
+               for (j = 0; j < FBNIC_RPC_TCAM_ACT_DW_PER_ENTRY; j++)
+                       *(data++) = rd32(fbd, FBNIC_RPC_TCAM_ACT(i, j));
+       }
+
+       /* FBNIC_RPC_TCAM_MACDA */
+       for (i = 0; i < FBNIC_RPC_TCAM_MACDA_NUM_ENTRIES; i++) {
+               for (j = 0; j < FBNIC_RPC_TCAM_MACDA_DW_PER_ENTRY; j++)
+                       *(data++) = rd32(fbd, FBNIC_RPC_TCAM_MACDA(i, j));
+       }
+
+       /* FBNIC_RPC_TCAM_OUTER_IPSRC */
+       for (i = 0; i < FBNIC_RPC_TCAM_OUTER_IPSRC_NUM_ENTRIES; i++) {
+               for (j = 0; j < FBNIC_RPC_TCAM_OUTER_IPSRC_DW_PER_ENTRY; j++)
+                       *(data++) = rd32(fbd, FBNIC_RPC_TCAM_OUTER_IPSRC(i, j));
+       }
+
+       /* FBNIC_RPC_TCAM_OUTER_IPDST */
+       for (i = 0; i < FBNIC_RPC_TCAM_OUTER_IPDST_NUM_ENTRIES; i++) {
+               for (j = 0; j < FBNIC_RPC_TCAM_OUTER_IPDST_DW_PER_ENTRY; j++)
+                       *(data++) = rd32(fbd, FBNIC_RPC_TCAM_OUTER_IPDST(i, j));
+       }
+
+       /* FBNIC_RPC_TCAM_IPSRC */
+       for (i = 0; i < FBNIC_RPC_TCAM_IPSRC_NUM_ENTRIES; i++) {
+               for (j = 0; j < FBNIC_RPC_TCAM_IPSRC_DW_PER_ENTRY; j++)
+                       *(data++) = rd32(fbd, FBNIC_RPC_TCAM_IPSRC(i, j));
+       }
+
+       /* FBNIC_RPC_TCAM_IPDST */
+       for (i = 0; i < FBNIC_RPC_TCAM_IPDST_NUM_ENTRIES; i++) {
+               for (j = 0; j < FBNIC_RPC_TCAM_IPDST_DW_PER_ENTRY; j++)
+                       *(data++) = rd32(fbd, FBNIC_RPC_TCAM_IPDST(i, j));
+       }
+
+       /* FBNIC_RPC_RSS_TBL */
+       for (i = 0; i < FBNIC_RPC_RSS_TBL_NUM_ENTRIES; i++) {
+               for (j = 0; j < FBNIC_RPC_RSS_TBL_DW_PER_ENTRY; j++)
+                       *(data++) = rd32(fbd, FBNIC_RPC_RSS_TBL(i, j));
+       }
+
+       *data_p = data;
+}
+
+void fbnic_csr_get_regs(struct fbnic_dev *fbd, u32 *data, u32 *regs_version)
+{
+       const struct fbnic_csr_bounds *bound;
+       u32 *start = data;
+       int i, j;
+
+       *regs_version = 1u;
+
+       /* Skip RPC_RAM section which cannot be dumped linearly */
+       for (i = 0, bound = fbnic_csr_sects;
+            i < ARRAY_SIZE(fbnic_csr_sects) - 1; i++, ++bound) {
+               *(data++) = bound->start;
+               *(data++) = bound->end - 1;
+               for (j = bound->start; j < bound->end; j++)
+                       *(data++) = rd32(fbd, j);
+       }
+
+       /* Dump the RPC_RAM as special case registers */
+       fbnic_csr_get_regs_rpc_ram(fbd, &data);
+
+       WARN_ON(data - start != fbnic_csr_regs_len(fbd));
+}
+
+int fbnic_csr_regs_len(struct fbnic_dev *fbd)
+{
+       int i, len = 0;
+
+       /* Dump includes start and end information of each section
+        * which results in an offset of 2
+        */
+       for (i = 0; i < ARRAY_SIZE(fbnic_csr_sects); i++)
+               len += fbnic_csr_sects[i].end - fbnic_csr_sects[i].start + 2;
+
+       return len;
+}
 
 #define FBNIC_RPC_TCAM_MACDA_VALUE             CSR_GENMASK(15, 0)
 #define FBNIC_RPC_TCAM_MACDA_MASK              CSR_GENMASK(31, 16)
 
+#define FBNIC_RPC_TCAM_OUTER_IPSRC(m, n)\
+       (0x08c00 + 0x08 * (n) + (m))            /* 0x023000 + 32*n + 4*m */
+#define FBNIC_RPC_TCAM_OUTER_IPDST(m, n)\
+       (0x08c48 + 0x08 * (n) + (m))            /* 0x023120 + 32*n + 4*m */
+#define FBNIC_RPC_TCAM_IPSRC(m, n)\
+       (0x08c90 + 0x08 * (n) + (m))            /* 0x023240 + 32*n + 4*m */
+#define FBNIC_RPC_TCAM_IPDST(m, n)\
+       (0x08cd8 + 0x08 * (n) + (m))            /* 0x023360 + 32*n + 4*m */
+
 #define FBNIC_RPC_RSS_TBL(n, m) \
        (0x08d20 + 0x100 * (n) + (m))           /* 0x023480 + 1024*n + 4*m */
 #define FBNIC_RPC_RSS_TBL_COUNT                        2
 #define FBNIC_MASTER_SPARE_0           0x0C41B         /* 0x3106c */
 #define FBNIC_CSR_END_MASTER           0x0C452 /* CSR section delimiter */
 
+/* MAC PCS registers */
+#define FBNIC_CSR_START_PCS            0x10000 /* CSR section delimiter */
+#define FBNIC_CSR_END_PCS              0x10668 /* CSR section delimiter */
+
+#define FBNIC_CSR_START_RSFEC          0x10800 /* CSR section delimiter */
+#define FBNIC_CSR_END_RSFEC            0x108c8 /* CSR section delimiter */
+
 /* MAC MAC registers (ASIC only) */
 #define FBNIC_CSR_START_MAC_MAC                0x11000 /* CSR section delimiter */
 #define FBNIC_MAC_COMMAND_CONFIG       0x11002         /* 0x44008 */
 
        }
 }
 
+static void fbnic_get_regs(struct net_device *netdev,
+                          struct ethtool_regs *regs, void *data)
+{
+       struct fbnic_net *fbn = netdev_priv(netdev);
+
+       fbnic_csr_get_regs(fbn->fbd, data, ®s->version);
+}
+
+static int fbnic_get_regs_len(struct net_device *netdev)
+{
+       struct fbnic_net *fbn = netdev_priv(netdev);
+
+       return fbnic_csr_regs_len(fbn->fbd) * sizeof(u32);
+}
+
 static const struct ethtool_ops fbnic_ethtool_ops = {
        .get_drvinfo            = fbnic_get_drvinfo,
+       .get_regs_len           = fbnic_get_regs_len,
+       .get_regs               = fbnic_get_regs,
        .get_ts_info            = fbnic_get_ts_info,
        .get_ts_stats           = fbnic_get_ts_stats,
        .get_eth_mac_stats      = fbnic_get_eth_mac_stats,