Index: igc_regs.h =================================================================== RCS file: /cvs/src/sys/dev/pci/igc_regs.h,v retrieving revision 1.2 diff -u -p -r1.2 igc_regs.h --- igc_regs.h 15 Aug 2023 08:27:30 -0000 1.2 +++ igc_regs.h 25 Mar 2024 13:04:43 -0000 @@ -164,6 +164,7 @@ /* Statistics Register Descriptions */ #define IGC_CRCERRS 0x04000 /* CRC Error Count - R/clr */ #define IGC_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */ +#define IGC_RXERRC 0x04004 /* Receive Error Count - R/clr */ #define IGC_MPC 0x04010 /* Missed Packet Count - R/clr */ #define IGC_SCC 0x04014 /* Single Collision Count - R/clr */ #define IGC_ECOL 0x04018 /* Excessive Collision Count - R/clr */ @@ -218,6 +219,8 @@ #define IGC_BPTC 0x040F4 /* Broadcast Packets Tx Count - R/clr */ #define IGC_TSCTC 0x040F8 /* TCP Segmentation Context Tx - R/clr */ #define IGC_IAC 0x04100 /* Interrupt Assertion Count */ +#define IGC_RPTHC 0x04104 /* Rx Packets To Host */ +#define IGC_HGPTC 0x04118 /* Host Good Packets Tx Count */ #define IGC_RXDMTC 0x04120 /* Rx Descriptor Minimum Threshold Count */ #define IGC_VFGPRC 0x00F10 Index: if_igc.c =================================================================== RCS file: /cvs/src/sys/dev/pci/if_igc.c,v retrieving revision 1.18 diff -u -p -r1.18 if_igc.c --- if_igc.c 23 Feb 2024 01:06:18 -0000 1.18 +++ if_igc.c 25 Mar 2024 13:04:43 -0000 @@ -30,6 +30,7 @@ #include "bpfilter.h" #include "vlan.h" +#include "kstat.h" #include #include @@ -41,6 +42,7 @@ #include #include #include +#include #include #include @@ -145,6 +147,10 @@ void igc_get_hw_control(struct igc_softc void igc_release_hw_control(struct igc_softc *); int igc_is_valid_ether_addr(uint8_t *); +#if NKSTAT > 0 +void igc_kstat_attach(struct igc_softc *); +#endif + /********************************************************************* * OpenBSD Device Interface Entry Points *********************************************************************/ @@ -279,6 +285,10 @@ igc_attach(struct device *parent, struct igc_get_hw_control(sc); printf(", address %s\n", ether_sprintf(sc->hw.mac.addr)); + +#if NKSTAT > 0 + igc_kstat_attach(sc); +#endif return; err_late: @@ -2453,3 +2463,289 @@ igc_is_valid_ether_addr(uint8_t *addr) return 1; } + +#if NKSTAT > 0 +enum igc_stat { + igc_stat_crcerrs, + igc_stat_algnerrc, + igc_stat_rxerrc, + igc_stat_mpc, + igc_stat_scc, + igc_stat_ecol, + igc_stat_mcc, + igc_stat_latecol, + igc_stat_colc, + igc_stat_rerc, + igc_stat_dc, + igc_stat_tncrs, + igc_stat_htdpmc, + igc_stat_rlec, + igc_stat_xonrxc, + igc_stat_xontxc, + igc_stat_xoffrxc, + igc_stat_xofftxc, + igc_stat_fcruc, + igc_stat_prc64, + igc_stat_prc127, + igc_stat_prc255, + igc_stat_prc511, + igc_stat_prc1023, + igc_stat_prc1522, + igc_stat_gprc, + igc_stat_bprc, + igc_stat_mprc, + igc_stat_gptc, + igc_stat_gorc, + igc_stat_gotc, + igc_stat_rnbc, + igc_stat_ruc, + igc_stat_rfc, + igc_stat_roc, + igc_stat_rjc, + igc_stat_mgtprc, + igc_stat_mgtpdc, + igc_stat_mgtptc, + igc_stat_tor, + igc_stat_tot, + igc_stat_tpr, + igc_stat_tpt, + igc_stat_ptc64, + igc_stat_ptc127, + igc_stat_ptc255, + igc_stat_ptc511, + igc_stat_ptc1023, + igc_stat_ptc1522, + igc_stat_mptc, + igc_stat_bptc, + igc_stat_tsctc, + igc_stat_iac, + igc_stat_rpthc, + igc_stat_tlpic, + igc_stat_rlpic, + igc_stat_hgptc, + igc_stat_rxdmtc, + igc_stat_hgorc, + igc_stat_hgotc, + igc_stat_lenerrs, + + igc_stat_count +}; + +struct igc_counter { + const char *name; + enum kstat_kv_unit unit; + uint32_t reg; +}; + +static const struct igc_counter igc_counters[igc_stat_count] = { + [igc_stat_crcerrs] = + { "crc errs", KSTAT_KV_U_NONE, IGC_CRCERRS }, + [igc_stat_algnerrc] = + { "alignment errs", KSTAT_KV_U_NONE, IGC_ALGNERRC }, + [igc_stat_rxerrc] = + { "rx errs", KSTAT_KV_U_NONE, IGC_RXERRC }, + [igc_stat_mpc] = + { "missed pkts", KSTAT_KV_U_NONE, IGC_MPC }, + [igc_stat_scc] = + { "single colls", KSTAT_KV_U_NONE, IGC_SCC }, + [igc_stat_ecol] = + { "excessive colls", KSTAT_KV_U_NONE, IGC_ECOL }, + [igc_stat_mcc] = + { "multiple colls", KSTAT_KV_U_NONE, IGC_MCC }, + [igc_stat_latecol] = + { "late colls", KSTAT_KV_U_NONE, IGC_LATECOL }, + [igc_stat_colc] = + { "collisions", KSTAT_KV_U_NONE, IGC_COLC }, + [igc_stat_rerc] = + { "recv errs", KSTAT_KV_U_NONE, IGC_RERC }, + [igc_stat_dc] = + { "defers", KSTAT_KV_U_NONE, IGC_DC }, + [igc_stat_tncrs] = + { "tx no crs", KSTAT_KV_U_NONE, IGC_TNCRS}, + [igc_stat_htdpmc] = + { "host tx discards", KSTAT_KV_U_NONE, IGC_HTDPMC }, + [igc_stat_rlec] = + { "recv len errs", KSTAT_KV_U_NONE, IGC_RLEC }, + [igc_stat_xonrxc] = + { "xon rx", KSTAT_KV_U_NONE, IGC_XONRXC }, + [igc_stat_xontxc] = + { "xon tx", KSTAT_KV_U_NONE, IGC_XONTXC }, + [igc_stat_xoffrxc] = + { "xoff rx", KSTAT_KV_U_NONE, IGC_XOFFRXC }, + [igc_stat_xofftxc] = + { "xoff tx", KSTAT_KV_U_NONE, IGC_XOFFTXC }, + [igc_stat_fcruc] = + { "fc rx unsupp", KSTAT_KV_U_NONE, IGC_FCRUC }, + [igc_stat_prc64] = + { "rx 64B", KSTAT_KV_U_PACKETS, IGC_PRC64 }, + [igc_stat_prc127] = + { "rx 65-127B", KSTAT_KV_U_PACKETS, IGC_PRC127 }, + [igc_stat_prc255] = + { "rx 128-255B", KSTAT_KV_U_PACKETS, IGC_PRC255 }, + [igc_stat_prc511] = + { "rx 256-511B", KSTAT_KV_U_PACKETS, IGC_PRC511 }, + [igc_stat_prc1023] = + { "rx 512-1023B", KSTAT_KV_U_PACKETS, IGC_PRC1023 }, + [igc_stat_prc1522] = + { "rx 1024-maxB", KSTAT_KV_U_PACKETS, IGC_PRC1522 }, + [igc_stat_gprc] = + { "rx good", KSTAT_KV_U_PACKETS, IGC_GPRC }, + [igc_stat_bprc] = + { "rx bcast", KSTAT_KV_U_PACKETS, IGC_BPRC }, + [igc_stat_mprc] = + { "rx mcast", KSTAT_KV_U_PACKETS, IGC_MPRC }, + [igc_stat_gptc] = + { "tx good", KSTAT_KV_U_PACKETS, IGC_GPTC }, + [igc_stat_gorc] = + { "rx good", KSTAT_KV_U_BYTES, 0 }, + [igc_stat_gotc] = + { "tx good", KSTAT_KV_U_BYTES, 0 }, + [igc_stat_rnbc] = + { "rx no bufs", KSTAT_KV_U_NONE, IGC_RNBC }, + [igc_stat_ruc] = + { "rx undersize", KSTAT_KV_U_NONE, IGC_RUC }, + [igc_stat_rfc] = + { "rx frags", KSTAT_KV_U_NONE, IGC_RFC }, + [igc_stat_roc] = + { "rx oversize", KSTAT_KV_U_NONE, IGC_ROC }, + [igc_stat_rjc] = + { "rx jabbers", KSTAT_KV_U_NONE, IGC_RJC }, + [igc_stat_mgtprc] = + { "rx mgmt", KSTAT_KV_U_PACKETS, IGC_MGTPRC }, + [igc_stat_mgtpdc] = + { "rx mgmt drops", KSTAT_KV_U_PACKETS, IGC_MGTPDC }, + [igc_stat_mgtptc] = + { "tx mgmt", KSTAT_KV_U_PACKETS, IGC_MGTPTC }, + [igc_stat_tor] = + { "rx total", KSTAT_KV_U_BYTES, 0 }, + [igc_stat_tot] = + { "tx total", KSTAT_KV_U_BYTES, 0 }, + [igc_stat_tpr] = + { "rx total", KSTAT_KV_U_PACKETS, IGC_TPR }, + [igc_stat_tpt] = + { "tx total", KSTAT_KV_U_PACKETS, IGC_TPT }, + [igc_stat_ptc64] = + { "tx 64B", KSTAT_KV_U_PACKETS, IGC_PTC64 }, + [igc_stat_ptc127] = + { "tx 65-127B", KSTAT_KV_U_PACKETS, IGC_PTC127 }, + [igc_stat_ptc255] = + { "tx 128-255B", KSTAT_KV_U_PACKETS, IGC_PTC255 }, + [igc_stat_ptc511] = + { "tx 256-511B", KSTAT_KV_U_PACKETS, IGC_PTC511 }, + [igc_stat_ptc1023] = + { "tx 512-1023B", KSTAT_KV_U_PACKETS, IGC_PTC1023 }, + [igc_stat_ptc1522] = + { "tx 1024-maxB", KSTAT_KV_U_PACKETS, IGC_PTC1522 }, + [igc_stat_mptc] = + { "tx mcast", KSTAT_KV_U_PACKETS, IGC_MPTC }, + [igc_stat_bptc] = + { "tx bcast", KSTAT_KV_U_PACKETS, IGC_BPTC }, + [igc_stat_tsctc] = + { "tx tso ctx", KSTAT_KV_U_NONE, IGC_TSCTC }, + [igc_stat_iac] = + { "interrupts", KSTAT_KV_U_NONE, IGC_IAC }, + [igc_stat_rpthc] = + { "rx to host", KSTAT_KV_U_PACKETS, IGC_RPTHC }, + [igc_stat_tlpic] = + { "eee tx lpi", KSTAT_KV_U_NONE, IGC_TLPIC }, + [igc_stat_rlpic] = + { "eee rx lpi", KSTAT_KV_U_NONE, IGC_RLPIC }, + [igc_stat_hgptc] = + { "host rx", KSTAT_KV_U_PACKETS, IGC_HGPTC }, + [igc_stat_rxdmtc] = + { "rxd min thresh", KSTAT_KV_U_NONE, IGC_RXDMTC }, + [igc_stat_hgorc] = + { "host good rx", KSTAT_KV_U_BYTES, 0 }, + [igc_stat_hgotc] = + { "host good tx", KSTAT_KV_U_BYTES, 0 }, + [igc_stat_lenerrs] = + { "len errs", KSTAT_KV_U_NONE, IGC_LENERRS }, +}; + +static void +igc_stat_read(struct igc_softc *sc) +{ + struct igc_hw *hw = &sc->hw; + struct kstat *ks = sc->ks; + struct kstat_kv *kvs = ks->ks_data; + unsigned int i; + + for (i = 0; i < nitems(igc_counters); i++) { + const struct igc_counter *c = igc_counters; + if (c->reg == 0) + continue; + + kstat_kv_u64(&kvs[i]) += IGC_READ_REG(hw, c->reg); + } +} + +static void +igc_kstat_tick(void *arg) +{ + struct igc_softc *sc = arg; + + if (mtx_enter_try(&sc->ks_mtx)) { + igc_stat_read(sc); + mtx_leave(&sc->ks_mtx); + } + + timeout_add_sec(&sc->ks_tmo, 4); +} + +static int +igc_kstat_read(struct kstat *ks) +{ + struct igc_softc *sc = ks->ks_softc; + + igc_stat_read(sc); + nanouptime(&ks->ks_updated); + + return (0); +} + +void +igc_kstat_attach(struct igc_softc *sc) +{ + struct kstat *ks; + struct kstat_kv *kvs; + size_t len; + unsigned int i; + + mtx_init(&sc->ks_mtx, IPL_SOFTCLOCK); + timeout_set(&sc->ks_tmo, igc_kstat_tick, sc); + + kvs = mallocarray(sizeof(*kvs), nitems(igc_counters), M_DEVBUF, + M_WAITOK|M_ZERO|M_CANFAIL); + if (kvs == NULL) { + printf("%s: unable to allocate igc kstats\n", DEVNAME(sc)); + return; + } + len = sizeof(*kvs) * nitems(igc_counters); + + ks = kstat_create(DEVNAME(sc), 0, "igc-stats", 0, KSTAT_T_KV, 0); + if (ks == NULL) { + printf("%s: unable to create igc kstats\n", DEVNAME(sc)); + free(kvs, M_DEVBUF, len); + return; + } + + for (i = 0; i < nitems(igc_counters); i++) { + const struct igc_counter *c = &igc_counters[i]; + kstat_kv_unit_init(&kvs[i], c->name, + KSTAT_KV_T_COUNTER64, c->unit); + } + + ks->ks_softc = sc; + ks->ks_data = kvs; + ks->ks_datalen = len; + ks->ks_read = igc_kstat_read; + kstat_set_mutex(ks, &sc->ks_mtx); + + kstat_install(ks); + + sc->ks = ks; + + igc_kstat_tick(sc); /* let's gooo */ +} + +#endif /* NKSTAT > 0 */ Index: if_igc.h =================================================================== RCS file: /cvs/src/sys/dev/pci/if_igc.h,v retrieving revision 1.2 diff -u -p -r1.2 if_igc.h --- if_igc.h 9 Jan 2022 05:42:50 -0000 1.2 +++ if_igc.h 25 Mar 2024 13:04:43 -0000 @@ -199,6 +199,7 @@ /* Forward declaration. */ struct igc_hw; +struct kstat; struct igc_osdep { bus_dma_tag_t os_dmat; @@ -320,6 +321,11 @@ struct igc_softc { /* Multicast array memory */ uint8_t *mta; + + /* Counters */ + struct mutex ks_mtx; + struct timeout ks_tmo; + struct kstat *ks; }; #define DEVNAME(_sc) ((_sc)->sc_dev.dv_xname)