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