[PATCH v5 06/14] net/enetc: support registers dump

Gagandeep Singh <[email protected]>
Newsgroups org.dpdk.dev
Message-ID <[email protected]>
Implement the .get_reg operation for the ENETC4 PF and VF PMDs to dump
the device registers via rte_eth_dev_get_reg_info.

The VF dumps the registers reachable by a virtual station interface
(VSI): the station interface and per-ring BD ring registers. Port
registers are not accessible by a VF.

The PF additionally dumps the port registers, which are only
accessible by the physical station interface (PSI).

Signed-off-by: Gagandeep Singh <[email protected]>
---
 doc/guides/nics/enetc4.rst             |  1 +
 doc/guides/nics/features/enetc4.ini    |  1 +
 doc/guides/rel_notes/release_26_11.rst |  1 +
 drivers/net/enetc/enetc.h              | 13 +++++
 drivers/net/enetc/enetc4_ethdev.c      | 70 ++++++++++++++++++++++++++
 drivers/net/enetc/enetc4_vf.c          | 62 +++++++++++++++++++++++
 6 files changed, 148 insertions(+)

diff --git a/doc/guides/nics/enetc4.rst b/doc/guides/nics/enetc4.rst
index fa93f40b22..16389aee5b 100644
--- a/doc/guides/nics/enetc4.rst
+++ b/doc/guides/nics/enetc4.rst
@@ -60,6 +60,7 @@ Key functionality includes:
   requested. RSC requires the FCS to be stripped, so it cannot be combined
   with the KEEP_CRC Rx offload.
 - Firmware version: The NETC IP version is reported via ``rte_eth_dev_fw_version_get``.
+- Registers dump: The station interface, port (PF only) and BD ring registers are dumped via ``rte_eth_dev_get_reg_info``.
 
 
 Prerequisites
diff --git a/doc/guides/nics/features/enetc4.ini b/doc/guides/nics/features/enetc4.ini
index eaf474e7ba..6540a43909 100644
--- a/doc/guides/nics/features/enetc4.ini
+++ b/doc/guides/nics/features/enetc4.ini
@@ -17,6 +17,7 @@ RSS hash             = Y
 Packet type parsing  = Y
 Basic stats          = Y
 FW version           = Y
+Registers dump       = Y
 L3 checksum offload  = Y
 L4 checksum offload  = Y
 CRC offload          = Y
diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst
index d212cce000..6fece98f28 100644
--- a/doc/guides/rel_notes/release_26_11.rst
+++ b/doc/guides/rel_notes/release_26_11.rst
@@ -67,6 +67,7 @@ New Features
     Users running a PF kernel older than 6.18.37 must pass ``vf_link_legacy=1``
     as a device argument, otherwise link speed reporting will be incorrect.
   * Added firmware version reporting for the ENETC4 VF.
+  * Added register dump support for ENETC4 PF and VF.
 
 Removed Items
 -------------
diff --git a/drivers/net/enetc/enetc.h b/drivers/net/enetc/enetc.h
index 27a617a62f..b70664eede 100644
--- a/drivers/net/enetc/enetc.h
+++ b/drivers/net/enetc/enetc.h
@@ -396,6 +396,19 @@ enetc_bd_unused(struct enetc_bdr *bdr)
 	return bdr->bd_count + bdr->next_to_clean - bdr->next_to_use - 1;
 }
 
+/* Per-ring Tx BDR registers dumped by .get_reg (shared by PF and VF) */
+static const uint32_t enetc4_txbdr_regs[] = {
+	ENETC_TBMR, ENETC_TBSR, ENETC_TBBAR0, ENETC_TBBAR1,
+	ENETC_TBCIR, ENETC_TBLENR,
+};
+
+/* Per-ring Rx BDR registers dumped by .get_reg (shared by PF and VF) */
+static const uint32_t enetc4_rxbdr_regs[] = {
+	ENETC_RBMR, ENETC_RBSR, ENETC_RBBSR, ENETC_RBCIR,
+	ENETC_RBBAR0, ENETC_RBBAR1, ENETC_RBPIR, ENETC_RBLENR,
+};
+
+
 /* CBDR prototypes */
 int enetc4_setup_cbdr(struct rte_eth_dev *dev, struct enetc_hw *hw,
 			int bd_count, struct netc_cbdr *cbdr);
