diff options
-rw-r--r-- | sys/dev/re/if_re.c | 154 | ||||
-rw-r--r-- | sys/pci/if_rlreg.h | 16 |
2 files changed, 146 insertions, 24 deletions
diff --git a/sys/dev/re/if_re.c b/sys/dev/re/if_re.c index 0f8baa9..95983af 100644 --- a/sys/dev/re/if_re.c +++ b/sys/dev/re/if_re.c @@ -123,6 +123,7 @@ __FBSDID("$FreeBSD$"); #include <sys/socket.h> #include <sys/lock.h> #include <sys/mutex.h> +#include <sys/sysctl.h> #include <sys/taskqueue.h> #include <net/if.h> @@ -281,6 +282,9 @@ static void re_clrwol (struct rl_softc *); static int re_diag (struct rl_softc *); #endif +static void re_add_sysctls (struct rl_softc *); +static int re_sysctl_stats (SYSCTL_HANDLER_ARGS); + static device_method_t re_methods[] = { /* Device interface */ DEVMETHOD(device_probe, re_probe), @@ -1084,6 +1088,35 @@ re_allocmem(device_t dev, struct rl_softc *sc) } } + /* Create DMA map for statistics. */ + error = bus_dma_tag_create(sc->rl_parent_tag, RL_DUMP_ALIGN, 0, + BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, + sizeof(struct rl_stats), 1, sizeof(struct rl_stats), 0, NULL, NULL, + &sc->rl_ldata.rl_stag); + if (error) { + device_printf(dev, "could not create statistics DMA tag\n"); + return (error); + } + /* Allocate DMA'able memory for statistics. */ + error = bus_dmamem_alloc(sc->rl_ldata.rl_stag, + (void **)&sc->rl_ldata.rl_stats, + BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, + &sc->rl_ldata.rl_smap); + if (error) { + device_printf(dev, + "could not allocate statistics DMA memory\n"); + return (error); + } + /* Load the map for statistics. */ + sc->rl_ldata.rl_stats_addr = 0; + error = bus_dmamap_load(sc->rl_ldata.rl_stag, sc->rl_ldata.rl_smap, + sc->rl_ldata.rl_stats, sizeof(struct rl_stats), re_dma_map_addr, + &sc->rl_ldata.rl_stats_addr, BUS_DMA_NOWAIT); + if (error != 0 || sc->rl_ldata.rl_stats_addr == 0) { + device_printf(dev, "could not load statistics DMA memory\n"); + return (ENOMEM); + } + return (0); } @@ -1374,6 +1407,7 @@ re_attach(device_t dev) error = re_allocmem(dev, sc); if (error) goto fail; + re_add_sysctls(sc); ifp = sc->rl_ifp = if_alloc(IFT_ETHER); if (ifp == NULL) { @@ -1603,22 +1637,26 @@ re_detach(device_t dev) /* Unload and free the RX DMA ring memory and map */ if (sc->rl_ldata.rl_rx_list_tag) { - bus_dmamap_unload(sc->rl_ldata.rl_rx_list_tag, - sc->rl_ldata.rl_rx_list_map); - bus_dmamem_free(sc->rl_ldata.rl_rx_list_tag, - sc->rl_ldata.rl_rx_list, - sc->rl_ldata.rl_rx_list_map); + if (sc->rl_ldata.rl_rx_list_map) + bus_dmamap_unload(sc->rl_ldata.rl_rx_list_tag, + sc->rl_ldata.rl_rx_list_map); + if (sc->rl_ldata.rl_rx_list_map && sc->rl_ldata.rl_rx_list) + bus_dmamem_free(sc->rl_ldata.rl_rx_list_tag, + sc->rl_ldata.rl_rx_list, + sc->rl_ldata.rl_rx_list_map); bus_dma_tag_destroy(sc->rl_ldata.rl_rx_list_tag); } /* Unload and free the TX DMA ring memory and map */ if (sc->rl_ldata.rl_tx_list_tag) { - bus_dmamap_unload(sc->rl_ldata.rl_tx_list_tag, - sc->rl_ldata.rl_tx_list_map); - bus_dmamem_free(sc->rl_ldata.rl_tx_list_tag, - sc->rl_ldata.rl_tx_list, - sc->rl_ldata.rl_tx_list_map); + if (sc->rl_ldata.rl_tx_list_map) + bus_dmamap_unload(sc->rl_ldata.rl_tx_list_tag, + sc->rl_ldata.rl_tx_list_map); + if (sc->rl_ldata.rl_tx_list_map && sc->rl_ldata.rl_tx_list) + bus_dmamem_free(sc->rl_ldata.rl_tx_list_tag, + sc->rl_ldata.rl_tx_list, + sc->rl_ldata.rl_tx_list_map); bus_dma_tag_destroy(sc->rl_ldata.rl_tx_list_tag); } @@ -1643,11 +1681,12 @@ re_detach(device_t dev) /* Unload and free the stats buffer and map */ if (sc->rl_ldata.rl_stag) { - bus_dmamap_unload(sc->rl_ldata.rl_stag, - sc->rl_ldata.rl_rx_list_map); - bus_dmamem_free(sc->rl_ldata.rl_stag, - sc->rl_ldata.rl_stats, - sc->rl_ldata.rl_smap); + if (sc->rl_ldata.rl_smap) + bus_dmamap_unload(sc->rl_ldata.rl_stag, + sc->rl_ldata.rl_smap); + if (sc->rl_ldata.rl_smap && sc->rl_ldata.rl_stats) + bus_dmamem_free(sc->rl_ldata.rl_stag, + sc->rl_ldata.rl_stats, sc->rl_ldata.rl_smap); bus_dma_tag_destroy(sc->rl_ldata.rl_stag); } @@ -3185,3 +3224,88 @@ re_clrwol(struct rl_softc *sc) v &= ~RL_CFG5_WOL_LANWAKE; CSR_WRITE_1(sc, RL_CFG5, v); } + +static void +re_add_sysctls(struct rl_softc *sc) +{ + struct sysctl_ctx_list *ctx; + struct sysctl_oid_list *children; + + ctx = device_get_sysctl_ctx(sc->rl_dev); + children = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->rl_dev)); + + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "stats", + CTLTYPE_INT | CTLFLAG_RW, sc, 0, re_sysctl_stats, "I", + "Statistics Information"); +} + +static int +re_sysctl_stats(SYSCTL_HANDLER_ARGS) +{ + struct rl_softc *sc; + struct rl_stats *stats; + int error, i, result; + + result = -1; + error = sysctl_handle_int(oidp, &result, 0, req); + if (error || req->newptr == NULL) + return (error); + + if (result == 1) { + sc = (struct rl_softc *)arg1; + RL_LOCK(sc); + bus_dmamap_sync(sc->rl_ldata.rl_stag, + sc->rl_ldata.rl_smap, BUS_DMASYNC_PREREAD); + CSR_WRITE_4(sc, RL_DUMPSTATS_HI, + RL_ADDR_HI(sc->rl_ldata.rl_stats_addr)); + CSR_WRITE_4(sc, RL_DUMPSTATS_LO, + RL_ADDR_LO(sc->rl_ldata.rl_stats_addr)); + CSR_WRITE_4(sc, RL_DUMPSTATS_LO, + RL_ADDR_LO(sc->rl_ldata.rl_stats_addr | + RL_DUMPSTATS_START)); + for (i = RL_TIMEOUT; i > 0; i--) { + if ((CSR_READ_4(sc, RL_DUMPSTATS_LO) & + RL_DUMPSTATS_START) == 0) + break; + DELAY(1000); + } + bus_dmamap_sync(sc->rl_ldata.rl_stag, + sc->rl_ldata.rl_smap, BUS_DMASYNC_POSTREAD); + RL_UNLOCK(sc); + if (i == 0) { + device_printf(sc->rl_dev, + "DUMP statistics request timedout\n"); + return (ETIMEDOUT); + } + stats = sc->rl_ldata.rl_stats; + printf("%s statistics:\n", device_get_nameunit(sc->rl_dev)); + printf("Tx frames : %ju\n", + (uintmax_t)le64toh(stats->rl_tx_pkts)); + printf("Rx frames : %ju\n", + (uintmax_t)le64toh(stats->rl_rx_pkts)); + printf("Tx errors : %ju\n", + (uintmax_t)le64toh(stats->rl_tx_errs)); + printf("Rx errors : %u\n", + le32toh(stats->rl_rx_errs)); + printf("Rx missed frames : %u\n", + (uint32_t)le16toh(stats->rl_missed_pkts)); + printf("Rx frame alignment errs : %u\n", + (uint32_t)le16toh(stats->rl_rx_framealign_errs)); + printf("Tx single collisions : %u\n", + le32toh(stats->rl_tx_onecoll)); + printf("Tx multiple collisions : %u\n", + le32toh(stats->rl_tx_multicolls)); + printf("Rx unicast frames : %ju\n", + (uintmax_t)le64toh(stats->rl_rx_ucasts)); + printf("Rx broadcast frames : %ju\n", + (uintmax_t)le64toh(stats->rl_rx_bcasts)); + printf("Rx multicast frames : %u\n", + le32toh(stats->rl_rx_mcasts)); + printf("Tx aborts : %u\n", + (uint32_t)le16toh(stats->rl_tx_aborts)); + printf("Tx underruns : %u\n", + (uint32_t)le16toh(stats->rl_rx_underruns)); + } + + return (error); +} diff --git a/sys/pci/if_rlreg.h b/sys/pci/if_rlreg.h index 7d2c7e4..0b29474 100644 --- a/sys/pci/if_rlreg.h +++ b/sys/pci/if_rlreg.h @@ -723,19 +723,16 @@ struct rl_desc { * Statistics counter structure (8139C+ and 8169 only) */ struct rl_stats { - uint32_t rl_tx_pkts_lo; - uint32_t rl_tx_pkts_hi; - uint32_t rl_tx_errs_lo; - uint32_t rl_tx_errs_hi; - uint32_t rl_tx_errs; + uint64_t rl_tx_pkts; + uint64_t rl_rx_pkts; + uint64_t rl_tx_errs; + uint32_t rl_rx_errs; uint16_t rl_missed_pkts; uint16_t rl_rx_framealign_errs; uint32_t rl_tx_onecoll; uint32_t rl_tx_multicolls; - uint32_t rl_rx_ucasts_hi; - uint32_t rl_rx_ucasts_lo; - uint32_t rl_rx_bcasts_lo; - uint32_t rl_rx_bcasts_hi; + uint64_t rl_rx_ucasts; + uint64_t rl_rx_bcasts; uint32_t rl_rx_mcasts; uint16_t rl_tx_aborts; uint16_t rl_rx_underruns; @@ -769,6 +766,7 @@ struct rl_stats { #define RL_NTXSEGS 32 #define RL_RING_ALIGN 256 +#define RL_DUMP_ALIGN 64 #define RL_IFQ_MAXLEN 512 #define RL_TX_DESC_NXT(sc,x) ((x + 1) & ((sc)->rl_ldata.rl_tx_desc_cnt - 1)) #define RL_TX_DESC_PRV(sc,x) ((x - 1) & ((sc)->rl_ldata.rl_tx_desc_cnt - 1)) |