Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 22 Apr 2026 22:47:32 +0000
From:      Bjoern A. Zeeb <bz@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: 5cfbcaa13fb3 - stable/15 - dpaa2: ni: add more stats and link information
Message-ID:  <69e95004.39c3a.33a0f417@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch stable/15 has been updated by bz:

URL: https://cgit.FreeBSD.org/src/commit/?id=5cfbcaa13fb3176dc92574382558f4c4dbfc7d41

commit 5cfbcaa13fb3176dc92574382558f4c4dbfc7d41
Author:     Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2026-02-17 03:04:41 +0000
Commit:     Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2026-04-22 22:47:17 +0000

    dpaa2: ni: add more stats and link information
    
    In addition to the locally generated statistics counters, dpaa2 ni
    provides a larger set of counters than we currently export via
    sysctl.  Add (most of) the missing counters and descriptions.
    Around Page 3/4 there are some things left to do if we want.
    Also the manual was not clear on the descriptions of 3/0 and 3/1.
    
    The second half of the change adds another sysctl note which exports
    the link-state, speed, and capabilities set as a text-blob.  This is
    especially interesting in case the "ni" stops passing packets.
    From what I have found in that case the (internal) link state of the
    ni goes DOWN but we do not see an interrupt for a link-state change.
    
    Being able to diagnose the state helps to (manually) fix it for now
    by changing the media status to 10BaseT or none and then back to auto.
    That usually brings the internal link state back UP.
    
    PR:             279352
    Reviewed by:    dsl, tuexen
    Differential Revision: https://reviews.freebsd.org/D55321
    
    (cherry picked from commit c8cd633d78d04ff535960002ac9d1ab20f74b201)
---
 sys/dev/dpaa2/dpaa2_ni.c | 129 +++++++++++++++++++++++++++++++++++++++++------
 sys/dev/dpaa2/dpaa2_ni.h |   5 +-
 sys/dev/dpaa2/dpaa2_rc.c |   9 ++--
 3 files changed, 120 insertions(+), 23 deletions(-)

diff --git a/sys/dev/dpaa2/dpaa2_ni.c b/sys/dev/dpaa2/dpaa2_ni.c
index 5f9282e120e4..948e903f4329 100644
--- a/sys/dev/dpaa2/dpaa2_ni.c
+++ b/sys/dev/dpaa2/dpaa2_ni.c
@@ -57,6 +57,7 @@
 #include <sys/buf_ring.h>
 #include <sys/smp.h>
 #include <sys/proc.h>
+#include <sys/sbuf.h>
 
 #include <vm/vm.h>
 #include <vm/pmap.h>
