Index: sys/sys/kstat.h =================================================================== RCS file: /cvs/src/sys/sys/kstat.h,v retrieving revision 1.2 diff -u -p -r1.2 kstat.h --- sys/sys/kstat.h 31 Jan 2022 05:09:17 -0000 1.2 +++ sys/sys/kstat.h 21 Apr 2022 01:52:30 -0000 @@ -79,6 +79,9 @@ enum kstat_kv_type { KSTAT_KV_T_STR, /* trailing string */ KSTAT_KV_T_BYTES, /* trailing bytes */ KSTAT_KV_T_TEMP, /* temperature (uK) */ + KSTAT_KV_T_COUNTER16, + KSTAT_KV_T_UINT16, + KSTAT_KV_T_INT16, }; /* units only apply to integer types */ @@ -98,6 +101,8 @@ struct kstat_kv { int64_t v_s64; uint32_t v_u32; int32_t v_s32; + uint16_t v_u16; + int16_t v_s16; size_t v_len; } kv_v; enum kstat_kv_type kv_type; @@ -110,6 +115,8 @@ struct kstat_kv { #define kstat_kv_s64(_kv) (_kv)->kv_v.v_s64 #define kstat_kv_u32(_kv) (_kv)->kv_v.v_u32 #define kstat_kv_s32(_kv) (_kv)->kv_v.v_s32 +#define kstat_kv_u16(_kv) (_kv)->kv_v.v_u16 +#define kstat_kv_s16(_kv) (_kv)->kv_v.v_s16 #define kstat_kv_len(_kv) (_kv)->kv_v.v_len #define kstat_kv_temp(_kv) (_kv)->kv_v.v_u64 Index: sys/dev/ic/re.c =================================================================== RCS file: /cvs/src/sys/dev/ic/re.c,v retrieving revision 1.211 diff -u -p -r1.211 re.c --- sys/dev/ic/re.c 17 May 2021 11:59:53 -0000 1.211 +++ sys/dev/ic/re.c 21 Apr 2022 01:52:30 -0000 @@ -109,6 +109,7 @@ #include "bpfilter.h" #include "vlan.h" +#include "kstat.h" #include #include @@ -135,6 +136,10 @@ #include #endif +#if NKSTAT > 0 +#include +#endif + #include #include @@ -192,6 +197,9 @@ void re_setup_intr(struct rl_softc *, in #ifndef SMALL_KERNEL int re_wol(struct ifnet*, int); #endif +#if NKSTAT > 0 +void re_kstat_attach(struct rl_softc *); +#endif void in_delayed_cksum(struct mbuf *); @@ -1073,6 +1081,10 @@ re_attach(struct rl_softc *sc, const cha if_attach(ifp); ether_ifattach(ifp); +#if NKSTAT > 0 + re_kstat_attach(sc); +#endif + return (0); fail_8: @@ -2378,3 +2390,222 @@ re_wol(struct ifnet *ifp, int enable) return (0); } #endif + +#if NKSTAT > 0 + +#define RE_DTCCR_CMD (1U << 3) +#define RE_DTCCR_LO 0x10 +#define RE_DTCCR_HI 0x10 + +struct re_kstats { + struct kstat_kv tx_ok; + struct kstat_kv rx_ok; + struct kstat_kv tx_er; + struct kstat_kv rx_er; + struct kstat_kv miss_pkt; + struct kstat_kv fae; + struct kstat_kv tx_1col; + struct kstat_kv tx_mcol; + struct kstat_kv rx_ok_phy; + struct kstat_kv rx_ok_brd; + struct kstat_kv rx_ok_mul; + struct kstat_kv tx_abt; + struct kstat_kv tx_undrn; +}; + +static const struct re_kstats re_kstats_tpl = { + .tx_ok = KSTAT_KV_UNIT_INITIALIZER("TxOk", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), + .rx_ok = KSTAT_KV_UNIT_INITIALIZER("RxOk", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), + .tx_er = KSTAT_KV_UNIT_INITIALIZER("TxEr", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), + .rx_er = KSTAT_KV_UNIT_INITIALIZER("RxEr", + KSTAT_KV_T_COUNTER32, KSTAT_KV_U_PACKETS), + .miss_pkt = KSTAT_KV_UNIT_INITIALIZER("MissPkt", + KSTAT_KV_T_COUNTER16, KSTAT_KV_U_PACKETS), + .fae = KSTAT_KV_UNIT_INITIALIZER("FAE", + KSTAT_KV_T_COUNTER16, KSTAT_KV_U_PACKETS), + .tx_1col = KSTAT_KV_UNIT_INITIALIZER("Tx1Col", + KSTAT_KV_T_COUNTER32, KSTAT_KV_U_PACKETS), + .tx_mcol = KSTAT_KV_UNIT_INITIALIZER("TxMCol", + KSTAT_KV_T_COUNTER32, KSTAT_KV_U_PACKETS), + .rx_ok_phy = KSTAT_KV_UNIT_INITIALIZER("RxOkPhy", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), + .rx_ok_brd = KSTAT_KV_UNIT_INITIALIZER("RxOkBrd", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS), + .rx_ok_mul = KSTAT_KV_UNIT_INITIALIZER("RxOkMul", + KSTAT_KV_T_COUNTER32, KSTAT_KV_U_PACKETS), + .tx_abt = KSTAT_KV_UNIT_INITIALIZER("TxAbt", + KSTAT_KV_T_COUNTER16, KSTAT_KV_U_PACKETS), + .tx_undrn = KSTAT_KV_UNIT_INITIALIZER("TxUndrn", + KSTAT_KV_T_COUNTER16, KSTAT_KV_U_PACKETS), +}; + +struct re_kstat_softc { + struct re_stats *re_ks_sc_stats; + + bus_dmamap_t re_ks_sc_map; + bus_dma_segment_t re_ks_sc_seg; + int re_ks_sc_nsegs; + + struct rwlock re_ks_sc_rwl; +}; + +static int +re_kstat_read(struct kstat *ks) +{ + struct rl_softc *sc = ks->ks_softc; + struct re_kstat_softc *re_ks_sc = ks->ks_ptr; + bus_dmamap_t map; + uint64_t cmd; + uint32_t reg; + uint8_t command; + int tmo; + + command = CSR_READ_1(sc, RL_COMMAND); + if (!ISSET(command, RL_CMD_RX_ENB) || command == 0xff) + return (ENETDOWN); + + map = re_ks_sc->re_ks_sc_map; + cmd = map->dm_segs[0].ds_addr | RE_DTCCR_CMD; + + bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, + BUS_DMASYNC_PREREAD); + + CSR_WRITE_4(sc, RE_DTCCR_HI, cmd >> 32); + bus_space_barrier(sc->rl_btag, sc->rl_bhandle, RE_DTCCR_HI, 8, + BUS_SPACE_BARRIER_WRITE); + CSR_WRITE_4(sc, RE_DTCCR_LO, cmd >> 32); + bus_space_barrier(sc->rl_btag, sc->rl_bhandle, RE_DTCCR_LO, 4, + BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE); + + tmo = 1000; + do { + reg = CSR_READ_4(sc, RE_DTCCR_LO); + if (!ISSET(reg, RE_DTCCR_CMD)) + break; + + delay(10); + bus_space_barrier(sc->rl_btag, sc->rl_bhandle, RE_DTCCR_LO, 4, + BUS_SPACE_BARRIER_READ); + } while (--tmo); + + bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, + BUS_DMASYNC_POSTREAD); + + if (ISSET(reg, RE_DTCCR_CMD)) + return (EIO); + + nanouptime(&ks->ks_updated); + + return (0); +} + +static int +re_kstat_copy(struct kstat *ks, void *dst) +{ + struct re_kstat_softc *re_ks_sc = ks->ks_ptr; + struct re_stats *rs = re_ks_sc->re_ks_sc_stats; + struct re_kstats *kvs = dst; + + *kvs = re_kstats_tpl; + kstat_kv_u64(&kvs->tx_ok) = lemtoh64(&rs->re_tx_ok); + kstat_kv_u64(&kvs->rx_ok) = lemtoh64(&rs->re_rx_ok); + kstat_kv_u64(&kvs->tx_er) = lemtoh64(&rs->re_tx_er); + kstat_kv_u32(&kvs->rx_er) = lemtoh32(&rs->re_rx_er); + kstat_kv_u16(&kvs->miss_pkt) = lemtoh16(&rs->re_miss_pkt); + kstat_kv_u16(&kvs->fae) = lemtoh16(&rs->re_fae); + kstat_kv_u32(&kvs->tx_1col) = lemtoh32(&rs->re_tx_1col); + kstat_kv_u32(&kvs->tx_mcol) = lemtoh32(&rs->re_tx_mcol); + kstat_kv_u64(&kvs->rx_ok_phy) = lemtoh64(&rs->re_rx_ok_phy); + kstat_kv_u64(&kvs->rx_ok_brd) = lemtoh64(&rs->re_rx_ok_brd); + kstat_kv_u32(&kvs->rx_ok_mul) = lemtoh64(&rs->re_rx_ok_mul); + kstat_kv_u16(&kvs->tx_abt) = lemtoh64(&rs->re_tx_abt); + kstat_kv_u16(&kvs->tx_undrn) = lemtoh64(&rs->re_tx_undrn); + + return (0); +} + +void +re_kstat_attach(struct rl_softc *sc) +{ + struct re_kstat_softc *re_ks_sc; + struct kstat *ks; + + re_ks_sc = malloc(sizeof(*re_ks_sc), M_DEVBUF, M_NOWAIT); + if (re_ks_sc == NULL) { + printf("%s: cannot allocate kstat softc\n", + sc->sc_dev.dv_xname); + return; + } + + if (bus_dmamap_create(sc->sc_dmat, + sizeof(struct re_stats), 1, sizeof(struct re_stats), 0, + BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW | BUS_DMA_64BIT, + &re_ks_sc->re_ks_sc_map) != 0) { + printf("%s: cannot create counter dma memory map\n", + sc->sc_dev.dv_xname); + goto free; + } + + if (bus_dmamem_alloc(sc->sc_dmat, + sizeof(struct re_stats), /* 64bit alignment */ 8, 0, + &re_ks_sc->re_ks_sc_seg, 1, &re_ks_sc->re_ks_sc_nsegs, + BUS_DMA_NOWAIT | BUS_DMA_ZERO) != 0) { + printf("%s: cannot allocate counter dma memory\n", + sc->sc_dev.dv_xname); + goto destroy; + } + + if (bus_dmamem_map(sc->sc_dmat, + &re_ks_sc->re_ks_sc_seg, re_ks_sc->re_ks_sc_nsegs, + sizeof(struct re_stats), (caddr_t *)&re_ks_sc->re_ks_sc_stats, + BUS_DMA_NOWAIT) != 0) { + printf("%s: cannot map counter dma memory\n", + sc->sc_dev.dv_xname); + goto freedma; + } + + if (bus_dmamap_load(sc->sc_dmat, re_ks_sc->re_ks_sc_map, + (caddr_t)re_ks_sc->re_ks_sc_stats, sizeof(struct re_stats), + NULL, BUS_DMA_NOWAIT) != 0) { + printf("%s: cannot load counter dma memory\n", + sc->sc_dev.dv_xname); + goto unmap; + } + + ks = kstat_create(sc->sc_dev.dv_xname, 0, "re-stats", 0, + KSTAT_T_KV, 0); + if (ks == NULL) { + printf("%s: cannot create re-stats kstat\n", + sc->sc_dev.dv_xname); + goto unload; + } + + ks->ks_datalen = sizeof(re_kstats_tpl); + + rw_init(&re_ks_sc->re_ks_sc_rwl, "restats"); + kstat_set_wlock(ks, &re_ks_sc->re_ks_sc_rwl); + ks->ks_softc = sc; + ks->ks_ptr = re_ks_sc; + ks->ks_read = re_kstat_read; + ks->ks_copy = re_kstat_copy; + + kstat_install(ks); + + return; + +unload: + bus_dmamap_unload(sc->sc_dmat, re_ks_sc->re_ks_sc_map); +unmap: + bus_dmamem_unmap(sc->sc_dmat, + (caddr_t)re_ks_sc->re_ks_sc_stats, sizeof(struct re_stats)); +freedma: + bus_dmamem_free(sc->sc_dmat, &re_ks_sc->re_ks_sc_seg, 1); +destroy: + bus_dmamap_destroy(sc->sc_dmat, re_ks_sc->re_ks_sc_map); +free: + free(re_ks_sc, M_DEVBUF, sizeof(*re_ks_sc)); +} +#endif /* NKSTAT > 0 */ Index: sys/dev/ic/rtl81x9reg.h =================================================================== RCS file: /cvs/src/sys/dev/ic/rtl81x9reg.h,v retrieving revision 1.103 diff -u -p -r1.103 rtl81x9reg.h --- sys/dev/ic/rtl81x9reg.h 9 Jan 2022 05:42:38 -0000 1.103 +++ sys/dev/ic/rtl81x9reg.h 21 Apr 2022 01:52:30 -0000 @@ -690,23 +690,20 @@ struct rl_desc { /* * Statistics counter structure (8139C+ and 8169 only) */ -struct rl_stats { - u_int32_t rl_tx_pkts_lo; - u_int32_t rl_tx_pkts_hi; - u_int32_t rl_tx_errs_lo; - u_int32_t rl_tx_errs_hi; - u_int32_t rl_tx_errs; - u_int16_t rl_missed_pkts; - u_int16_t rl_rx_framealign_errs; - u_int32_t rl_tx_onecoll; - u_int32_t rl_tx_multicolls; - u_int32_t rl_rx_ucasts_hi; - u_int32_t rl_rx_ucasts_lo; - u_int32_t rl_rx_bcasts_lo; - u_int32_t rl_rx_bcasts_hi; - u_int32_t rl_rx_mcasts; - u_int16_t rl_tx_aborts; - u_int16_t rl_rx_underruns; +struct re_stats { + uint64_t re_tx_ok; + uint64_t re_rx_ok; + uint64_t re_tx_er; + uint32_t re_rx_er; + uint16_t re_miss_pkt; + uint16_t re_fae; + uint32_t re_tx_1col; + uint32_t re_tx_mcol; + uint64_t re_rx_ok_phy; + uint64_t re_rx_ok_brd; + uint32_t re_rx_ok_mul; + uint16_t re_tx_abt; + uint16_t re_tx_undrn; }; /* @@ -858,6 +855,8 @@ struct rl_list_data { int rl_rx_listnseg; }; +struct kstat; + struct rl_softc { struct device sc_dev; /* us, as a device */ void * sc_ih; /* interrupt vectoring */ @@ -930,6 +929,8 @@ struct rl_softc { #define RL_IMTYPE_SIM 1 /* simulated */ #define RL_IMTYPE_HW 2 /* hardware based */ int rl_timerintr; + + struct kstat *rl_kstat; }; /* Index: usr.bin/kstat/kstat.c =================================================================== RCS file: /cvs/src/usr.bin/kstat/kstat.c,v retrieving revision 1.8 diff -u -p -r1.8 kstat.c --- usr.bin/kstat/kstat.c 25 Jan 2021 06:55:59 -0000 1.8 +++ usr.bin/kstat/kstat.c 21 Apr 2022 01:52:30 -0000 @@ -351,6 +351,7 @@ kstat_kv(const void *d, ssize_t len) buf = d; do { kv = (const struct kstat_kv *)buf; + //const struct timespec *ts; buf += sizeof(*kv); len -= sizeof(*kv); @@ -381,6 +382,13 @@ kstat_kv(const void *d, ssize_t len) case KSTAT_KV_T_INT32: printf("%" PRId32, kstat_kv_s32(kv)); break; + case KSTAT_KV_T_COUNTER16: + case KSTAT_KV_T_UINT16: + printf("%" PRIu16, kstat_kv_u16(kv)); + break; + case KSTAT_KV_T_INT16: + printf("%" PRId16, kstat_kv_s16(kv)); + break; case KSTAT_KV_T_STR: blen = kstat_kv_len(kv); trailer = strdumpnl; @@ -401,6 +409,21 @@ kstat_kv(const void *d, ssize_t len) printf("%.2f degC", (f - 273150000.0) / 1000000.0); break; +#if 0 + case KSTAT_KV_T_MONOTIME: + ts = &kstat_kv_timespec(kv); + printf("monotime %lld.%09ld", ts->tv_sec, ts->tv_nsec); + break; + case KSTAT_KV_T_REALTIME: + ts = &kstat_kv_timespec(kv); + printf("realtime %lld.%09ld", ts->tv_sec, ts->tv_nsec); + break; + case KSTAT_KV_T_INTERVAL: + ts = &kstat_kv_timespec(kv); + printf("interval %lld.%09ld", ts->tv_sec, ts->tv_nsec); + break; +#endif + default: printf("unknown type %u, stopping\n", kv->kv_type); return; @@ -474,17 +497,17 @@ kstat_list(struct kstat_tree *kt, int fd } else id = ksreq->ks_id; - if (!kstat_filter_entry(kfs, ksreq)) { + if (kse->serrno != 0 || !kstat_filter_entry(kfs, ksreq)) { free(ksreq->ks_data); free(kse); continue; } - if (RBT_INSERT(kstat_tree, kt, kse) != NULL) - errx(1, "duplicate kstat entry"); - - if (kse->serrno != 0) - continue; + if (RBT_INSERT(kstat_tree, kt, kse) != NULL) { + errx(1, "duplicate kstat entry %s:%u:%s:%u", + ksreq->ks_provider, ksreq->ks_instance, + ksreq->ks_name, ksreq->ks_unit); + } while (ksreq->ks_datalen > len) { len = ksreq->ks_datalen;