]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
eth fbnic: Add debugfs hooks for tx/rx rings
authorMike Marciniszyn (Meta) <mike.marciniszyn@gmail.com>
Tue, 27 Jan 2026 20:06:44 +0000 (15:06 -0500)
committerJakub Kicinski <kuba@kernel.org>
Sat, 31 Jan 2026 01:57:12 +0000 (17:57 -0800)
Add debugfs hooks to display tx/rx rings for each napi
vector.

Note that the cloning mechanism in fbnic_ethtool.c for configuration
changes protects against concurrency issues with simultaneous config
changes along with debugs ring accesses.

The configuration switch builds up the new configuration offline,
takes the current config down, which removes the debugfs nv files, and
switches to the new configuration.   The new configuration is brought
up which brings the debugfs files back on top of the new configuration
rings.

The interaction with fbnic_queue_stop() and fbnic_queue_start() will
similarly delete and add the files for the indicated vector.

Signed-off-by: Mike Marciniszyn (Meta) <mike.marciniszyn@gmail.com>
Link: https://patch.msgid.link/20260127200644.11640-3-mike.marciniszyn@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/meta/fbnic/fbnic_csr.h
drivers/net/ethernet/meta/fbnic/fbnic_debugfs.c
drivers/net/ethernet/meta/fbnic/fbnic_pci.c
drivers/net/ethernet/meta/fbnic/fbnic_txrx.c
drivers/net/ethernet/meta/fbnic/fbnic_txrx.h

