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 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 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 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