Add rte_pmd_mcdma_qcsr_read() and rte_pmd_mcdma_qcsr_dump() to snapshot
and print queue control/status registers together with driver software
indices. Document the QCSR helpers in mcdma.rst.

Co-developed-by: Cheryl Bansal <[email protected]>
Signed-off-by: Cheryl Bansal <[email protected]>
Signed-off-by: Subhransu S. Prusty <[email protected]>
---
 doc/guides/nics/mcdma.rst                |  10 +-
 drivers/net/altera/mcdma/rte_pmd_mcdma.c | 178 +++++++++++++++++++++++
 drivers/net/altera/mcdma/rte_pmd_mcdma.h |  79 ++++++++++
 3 files changed, 265 insertions(+), 2 deletions(-)

diff --git a/doc/guides/nics/mcdma.rst b/doc/guides/nics/mcdma.rst
index 3bbd345d575c..a41997f1618d 100644
--- a/doc/guides/nics/mcdma.rst
+++ b/doc/guides/nics/mcdma.rst
@@ -107,8 +107,14 @@ defined by the FPGA application connected to the MCDMA IP.
 Experimental driver API
 -----------------------
 
-The header ``rte_pmd_mcdma.h`` provides experimental helpers to access
- the PIO BAR:
+The header ``rte_pmd_mcdma.h`` provides experimental helpers to inspect queue
+state and access the PIO BAR:
+
+rte_pmd_mcdma_qcsr_read()
+   Read QCSR registers and software queue indices for one queue.
+
+rte_pmd_mcdma_qcsr_dump()
+   Dump decoded QCSR state to a ``FILE`` stream.
 
 rte_pmd_mcdma_pio_read64() / rte_pmd_mcdma_pio_write64()
    Read or write 64-bit registers in the mapped PIO BAR. ``pio_read64`` returns
diff --git a/drivers/net/altera/mcdma/rte_pmd_mcdma.c 
b/drivers/net/altera/mcdma/rte_pmd_mcdma.c
index 49d7d97b90bc..3736c7b45913 100644
--- a/drivers/net/altera/mcdma/rte_pmd_mcdma.c
+++ b/drivers/net/altera/mcdma/rte_pmd_mcdma.c
@@ -38,6 +38,82 @@ mcdma_pmd_port_get(uint16_t port_id, struct rte_eth_dev 
**eth_dev)
        return 0;
 }
 