@@ -358,19 +359,43 @@ static struct dpni_stat {
 	int	 cnt;
 	char	*name;
 	char	*desc;
-} dpni_stat_sysctls[DPAA2_NI_STAT_SYSCTLS] = {
+} dpni_stat_sysctls[] = {
 	/* PAGE, COUNTER, NAME, DESCRIPTION */
-	{  0, 0, "in_all_frames",	"All accepted ingress frames" },
-	{  0, 1, "in_all_bytes",	"Bytes in all accepted ingress frames" },
-	{  0, 2, "in_multi_frames",	"Multicast accepted ingress frames" },
-	{  1, 0, "eg_all_frames",	"All egress frames transmitted" },
-	{  1, 1, "eg_all_bytes",	"Bytes in all frames transmitted" },
-	{  1, 2, "eg_multi_frames",	"Multicast egress frames transmitted" },
-	{  2, 0, "in_filtered_frames",	"All ingress frames discarded due to "
-	   				"filtering" },
-	{  2, 1, "in_discarded_frames",	"All frames discarded due to errors" },
-	{  2, 2, "in_nobuf_discards",	"Discards on ingress side due to buffer "
-	   				"depletion in DPNI buffer pools" },
+	{ 0, 0, "in_all_frames",	"All accepted ingress frames" },
+	{ 0, 1, "in_all_bytes",		"Bytes in all accepted ingress frames" },
+	{ 0, 2, "in_mc_frames",		"Multicast accepted ingress frames" },
+	{ 0, 3, "in_mc_bytes",		"Bytes in received multicast frames" },
+	{ 0, 4, "in_bc_frames",		"Broadcast accepted ingress frames" },
+	{ 0, 5, "in_bc_bytes",		"Bytes in broadcast multicast frames" },
+
+	{ 1, 0, "eg_all_frames",	"All egress frames transmitted" },
+	{ 1, 1, "eg_all_bytes",		"Bytes in all frames transmitted" },
+	{ 1, 2, "eg_mc_frames",		"Multicast egress frames transmitted" },
+	{ 1, 3, "eg_mc_bytes",		"Bytes in transmitted multicast frame" },
+	{ 1, 4, "eg_bc_frames",		"Broadcast egress frames transmitted" },
+	{ 1, 5, "eg_bc_bytes",		"Bytes in broadcast multicast frames" },
+
+	{ 2, 0, "in_filtered_frames",	"All ingress frames discarded due to filtering" },
+	{ 2, 1, "in_discarded_frames",	"All frames discarded due to errors" },
+	{ 2, 2, "in_nobuf_discards",	"Discards on ingress side due to buffer depletion in DPNI buffer pools" },
+	{ 2, 3, "eg_frames_disc",	"Frames discarded on transmit due to DPNI configuration and/or frame state" },
+	{ 2, 4, "eg_frames_tx",		"Frames that have been confirmed after transmission" },
+
+	/* XXX FIXME Page 3/4 can take a param as well not encoded here. */
+	/* XXX 3/0 and 3/1 have the same description in the manual?  Where's the difference? */
+	{ 3, 0, "bytes_dequeued",	"Cumulative count of the number of bytes dequeued" },
+	{ 3, 1, "frames_dequeued",	"Cumulative count of the number of frames dequeued" },
+	{ 3, 2, "bytes_enqueued_rej",	"Cumulative count of the number of bytes in all frames whose enqueue was rejected." },
+	{ 3, 3, "frames_enqueued_rej",	"Cumulative count of all frame enqueues rejected." },
+
+	{ 4, 0, "fames_rej_tc",		"Rejected frames in associated congestion point (valid if this TC has an associated congestion point)" },
+	{ 4, 1, "bytes_rej_tc",		"Rejected bytes in associated congestion point (valid if this TC has an associated congestion point)" },
+
+	{ 5, 0, "pol_red",		"Policer RED packet counter. 32bit value valid only when policer is enabled." },
+	{ 5, 1, "pol_yel",		"Policer YELLOW packet counter. 32bit value valid only when policer is enabled." },
+	{ 5, 2, "pol_gre",		"Policer GREEN packet counter. 32bit value valid only when policer is enabled." },
+	{ 5, 3, "pol_re_red",		"Policer recolored RED packet counter. 32bit value valid only when policer is enabled." },
+	{ 5, 4, "pol_re_yel",		"Policer recolored YELLOW packet counter. 32bit value valid only when policer is enabled." },
 };
 
 struct dpaa2_ni_rx_ctx {
@@ -453,6 +478,7 @@ static int dpaa2_ni_tx_conf(struct dpaa2_channel *, struct dpaa2_ni_fq *,
 static int dpaa2_ni_collect_stats(SYSCTL_HANDLER_ARGS);
 static int dpaa2_ni_collect_buf_num(SYSCTL_HANDLER_ARGS);
 static int dpaa2_ni_collect_buf_free(SYSCTL_HANDLER_ARGS);
+static int dpaa2_ni_sysctl_link_state(SYSCTL_HANDLER_ARGS);
 
 static int
 dpaa2_ni_probe(device_t dev)
@@ -1720,7 +1746,7 @@ dpaa2_ni_setup_sysctls(struct dpaa2_ni_softc *sc)
 	node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "stats",
 	    CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "DPNI Statistics");
 	parent = SYSCTL_CHILDREN(node);
-	for (i = 0; i < DPAA2_NI_STAT_SYSCTLS; ++i) {
+	for (i = 0; i < nitems(dpni_stat_sysctls); ++i) {
 		SYSCTL_ADD_PROC(ctx, parent, i, dpni_stat_sysctls[i].name,
 		    CTLTYPE_U64 | CTLFLAG_RD, sc, 0, dpaa2_ni_collect_stats,
 		    "IU", dpni_stat_sysctls[i].desc);
@@ -1757,9 +1783,8 @@ dpaa2_ni_setup_sysctls(struct dpaa2_ni_softc *sc)
 	    CTLTYPE_U32 | CTLFLAG_RD, sc, 0, dpaa2_ni_collect_buf_free,
 	    "IU", "number of free Rx buffers in the buffer pool");
 
- 	parent = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev));
-
 	/* Add channels statistics. */
