xref: /freebsd/sys/dev/rge/if_rge_sysctl.c (revision 4bf8ce037dc8fa699be87350bb6467f1b74cb96d)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2025 Adrian Chadd <adrian@FreeBSD.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/param.h>
20 #include <sys/systm.h>
21 #include <sys/sysctl.h>
22 #include <sys/sockio.h>
23 #include <sys/mbuf.h>
24 #include <sys/malloc.h>
25 #include <sys/endian.h>
26 #include <sys/socket.h>
27 #include <net/if.h>
28 #include <net/if_media.h>
29 #include <sys/queue.h>
30 #include <sys/taskqueue.h>
31 #include <sys/bus.h>
32 #include <sys/module.h>
33 #include <sys/rman.h>
34 
35 #include <netinet/in.h>
36 #include <netinet/if_ether.h>
37 
38 #include <net/bpf.h>
39 #include <net/ethernet.h>
40 #include <net/if.h>
41 #include <net/if_var.h>
42 #include <net/if_arp.h>
43 #include <net/if_dl.h>
44 #include <net/if_media.h>
45 #include <net/if_types.h>
46 #include <net/if_vlan_var.h>
47 
48 #include <machine/bus.h>
49 #include <machine/resource.h>
50 
51 #include <dev/mii/mii.h>
52 
53 #include <dev/pci/pcivar.h>
54 #include <dev/pci/pcireg.h>
55 
56 #include "if_rge_vendor.h"
57 #include "if_rgereg.h"
58 #include "if_rgevar.h"
59 #include "if_rge_debug.h"
60 #include "if_rge_sysctl.h"
61 
62 static void
rge_sysctl_drv_stats_attach(struct rge_softc * sc)63 rge_sysctl_drv_stats_attach(struct rge_softc *sc)
64 {
65 	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
66 	struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
67 	struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree);
68 
69 	/* Create stats node */
70 	tree = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "drv_stats",
71 	    CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "driver statistics");
72 	child = SYSCTL_CHILDREN(tree);
73 
74 	/* Driver stats */
75 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "transmit_call_cnt", CTLFLAG_RD,
76 	    &sc->sc_drv_stats.transmit_call_cnt, "Calls to rge_transmit");
77 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "transmit_stopped_cnt",
78 	    CTLFLAG_RD, &sc->sc_drv_stats.transmit_stopped_cnt,
79 	        "rge_transmit calls to a stopped interface");
80 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "transmit_full_cnt",
81 	    CTLFLAG_RD, &sc->sc_drv_stats.transmit_full_cnt,
82 	        "rge_transmit calls to a full tx queue");
83 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "transmit_queued_cnt",
84 	    CTLFLAG_RD, &sc->sc_drv_stats.transmit_queued_cnt,
85 	        "rge_transmit calls which queued a frame");
86 
87 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "intr_cnt",
88 	    CTLFLAG_RD, &sc->sc_drv_stats.intr_cnt,
89 	        "incoming interrupts");
90 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "intr_system_errcnt",
91 	    CTLFLAG_RD, &sc->sc_drv_stats.intr_system_err_cnt,
92 	        "INTR_SYSTEM_ERR interrupt leading to a hardware reset");
93 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "rxeof_cnt",
94 	    CTLFLAG_RD, &sc->sc_drv_stats.rxeof_cnt,
95 	        "calls to rxeof() to process RX frames");
96 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "txeof_cnt",
97 	    CTLFLAG_RD, &sc->sc_drv_stats.txeof_cnt,
98 	        "calls to rxeof() to process TX frame completions");
99 
100 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "link_state_change_cnt",
101 	    CTLFLAG_RD, &sc->sc_drv_stats.link_state_change_cnt,
102 	        "link state changes");
103 
104 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "tx_task_cnt",
105 	    CTLFLAG_RD, &sc->sc_drv_stats.tx_task_cnt,
106 	        "calls to tx_task task to send queued frames");
107 
108 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "recv_input_cnt",
109 	    CTLFLAG_RD, &sc->sc_drv_stats.recv_input_cnt,
110 	        "calls to if_input to process frames");
111 
112 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "rx_desc_err_multidesc",
113 	    CTLFLAG_RD, &sc->sc_drv_stats.rx_desc_err_multidesc,
114 	        "multi-descriptor RX frames (unsupported, so dropped)");
115 
116 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "tx_watchdog_timeout_cnt",
117 	    CTLFLAG_RD, &sc->sc_drv_stats.tx_watchdog_timeout_cnt,
118 	        "TX watchdog timeouts");
119 
120 	/* TX encap counters */
121 
122 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "tx_encap_cnt",
123 	    CTLFLAG_RD, &sc->sc_drv_stats.tx_encap_cnt, "calls to rge_encap()");
124 
125 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "tx_encap_refrag_cnt",
126 	    CTLFLAG_RD, &sc->sc_drv_stats.tx_encap_refrag_cnt,
127 	    "How often rge_encap() has re-linearised TX mbufs");
128 
129 	/* TX checksum counters */
130 
131 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "tx_encap_err_toofrag",
132 	    CTLFLAG_RD, &sc->sc_drv_stats.tx_encap_err_toofrag,
133 	    "How often rge_encap() failed to defrag a TX mbuf");
134 
135 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "tx_offload_ip_csum_set",
136 	    CTLFLAG_RD, &sc->sc_drv_stats.tx_offload_ip_csum_set,
137 	    "Number of frames with TX'ed with IPv4 checksum offload set");
138 
139 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "tx_offload_tcp_csum_set",
140 	    CTLFLAG_RD, &sc->sc_drv_stats.tx_offload_tcp_csum_set,
141 	    "Number of frames TX'ed with TCP checksum offload set");
142 
143 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "tx_offload_udp_csum_set",
144 	    CTLFLAG_RD, &sc->sc_drv_stats.tx_offload_udp_csum_set,
145 	    "Number of frames TX'ed with UDP checksum offload set");
146 
147 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "tx_offload_vlan_tag_set",
148 	    CTLFLAG_RD, &sc->sc_drv_stats.tx_offload_vlan_tag_set,
149 	    "Number of frames TX'ed with VLAN offload tag set");
150 
151 	/* RX counters */
152 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "rx_ether_csum_err",
153 	    CTLFLAG_RD, &sc->sc_drv_stats.rx_ether_csum_err,
154 	    "Number of frames RX'ed with invalid ethernet CRC");
155 
156 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "rx_offload_vlan_tag",
157 	    CTLFLAG_RD, &sc->sc_drv_stats.rx_offload_vlan_tag,
158 	    "Number of frames RX'ed with offload VLAN tag");
159 
160 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "rx_jumbo_frag",
161 	    CTLFLAG_RD, &sc->sc_drv_stats.rx_desc_jumbo_frag,
162 	    "Number of descriptors RX'ed as part of a multi-descriptor frame");
163 
164 	/* RX checksum offload counters */
165 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "rx_offload_csum_ipv4_exists",
166 	    CTLFLAG_RD, &sc->sc_drv_stats.rx_offload_csum_ipv4_exists,
167 	    "Number of frames RX'ed with IPv4 checksum offload set");
168 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "rx_offload_csum_ipv4_valid",
169 	    CTLFLAG_RD, &sc->sc_drv_stats.rx_offload_csum_ipv4_valid,
170 	    "Number of frames RX'ed with IPv4 checksum offload valid");
171 
172 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "rx_offload_csum_tcp_exists",
173 	    CTLFLAG_RD, &sc->sc_drv_stats.rx_offload_csum_tcp_exists,
174 	    "Number of frames RX'ed with TCP checksum offload set");
175 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "rx_offload_csum_tcp_valid",
176 	    CTLFLAG_RD, &sc->sc_drv_stats.rx_offload_csum_tcp_valid,
177 	    "Number of frames RX'ed with TCP checksum offload valid");
178 
179 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "rx_offload_csum_udp_exists",
180 	    CTLFLAG_RD, &sc->sc_drv_stats.rx_offload_csum_udp_exists,
181 	    "Number of frames RX'ed with UDP checksum offload set");
182 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "rx_offload_csum_udp_valid",
183 	    CTLFLAG_RD, &sc->sc_drv_stats.rx_offload_csum_udp_valid,
184 	    "Number of frames RX'ed with UDP checksum offload valid");
185 }
186 
187 static void
rge_sysctl_mac_stats_attach(struct rge_softc * sc)188 rge_sysctl_mac_stats_attach(struct rge_softc *sc)
189 {
190 	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
191 	struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
192 	struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree);
193 	struct rge_mac_stats *ss = &sc->sc_mac_stats;
194 
195 	/* Create stats node */
196 	tree = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "mac_stats",
197 	    CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "mac statistics");
198 	child = SYSCTL_CHILDREN(tree);
199 
200 	/* MAC statistics */
201 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "rge_tx_ok", CTLFLAG_RD,
202 	    &ss->lcl_stats.rge_tx_ok, "");
203 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "rge_rx_ok", CTLFLAG_RD,
204 	    &ss->lcl_stats.rge_rx_ok, "");
205 
206 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "rge_tx_er", CTLFLAG_RD,
207 	    &ss->lcl_stats.rge_tx_er, "");
208 	/* uint32_t rge_rx_er */
209 
210 	/* uint16_t rge_miss_pkt */
211 	/* uint16_t rge_fae */
212 	/* uint32_t rge_tx_1col */
213 	/* uint32_t rge_tx_mcol */
214 
215 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "rge_rx_ok_phy", CTLFLAG_RD,
216 	    &ss->lcl_stats.rge_rx_ok_phy, "");
217 	SYSCTL_ADD_QUAD(ctx, child, OID_AUTO, "rge_rx_ok_brd", CTLFLAG_RD,
218 	    &ss->lcl_stats.rge_rx_ok_brd, "");
219 
220 	/* uint32_t rge_rx_ok_mul */
221 	/* uint16_t rge_tx_abt */
222 	/* uint16_t rge_tx_undrn */
223 }
224 
225 void
rge_sysctl_attach(struct rge_softc * sc)226 rge_sysctl_attach(struct rge_softc *sc)
227 {
228 	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
229 	struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
230 
231 	SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
232 	    "debug", CTLFLAG_RW, &sc->sc_debug, 0,
233 	    "control debugging printfs");
234 
235 	/* Stats */
236 	rge_sysctl_drv_stats_attach(sc);
237 	rge_sysctl_mac_stats_attach(sc);
238 }
239