+static struct mcdma_queue *
+mcdma_pmd_queue_get(struct rte_eth_dev *dev, uint16_t queue_id,
+                   enum rte_pmd_mcdma_queue_dir dir)
+{
+       if (dir == RTE_PMD_MCDMA_QUEUE_TX) {
+               if (queue_id >= dev->data->nb_tx_queues)
+                       return NULL;
+               return dev->data->tx_queues[queue_id];
+       }
+
+       if (queue_id >= dev->data->nb_rx_queues)
+               return NULL;
+
+       return dev->data->rx_queues[queue_id];
+}
+
+static void
+mcdma_qcsr_regs_read(struct mcdma_queue *q, struct rte_pmd_mcdma_qcsr *regs)
+{
+       regs->q_ctrl = mcdma_qcsr_reg_readl(q->qcsr, MCDMA_QCSR_Q_CTRL);
+       regs->q_start_addr_l = mcdma_qcsr_reg_readl(q->qcsr,
+                                                   MCDMA_QCSR_Q_START_ADDR_L);
+       regs->q_start_addr_h = mcdma_qcsr_reg_readl(q->qcsr,
+                                                   MCDMA_QCSR_Q_START_ADDR_H);
+       regs->q_size = mcdma_qcsr_reg_readl(q->qcsr, MCDMA_QCSR_Q_SIZE);
+       regs->q_tail_pointer = mcdma_qcsr_reg_readl(q->qcsr,
+                                                   MCDMA_QCSR_Q_TAIL_POINTER);
+       regs->q_head_pointer = mcdma_qcsr_reg_readl(q->qcsr,
+                                                   MCDMA_QCSR_Q_HEAD_POINTER);
+       regs->q_completed_pointer = mcdma_qcsr_reg_readl(q->qcsr,
+                                                        
MCDMA_QCSR_Q_COMPLETED_POINTER);
+       regs->q_consumed_head_addr_l = mcdma_qcsr_reg_readl(q->qcsr,
+                       MCDMA_QCSR_Q_CONSUMED_HEAD_ADDR_L);
+       regs->q_consumed_head_addr_h = mcdma_qcsr_reg_readl(q->qcsr,
+                       MCDMA_QCSR_Q_CONSUMED_HEAD_ADDR_H);
+       regs->q_batch_delay = mcdma_qcsr_reg_readl(q->qcsr,
+                                                  MCDMA_QCSR_Q_BATCH_DELAY);
+       regs->q_debug_status_1 = mcdma_qcsr_reg_readl(q->qcsr,
+                                                     
MCDMA_QCSR_Q_DEBUG_STATUS_1);
+       regs->q_debug_status_2 = mcdma_qcsr_reg_readl(q->qcsr,
+                                                     
MCDMA_QCSR_Q_DEBUG_STATUS_2);
+       regs->q_data_drp_err_ctr = mcdma_qcsr_reg_readl(q->qcsr,
+                       MCDMA_QCSR_Q_DATA_DRP_ERR_CTR);
+       regs->q_payload_count = mcdma_qcsr_reg_readl(q->qcsr,
+                                                    
MCDMA_QCSR_Q_PAYLOAD_COUNT);
+       regs->q_reset = mcdma_qcsr_reg_readl(q->qcsr, MCDMA_QCSR_Q_RESET);
+       regs->q_cpl_timeout = mcdma_qcsr_reg_readl(q->qcsr,
+                                                  MCDMA_QCSR_Q_CPL_TIMEOUT);
+
+       rte_rmb();
+       regs->prod_didx = q->prod_didx;
+       regs->cons_didx = q->cons_didx;
+       regs->freed_cons_didx = q->freed_cons_didx;
+       regs->submitted_didx = q->submitted_didx;
+       regs->num_descs = q->num_descs;
+}
+
+static void
+mcdma_qcsr_dump_decoded(FILE *f, const struct rte_pmd_mcdma_qcsr *regs)
+{
+       mcdma_qcsr_q_ctrl_t q_ctrl;
+
+       q_ctrl.val = regs->q_ctrl;
+       fprintf(f, "  Q_CTRL decoded: q_en=%u q_wb_en=%u q_intr_en=%u\n",
+               q_ctrl.field.q_en, q_ctrl.field.q_wb_en, 
q_ctrl.field.q_intr_en);
+
+       if (regs->q_head_pointer & MCDMA_QCSR_PTR_ERR_MASK)
+               fprintf(f, "  Q_HEAD_POINTER error bit set\n");
+       if (regs->q_completed_pointer & MCDMA_QCSR_PTR_ERR_MASK)
+               fprintf(f, "  Q_COMPLETED_POINTER error bit set\n");
+       if (regs->q_data_drp_err_ctr & MCDMA_QCSR_DRP_CTR_VALID) {
+               fprintf(f, "  Q_DATA_DRP_ERR_CTR drop_count=%u\n",
+                       regs->q_data_drp_err_ctr & MCDMA_QCSR_DRP_CTR_CNT_MASK);
+       }
+}
+
 static int
 mcdma_pio_offset_check(const struct mcdma_pci_device *priv, uint64_t offset)
 {
@@ -104,3 +180,105 @@ rte_pmd_mcdma_pio_write64(uint16_t port_id, uint64_t 
offset, uint64_t val)
        mcdma_pio_reg_write64(priv->pio, offset, val);
        return 0;
 }
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_mcdma_qcsr_read, 26.11)
+int
+rte_pmd_mcdma_qcsr_read(uint16_t port_id, uint16_t queue_id,
+                       enum rte_pmd_mcdma_queue_dir dir,
+                       struct rte_pmd_mcdma_qcsr *regs)
+{
+       struct rte_eth_dev *dev;
+       struct mcdma_queue *q;
+       int ret;
+
+       if (regs == NULL)
+               return -EINVAL;
+
+       if (dir != RTE_PMD_MCDMA_QUEUE_RX && dir != RTE_PMD_MCDMA_QUEUE_TX)
+               return -EINVAL;
+
+       ret = mcdma_pmd_port_get(port_id, &dev);
+       if (ret != 0)
+               return ret;
+
+       q = mcdma_pmd_queue_get(dev, queue_id, dir);
+       if (q == NULL || q->qcsr == NULL)
+               return -EINVAL;
+
+       memset(regs, 0, sizeof(*regs));
+       mcdma_qcsr_regs_read(q, regs);
+       return 0;
+}
+
+static void
+mcdma_qcsr_dump_reg(FILE *f, const char *name, uint32_t offset, uint32_t val)
+{
+       fprintf(f, "  %s @ 0x%03x = 0x%08x (%u)\n", name, offset, val, val);
+}
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_mcdma_qcsr_dump, 26.11)
+int
+rte_pmd_mcdma_qcsr_dump(uint16_t port_id, uint16_t queue_id,
+                       enum rte_pmd_mcdma_queue_dir dir, FILE *f)
+{
+       struct rte_pmd_mcdma_qcsr regs;
+       uint64_t qbuf_dma;
+       int ret;
+
+       if (f == NULL)
+               f = stdout;
+
+       ret = rte_pmd_mcdma_qcsr_read(port_id, queue_id, dir, &regs);
+       if (ret != 0)
+               return ret;
+
+       qbuf_dma = ((uint64_t)regs.q_start_addr_h << 32) | regs.q_start_addr_l;
+
+       fprintf(f, "MCDMA QCSR dump port %u queue %u %s\n",
+               port_id, queue_id,
+               dir == RTE_PMD_MCDMA_QUEUE_TX ? "TX" : "RX");
+       fprintf(f, "  ring_dma=0x%016llx ring_size_log2=%u\n",
+               (unsigned long long)qbuf_dma, regs.q_size);
+
+       mcdma_qcsr_dump_reg(f, "Q_CTRL", MCDMA_QCSR_Q_CTRL, regs.q_ctrl);
+       mcdma_qcsr_dump_reg(f, "Q_START_ADDR_L", MCDMA_QCSR_Q_START_ADDR_L,
+                           regs.q_start_addr_l);
+       mcdma_qcsr_dump_reg(f, "Q_START_ADDR_H", MCDMA_QCSR_Q_START_ADDR_H,
+                           regs.q_start_addr_h);
+       mcdma_qcsr_dump_reg(f, "Q_SIZE", MCDMA_QCSR_Q_SIZE, regs.q_size);
+       mcdma_qcsr_dump_reg(f, "Q_TAIL_POINTER", MCDMA_QCSR_Q_TAIL_POINTER,
+                           regs.q_tail_pointer);
+       mcdma_qcsr_dump_reg(f, "Q_HEAD_POINTER", MCDMA_QCSR_Q_HEAD_POINTER,
+                           regs.q_head_pointer);
+       mcdma_qcsr_dump_reg(f, "Q_COMPLETED_POINTER",
+                           MCDMA_QCSR_Q_COMPLETED_POINTER,
+                           regs.q_completed_pointer);
+       mcdma_qcsr_dump_reg(f, "Q_CONSUMED_HEAD_ADDR_L",
+                           MCDMA_QCSR_Q_CONSUMED_HEAD_ADDR_L,
+                           regs.q_consumed_head_addr_l);
+       mcdma_qcsr_dump_reg(f, "Q_CONSUMED_HEAD_ADDR_H",
+                           MCDMA_QCSR_Q_CONSUMED_HEAD_ADDR_H,
+                           regs.q_consumed_head_addr_h);
+       mcdma_qcsr_dump_reg(f, "Q_BATCH_DELAY", MCDMA_QCSR_Q_BATCH_DELAY,
+                           regs.q_batch_delay);
+       mcdma_qcsr_dump_reg(f, "Q_DEBUG_STATUS_1", MCDMA_QCSR_Q_DEBUG_STATUS_1,
+                           regs.q_debug_status_1);
+       mcdma_qcsr_dump_reg(f, "Q_DEBUG_STATUS_2", MCDMA_QCSR_Q_DEBUG_STATUS_2,
+                           regs.q_debug_status_2);
+       mcdma_qcsr_dump_reg(f, "Q_DATA_DRP_ERR_CTR",
+                           MCDMA_QCSR_Q_DATA_DRP_ERR_CTR,
+                           regs.q_data_drp_err_ctr);
+       mcdma_qcsr_dump_reg(f, "Q_PAYLOAD_COUNT", MCDMA_QCSR_Q_PAYLOAD_COUNT,
+                           regs.q_payload_count);
+       mcdma_qcsr_dump_reg(f, "Q_RESET", MCDMA_QCSR_Q_RESET, regs.q_reset);
+       mcdma_qcsr_dump_reg(f, "Q_CPL_TIMEOUT", MCDMA_QCSR_Q_CPL_TIMEOUT,
+                           regs.q_cpl_timeout);
+
+       fprintf(f, "  SW prod_didx=%u cons_didx=%u freed_cons_didx=%u "
+               "submitted_didx=%u num_descs=%u\n",
+               regs.prod_didx, regs.cons_didx, regs.freed_cons_didx,
+               regs.submitted_didx, regs.num_descs);
+
+       mcdma_qcsr_dump_decoded(f, &regs);
+       return 0;
+}
diff --git a/drivers/net/altera/mcdma/rte_pmd_mcdma.h 
b/drivers/net/altera/mcdma/rte_pmd_mcdma.h
index d76babbdf7e0..7b4ad83c07a2 100644
--- a/drivers/net/altera/mcdma/rte_pmd_mcdma.h
+++ b/drivers/net/altera/mcdma/rte_pmd_mcdma.h
@@ -16,6 +16,85 @@
 
 #include <rte_compat.h>
 
