Index: if_mcx.c =================================================================== RCS file: /cvs/src/sys/dev/pci/if_mcx.c,v retrieving revision 1.58 diff -u -p -r1.58 if_mcx.c --- if_mcx.c 26 Jun 2020 05:05:42 -0000 1.58 +++ if_mcx.c 26 Jun 2020 06:16:57 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: if_mcx.c,v 1.58 2020/06/26 05:05:42 dlg Exp $ */ +/* $OpenBSD: if_mcx.c,v 1.57 2020/06/26 03:07:10 dlg Exp $ */ /* * Copyright (c) 2017 David Gwynne @@ -19,6 +19,7 @@ #include "bpfilter.h" #include "vlan.h" +#include "kstat.h" #include #include @@ -44,6 +45,10 @@ #include #endif +#if NKSTAT > 0 +#include +#endif + #include #include @@ -453,28 +458,30 @@ CTASSERT(sizeof(struct mcx_reg_ppcnt) == CTASSERT((offsetof(struct mcx_reg_ppcnt, ppcnt_counter_set) % sizeof(uint64_t)) == 0); -struct mcx_ppcnt_ieee8023 { - uint64_t frames_transmitted_ok; - uint64_t frames_received_ok; - uint64_t frame_check_sequence_errors; - uint64_t alignment_errors; - uint64_t octets_transmitted_ok; - uint64_t octets_received_ok; - uint64_t multicast_frames_xmitted_ok; - uint64_t broadcast_frames_xmitted_ok; - uint64_t multicast_frames_received_ok; - uint64_t broadcast_frames_received_ok; - uint64_t in_range_length_errors; - uint64_t out_of_range_length_field; - uint64_t frame_too_long_errors; - uint64_t symbol_error_during_carrier; - uint64_t mac_control_frames_transmitted; - uint64_t mac_control_frames_received; - uint64_t unsupported_opcodes_received; - uint64_t pause_mac_ctrl_frames_received; - uint64_t pause_mac_ctrl_frames_transmitted; +enum mcx_ppcnt_ieee8023 { + frames_transmitted_ok, + frames_received_ok, + frame_check_sequence_errors, + alignment_errors, + octets_transmitted_ok, + octets_received_ok, + multicast_frames_xmitted_ok, + broadcast_frames_xmitted_ok, + multicast_frames_received_ok, + broadcast_frames_received_ok, + in_range_length_errors, + out_of_range_length_field, + frame_too_long_errors, + symbol_error_during_carrier, + mac_control_frames_transmitted, + mac_control_frames_received, + unsupported_opcodes_received, + pause_mac_ctrl_frames_received, + pause_mac_ctrl_frames_transmitted, + + mcx_ppcnt_ieee8023_count }; -CTASSERT(sizeof(struct mcx_ppcnt_ieee8023) == 0x98); +CTASSERT(mcx_ppcnt_ieee8023_count * sizeof(uint64_t) == 0x98); struct mcx_ppcnt_rfc2863 { uint64_t in_octets; @@ -2124,12 +2131,23 @@ struct mcx_softc { unsigned int sc_nqueues; int sc_num_cq; + +#if NKSTAT > 0 + struct kstat *sc_kstat_ieee8023; + struct kstat *sc_kstat_rfc2863; + struct kstat *sc_kstat_rfc2819; + struct kstat *sc_kstat_rfc3635; +#endif }; #define DEVNAME(_sc) ((_sc)->sc_dev.dv_xname) static int mcx_match(struct device *, void *, void *); static void mcx_attach(struct device *, struct device *, void *); +#if NKSTAT > 0 +static void mcx_kstat_attach(struct mcx_softc *); +#endif + static int mcx_version(struct mcx_softc *); static int mcx_init_wait(struct mcx_softc *); static int mcx_enable_hca(struct mcx_softc *); @@ -2568,6 +2586,10 @@ mcx_attach(struct device *parent, struct } sc->sc_extra_mcast = 0; memset(sc->sc_mcast_flows, 0, sizeof(sc->sc_mcast_flows)); + +#if NKSTAT > 0 + mcx_kstat_attach(sc); +#endif return; teardown: @@ -7130,3 +7152,172 @@ mcx_hwmem_free(struct mcx_softc *sc, str mhm->mhm_npages = 0; } + +#if NKSTAT > 0 +static const struct kstat_kv mcx_kstat_ieee8023_tpl[] = { + KSTAT_KV_UNIT_INITIALIZER("Good Tx", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), + KSTAT_KV_UNIT_INITIALIZER("Good Rx", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), + KSTAT_KV_UNIT_INITIALIZER("FCS Errs", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), + KSTAT_KV_UNIT_INITIALIZER("Alignment Errs", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), + KSTAT_KV_UNIT_INITIALIZER("Good Tx", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_BYTES), + KSTAT_KV_UNIT_INITIALIZER("Good Rx", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_BYTES), + KSTAT_KV_UNIT_INITIALIZER("Multicast Tx", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), + KSTAT_KV_UNIT_INITIALIZER("Broadcast Tx", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), + KSTAT_KV_UNIT_INITIALIZER("Multicast Rx", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), + KSTAT_KV_UNIT_INITIALIZER("Broadcast Rx", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), + KSTAT_KV_UNIT_INITIALIZER("In Range Len", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), + KSTAT_KV_UNIT_INITIALIZER("Out Of Range Len", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), + KSTAT_KV_UNIT_INITIALIZER("Frame Too Long", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), + KSTAT_KV_UNIT_INITIALIZER("Symbol Errs", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), + KSTAT_KV_UNIT_INITIALIZER("MAC Ctrl Tx", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), + KSTAT_KV_UNIT_INITIALIZER("MAC Ctrl Rx", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), + KSTAT_KV_UNIT_INITIALIZER("MAC Ctrl Unsup", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), + KSTAT_KV_UNIT_INITIALIZER("Pause Rx", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), + KSTAT_KV_UNIT_INITIALIZER("Pause Tx", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), +}; +CTASSERT(nitems(mcx_kstat_ieee8023_tpl) == mcx_ppcnt_ieee8023_count); + +struct mcx_kstat_rfc2863 { + struct kstat_kv in_octets; + struct kstat_kv in_ucast_pkts; + struct kstat_kv in_discards; + struct kstat_kv in_errors; + struct kstat_kv in_unknown_protos; + struct kstat_kv out_octets; + struct kstat_kv out_ucast_pkts; + struct kstat_kv out_discards; + struct kstat_kv out_errors; + struct kstat_kv in_multicast_pkts; + struct kstat_kv in_broadcast_pkts; + struct kstat_kv out_multicast_pkts; + struct kstat_kv out_broadcast_pkts; +}; + +struct mcx_kstat_rfc2819 { + struct kstat_kv drop_events; + struct kstat_kv octets; + struct kstat_kv pkts; + struct kstat_kv broadcast_pkts; + struct kstat_kv multicast_pkts; + struct kstat_kv crc_align_errors; + struct kstat_kv undersize_pkts; + struct kstat_kv oversize_pkts; + struct kstat_kv fragments; + struct kstat_kv jabbers; + struct kstat_kv collisions; + struct kstat_kv pkts64octets; + struct kstat_kv pkts65to127octets; + struct kstat_kv pkts128to255octets; + struct kstat_kv pkts256to511octets; + struct kstat_kv pkts512to1023octets; + struct kstat_kv pkts1024to1518octets; + struct kstat_kv pkts1519to2047octets; + struct kstat_kv pkts2048to4095octets; + struct kstat_kv pkts4096to8191octets; + struct kstat_kv pkts8192to10239octets; +}; + +struct mcx_kstat_rfc3635 { + struct kstat_kv alignment_errors; + struct kstat_kv fcs_errors; + struct kstat_kv single_collision_frames; + struct kstat_kv multiple_collision_frames; + struct kstat_kv sqe_test_errors; + struct kstat_kv deferred_transmissions; + struct kstat_kv late_collisions; + struct kstat_kv excessive_collisions; + struct kstat_kv internal_mac_transmit_errors; + struct kstat_kv carrier_sense_errors; + struct kstat_kv frame_too_longs; + struct kstat_kv internal_mac_receive_errors; + struct kstat_kv symbol_errors; + struct kstat_kv control_in_unknown_opcodes; + struct kstat_kv control_in_pause_frames; + struct kstat_kv control_out_pause_frames; +}; + +static int mcx_kstat_ieee8023_read(struct kstat *); +static int mcx_kstat_ieee8023_copy(struct kstat *, void *); + +static void +mcx_kstat_attach(struct mcx_softc *sc) +{ + struct kstat *ks; + + ks = kstat_create(DEVNAME(sc), 0, "ieee802.3", 0, KSTAT_T_KV, 0); + if (ks != NULL) { + /* we carry the raw counters from read to copy */ + ks->ks_data = mallocarray(nitems(mcx_kstat_ieee8023_tpl), + sizeof(uint64_t), M_DEVBUF, M_WAITOK); + + /* but use the template when copying out */ + ks->ks_datalen = sizeof(mcx_kstat_ieee8023_tpl); + + ks->ks_softc = sc; + ks->ks_read = mcx_kstat_ieee8023_read; + ks->ks_copy = mcx_kstat_ieee8023_copy; + + kstat_install(ks); + } +} + +static int +mcx_kstat_ieee8023_read(struct kstat *ks) +{ + struct mcx_softc *sc = ks->ks_softc; + struct mcx_reg_ppcnt ppcnt = { + .ppcnt_grp = MCX_REG_PPCNT_GRP_IEEE8023, + }; + int rv; + + KERNEL_LOCK(); /* XXX */ + rv = mcx_access_hca_reg(sc, MCX_REG_PPCNT, MCX_REG_OP_READ, + &ppcnt, sizeof(ppcnt)); + KERNEL_UNLOCK(); + if (rv != 0) + return (EIO); + + memcpy(ks->ks_data, ppcnt.ppcnt_counter_set, + nitems(mcx_kstat_ieee8023_tpl) * sizeof(uint64_t)); + + nanouptime(&ks->ks_updated); + + return (0); +} + +static int +mcx_kstat_ieee8023_copy(struct kstat *ks, void *dst) +{ + struct kstat_kv *kvs = dst; + uint64_t *vs = ks->ks_data; + struct kstat_kv *kv; + unsigned int i; + + for (i = 0; i < nitems(mcx_kstat_ieee8023_tpl); i++) { + kv = &kvs[i]; + *kv = mcx_kstat_ieee8023_tpl[i]; + kstat_kv_u64(kv) = vs[i]; + } + + return (0); +} +#endif /* NKSTAT > 0 */