diff --git a/drivers/net/enetc/enetc4_ethdev.c b/drivers/net/enetc/enetc4_ethdev.c
index b60c8f6f48..bccd418e32 100644
--- a/drivers/net/enetc/enetc4_ethdev.c
+++ b/drivers/net/enetc/enetc4_ethdev.c
@@ -1172,6 +1172,75 @@ enetc4_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused,
 	return ptypes;
 }
 
+/* Station interface registers dumped by .get_reg */
+static const uint32_t enetc4_pf_si_regs[] = {
+	ENETC_SIMR, ENETC_SICAPR0, ENETC_SIPMAR0, ENETC_SIPMAR1,
+	ENETC4_SIROCT0, ENETC4_SIRFRM0, ENETC4_SITOCT0, ENETC4_SITFRM0,
+	ENETC4_SITDFCR,
+};
+
+/* Port registers dumped by .get_reg (accessible only by the PF) */
+static const uint32_t enetc4_pf_port_regs[] = {
+	ENETC4_PMR, ENETC4_PSIPMMR, ENETC4_PMAR0, ENETC4_PMAR1,
+	ENETC4_PM_CMD_CFG(0), ENETC4_PM_MAXFRM(0), ENETC4_PM_IF_MODE(0),
+	ENETC4_PM_IF_STATUS(0),
+};
+
+/*
+ * Dump the PF-accessible registers: station interface, port and per-ring
+ * BD ring registers. When info->data is NULL, only the register count and
+ * width are reported so the caller can size its buffer.
+ */
+static int
+enetc4_get_regs(struct rte_eth_dev *dev, struct rte_dev_reg_info *regs)
+{
+	struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct enetc_hw *enetc_hw = &hw->hw;
+	uint32_t count, addr;
+	uint32_t *buf;
+	uint16_t i, j;
+
+	count = RTE_DIM(enetc4_pf_si_regs);
+	count += RTE_DIM(enetc4_pf_port_regs);
+	count += RTE_DIM(enetc4_txbdr_regs) * dev->data->nb_tx_queues;
+	count += RTE_DIM(enetc4_rxbdr_regs) * dev->data->nb_rx_queues;
+
+	if (regs->data == NULL) {
+		regs->length = count;
+		regs->width = sizeof(uint32_t);
+		return 0;
+	}
+
+	if (regs->length && regs->length < count)
+		return -ENOTSUP;
+
+	buf = regs->data;
+
+	for (i = 0; i < RTE_DIM(enetc4_pf_si_regs); i++)
+		*buf++ = enetc4_rd(enetc_hw, enetc4_pf_si_regs[i]);
+
+	for (i = 0; i < RTE_DIM(enetc4_pf_port_regs); i++)
+		*buf++ = enetc4_port_rd(enetc_hw, enetc4_pf_port_regs[i]);
+
+	for (i = 0; i < dev->data->nb_tx_queues; i++) {
+		for (j = 0; j < RTE_DIM(enetc4_txbdr_regs); j++) {
+			addr = ENETC_BDR(TX, i, enetc4_txbdr_regs[j]);
+			*buf++ = enetc4_rd(enetc_hw, addr);
+		}
+	}
+
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		for (j = 0; j < RTE_DIM(enetc4_rxbdr_regs); j++) {
+			addr = ENETC_BDR(RX, i, enetc4_rxbdr_regs[j]);
+			*buf++ = enetc4_rd(enetc_hw, addr);
+		}
+	}
+
+	regs->version = hw->device_id << 16 | hw->revision_id;
+
+	return 0;
+}
+
 /*
  * The set of PCI devices this driver supports
  */