+	parent = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev));
 	node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "channels",
 	    CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "DPNI Channels");
 	parent = SYSCTL_CHILDREN(node);
@@ -1778,6 +1803,13 @@ dpaa2_ni_setup_sysctls(struct dpaa2_ni_softc *sc)
 		    "Tx dropped counter");
 	}
 
+	/* Add Link debugging options. */
+	parent = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev));
+	node = SYSCTL_ADD_PROC(ctx, parent, OID_AUTO, "link",
+	    CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
+	    sc, 0, dpaa2_ni_sysctl_link_state,
+	    "A", "DPNI link state information");
+
 	return (0);
 }
 
@@ -3422,7 +3454,7 @@ dpaa2_ni_collect_stats(SYSCTL_HANDLER_ARGS)
 	struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev);
 	struct dpaa2_devinfo *dinfo = device_get_ivars(dev);
 	struct dpaa2_cmd cmd;
-	uint64_t cnt[DPAA2_NI_STAT_COUNTERS];
+	uint64_t cnt[DPAA2_NI_STAT_COUNTERS_PER_PAGE];
 	uint64_t result = 0;
 	uint16_t rc_token, ni_token;
 	int error;
@@ -3454,6 +3486,71 @@ exit:
 	return (sysctl_handle_64(oidp, &result, 0, req));
 }
 
