dlg@o1000 pci$ kstat msk-mib msk0:0:msk-mib:0 InUnicasts: 4607 packets InBroadcasts: 6912 packets InPause: 0 packets InMulticasts: 12 packets InFCSErr: 0 packets InGoodOctets: 1396586 bytes InBadOctets: 0 bytes Undersize: 0 packets Fragments: 0 packets In64Octets: 3805 packets In127Octets: 5107 packets In255Octets: 1040 packets In511Octets: 1470 packets In1023Octets: 94 packets In1518Octets: 15 packets InMaxOctets: 0 packets OverSize: 0 packets Jabber: 0 packets Overflow: 2 packets OutUnicasts: 4464 packets OutBroadcasts: 7 packets OutPause: 0 packets OutMulticasts: 0 packets OutOctets: 1522718 bytes Out64Octets: 10 packets Out127Octets: 1247 packets Out255Octets: 1569 packets Out511Octets: 1125 packets Out1023Octets: 46 packets Out1518Octets: 474 packets OutMaxOctets: 0 packets Collisions: 0 Late: 0 Excessive: 0 packets Multiple: 0 packets Single: 0 packets Underflow: 0 packets Index: if_msk.c =================================================================== RCS file: /cvs/src/sys/dev/pci/if_msk.c,v retrieving revision 1.137 diff -u -p -r1.137 if_msk.c --- if_msk.c 5 Jan 2022 03:53:26 -0000 1.137 +++ if_msk.c 7 Jan 2022 02:56:53 -0000 @@ -87,6 +87,7 @@ */ #include "bpfilter.h" +#include "kstat.h" #include #include @@ -110,6 +111,10 @@ #include #endif +#if NKSTAT > 0 +#include +#endif + #include #include @@ -120,6 +125,53 @@ #include #include +#define MSK_STATUS_OWN_SHIFT 63 +#define MSK_STATUS_OWN_MASK 0x1 +#define MSK_STATUS_OPCODE_SHIFT 56 +#define MSK_STATUS_OPCODE_MASK 0x7f + +#define MSK_STATUS_OWN(_d) \ + (((_d) >> MSK_STATUS_OWN_SHIFT) & MSK_STATUS_OWN_MASK) +#define MSK_STATUS_OPCODE(_d) \ + (((_d) >> MSK_STATUS_OPCODE_SHIFT) & MSK_STATUS_OPCODE_MASK) + +#define MSK_STATUS_OPCODE_RXSTAT 0x60 +#define MSK_STATUS_OPCODE_RXTIMESTAMP 0x61 +#define MSK_STATUS_OPCODE_RXVLAN 0x62 +#define MSK_STATUS_OPCODE_RXCKSUM 0x64 +#define MSK_STATUS_OPCODE_RXCKSUMVLAN \ + (MSK_STATUS_OPCODE_RXVLAN | MSK_STATUS_OPCODE_RXCKSUM) +#define MSK_STATUS_OPCODE_RXTIMEVLAN \ + (MSK_STATUS_OPCODE_RXVLAN | MSK_STATUS_OPCODE_RXTIMESTAMP) +#define MSK_STATUS_OPCODE_RSS_HASH 0x65 +#define MSK_STATUS_OPCODE_TXIDX 0x68 +#define MSK_STATUS_OPCODE_MACSEC 0x6c +#define MSK_STATUS_OPCODE_PUTIDX 0x70 + +#define MSK_STATUS_RXSTAT_PORT_SHIFT 48 +#define MSK_STATUS_RXSTAT_PORT_MASK 0x1 +#define MSK_STATUS_RXSTAT_LEN_SHIFT 32 +#define MSK_STATUS_RXSTAT_LEN_MASK 0xffff +#define MSK_STATUS_RXSTAT_STATUS_SHIFT 0 +#define MSK_STATUS_RXSTAT_STATUS_MASK 0xffffffff + +#define MSK_STATUS_RXSTAT_PORT(_d) \ + (((_d) >> MSK_STATUS_RXSTAT_PORT_SHIFT) & MSK_STATUS_RXSTAT_PORT_MASK) +#define MSK_STATUS_RXSTAT_LEN(_d) \ + (((_d) >> MSK_STATUS_RXSTAT_LEN_SHIFT) & MSK_STATUS_RXSTAT_LEN_MASK) +#define MSK_STATUS_RXSTAT_STATUS(_d) \ + (((_d) >> MSK_STATUS_RXSTAT_STATUS_SHIFT) & MSK_STATUS_RXSTAT_STATUS_MASK) + +#define MSK_STATUS_TXIDX_PORTA_SHIFT 0 +#define MSK_STATUS_TXIDX_PORTA_MASK 0xfff +#define MSK_STATUS_TXIDX_PORTB_SHIFT 24 +#define MSK_STATUS_TXIDX_PORTB_MASK 0xfff + +#define MSK_STATUS_TXIDX_PORTA(_d) \ + (((_d) >> MSK_STATUS_TXIDX_PORTA_SHIFT) & MSK_STATUS_TXIDX_PORTA_MASK) +#define MSK_STATUS_TXIDX_PORTB(_d) \ + (((_d) >> MSK_STATUS_TXIDX_PORTB_SHIFT) & MSK_STATUS_TXIDX_PORTB_MASK) + int mskc_probe(struct device *, void *, void *); void mskc_attach(struct device *, struct device *self, void *aux); int mskc_detach(struct device *, int); @@ -171,6 +223,82 @@ void msk_dump_bytes(const char *, int); #define DPRINTFN(n,x) #endif +#if NKSTAT > 0 +struct msk_mib { + const char *name; + uint32_t reg; + enum kstat_kv_type type; + enum kstat_kv_unit unit; +}; + +#define C32 KSTAT_KV_T_COUNTER32 +#define C64 KSTAT_KV_T_COUNTER64 + +#define PKTS KSTAT_KV_U_PACKETS +#define BYTES KSTAT_KV_U_BYTES +#define NONE KSTAT_KV_U_NONE + +static const struct msk_mib msk_mib[] = { + { "InUnicasts", 0x100, C32, PKTS }, + { "InBroadcasts", 0x108, C32, PKTS }, + { "InPause", 0x110, C32, PKTS }, + { "InMulticasts", 0x118, C32, PKTS }, + { "InFCSErr", 0x120, C32, PKTS }, + { "InGoodOctets", 0x130, C64, BYTES }, + { "InBadOctets", 0x140, C64, BYTES }, + { "Undersize", 0x150, C32, PKTS }, + { "Fragments", 0x158, C32, PKTS }, + { "In64Octets", 0x160, C32, PKTS }, + { "In127Octets", 0x168, C32, PKTS }, + { "In255Octets", 0x170, C32, PKTS }, + { "In511Octets", 0x178, C32, PKTS }, + { "In1023Octets", 0x180, C32, PKTS }, + { "In1518Octets", 0x188, C32, PKTS }, + { "InMaxOctets", 0x190, C32, PKTS }, + { "OverSize", 0x198, C32, PKTS }, + { "Jabber", 0x1a8, C32, PKTS }, + { "Overflow", 0x1b0, C32, PKTS }, + + { "OutUnicasts", 0x1c0, C32, PKTS }, + { "OutBroadcasts", 0x1c8, C32, PKTS }, + { "OutPause", 0x1d0, C32, PKTS }, + { "OutMulticasts", 0x1d8, C32, PKTS }, + { "OutOctets", 0x1e0, C64, BYTES }, + { "Out64Octets", 0x1f0, C32, PKTS }, + { "Out127Octets", 0x1f8, C32, PKTS }, + { "Out255Octets", 0x200, C32, PKTS }, + { "Out511Octets", 0x208, C32, PKTS }, + { "Out1023Octets", 0x210, C32, PKTS }, + { "Out1518Octets", 0x218, C32, PKTS }, + { "OutMaxOctets", 0x220, C32, PKTS }, + { "Collisions", 0x230, C32, NONE }, + { "Late", 0x238, C32, NONE }, + { "Excessive", 0x240, C32, PKTS }, + { "Multiple", 0x248, C32, PKTS }, + { "Single", 0x250, C32, PKTS }, + { "Underflow", 0x258, C32, PKTS }, +}; + +#undef C32 +#undef C64 + +#undef PKTS +#undef BYTES +#undef NONE + +struct msk_kstat { + struct rwlock lock; + struct kstat *ks; +}; + +static uint32_t msk_mib_read32(struct sk_if_softc *, uint32_t); +static uint64_t msk_mib_read64(struct sk_if_softc *, uint32_t); + +void msk_kstat_attach(struct sk_if_softc *); +void msk_kstat_detach(struct sk_if_softc *); +int msk_kstat_read(struct kstat *ks); +#endif + /* supported device vendors */ const struct pci_matchid mskc_devices[] = { { PCI_VENDOR_DLINK, PCI_PRODUCT_DLINK_DGE550SX }, @@ -624,6 +752,7 @@ mskc_reset(struct sk_softc *sc) { u_int32_t imtimer_ticks, reg1; int reg; + unsigned int i; DPRINTFN(2, ("mskc_reset\n")); @@ -758,8 +887,8 @@ mskc_reset(struct sk_softc *sc) } /* Reset status ring. */ - bzero(sc->sk_status_ring, - MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc)); + for (i = 0; i < MSK_STATUS_RING_CNT; i++) + sc->sk_status_ring[i] = htole64(0); sc->sk_status_idx = 0; sk_win_write_4(sc, SK_STAT_BMU_CSR, SK_STAT_BMU_RESET); @@ -982,6 +1111,10 @@ msk_attach(struct device *parent, struct if_attach(ifp); ether_ifattach(ifp); +#if NKSTAT > 0 + msk_kstat_attach(sc_if); +#endif + DPRINTFN(2, ("msk_attach: end\n")); return; @@ -1014,6 +1147,10 @@ msk_detach(struct device *self, int flag msk_stop(sc_if, 1); +#if NKSTAT > 0 + msk_kstat_detach(sc_if); +#endif + /* Detach any PHYs we might have. */ if (LIST_FIRST(&sc_if->sk_mii.mii_phys) != NULL) mii_detach(&sc_if->sk_mii, MII_PHY_ANY, MII_OFFSET_ANY); @@ -1138,8 +1275,8 @@ mskc_attach(struct device *parent, struc sc->sk_pc = pc; if (bus_dmamem_alloc(sc->sc_dmatag, - MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc), - MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc), + MSK_STATUS_RING_CNT * sizeof(uint64_t), + MSK_STATUS_RING_CNT * sizeof(uint64_t), 0, &sc->sk_status_seg, 1, &sc->sk_status_nseg, BUS_DMA_NOWAIT | BUS_DMA_ZERO)) { printf(": can't alloc status buffers\n"); @@ -1148,27 +1285,27 @@ mskc_attach(struct device *parent, struc if (bus_dmamem_map(sc->sc_dmatag, &sc->sk_status_seg, sc->sk_status_nseg, - MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc), + MSK_STATUS_RING_CNT * sizeof(uint64_t), &kva, BUS_DMA_NOWAIT)) { - printf(": can't map dma buffers (%lu bytes)\n", - (ulong)(MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc))); + printf(": can't map dma buffers (%zu bytes)\n", + MSK_STATUS_RING_CNT * sizeof(uint64_t)); goto fail_3; } if (bus_dmamap_create(sc->sc_dmatag, - MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc), 1, - MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc), 0, + MSK_STATUS_RING_CNT * sizeof(uint64_t), 1, + MSK_STATUS_RING_CNT * sizeof(uint64_t), 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW | BUS_DMA_64BIT, &sc->sk_status_map)) { printf(": can't create dma map\n"); goto fail_4; } if (bus_dmamap_load(sc->sc_dmatag, sc->sk_status_map, kva, - MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc), + MSK_STATUS_RING_CNT * sizeof(uint64_t), NULL, BUS_DMA_NOWAIT)) { printf(": can't load dma map\n"); goto fail_5; } - sc->sk_status_ring = (struct msk_status_desc *)kva; + sc->sk_status_ring = (uint64_t *)kva; /* Reset the adapter. */ mskc_reset(sc); @@ -1364,7 +1501,7 @@ mskc_attach(struct device *parent, struc fail_4: bus_dmamem_unmap(sc->sc_dmatag, (caddr_t)sc->sk_status_ring, - MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc)); + MSK_STATUS_RING_CNT * sizeof(uint64_t)); fail_3: bus_dmamem_free(sc->sc_dmatag, &sc->sk_status_seg, sc->sk_status_nseg); @@ -1395,7 +1532,7 @@ mskc_detach(struct device *self, int fla if (sc->sk_status_nseg > 0) { bus_dmamap_destroy(sc->sc_dmatag, sc->sk_status_map); bus_dmamem_unmap(sc->sc_dmatag, (caddr_t)sc->sk_status_ring, - MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc)); + MSK_STATUS_RING_CNT * sizeof(uint64_t)); bus_dmamem_free(sc->sc_dmatag, &sc->sk_status_seg, sc->sk_status_nseg); } @@ -1749,7 +1886,6 @@ int msk_intr(void *xsc) { struct sk_softc *sc = xsc; - struct sk_if_softc *sc_if; struct sk_if_softc *sc_if0 = sc->sk_if[SK_PORT_A]; struct sk_if_softc *sc_if1 = sc->sk_if[SK_PORT_B]; struct mbuf_list ml[2] = { @@ -1758,8 +1894,9 @@ msk_intr(void *xsc) }; struct ifnet *ifp0 = NULL, *ifp1 = NULL; int claimed = 0; - u_int32_t status, sk_status; - struct msk_status_desc *cur_st; + u_int32_t status; + uint64_t *ring = sc->sk_status_ring; + uint64_t desc; status = CSR_READ_4(sc, SK_Y2_ISSR2); if (status == 0xffffffff) @@ -1788,43 +1925,41 @@ msk_intr(void *xsc) MSK_CDSTSYNC(sc, sc->sk_status_idx, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); - cur_st = &sc->sk_status_ring[sc->sk_status_idx]; - while (cur_st->sk_opcode & SK_Y2_STOPC_OWN) { - cur_st->sk_opcode &= ~SK_Y2_STOPC_OWN; - switch (cur_st->sk_opcode) { - case SK_Y2_STOPC_RXSTAT: - sc_if = sc->sk_if[cur_st->sk_link & 0x01]; - msk_rxeof(sc_if, &ml[cur_st->sk_link & 0x01], - lemtoh16(&cur_st->sk_len), - lemtoh32(&cur_st->sk_status)); + while (MSK_STATUS_OWN(desc = lemtoh64(&ring[sc->sk_status_idx]))) { + unsigned int opcode, port; + + ring[sc->sk_status_idx] = htole64(0); /* clear ownership */ + + opcode = MSK_STATUS_OPCODE(desc); + switch (opcode) { + case MSK_STATUS_OPCODE_RXSTAT: + port = MSK_STATUS_RXSTAT_PORT(desc); + msk_rxeof(sc->sk_if[port], &ml[port], + MSK_STATUS_RXSTAT_LEN(desc), + MSK_STATUS_RXSTAT_STATUS(desc)); break; case SK_Y2_STOPC_TXSTAT: - sk_status = lemtoh32(&cur_st->sk_status); - if (sc_if0) - msk_txeof(sc_if0, sk_status & 0xfff); + if (sc_if0) { + msk_txeof(sc_if0, + MSK_STATUS_TXIDX_PORTA(desc)); + } if (sc_if1) { - /* - * this would be easier as a 64bit - * load of the whole status descriptor, - * a shift, and a mask. - */ - unsigned int prod = (sk_status >> 24) & 0xff; - prod |= (lemtoh16(&cur_st->sk_len) & 0xf) << 8; - msk_txeof(sc_if1, prod); + msk_txeof(sc_if1, + MSK_STATUS_TXIDX_PORTB(desc)); } break; default: - printf("opcode=0x%x\n", cur_st->sk_opcode); + printf("opcode=0x%x\n", opcode); break; } - SK_INC(sc->sk_status_idx, MSK_STATUS_RING_CNT); - MSK_CDSTSYNC(sc, sc->sk_status_idx, - BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); - cur_st = &sc->sk_status_ring[sc->sk_status_idx]; + SK_INC(sc->sk_status_idx, MSK_STATUS_RING_CNT); } + MSK_CDSTSYNC(sc, sc->sk_status_idx, + BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); + if (status & SK_Y2_IMR_BMU) { CSR_WRITE_4(sc, SK_STAT_BMU_CSR, SK_STAT_BMU_IRQ_CLEAR); claimed = 1; @@ -2184,6 +2319,132 @@ struct cfattach msk_ca = { struct cfdriver msk_cd = { NULL, "msk", DV_IFNET }; + +#if NKSTAT > 0 +static uint32_t +msk_mib_read32(struct sk_if_softc *sc_if, uint32_t r) +{ + uint16_t hi, lo, xx; + + hi = SK_YU_READ_2(sc_if, r + 4); + for (;;) { + /* XXX barriers? */ + lo = SK_YU_READ_2(sc_if, r); + xx = SK_YU_READ_2(sc_if, r + 4); + + if (hi == xx) + break; + + hi = xx; + } + + return (((uint32_t)hi << 16) | (uint32_t) lo); +} + +static uint64_t +msk_mib_read64(struct sk_if_softc *sc_if, uint32_t r) +{ + uint32_t hi, lo, xx; + + hi = msk_mib_read32(sc_if, r + 8); + for (;;) { + lo = msk_mib_read32(sc_if, r); + xx = msk_mib_read32(sc_if, r + 8); + + if (hi == xx) + break; + + hi = xx; + } + + return (((uint64_t)hi << 32) | (uint64_t)lo); +} + +void +msk_kstat_attach(struct sk_if_softc *sc_if) +{ + struct kstat *ks; + struct kstat_kv *kvs; + struct msk_kstat *mks; + size_t i; + + ks = kstat_create(sc_if->sk_dev.dv_xname, 0, "msk-mib", 0, + KSTAT_T_KV, 0); + if (ks == NULL) { + /* oh well */ + return; + } + + mks = malloc(sizeof(*mks), M_DEVBUF, M_WAITOK); + rw_init(&mks->lock, "mskstat"); + mks->ks = ks; + + kvs = mallocarray(nitems(msk_mib), sizeof(*kvs), + M_DEVBUF, M_WAITOK|M_ZERO); + for (i = 0; i < nitems(msk_mib); i++) { + const struct msk_mib *m = &msk_mib[i]; + kstat_kv_unit_init(&kvs[i], m->name, m->type, m->unit); + } + + ks->ks_softc = sc_if; + ks->ks_data = kvs; + ks->ks_datalen = nitems(msk_mib) * sizeof(*kvs); + ks->ks_read = msk_kstat_read; + kstat_set_wlock(ks, &mks->lock); + + kstat_install(ks); + + sc_if->sk_kstat = mks; +} + +void +msk_kstat_detach(struct sk_if_softc *sc_if) +{ + struct msk_kstat *mks = sc_if->sk_kstat; + struct kstat_kv *kvs; + size_t kvslen; + + if (mks == NULL) + return; + + sc_if->sk_kstat = NULL; + + kvs = mks->ks->ks_data; + kvslen = mks->ks->ks_datalen; + + kstat_destroy(mks->ks); + free(kvs, M_DEVBUF, kvslen); + free(mks, M_DEVBUF, sizeof(*mks)); +} + +int +msk_kstat_read(struct kstat *ks) +{ + struct sk_if_softc *sc_if = ks->ks_softc; + struct kstat_kv *kvs = ks->ks_data; + size_t i; + + nanouptime(&ks->ks_updated); + + for (i = 0; i < nitems(msk_mib); i++) { + const struct msk_mib *m = &msk_mib[i]; + + switch (m->type) { + case KSTAT_KV_T_COUNTER32: + kstat_kv_u32(&kvs[i]) = msk_mib_read32(sc_if, m->reg); + break; + case KSTAT_KV_T_COUNTER64: + kstat_kv_u64(&kvs[i]) = msk_mib_read64(sc_if, m->reg); + break; + default: + panic("unexpected msk_mib type"); + /* NOTREACHED */ + } + } + + return (0); +} +#endif /* NKSTAT */ #ifdef MSK_DEBUG void Index: if_mskvar.h =================================================================== RCS file: /cvs/src/sys/dev/pci/if_mskvar.h,v retrieving revision 1.14 diff -u -p -r1.14 if_mskvar.h --- if_mskvar.h 6 Jan 2018 03:11:04 -0000 1.14 +++ if_mskvar.h 7 Jan 2022 02:56:53 -0000 @@ -117,7 +117,7 @@ struct msk_ring_data { #define MSK_CDOFF(x) offsetof(struct msk_ring_data, x) #define MSK_CDTXOFF(x) MSK_CDOFF(sk_tx_ring[(x)]) #define MSK_CDRXOFF(x) MSK_CDOFF(sk_rx_ring[(x)]) -#define MSK_CDSTOFF(x) ((x) * sizeof(struct msk_status_desc)) +#define MSK_CDSTOFF(x) ((x) * sizeof(uint64_t)) #define MSK_CDTXSYNC(sc, x, n, ops) \ do { \ @@ -150,13 +150,14 @@ do { \ #define MSK_CDSTSYNC(sc, x, ops) \ do { \ bus_dmamap_sync((sc)->sc_dmatag, (sc)->sk_status_map, \ - MSK_CDSTOFF((x)), sizeof(struct msk_status_desc), (ops)); \ + MSK_CDSTOFF((x)), sizeof(uint64_t), (ops)); \ } while (/*CONSTCOND*/0) #define SK_INC(x, y) (x) = (x + 1) % y /* Forward decl. */ struct sk_if_softc; +struct msk_kstat; /* Softc for the Yukon-II controller. */ struct sk_softc { @@ -175,7 +176,7 @@ struct sk_softc { u_int32_t sk_intrmask; bus_dma_tag_t sc_dmatag; struct sk_if_softc *sk_if[2]; - struct msk_status_desc *sk_status_ring; + uint64_t *sk_status_ring; bus_dmamap_t sk_status_map; bus_dma_segment_t sk_status_seg; int sk_status_nseg; @@ -206,6 +207,8 @@ struct sk_if_softc { struct sk_softc *sk_softc; /* parent controller */ int sk_tx_bmu; /* TX BMU register */ SIMPLEQ_HEAD(__sk_txmaphead, sk_txmap_entry) sk_txmap_head; + + struct msk_kstat *sk_kstat; }; struct skc_attach_args {