@@ -1190,6 +1259,7 @@ static const struct eth_dev_ops enetc4_ops = {
 	.link_update          = enetc4_link_update,
 	.stats_get            = enetc4_stats_get,
 	.stats_reset          = enetc4_stats_reset,
+	.get_reg              = enetc4_get_regs,
 	.promiscuous_enable   = enetc4_promiscuous_enable,
 	.promiscuous_disable  = enetc4_promiscuous_disable,
 	.rx_queue_setup       = enetc4_rx_queue_setup,
diff --git a/drivers/net/enetc/enetc4_vf.c b/drivers/net/enetc/enetc4_vf.c
index 50044eca3f..bf7829ee00 100644
--- a/drivers/net/enetc/enetc4_vf.c
+++ b/drivers/net/enetc/enetc4_vf.c
@@ -930,6 +930,66 @@ enetc4_vf_fw_version_get(struct rte_eth_dev *dev, char *fw_version, size_t fw_si
 	return 0;
 }
 
+/* VF station interface registers dumped by .get_reg */
+static const uint32_t enetc4_vf_si_regs[] = {
+	ENETC_SIMR, ENETC_SICAPR0, ENETC_SIPMAR0, ENETC_SIPMAR1,
+	ENETC4_SIROCT0, ENETC4_SIRFRM0, ENETC4_SITOCT0, ENETC4_SITFRM0,
+	ENETC4_SITDFCR, ENETC4_SIMSIVR, ENETC4_VSIIER, ENETC4_VSIIDR,
+	ENETC4_VSIMSGSR, ENETC4_VSIMSGRR,
+};
+
+/*
+ * Dump the VF-accessible registers. Only station interface and per-ring
+ * BD ring registers are reachable by a VF; port registers are not.
+ * When info->data is NULL, only the register count and width are
+ * reported so the caller can size its buffer.
+ */
+static int
+enetc4_vf_get_regs(struct rte_eth_dev *dev, struct rte_dev_reg_info *regs)
+{
+	struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct enetc_hw *enetc_hw = &hw->hw;
+	uint32_t count, addr;
+	uint32_t *buf;
+	uint16_t i, j;
+
+	count = RTE_DIM(enetc4_vf_si_regs);
+	count += RTE_DIM(enetc4_txbdr_regs) * dev->data->nb_tx_queues;
+	count += RTE_DIM(enetc4_rxbdr_regs) * dev->data->nb_rx_queues;
+
+	if (regs->data == NULL) {
+		regs->length = count;
+		regs->width = sizeof(uint32_t);
+		return 0;
+	}
+
+	if (regs->length && regs->length < count)
+		return -ENOTSUP;
+
+	buf = regs->data;
+
+	for (i = 0; i < RTE_DIM(enetc4_vf_si_regs); i++)
+		*buf++ = enetc_rd(enetc_hw, enetc4_vf_si_regs[i]);
+
+	for (i = 0; i < dev->data->nb_tx_queues; i++) {
+		for (j = 0; j < RTE_DIM(enetc4_txbdr_regs); j++) {
+			addr = ENETC_BDR(TX, i, enetc4_txbdr_regs[j]);
+			*buf++ = enetc_rd(enetc_hw, addr);
+		}
+	}
+
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		for (j = 0; j < RTE_DIM(enetc4_rxbdr_regs); j++) {
+			addr = ENETC_BDR(RX, i, enetc4_rxbdr_regs[j]);
+			*buf++ = enetc_rd(enetc_hw, addr);
+		}
+	}
+
+	regs->version = hw->device_id << 16 | hw->revision_id;
+
+	return 0;
+}
+
 static int
 enetc4_vf_link_update_dummy(struct rte_eth_dev *dev __rte_unused,
 			    int wait_to_complete __rte_unused)
@@ -1468,6 +1528,7 @@ static const struct eth_dev_ops enetc4_vf_ops_no_vsi_m = {
 	.dev_close            = enetc4_dev_close,
 	.stats_get            = enetc4_vf_stats_get,
 	.dev_infos_get        = enetc4_vf_dev_infos_get,
+	.get_reg              = enetc4_vf_get_regs,
 	.mtu_set              = enetc4_vf_mtu_set,
 	.link_update	      = enetc4_vf_link_update_dummy,
 	.rx_queue_setup       = enetc4_rx_queue_setup,
@@ -1489,6 +1550,7 @@ static const struct eth_dev_ops enetc4_vf_ops = {
 	.stats_get            = enetc4_vf_stats_get,
 	.dev_infos_get        = enetc4_vf_dev_infos_get,
 	.fw_version_get       = enetc4_vf_fw_version_get,
+	.get_reg              = enetc4_vf_get_regs,
 	.mtu_set              = enetc4_vf_mtu_set,
 	.mac_addr_set         = enetc4_vf_set_mac_addr,
 	.mac_addr_add	      = enetc4_vf_mac_addr_add,
-- 
2.25.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.