+/** MCDMA queue direction for PMD APIs. */
+enum rte_pmd_mcdma_queue_dir {
+       RTE_PMD_MCDMA_QUEUE_RX = 0, /**< Device-to-host (RX). */
+       RTE_PMD_MCDMA_QUEUE_TX = 1, /**< Host-to-device (TX). */
+};
+
+/** Snapshot of one queue's QCSR registers and driver state. */
+struct rte_pmd_mcdma_qcsr {
+       uint32_t q_ctrl;
+       uint32_t q_start_addr_l;
+       uint32_t q_start_addr_h;
+       uint32_t q_size;
+       uint32_t q_tail_pointer;
+       uint32_t q_head_pointer;
+       uint32_t q_completed_pointer;
+       uint32_t q_consumed_head_addr_l;
+       uint32_t q_consumed_head_addr_h;
+       uint32_t q_batch_delay;
+       uint32_t q_debug_status_1;
+       uint32_t q_debug_status_2;
+       uint32_t q_data_drp_err_ctr;
+       uint32_t q_payload_count;
+       uint32_t q_reset;
+       uint32_t q_cpl_timeout;
+
+       uint16_t prod_didx;
+       uint16_t cons_didx;
+       uint16_t freed_cons_didx;
+       uint16_t submitted_didx;
+       uint32_t num_descs;
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Read QCSR registers and software queue state for one queue.
+ *
+ * @param port_id
+ *   Port identifier.
+ * @param queue_id
+ *   Queue identifier.
+ * @param dir
+ *   Queue direction (RX or TX).
+ * @param regs
+ *   Output register snapshot.
+ *
+ * @return
+ *   0 on success, negative errno on failure.
+ */
+__rte_experimental
+int
+rte_pmd_mcdma_qcsr_read(uint16_t port_id, uint16_t queue_id,
+                       enum rte_pmd_mcdma_queue_dir dir,
+                       struct rte_pmd_mcdma_qcsr *regs);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Dump QCSR registers and software queue state to a stream.
+ *
+ * @param port_id
+ *   Port identifier.
+ * @param queue_id
+ *   Queue identifier.
+ * @param dir
+ *   Queue direction (RX or TX).
+ * @param f
+ *   Output stream. Uses stdout if NULL.
+ *
+ * @return
+ *   0 on success, negative errno on failure.
+ */
+__rte_experimental
+int
+rte_pmd_mcdma_qcsr_dump(uint16_t port_id, uint16_t queue_id,
+                       enum rte_pmd_mcdma_queue_dir dir, FILE *f);
+
 /**
  * @warning
  * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
-- 
2.34.1

Reply via email to