index 422265dc7abd6483e793a2311cfdfcdfc4dcce20..b717db879cd31bf5279e18e0f63d817d6e42b38b 100644 (file)
@@ -1019,6 +1019,9 @@ enum {
 #define FBNIC_QUEUE_TWQ_CTL_ENABLE             CSR_BIT(1)
 #define FBNIC_QUEUE_TWQ0_TAIL          0x002           /* 0x008 */
 #define FBNIC_QUEUE_TWQ1_TAIL          0x003           /* 0x00c */
+#define FBNIC_QUEUE_TWQ0_PTRS          0x004           /* 0x010 */
+#define FBNIC_QUEUE_TWQ1_PTRS          0x005           /* 0x014 */
+#define FBNIC_QUEUE_TWQ_PTRS_HEAD_MASK         CSR_GENMASK(31, 16)
 
 #define FBNIC_QUEUE_TWQ0_SIZE          0x00a           /* 0x028 */
 #define FBNIC_QUEUE_TWQ1_SIZE          0x00b           /* 0x02c */
@@ -1042,6 +1045,8 @@ enum {
 #define FBNIC_QUEUE_TCQ_CTL_ENABLE             CSR_BIT(1)
 
 #define FBNIC_QUEUE_TCQ_HEAD           0x081           /* 0x204 */
+#define FBNIC_QUEUE_TCQ_PTRS           0x082           /* 0x208 */
+#define FBNIC_QUEUE_TCQ_PTRS_TAIL_MASK         CSR_GENMASK(31, 16)
 
 #define FBNIC_QUEUE_TCQ_SIZE           0x084           /* 0x210 */
 #define FBNIC_QUEUE_TCQ_SIZE_MASK              CSR_GENMASK(3, 0)
@@ -1075,6 +1080,9 @@ enum {
 #define FBNIC_QUEUE_RCQ_CTL_ENABLE             CSR_BIT(1)
 
 #define FBNIC_QUEUE_RCQ_HEAD           0x201           /* 0x804 */
+#define FBNIC_QUEUE_RCQ_PTRS           0x202           /* 0x808 */
+#define FBNIC_QUEUE_RCQ_PTRS_TAIL_MASK         CSR_GENMASK(31, 16)
+#define FBNIC_QUEUE_RCQ_PTRS_HEAD_MASK         CSR_GENMASK(15, 0)
 
 #define FBNIC_QUEUE_RCQ_SIZE           0x204           /* 0x810 */
 #define FBNIC_QUEUE_RCQ_SIZE_MASK              CSR_GENMASK(3, 0)
@@ -1090,6 +1098,10 @@ enum {
 
 #define FBNIC_QUEUE_BDQ_HPQ_TAIL       0x241           /* 0x904 */
 #define FBNIC_QUEUE_BDQ_PPQ_TAIL       0x242           /* 0x908 */
+#define FBNIC_QUEUE_BDQ_HPQ_PTRS       0x243           /* 0x90c */
+#define FBNIC_QUEUE_BDQ_PPQ_PTRS       0x244           /* 0x910 */
+#define FBNIC_QUEUE_BDQ_PTRS_HEAD_MASK         CSR_GENMASK(31, 16)
+#define FBNIC_QUEUE_BDQ_PTRS_TAIL_MASK         CSR_GENMASK(15, 0)
 
 #define FBNIC_QUEUE_BDQ_HPQ_SIZE       0x247           /* 0x91c */
 #define FBNIC_QUEUE_BDQ_PPQ_SIZE       0x248           /* 0x920 */
index 9cdd03bfec34085061b2b2d3693d9873ff062879..08270db2dee8644230486c3697bbfcd917d351ee 100644 (file)
@@ -7,9 +7,12 @@
 #include <linux/seq_file.h>
 
 #include "fbnic.h"
+#include "fbnic_txrx.h"
 
 static struct dentry *fbnic_dbg_root;
 
+/* Descriptor Seq Functions */
+
 static void fbnic_dbg_desc_break(struct seq_file *s, int i)
 {
        while (i--)
@@ -18,6 +21,362 @@ static void fbnic_dbg_desc_break(struct seq_file *s, int i)
        seq_putc(s, '\n');
 }
 
+static void fbnic_dbg_ring_show(struct seq_file *s)
+{
+       struct fbnic_ring *ring = s->private;
+       unsigned long doorbell_offset;
+       u32 head = 0, tail = 0;
+       u32 __iomem *csr_base;
+
+       csr_base = fbnic_ring_csr_base(ring);
+       doorbell_offset = ring->doorbell - csr_base;
+
+       seq_printf(s, "doorbell CSR: %#05lx q_idx: %d\n",
+                  doorbell_offset, ring->q_idx);
+       seq_printf(s, "size_mask: %#06x size: %zu flags: 0x%02x\n",
+                  ring->size_mask, ring->size, ring->flags);
+       seq_printf(s, "SW: head: %#06x tail: %#06x\n",
+                  ring->head, ring->tail);
+
+       switch (doorbell_offset) {
+       case FBNIC_QUEUE_TWQ0_TAIL:
+               tail = readl(csr_base + FBNIC_QUEUE_TWQ0_PTRS);
+               head = FIELD_GET(FBNIC_QUEUE_TWQ_PTRS_HEAD_MASK, tail);
+               break;
+       case FBNIC_QUEUE_TWQ1_TAIL:
+               tail = readl(csr_base + FBNIC_QUEUE_TWQ1_PTRS);
+               head = FIELD_GET(FBNIC_QUEUE_TWQ_PTRS_HEAD_MASK, tail);
+               break;
+       case FBNIC_QUEUE_TCQ_HEAD:
+               head = readl(csr_base + FBNIC_QUEUE_TCQ_PTRS);
+               tail = FIELD_GET(FBNIC_QUEUE_TCQ_PTRS_TAIL_MASK, head);
+               break;
+       case FBNIC_QUEUE_BDQ_HPQ_TAIL:
+               tail = readl(csr_base + FBNIC_QUEUE_BDQ_HPQ_PTRS);
+               head = FIELD_GET(FBNIC_QUEUE_BDQ_PTRS_HEAD_MASK, tail);
+               break;
+       case FBNIC_QUEUE_BDQ_PPQ_TAIL:
+               tail = readl(csr_base + FBNIC_QUEUE_BDQ_PPQ_PTRS);
+               head = FIELD_GET(FBNIC_QUEUE_BDQ_PTRS_HEAD_MASK, tail);
+               break;
+       case FBNIC_QUEUE_RCQ_HEAD:
+               head = readl(csr_base + FBNIC_QUEUE_RCQ_PTRS);
+               tail = FIELD_GET(FBNIC_QUEUE_RCQ_PTRS_TAIL_MASK, head);
+               break;
+       }
+
+       tail &= FBNIC_QUEUE_BDQ_PTRS_TAIL_MASK;
+       head &= FBNIC_QUEUE_RCQ_PTRS_HEAD_MASK;
+
+       seq_printf(s, "HW: head: %#06x tail: %#06x\n", head, tail);
+
+       seq_puts(s, "\n");
+}
+
+static void fbnic_dbg_twd_desc_seq_show(struct seq_file *s, int i)
+{
+       struct fbnic_ring *ring = s->private;
+       u64 twd = le64_to_cpu(ring->desc[i]);
+
+       switch (FIELD_GET(FBNIC_TWD_TYPE_MASK, twd)) {
+       case FBNIC_TWD_TYPE_META:
+               seq_printf(s, "%04x %#06llx  %llx %llx %llx %llx %llx %#llx %#llx %llx %#04llx %#04llx %llx %#04llx\n",
+                          i, FIELD_GET(FBNIC_TWD_LEN_MASK, twd),
+                          FIELD_GET(FBNIC_TWD_TYPE_MASK, twd),
+                          FIELD_GET(FBNIC_TWD_FLAG_REQ_COMPLETION, twd),
+                          FIELD_GET(FBNIC_TWD_FLAG_REQ_CSO, twd),
+                          FIELD_GET(FBNIC_TWD_FLAG_REQ_LSO, twd),
+                          FIELD_GET(FBNIC_TWD_FLAG_REQ_TS, twd),
+                          FIELD_GET(FBNIC_TWD_L4_HLEN_MASK, twd),
+                          FIELD_GET(FBNIC_TWD_CSUM_OFFSET_MASK, twd),
+                          FIELD_GET(FBNIC_TWD_L4_TYPE_MASK, twd),
+                          FIELD_GET(FBNIC_TWD_L3_IHLEN_MASK, twd),
+                          FIELD_GET(FBNIC_TWD_L3_OHLEN_MASK, twd),
+                          FIELD_GET(FBNIC_TWD_L3_TYPE_MASK, twd),
+                          FIELD_GET(FBNIC_TWD_L2_HLEN_MASK, twd));
+               break;
+       default:
+               seq_printf(s, "%04x %#06llx  %llx %#014llx\n", i,
+                          FIELD_GET(FBNIC_TWD_LEN_MASK, twd),
+                          FIELD_GET(FBNIC_TWD_TYPE_MASK, twd),
+                          FIELD_GET(FBNIC_TWD_ADDR_MASK, twd));
+               break;
+       }
+}
+
+static int fbnic_dbg_twq_desc_seq_show(struct seq_file *s, void *v)
+{
+       struct fbnic_ring *ring = s->private;
+       char hdr[80];
+       int i;
+
+       /* Generate header on first entry */
+       fbnic_dbg_ring_show(s);
+       snprintf(hdr, sizeof(hdr), "%4s %5s %s %s\n",
+                "DESC", "LEN/MSS", "T", "METADATA/TIMESTAMP/BUFFER_ADDR");
+       seq_puts(s, hdr);
+       fbnic_dbg_desc_break(s, strnlen(hdr, sizeof(hdr)));
+
+       /* Display descriptor */
+       if (!ring->desc) {
+               seq_puts(s, "Descriptor ring not allocated.\n");
+               return 0;
+       }
+
+       for (i = 0; i <= ring->size_mask; i++)
+               fbnic_dbg_twd_desc_seq_show(s, i);
+
+       return 0;
+}
+
+static int fbnic_dbg_tcq_desc_seq_show(struct seq_file *s, void *v)
+{
+       struct fbnic_ring *ring = s->private;
+       char hdr[80];
+       int i;
+
+       /* Generate header on first entry */
+       fbnic_dbg_ring_show(s);
+       snprintf(hdr, sizeof(hdr), "%4s %s %s %s %5s %-16s %-6s %-6s\n",
+                "DESC", "D", "T", "Q", "STATUS", "TIMESTAMP", "HEAD1", "HEAD0");
+       seq_puts(s, hdr);
+       fbnic_dbg_desc_break(s, strnlen(hdr, sizeof(hdr)));
+
+       /* Display descriptor */
+       if (!ring->desc) {
+               seq_puts(s, "Descriptor ring not allocated.\n");
+               return 0;
+       }
+
+       for (i = 0; i <= ring->size_mask; i++) {
+               u64 tcd = le64_to_cpu(ring->desc[i]);
+
+               switch (FIELD_GET(FBNIC_TCD_TYPE_MASK, tcd)) {
+               case FBNIC_TCD_TYPE_0:
+                       seq_printf(s, "%04x %llx %llx %llx %#05llx %-17s %#06llx %#06llx\n",
+                                  i, FIELD_GET(FBNIC_TCD_DONE, tcd),
+                                  FIELD_GET(FBNIC_TCD_TYPE_MASK, tcd),
+                                  FIELD_GET(FBNIC_TCD_TWQ1, tcd),
+                                  FIELD_GET(FBNIC_TCD_STATUS_MASK, tcd),
+                                  "",
+                                  FIELD_GET(FBNIC_TCD_TYPE0_HEAD1_MASK, tcd),
+                                  FIELD_GET(FBNIC_TCD_TYPE0_HEAD0_MASK, tcd));
+                       break;
+               case FBNIC_TCD_TYPE_1:
+                       seq_printf(s, "%04x %llx %llx %llx %#05llx  %#012llx\n",
+                                  i, FIELD_GET(FBNIC_TCD_DONE, tcd),
+                                  FIELD_GET(FBNIC_TCD_TYPE_MASK, tcd),
+                                  FIELD_GET(FBNIC_TCD_TWQ1, tcd),
+                                  FIELD_GET(FBNIC_TCD_STATUS_MASK, tcd),
+                                  FIELD_GET(FBNIC_TCD_TYPE1_TS_MASK, tcd));
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+static int fbnic_dbg_bdq_desc_seq_show(struct seq_file *s, void *v)
+{
+       struct fbnic_ring *ring = s->private;
+       char hdr[80];
+       int i;
+
+       /* Generate header on first entry */
+       fbnic_dbg_ring_show(s);
+       snprintf(hdr, sizeof(hdr), "%4s %-4s %s\n",
+                "DESC", "ID", "BUFFER_ADDR");
+       seq_puts(s, hdr);
+       fbnic_dbg_desc_break(s, strnlen(hdr, sizeof(hdr)));
+
+       /* Display descriptor */
+       if (!ring->desc) {
+               seq_puts(s, "Descriptor ring not allocated.\n");
+               return 0;
+       }
+
+       for (i = 0; i <= ring->size_mask; i++) {
+               u64 bd = le64_to_cpu(ring->desc[i]);
+
+               seq_printf(s, "%04x %#04llx %#014llx\n", i,
+                          FIELD_GET(FBNIC_BD_DESC_ID_MASK, bd),
+                          FIELD_GET(FBNIC_BD_DESC_ADDR_MASK, bd));
+       }
+
+       return 0;
+}
+
+static void fbnic_dbg_rcd_desc_seq_show(struct seq_file *s, int i)
+{
+       struct fbnic_ring *ring = s->private;
+       u64 rcd = le64_to_cpu(ring->desc[i]);
+
+       switch (FIELD_GET(FBNIC_RCD_TYPE_MASK, rcd)) {
+       case FBNIC_RCD_TYPE_HDR_AL:
+       case FBNIC_RCD_TYPE_PAY_AL:
+               seq_printf(s, "%04x %llx %llx %llx %#06llx      %#06llx   %#06llx\n",
+                          i, FIELD_GET(FBNIC_RCD_DONE, rcd),
+                          FIELD_GET(FBNIC_RCD_TYPE_MASK, rcd),
+                          FIELD_GET(FBNIC_RCD_AL_PAGE_FIN, rcd),
+                          FIELD_GET(FBNIC_RCD_AL_BUFF_OFF_MASK, rcd),
+                          FIELD_GET(FBNIC_RCD_AL_BUFF_LEN_MASK, rcd),
+                          FIELD_GET(FBNIC_RCD_AL_BUFF_ID_MASK, rcd));
+               break;
+       case FBNIC_RCD_TYPE_OPT_META:
+               seq_printf(s, "%04x %llx %llx %llx %llx %llx      %#06llx   %#012llx\n",
+                          i, FIELD_GET(FBNIC_RCD_DONE, rcd),
+                          FIELD_GET(FBNIC_RCD_TYPE_MASK, rcd),
+                          FIELD_GET(FBNIC_RCD_OPT_META_TYPE_MASK, rcd),
+                          FIELD_GET(FBNIC_RCD_OPT_META_TS, rcd),
+                          FIELD_GET(FBNIC_RCD_OPT_META_ACTION, rcd),
+                          FIELD_GET(FBNIC_RCD_OPT_META_ACTION_MASK, rcd),
+                          FIELD_GET(FBNIC_RCD_OPT_META_TS_MASK, rcd));
+               break;
+       case FBNIC_RCD_TYPE_META:
+               seq_printf(s, "%04x %llx %llx %llx %llx %llx %llx %llx %llx %llx %#06llx   %#010llx\n",
+                          i, FIELD_GET(FBNIC_RCD_DONE, rcd),
+                          FIELD_GET(FBNIC_RCD_TYPE_MASK, rcd),
+                          FIELD_GET(FBNIC_RCD_META_ECN, rcd),
+                          FIELD_GET(FBNIC_RCD_META_L4_CSUM_UNNECESSARY, rcd),
+                          FIELD_GET(FBNIC_RCD_META_ERR_MAC_EOP, rcd),
+                          FIELD_GET(FBNIC_RCD_META_ERR_TRUNCATED_FRAME, rcd),
+                          FIELD_GET(FBNIC_RCD_META_ERR_PARSER, rcd),
+                          FIELD_GET(FBNIC_RCD_META_L4_TYPE_MASK, rcd),
+                          FIELD_GET(FBNIC_RCD_META_L3_TYPE_MASK, rcd),
+                          FIELD_GET(FBNIC_RCD_META_L2_CSUM_MASK, rcd),
+                          FIELD_GET(FBNIC_RCD_META_RSS_HASH_MASK, rcd));
+               break;
+       }
+}
+
+static int fbnic_dbg_rcq_desc_seq_show(struct seq_file *s, void *v)
+{
+       struct fbnic_ring *ring = s->private;
+       char hdr[80];
+       int i;
+
+       /* Generate header on first entry */
+       fbnic_dbg_ring_show(s);
+       snprintf(hdr, sizeof(hdr),
+                "%18s %s %s\n", "OFFSET/", "L", "L");
+       seq_puts(s, hdr);
+       snprintf(hdr, sizeof(hdr),
+                "%4s %s %s %s %s %s %s %s %s %s %-8s %s\n",
+                "DESC", "D", "T", "F", "C", "M", "T", "P", "4", "3", "LEN/CSUM", "ID/TS/RSS");
+       seq_puts(s, hdr);
+       fbnic_dbg_desc_break(s, strnlen(hdr, sizeof(hdr)));
+
+       /* Display descriptor */
+       if (!ring->desc) {
+               seq_puts(s, "Descriptor ring not allocated.\n");
+               return 0;
+       }
+
+       for (i = 0; i <= ring->size_mask; i++)
+               fbnic_dbg_rcd_desc_seq_show(s, i);
+
+       return 0;
+}
+
+static int fbnic_dbg_desc_open(struct inode *inode, struct file *file)
+{
+       struct fbnic_ring *ring = inode->i_private;
+       int (*show)(struct seq_file *s, void *v);
+
+       switch (ring->doorbell - fbnic_ring_csr_base(ring)) {
+       case FBNIC_QUEUE_TWQ0_TAIL:
+       case FBNIC_QUEUE_TWQ1_TAIL:
+               show = fbnic_dbg_twq_desc_seq_show;
+               break;
+       case FBNIC_QUEUE_TCQ_HEAD:
+               show = fbnic_dbg_tcq_desc_seq_show;
+               break;
+       case FBNIC_QUEUE_BDQ_HPQ_TAIL:
+       case FBNIC_QUEUE_BDQ_PPQ_TAIL:
+               show = fbnic_dbg_bdq_desc_seq_show;
+               break;
+       case FBNIC_QUEUE_RCQ_HEAD:
+               show = fbnic_dbg_rcq_desc_seq_show;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return single_open(file, show, ring);
+}
+
+static const struct file_operations fbnic_dbg_desc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = fbnic_dbg_desc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+void fbnic_dbg_nv_init(struct fbnic_napi_vector *nv)
+{
+       struct fbnic_dev *fbd = nv->fbd;
+       char name[16];
+       int i, j;
+
+       /* Generate a folder for each napi vector */
+       snprintf(name, sizeof(name), "nv.%03d", nv->v_idx);
+
+       nv->dbg_nv = debugfs_create_dir(name, fbd->dbg_fbd);
+
+       /* Generate a file for each Tx ring in the napi vector */
+       for (i = 0; i < nv->txt_count; i++) {
+               struct fbnic_q_triad *qt = &nv->qt[i];
+               unsigned int hw_idx;
+
+               hw_idx = fbnic_ring_csr_base(&qt->cmpl) -
+                         &fbd->uc_addr0[FBNIC_QUEUE(0)];
+               hw_idx /= FBNIC_QUEUE_STRIDE;
+
+               snprintf(name, sizeof(name), "twq0.%03d", hw_idx);
+               debugfs_create_file(name, 0400, nv->dbg_nv, &qt->sub0,
+                                   &fbnic_dbg_desc_fops);
+
+               snprintf(name, sizeof(name), "twq1.%03d", hw_idx);
+               debugfs_create_file(name, 0400, nv->dbg_nv, &qt->sub1,
+                                   &fbnic_dbg_desc_fops);
+
+               snprintf(name, sizeof(name), "tcq.%03d", hw_idx);
+               debugfs_create_file(name, 0400, nv->dbg_nv, &qt->cmpl,
+                                   &fbnic_dbg_desc_fops);
+       }
+
+       /* Generate a file for each Rx ring in the napi vector */
+       for (j = 0; j < nv->rxt_count; j++, i++) {
+               struct fbnic_q_triad *qt = &nv->qt[i];
+               unsigned int hw_idx;
+
+               hw_idx = fbnic_ring_csr_base(&qt->cmpl) -
+                         &fbd->uc_addr0[FBNIC_QUEUE(0)];
+               hw_idx /= FBNIC_QUEUE_STRIDE;
+
+               snprintf(name, sizeof(name), "hpq.%03d", hw_idx);
+               debugfs_create_file(name, 0400, nv->dbg_nv, &qt->sub0,
+                                   &fbnic_dbg_desc_fops);
+
+               snprintf(name, sizeof(name), "ppq.%03d", hw_idx);
+               debugfs_create_file(name, 0400, nv->dbg_nv, &qt->sub1,
+                                   &fbnic_dbg_desc_fops);
+
+               snprintf(name, sizeof(name), "rcq.%03d", hw_idx);
+               debugfs_create_file(name, 0400, nv->dbg_nv, &qt->cmpl,
+                                   &fbnic_dbg_desc_fops);
+       }
+}
+
+void fbnic_dbg_nv_exit(struct fbnic_napi_vector *nv)
+{
+       debugfs_remove_recursive(nv->dbg_nv);
+       nv->dbg_nv = NULL;
+}
+
 static int fbnic_dbg_mac_addr_show(struct seq_file *s, void *v)
 {
        struct fbnic_dev *fbd = s->private;
index 9240673c7533d2bcb9d6b2f86f54a46fd648c26c..6f9389748a7d90112bf804ca8dfa8f00882a893e 100644 (file)
@@ -142,10 +142,14 @@ void fbnic_up(struct fbnic_net *fbn)
        netif_tx_start_all_queues(fbn->netdev);
 
        fbnic_service_task_start(fbn);
+
+       fbnic_dbg_up(fbn);
 }
 
 void fbnic_down_noidle(struct fbnic_net *fbn)
 {
+       fbnic_dbg_down(fbn);
+
        fbnic_service_task_stop(fbn);
 
        /* Disable Tx/Rx Processing */
index e36ed25462b481f56dc49ce87f8165369911fe34..e29959241ff3b444da393fa1c2aa1239fe528b73 100644 (file)
@@ -39,7 +39,7 @@ struct fbnic_xmit_cb {
 
 #define FBNIC_XMIT_NOUNMAP     ((void *)1)
 
-static u32 __iomem *fbnic_ring_csr_base(const struct fbnic_ring *ring)
+u32 __iomem *fbnic_ring_csr_base(const struct fbnic_ring *ring)
 {
        unsigned long csr_base = (unsigned long)ring->doorbell;
 
@@ -2255,6 +2255,22 @@ fbnic_nv_disable(struct fbnic_net *fbn, struct fbnic_napi_vector *nv)
        fbnic_wrfl(fbn->fbd);
 }
 
+void fbnic_dbg_down(struct fbnic_net *fbn)
+{
+       int i;
+
+       for (i = 0; i < fbn->num_napi; i++)
+               fbnic_dbg_nv_exit(fbn->napi[i]);
+}
+
+void fbnic_dbg_up(struct fbnic_net *fbn)
+{
+       int i;
+
+       for (i = 0; i < fbn->num_napi; i++)
+               fbnic_dbg_nv_init(fbn->napi[i]);
+}
+
 void fbnic_disable(struct fbnic_net *fbn)
 {
        struct fbnic_dev *fbd = fbn->fbd;
@@ -2861,6 +2877,7 @@ static void __fbnic_nv_restart(struct fbnic_net *fbn,
 
        for (i = 0; i < nv->txt_count; i++)
                netif_wake_subqueue(fbn->netdev, nv->qt[i].sub0.q_idx);
+       fbnic_dbg_nv_init(nv);
 }
 
 static int fbnic_queue_start(struct net_device *dev,
@@ -2895,6 +2912,7 @@ static int fbnic_queue_stop(struct net_device *dev, void *qmem, int idx)
 
        real = container_of(fbn->rx[idx], struct fbnic_q_triad, cmpl);
        nv = fbn->napi[idx % fbn->num_napi];
+       fbnic_dbg_nv_exit(nv);
 
        napi_disable_locked(&nv->napi);
        fbnic_nv_irq_disable(nv);
index 27776e844e29bfcea9bf20a57e30d2b545a2e366..b9560103ab863caeb90e038577965371c61762ff 100644 (file)
@@ -151,6 +151,7 @@ struct fbnic_napi_vector {
        struct napi_struct napi;
        struct device *dev;             /* Device for DMA unmapping */
        struct fbnic_dev *fbd;
+       struct dentry *dbg_nv;
 
        u16 v_idx;
        u8 txt_count;
@@ -187,9 +188,12 @@ void fbnic_napi_disable(struct fbnic_net *fbn);
 void fbnic_config_drop_mode(struct fbnic_net *fbn, bool tx_pause);
 void fbnic_enable(struct fbnic_net *fbn);
 void fbnic_disable(struct fbnic_net *fbn);
+void fbnic_dbg_up(struct fbnic_net *fbn);
+void fbnic_dbg_down(struct fbnic_net *fbn);
 void fbnic_flush(struct fbnic_net *fbn);
 void fbnic_fill(struct fbnic_net *fbn);
 
+u32 __iomem *fbnic_ring_csr_base(const struct fbnic_ring *ring);
 void fbnic_napi_depletion_check(struct net_device *netdev);
 int fbnic_wait_all_queues_idle(struct fbnic_dev *fbd, bool may_fail);
 
@@ -198,4 +202,6 @@ static inline int fbnic_napi_idx(const struct fbnic_napi_vector *nv)
        return nv->v_idx - FBNIC_NON_NAPI_VECTORS;
 }
 
+void fbnic_dbg_nv_init(struct fbnic_napi_vector *nv);
+void fbnic_dbg_nv_exit(struct fbnic_napi_vector *nv);
 #endif /* _FBNIC_TXRX_H_ */