Module Name: src Committed By: yamaguchi Date: Thu Jan 9 02:43:45 UTC 2020
Modified Files: src/sys/dev/pci: if_ixl.c Log Message: ixl(4) supports in-chip statistic counters per port To generate a diff of this commit: cvs rdiff -u -r1.16 -r1.17 src/sys/dev/pci/if_ixl.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/pci/if_ixl.c diff -u src/sys/dev/pci/if_ixl.c:1.16 src/sys/dev/pci/if_ixl.c:1.17 --- src/sys/dev/pci/if_ixl.c:1.16 Wed Jan 8 09:12:11 2020 +++ src/sys/dev/pci/if_ixl.c Thu Jan 9 02:43:45 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: if_ixl.c,v 1.16 2020/01/08 09:12:11 yamaguchi Exp $ */ +/* $NetBSD: if_ixl.c,v 1.17 2020/01/09 02:43:45 yamaguchi Exp $ */ /* * Copyright (c) 2013-2015, Intel Corporation @@ -485,6 +485,82 @@ struct ixl_product { unsigned int product_id; }; +struct ixl_stats_counters { + bool isc_has_offset; + struct evcnt isc_crc_errors; + uint64_t isc_crc_errors_offset; + struct evcnt isc_illegal_bytes; + uint64_t isc_illegal_bytes_offset; + struct evcnt isc_rx_bytes; + uint64_t isc_rx_bytes_offset; + struct evcnt isc_rx_discards; + uint64_t isc_rx_discards_offset; + struct evcnt isc_rx_unicast; + uint64_t isc_rx_unicast_offset; + struct evcnt isc_rx_multicast; + uint64_t isc_rx_multicast_offset; + struct evcnt isc_rx_broadcast; + uint64_t isc_rx_broadcast_offset; + struct evcnt isc_rx_size_64; + uint64_t isc_rx_size_64_offset; + struct evcnt isc_rx_size_127; + uint64_t isc_rx_size_127_offset; + struct evcnt isc_rx_size_255; + uint64_t isc_rx_size_255_offset; + struct evcnt isc_rx_size_511; + uint64_t isc_rx_size_511_offset; + struct evcnt isc_rx_size_1023; + uint64_t isc_rx_size_1023_offset; + struct evcnt isc_rx_size_1522; + uint64_t isc_rx_size_1522_offset; + struct evcnt isc_rx_size_big; + uint64_t isc_rx_size_big_offset; + struct evcnt isc_rx_undersize; + uint64_t isc_rx_undersize_offset; + struct evcnt isc_rx_oversize; + uint64_t isc_rx_oversize_offset; + struct evcnt isc_rx_fragments; + uint64_t isc_rx_fragments_offset; + struct evcnt isc_rx_jabber; + uint64_t isc_rx_jabber_offset; + struct evcnt isc_tx_bytes; + uint64_t isc_tx_bytes_offset; + struct evcnt isc_tx_dropped_link_down; + uint64_t isc_tx_dropped_link_down_offset; + struct evcnt isc_tx_unicast; + uint64_t isc_tx_unicast_offset; + struct evcnt isc_tx_multicast; + uint64_t isc_tx_multicast_offset; + struct evcnt isc_tx_broadcast; + uint64_t isc_tx_broadcast_offset; + struct evcnt isc_tx_size_64; + uint64_t isc_tx_size_64_offset; + struct evcnt isc_tx_size_127; + uint64_t isc_tx_size_127_offset; + struct evcnt isc_tx_size_255; + uint64_t isc_tx_size_255_offset; + struct evcnt isc_tx_size_511; + uint64_t isc_tx_size_511_offset; + struct evcnt isc_tx_size_1023; + uint64_t isc_tx_size_1023_offset; + struct evcnt isc_tx_size_1522; + uint64_t isc_tx_size_1522_offset; + struct evcnt isc_tx_size_big; + uint64_t isc_tx_size_big_offset; + struct evcnt isc_mac_local_faults; + uint64_t isc_mac_local_faults_offset; + struct evcnt isc_mac_remote_faults; + uint64_t isc_mac_remote_faults_offset; + struct evcnt isc_link_xon_rx; + uint64_t isc_link_xon_rx_offset; + struct evcnt isc_link_xon_tx; + uint64_t isc_link_xon_tx_offset; + struct evcnt isc_link_xoff_rx; + uint64_t isc_link_xoff_rx_offset; + struct evcnt isc_link_xoff_tx; + uint64_t isc_link_xoff_tx_offset; +}; + /* * Locking notes: * + a field in ixl_tx_ring is protected by txr_lock (a spin mutex), and @@ -508,9 +584,15 @@ struct ixl_softc { bool sc_attached; bool sc_dead; bool sc_rxctl_atq; + uint32_t sc_port; struct sysctllog *sc_sysctllog; struct workqueue *sc_workq; struct workqueue *sc_workq_txrx; + int sc_stats_intval; + callout_t sc_stats_callout; + struct ixl_work sc_stats_task; + struct ixl_stats_counters + sc_stats_counters; uint8_t sc_enaddr[ETHER_ADDR_LEN]; struct ifmedia sc_media; uint64_t sc_media_status; @@ -613,6 +695,9 @@ do { \ #define DDPRINTF(sc, fmt, args...) __nothing #endif #define IXL_NOMSIX false +#ifndef IXL_STATS_INTERVAL_MSEC +#define IXL_STATS_INTERVAL_MSEC 10000 +#endif static enum i40e_mac_type ixl_mactype(pci_product_id_t); @@ -742,6 +827,8 @@ static int ixl_setup_interrupts(struct i static void ixl_teardown_interrupts(struct ixl_softc *); static int ixl_setup_stats(struct ixl_softc *); static void ixl_teardown_stats(struct ixl_softc *); +static void ixl_stats_callout(void *); +static void ixl_stats_update(void *); static int ixl_setup_sysctls(struct ixl_softc *); static void ixl_teardown_sysctls(struct ixl_softc *); static int ixl_queue_pairs_alloc(struct ixl_softc *); @@ -973,7 +1060,8 @@ ixl_attach(device_t parent, device_t sel port = ixl_rd(sc, I40E_PFGEN_PORTNUM); port &= I40E_PFGEN_PORTNUM_PORT_NUM_MASK; port >>= I40E_PFGEN_PORTNUM_PORT_NUM_SHIFT; - aprint_normal(": port %u", port); + sc->sc_port = port; + aprint_normal(": port %u", sc->sc_port); ari = ixl_rd(sc, I40E_GLPCI_CAPSUP); ari &= I40E_GLPCI_CAPSUP_ARI_EN_MASK; @@ -1261,6 +1349,10 @@ ixl_attach(device_t parent, device_t sel sc->sc_tx_intr_process_limit = IXL_TX_INTR_PROCESS_LIMIT; sc->sc_rx_intr_process_limit = IXL_RX_INTR_PROCESS_LIMIT; + ixl_stats_update(sc); + sc->sc_stats_counters.isc_has_offset = true; + callout_schedule(&sc->sc_stats_callout, mstohz(sc->sc_stats_intval)); + if (pmf_device_register(self, NULL, NULL) != true) aprint_debug_dev(self, "couldn't establish power handler\n"); sc->sc_attached = true; @@ -1328,6 +1420,9 @@ ixl_detach(device_t self, int flags) ixl_disable_other_intr(sc); + callout_stop(&sc->sc_stats_callout); + ixl_work_wait(sc->sc_workq, &sc->sc_stats_task); + /* wait for ATQ handler */ mutex_enter(&sc->sc_atq_lock); mutex_exit(&sc->sc_atq_lock); @@ -5447,6 +5542,7 @@ ixl_setup_stats(struct ixl_softc *sc) struct ixl_queue_pair *qp; struct ixl_tx_ring *txr; struct ixl_rx_ring *rxr; + struct ixl_stats_counters *isc; unsigned int i; for (i = 0; i < sc->sc_nqueue_pairs_max; i++) { @@ -5491,6 +5587,90 @@ ixl_setup_stats(struct ixl_softc *sc) evcnt_attach_dynamic(&sc->sc_event_crit_err, EVCNT_TYPE_MISC, NULL, device_xname(sc->sc_dev), "Critical error"); + isc = &sc->sc_stats_counters; + evcnt_attach_dynamic(&isc->isc_crc_errors, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "CRC errors"); + evcnt_attach_dynamic(&isc->isc_illegal_bytes, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Illegal bytes"); + evcnt_attach_dynamic(&isc->isc_mac_local_faults, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Mac local faults"); + evcnt_attach_dynamic(&isc->isc_mac_remote_faults, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Mac remote faults"); + evcnt_attach_dynamic(&isc->isc_link_xon_rx, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Rx xon"); + evcnt_attach_dynamic(&isc->isc_link_xon_tx, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Tx xon"); + evcnt_attach_dynamic(&isc->isc_link_xoff_rx, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Rx xoff"); + evcnt_attach_dynamic(&isc->isc_link_xoff_tx, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Tx xoff"); + evcnt_attach_dynamic(&isc->isc_rx_fragments, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Rx fragments"); + evcnt_attach_dynamic(&isc->isc_rx_jabber, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Rx jabber"); + + evcnt_attach_dynamic(&isc->isc_rx_size_64, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Rx size 64"); + evcnt_attach_dynamic(&isc->isc_rx_size_127, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Rx size 127"); + evcnt_attach_dynamic(&isc->isc_rx_size_255, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Rx size 255"); + evcnt_attach_dynamic(&isc->isc_rx_size_511, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Rx size 511"); + evcnt_attach_dynamic(&isc->isc_rx_size_1023, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Rx size 1023"); + evcnt_attach_dynamic(&isc->isc_rx_size_1522, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Rx size 1522"); + evcnt_attach_dynamic(&isc->isc_rx_size_big, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Rx jumbo packets"); + evcnt_attach_dynamic(&isc->isc_rx_undersize, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Rx under size"); + evcnt_attach_dynamic(&isc->isc_rx_oversize, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Rx over size"); + + evcnt_attach_dynamic(&isc->isc_rx_bytes, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Rx bytes / port"); + evcnt_attach_dynamic(&isc->isc_rx_discards, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Rx discards / port"); + evcnt_attach_dynamic(&isc->isc_rx_unicast, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Rx unicast / port"); + evcnt_attach_dynamic(&isc->isc_rx_multicast, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Rx multicast / port"); + evcnt_attach_dynamic(&isc->isc_rx_broadcast, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Rx broadcast / port"); + + evcnt_attach_dynamic(&isc->isc_tx_size_64, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Tx size 64"); + evcnt_attach_dynamic(&isc->isc_tx_size_127, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Tx size 127"); + evcnt_attach_dynamic(&isc->isc_tx_size_255, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Tx size 255"); + evcnt_attach_dynamic(&isc->isc_tx_size_511, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Tx size 511"); + evcnt_attach_dynamic(&isc->isc_tx_size_1023, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Tx size 1023"); + evcnt_attach_dynamic(&isc->isc_tx_size_1522, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Tx size 1522"); + evcnt_attach_dynamic(&isc->isc_tx_size_big, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Tx jumbo packets"); + + evcnt_attach_dynamic(&isc->isc_tx_bytes, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Tx bytes / port"); + evcnt_attach_dynamic(&isc->isc_tx_dropped_link_down, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), + "Tx dropped due to link down / port"); + evcnt_attach_dynamic(&isc->isc_tx_unicast, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Tx unicast / port"); + evcnt_attach_dynamic(&isc->isc_tx_multicast, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Tx multicast / port"); + evcnt_attach_dynamic(&isc->isc_tx_broadcast, EVCNT_TYPE_MISC, + NULL, device_xname(sc->sc_dev), "Tx broadcast / port"); + + sc->sc_stats_intval = IXL_STATS_INTERVAL_MSEC; + callout_init(&sc->sc_stats_callout, CALLOUT_MPSAFE); + callout_setfunc(&sc->sc_stats_callout, ixl_stats_callout, sc); + ixl_work_set(&sc->sc_stats_task, ixl_stats_update, sc); + return 0; } @@ -5499,6 +5679,7 @@ ixl_teardown_stats(struct ixl_softc *sc) { struct ixl_tx_ring *txr; struct ixl_rx_ring *rxr; + struct ixl_stats_counters *isc; unsigned int i; for (i = 0; i < sc->sc_nqueue_pairs_max; i++) { @@ -5519,11 +5700,286 @@ ixl_teardown_stats(struct ixl_softc *sc) evcnt_detach(&rxr->rxr_defer); } + isc = &sc->sc_stats_counters; + evcnt_detach(&isc->isc_crc_errors); + evcnt_detach(&isc->isc_illegal_bytes); + evcnt_detach(&isc->isc_mac_local_faults); + evcnt_detach(&isc->isc_mac_remote_faults); + evcnt_detach(&isc->isc_link_xon_rx); + evcnt_detach(&isc->isc_link_xon_tx); + evcnt_detach(&isc->isc_link_xoff_rx); + evcnt_detach(&isc->isc_link_xoff_tx); + evcnt_detach(&isc->isc_rx_fragments); + evcnt_detach(&isc->isc_rx_jabber); + evcnt_detach(&isc->isc_rx_bytes); + evcnt_detach(&isc->isc_rx_discards); + evcnt_detach(&isc->isc_rx_unicast); + evcnt_detach(&isc->isc_rx_multicast); + evcnt_detach(&isc->isc_rx_broadcast); + evcnt_detach(&isc->isc_rx_size_64); + evcnt_detach(&isc->isc_rx_size_127); + evcnt_detach(&isc->isc_rx_size_255); + evcnt_detach(&isc->isc_rx_size_511); + evcnt_detach(&isc->isc_rx_size_1023); + evcnt_detach(&isc->isc_rx_size_1522); + evcnt_detach(&isc->isc_rx_size_big); + evcnt_detach(&isc->isc_rx_undersize); + evcnt_detach(&isc->isc_rx_oversize); + evcnt_detach(&isc->isc_tx_bytes); + evcnt_detach(&isc->isc_tx_dropped_link_down); + evcnt_detach(&isc->isc_tx_unicast); + evcnt_detach(&isc->isc_tx_multicast); + evcnt_detach(&isc->isc_tx_broadcast); + evcnt_detach(&isc->isc_tx_size_64); + evcnt_detach(&isc->isc_tx_size_127); + evcnt_detach(&isc->isc_tx_size_255); + evcnt_detach(&isc->isc_tx_size_511); + evcnt_detach(&isc->isc_tx_size_1023); + evcnt_detach(&isc->isc_tx_size_1522); + evcnt_detach(&isc->isc_tx_size_big); + evcnt_detach(&sc->sc_event_atq); evcnt_detach(&sc->sc_event_link); evcnt_detach(&sc->sc_event_ecc_err); evcnt_detach(&sc->sc_event_pci_exception); evcnt_detach(&sc->sc_event_crit_err); + + callout_destroy(&sc->sc_stats_callout); +} + +static void +ixl_stats_callout(void *xsc) +{ + struct ixl_softc *sc = xsc; + + ixl_work_add(sc->sc_workq, &sc->sc_stats_task); + callout_schedule(&sc->sc_stats_callout, mstohz(sc->sc_stats_intval)); +} + +static uint64_t +ixl_stat_delta(struct ixl_softc *sc, uint32_t reg_hi, uint32_t reg_lo, + uint64_t *offset, bool has_offset) +{ + uint64_t value, delta; + int bitwidth; + + bitwidth = reg_hi == 0 ? 32 : 48; + + value = ixl_rd(sc, reg_lo); + + if (bitwidth > 32) { + value |= ((uint64_t)ixl_rd(sc, reg_hi) << 32); + } + + if (__predict_true(has_offset)) { + delta = value; + if (value < *offset) + delta += ((uint64_t)1 << bitwidth); + delta -= *offset; + } else { + delta = 0; + } + atomic_swap_64(offset, value); + + return delta; +} + +static void +ixl_stats_update(void *xsc) +{ + struct ixl_softc *sc = xsc; + struct ixl_stats_counters *isc; + uint64_t delta; + + isc = &sc->sc_stats_counters; + + /* errors */ + delta = ixl_stat_delta(sc, + 0, I40E_GLPRT_CRCERRS(sc->sc_port), + &isc->isc_crc_errors_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_crc_errors.ev_count, delta); + + delta = ixl_stat_delta(sc, + 0, I40E_GLPRT_ILLERRC(sc->sc_port), + &isc->isc_illegal_bytes_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_illegal_bytes.ev_count, delta); + + /* rx */ + delta = ixl_stat_delta(sc, + I40E_GLPRT_GORCH(sc->sc_port), I40E_GLPRT_GORCL(sc->sc_port), + &isc->isc_rx_bytes_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_rx_bytes.ev_count, delta); + + delta = ixl_stat_delta(sc, + 0, I40E_GLPRT_RDPC(sc->sc_port), + &isc->isc_rx_discards_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_rx_discards.ev_count, delta); + + delta = ixl_stat_delta(sc, + I40E_GLPRT_UPRCH(sc->sc_port), I40E_GLPRT_UPRCL(sc->sc_port), + &isc->isc_rx_unicast_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_rx_unicast.ev_count, delta); + + delta = ixl_stat_delta(sc, + I40E_GLPRT_MPRCH(sc->sc_port), I40E_GLPRT_MPRCL(sc->sc_port), + &isc->isc_rx_multicast_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_rx_multicast.ev_count, delta); + + delta = ixl_stat_delta(sc, + I40E_GLPRT_BPRCH(sc->sc_port), I40E_GLPRT_BPRCL(sc->sc_port), + &isc->isc_rx_broadcast_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_rx_broadcast.ev_count, delta); + + /* Packet size stats rx */ + delta = ixl_stat_delta(sc, + I40E_GLPRT_PRC64H(sc->sc_port), I40E_GLPRT_PRC64L(sc->sc_port), + &isc->isc_rx_size_64_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_rx_size_64.ev_count, delta); + + delta = ixl_stat_delta(sc, + I40E_GLPRT_PRC127H(sc->sc_port), I40E_GLPRT_PRC127L(sc->sc_port), + &isc->isc_rx_size_127_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_rx_size_127.ev_count, delta); + + delta = ixl_stat_delta(sc, + I40E_GLPRT_PRC255H(sc->sc_port), I40E_GLPRT_PRC255L(sc->sc_port), + &isc->isc_rx_size_255_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_rx_size_255.ev_count, delta); + + delta = ixl_stat_delta(sc, + I40E_GLPRT_PRC511H(sc->sc_port), I40E_GLPRT_PRC511L(sc->sc_port), + &isc->isc_rx_size_511_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_rx_size_511.ev_count, delta); + + delta = ixl_stat_delta(sc, + I40E_GLPRT_PRC1023H(sc->sc_port), I40E_GLPRT_PRC1023L(sc->sc_port), + &isc->isc_rx_size_1023_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_rx_size_1023.ev_count, delta); + + delta = ixl_stat_delta(sc, + I40E_GLPRT_PRC1522H(sc->sc_port), I40E_GLPRT_PRC1522L(sc->sc_port), + &isc->isc_rx_size_1522_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_rx_size_1522.ev_count, delta); + + delta = ixl_stat_delta(sc, + I40E_GLPRT_PRC9522H(sc->sc_port), I40E_GLPRT_PRC9522L(sc->sc_port), + &isc->isc_rx_size_big_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_rx_size_big.ev_count, delta); + + delta = ixl_stat_delta(sc, + 0, I40E_GLPRT_RUC(sc->sc_port), + &isc->isc_rx_undersize_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_rx_undersize.ev_count, delta); + + delta = ixl_stat_delta(sc, + 0, I40E_GLPRT_ROC(sc->sc_port), + &isc->isc_rx_oversize_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_rx_oversize.ev_count, delta); + + /* tx */ + delta = ixl_stat_delta(sc, + I40E_GLPRT_GOTCH(sc->sc_port), I40E_GLPRT_GOTCL(sc->sc_port), + &isc->isc_tx_bytes_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_tx_bytes.ev_count, delta); + + delta = ixl_stat_delta(sc, + 0, I40E_GLPRT_TDOLD(sc->sc_port), + &isc->isc_tx_dropped_link_down_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_tx_dropped_link_down.ev_count, delta); + + delta = ixl_stat_delta(sc, + I40E_GLPRT_UPTCH(sc->sc_port), I40E_GLPRT_UPTCL(sc->sc_port), + &isc->isc_tx_unicast_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_tx_unicast.ev_count, delta); + + delta = ixl_stat_delta(sc, + I40E_GLPRT_MPTCH(sc->sc_port), I40E_GLPRT_MPTCL(sc->sc_port), + &isc->isc_tx_multicast_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_tx_multicast.ev_count, delta); + + delta = ixl_stat_delta(sc, + I40E_GLPRT_BPTCH(sc->sc_port), I40E_GLPRT_BPTCL(sc->sc_port), + &isc->isc_tx_broadcast_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_tx_broadcast.ev_count, delta); + + /* Packet size stats tx */ + delta = ixl_stat_delta(sc, + I40E_GLPRT_PTC64L(sc->sc_port), I40E_GLPRT_PTC64L(sc->sc_port), + &isc->isc_tx_size_64_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_tx_size_64.ev_count, delta); + + delta = ixl_stat_delta(sc, + I40E_GLPRT_PTC127H(sc->sc_port), I40E_GLPRT_PTC127L(sc->sc_port), + &isc->isc_tx_size_127_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_tx_size_127.ev_count, delta); + + delta = ixl_stat_delta(sc, + I40E_GLPRT_PTC255H(sc->sc_port), I40E_GLPRT_PTC255L(sc->sc_port), + &isc->isc_tx_size_255_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_tx_size_255.ev_count, delta); + + delta = ixl_stat_delta(sc, + I40E_GLPRT_PTC511H(sc->sc_port), I40E_GLPRT_PTC511L(sc->sc_port), + &isc->isc_tx_size_511_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_tx_size_511.ev_count, delta); + + delta = ixl_stat_delta(sc, + I40E_GLPRT_PTC1023H(sc->sc_port), I40E_GLPRT_PTC1023L(sc->sc_port), + &isc->isc_tx_size_1023_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_tx_size_1023.ev_count, delta); + + delta = ixl_stat_delta(sc, + I40E_GLPRT_PTC1522H(sc->sc_port), I40E_GLPRT_PTC1522L(sc->sc_port), + &isc->isc_tx_size_1522_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_tx_size_1522.ev_count, delta); + + delta = ixl_stat_delta(sc, + I40E_GLPRT_PTC9522H(sc->sc_port), I40E_GLPRT_PTC9522L(sc->sc_port), + &isc->isc_tx_size_big_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_tx_size_big.ev_count, delta); + + /* mac faults */ + delta = ixl_stat_delta(sc, + 0, I40E_GLPRT_MLFC(sc->sc_port), + &isc->isc_mac_local_faults_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_mac_local_faults.ev_count, delta); + + delta = ixl_stat_delta(sc, + 0, I40E_GLPRT_MRFC(sc->sc_port), + &isc->isc_mac_remote_faults_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_mac_remote_faults.ev_count, delta); + + /* Flow control (LFC) stats */ + delta = ixl_stat_delta(sc, + 0, I40E_GLPRT_LXONRXC(sc->sc_port), + &isc->isc_link_xon_rx_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_link_xon_rx.ev_count, delta); + + delta = ixl_stat_delta(sc, + 0, I40E_GLPRT_LXONTXC(sc->sc_port), + &isc->isc_link_xon_tx_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_link_xon_tx.ev_count, delta); + + delta = ixl_stat_delta(sc, + 0, I40E_GLPRT_LXOFFRXC(sc->sc_port), + &isc->isc_link_xoff_rx_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_link_xoff_rx.ev_count, delta); + + delta = ixl_stat_delta(sc, + 0, I40E_GLPRT_LXOFFTXC(sc->sc_port), + &isc->isc_link_xoff_tx_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_link_xoff_tx.ev_count, delta); + + /* fragments */ + delta = ixl_stat_delta(sc, + 0, I40E_GLPRT_RFC(sc->sc_port), + &isc->isc_rx_fragments_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_rx_fragments.ev_count, delta); + + delta = ixl_stat_delta(sc, + 0, I40E_GLPRT_RJC(sc->sc_port), + &isc->isc_rx_jabber_offset, isc->isc_has_offset); + atomic_add_64(&isc->isc_rx_jabber.ev_count, delta); } static int @@ -5551,6 +6007,11 @@ ixl_setup_sysctls(struct ixl_softc *sc) if (error) goto out; + error = sysctl_createv(log, 0, &rnode, NULL, + CTLFLAG_READONLY, CTLTYPE_INT, "stats_interval", + SYSCTL_DESCR("Statistics collection interval in milliseconds"), + NULL, 0, &sc->sc_stats_intval, 0, CTL_CREATE, CTL_EOL); + error = sysctl_createv(log, 0, &rnode, &rxnode, 0, CTLTYPE_NODE, "rx", SYSCTL_DESCR("ixl information and settings for Rx"),