+static int
+dpaa2_ni_sysctl_link_state(SYSCTL_HANDLER_ARGS)
+{
+	struct dpaa2_ni_softc *sc;
+	struct dpaa2_devinfo *rcinfo;
+	struct dpaa2_devinfo *dinfo;
+	struct dpaa2_cmd cmd;
+	struct dpaa2_ni_link_state ls;
+	struct sbuf s;
+	int error;
+	uint16_t rc_token, ni_token;
+
+	if (req->newptr)
+		return (EPERM);
+
+	sc = (struct dpaa2_ni_softc *)arg1;
+
+	rcinfo = device_get_ivars(device_get_parent(sc->dev));
+	dinfo = device_get_ivars(sc->dev);
+
+	DPAA2_CMD_INIT(&cmd);
+
+	error = DPAA2_CMD_RC_OPEN(sc->dev, sc->dev, &cmd, rcinfo->id, &rc_token);
+	if (error != 0) {
+		device_printf(sc->dev, "%s: failed to open resource container: "
+		    "id=%d, error=%d\n", __func__, rcinfo->id, error);
+		goto exit;
+	}
+	error = DPAA2_CMD_NI_OPEN(sc->dev, sc->dev, &cmd, dinfo->id, &ni_token);
+	if (error != 0) {
+		device_printf(sc->dev, "%s: failed to open network interface: "
+		    "id=%d, error=%d\n", __func__, dinfo->id, error);
+		goto close_rc;
+	}
+
+	error = DPAA2_CMD_NI_GET_LINK_STATE(sc->dev, sc->dev, &cmd, &ls);
+
+	(void)DPAA2_CMD_NI_CLOSE(sc->dev, sc->dev, DPAA2_CMD_TK(&cmd, ni_token));
+close_rc:
+	(void)DPAA2_CMD_RC_CLOSE(sc->dev, sc->dev, DPAA2_CMD_TK(&cmd, rc_token));
+
+	if (error != 0)
+		goto exit;
+
+#define	NI_LINK_STATE_OPTIONS_BITS					\
+    "\20\1AUTONEG\2HDX\3PAUSE\4ASYM_PAUSE"
+
+	sbuf_new_for_sysctl(&s, NULL, 1024, req);
+	sbuf_putc(&s, '\n');
+	sbuf_printf(&s, "Link State: %s (%s)\n", ls.link_up ? "UP" : "DOWN",
+	    ls.state_valid ? "VALID" : "IGNORE");
+	sbuf_printf(&s, "Link Rate: %ju\n", (uintmax_t)ls.rate);
+	sbuf_printf(&s, "Link Options: %b\n",
+	    (int)ls.options, NI_LINK_STATE_OPTIONS_BITS);
+	sbuf_printf(&s, "Link Speed Capabilities: %#018jx\n",
+	    (uintmax_t)ls.sup_speeds);
+	sbuf_printf(&s, "Link Speed Advertised for autoneg: %#018jx\n",
+	    (uintmax_t)ls.adv_speeds);
+	sbuf_finish(&s);
+	sbuf_delete(&s);
+
+exit:
+	return (error);
+}
+
 static int
 dpaa2_ni_collect_buf_num(SYSCTL_HANDLER_ARGS)
 {
diff --git a/sys/dev/dpaa2/dpaa2_ni.h b/sys/dev/dpaa2/dpaa2_ni.h
index 9b1397fc544d..51da539dfa66 100644
--- a/sys/dev/dpaa2/dpaa2_ni.h
+++ b/sys/dev/dpaa2/dpaa2_ni.h
@@ -69,9 +69,8 @@
 #define DPAA2_NI_BUFS_PER_TX	(1 << 7)
 #define DPAA2_NI_MAX_BPTX	(1 << 8)
 
-/* Number of the DPNI statistics counters. */
-#define DPAA2_NI_STAT_COUNTERS	7u
-#define	DPAA2_NI_STAT_SYSCTLS	9u
+/* Number of the DPNI statistics counters per page. */
+#define	DPAA2_NI_STAT_COUNTERS_PER_PAGE	7u
 
 /* Error and status bits in the frame annotation status word. */
 #define DPAA2_NI_FAS_DISC	0x80000000 /* debug frame */
diff --git a/sys/dev/dpaa2/dpaa2_rc.c b/sys/dev/dpaa2/dpaa2_rc.c
index 3cb2fdfeaa2e..11bcf4fae717 100644
--- a/sys/dev/dpaa2/dpaa2_rc.c
+++ b/sys/dev/dpaa2/dpaa2_rc.c
@@ -1391,9 +1391,10 @@ dpaa2_rc_ni_get_link_state(device_t dev, device_t child, struct dpaa2_cmd *cmd,
 {
 	struct __packed link_state_resp {
 		uint32_t	_reserved1;
-		uint32_t	flags;
+		uint8_t		flags;
+		uint8_t		_reserved2[3];
 		uint32_t	rate;
-		uint32_t	_reserved2;
+		uint32_t	_reserved3;
 		uint64_t	options;
 		uint64_t	supported;
 		uint64_t	advert;
@@ -1890,7 +1891,7 @@ dpaa2_rc_ni_get_statistics(device_t dev, device_t child, struct dpaa2_cmd *cmd,
 		uint16_t	param;
 	} *args;
 	struct __packed get_statistics_resp {
-		uint64_t	cnt[7];
+		uint64_t	cnt[DPAA2_NI_STAT_COUNTERS_PER_PAGE];
 	} *resp;
 	struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
 	int error;
@@ -1907,7 +1908,7 @@ dpaa2_rc_ni_get_statistics(device_t dev, device_t child, struct dpaa2_cmd *cmd,
 	error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_GET_STATISTICS);
 	if (!error) {
 		resp = (struct get_statistics_resp *) &cmd->params[0];
-		for (int i = 0; i < DPAA2_NI_STAT_COUNTERS; i++)
+		for (int i = 0; i < DPAA2_NI_STAT_COUNTERS_PER_PAGE; i++)
 			cnt[i] = resp->cnt[i];
 	}
 


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69e95004.39c3a.33a0f417>