Add groups for MAC statistics, NFP's MAC/PHY maintains a mix of IEEE 802.3 and RMON-compatible statistics. Use the RMON stats for driver drops and error counters as well.
Since the MAC stats are quite large initialize the hstat bitmap when driver is loaded. Signed-off-by: Jakub Kicinski <jakub.kicin...@netronome.com> --- .../net/ethernet/netronome/nfp/nfp_hstat.c | 257 +++++++++++++++++- drivers/net/ethernet/netronome/nfp/nfp_main.c | 1 + drivers/net/ethernet/netronome/nfp/nfp_main.h | 2 + 3 files changed, 257 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_hstat.c b/drivers/net/ethernet/netronome/nfp/nfp_hstat.c index 9300996e756c..cd97cd2676f6 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_hstat.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_hstat.c @@ -4,6 +4,217 @@ #include <net/hstats.h> #include "nfp_net.h" +#include "nfp_port.h" + +/* MAC stats */ +static const struct nfp_stat_pair { + u32 attr; + u32 offset; +} nfp_mac_stats_rx[] = { + { + IFLA_HSTATS_STAT_RFC2819_etherStatsOctets, + NFP_MAC_STATS_RX_IN_OCTETS + }, { + IFLA_HSTATS_STAT_IEEE8023_FrameTooLongErrors, + NFP_MAC_STATS_RX_FRAME_TOO_LONG_ERRORS + }, { + IFLA_HSTATS_STAT_IEEE8023_InRangeLengthErrors, + NFP_MAC_STATS_RX_RANGE_LENGTH_ERRORS + }, + /* missing NFP_MAC_STATS_RX_VLAN_RECEIVED_OK, no standard counter */ + { + IFLA_HSTATS_STAT_RFC2863_Errors, + NFP_MAC_STATS_RX_IN_ERRORS + }, { + IFLA_HSTATS_STAT_RFC2819_etherStatsBroadcastPkts, + NFP_MAC_STATS_RX_IN_BROADCAST_PKTS + }, { + IFLA_HSTATS_STAT_RFC2819_etherStatsDropEvents, + NFP_MAC_STATS_RX_DROP_EVENTS + }, { + IFLA_HSTATS_STAT_IEEE8023_AlignmentErrors, + NFP_MAC_STATS_RX_ALIGNMENT_ERRORS + }, { + IFLA_HSTATS_STAT_IEEE8023_PAUSEMACCtrlFrames, + NFP_MAC_STATS_RX_PAUSE_MAC_CTRL_FRAMES + }, { + IFLA_HSTATS_STAT_IEEE8023_FramesOK, + NFP_MAC_STATS_RX_FRAMES_RECEIVED_OK + }, { + IFLA_HSTATS_STAT_IEEE8023_FrameCheckSequenceErrors, + NFP_MAC_STATS_RX_FRAME_CHECK_SEQUENCE_ERRORS + }, { + IFLA_HSTATS_STAT_RFC2863_UcastPkts, + NFP_MAC_STATS_RX_UNICAST_PKTS + }, { + IFLA_HSTATS_STAT_RFC2819_etherStatsMulticastPkts, + NFP_MAC_STATS_RX_MULTICAST_PKTS + }, { + IFLA_HSTATS_STAT_RFC2819_etherStatsPkts, + NFP_MAC_STATS_RX_PKTS + }, { + IFLA_HSTATS_STAT_RFC2819_etherStatsUndersizePkts, + NFP_MAC_STATS_RX_UNDERSIZE_PKTS + }, { + IFLA_HSTATS_STAT_RFC2819_etherStatsPkts64Octets, + NFP_MAC_STATS_RX_PKTS_64_OCTETS + }, { + IFLA_HSTATS_STAT_RFC2819_etherStatsPkts65to127Octets, + NFP_MAC_STATS_RX_PKTS_65_TO_127_OCTETS + }, { + IFLA_HSTATS_STAT_RFC2819_etherStatsPkts512to1023Octets, + NFP_MAC_STATS_RX_PKTS_512_TO_1023_OCTETS + }, { + IFLA_HSTATS_STAT_RFC2819_etherStatsPkts1024to1518Octets, + NFP_MAC_STATS_RX_PKTS_1024_TO_1518_OCTETS + }, { + IFLA_HSTATS_STAT_RFC2819_etherStatsJabbers, + NFP_MAC_STATS_RX_JABBERS + }, { + IFLA_HSTATS_STAT_RFC2819_etherStatsFragments, + NFP_MAC_STATS_RX_FRAGMENTS + }, { + IFLA_HSTATS_STAT_RFC2819_etherStatsPkts128to255Octets, + NFP_MAC_STATS_RX_PKTS_128_TO_255_OCTETS + }, { + IFLA_HSTATS_STAT_RFC2819_etherStatsPkts256to511Octets, + NFP_MAC_STATS_RX_PKTS_256_TO_511_OCTETS + }, { + IFLA_HSTATS_STAT_RFC2819EXT_etherStatsPkts1519toMaxOctets, + NFP_MAC_STATS_RX_PKTS_1519_TO_MAX_OCTETS + }, { + IFLA_HSTATS_STAT_RFC2819_etherStatsOversizePkts, + NFP_MAC_STATS_RX_OVERSIZE_PKTS + }, { + IFLA_HSTATS_STAT_IEEE8023_MACControlFrames, + NFP_MAC_STATS_RX_MAC_CTRL_FRAMES_RECEIVED + } +}, nfp_mac_stats_tx[] = { + { + IFLA_HSTATS_STAT_RFC2819_etherStatsOctets, + NFP_MAC_STATS_TX_OUT_OCTETS + }, + /* missing NFP_MAC_STATS_TX_VLAN_TRANSMITTED_OK, no standard counter */ + { + IFLA_HSTATS_STAT_RFC2863_Errors, + NFP_MAC_STATS_TX_OUT_ERRORS + }, { + IFLA_HSTATS_STAT_RFC2819_etherStatsBroadcastPkts, + NFP_MAC_STATS_TX_BROADCAST_PKTS + }, { + IFLA_HSTATS_STAT_RFC2819_etherStatsPkts64Octets, + NFP_MAC_STATS_TX_PKTS_64_OCTETS + }, { + IFLA_HSTATS_STAT_RFC2819_etherStatsPkts256to511Octets, + NFP_MAC_STATS_TX_PKTS_256_TO_511_OCTETS + }, { + IFLA_HSTATS_STAT_RFC2819_etherStatsPkts512to1023Octets, + NFP_MAC_STATS_TX_PKTS_512_TO_1023_OCTETS + }, { + IFLA_HSTATS_STAT_IEEE8023_PAUSEMACCtrlFrames, + NFP_MAC_STATS_TX_PAUSE_MAC_CTRL_FRAMES + }, { + IFLA_HSTATS_STAT_IEEE8023_FramesOK, + NFP_MAC_STATS_TX_FRAMES_TRANSMITTED_OK + }, { + IFLA_HSTATS_STAT_RFC2863_UcastPkts, + NFP_MAC_STATS_TX_UNICAST_PKTS + }, { + IFLA_HSTATS_STAT_RFC2819_etherStatsMulticastPkts, + NFP_MAC_STATS_TX_MULTICAST_PKTS + }, { + IFLA_HSTATS_STAT_RFC2819_etherStatsPkts65to127Octets, + NFP_MAC_STATS_TX_PKTS_65_TO_127_OCTETS + }, { + IFLA_HSTATS_STAT_RFC2819_etherStatsPkts128to255Octets, + NFP_MAC_STATS_TX_PKTS_128_TO_255_OCTETS + }, { + IFLA_HSTATS_STAT_RFC2819_etherStatsPkts1024to1518Octets, + NFP_MAC_STATS_TX_PKTS_1024_TO_1518_OCTETS + }, { + IFLA_HSTATS_STAT_RFC2819EXT_etherStatsPkts1519toMaxOctets, + NFP_MAC_STATS_TX_PKTS_1519_TO_MAX_OCTETS + } +}; + +static int +nfp_hstat_mac_get(struct net_device *netdev, struct rtnl_hstat_req *req, + const struct rtnl_hstat_group *grp) +{ + const struct nfp_stat_pair *pairs; + struct nfp_port *port; + unsigned int dir, i; + + port = nfp_port_from_netdev(netdev); + if (!__nfp_port_get_eth_port(port) || !port->eth_stats) + return -EINVAL; + + dir = rtnl_hstat_qual_get(req, RTNL_HSTATS_QUAL_DIRECTION); + pairs = dir == IFLA_HSTATS_QUAL_DIR_RX ? + nfp_mac_stats_rx : nfp_mac_stats_tx; + + for (i = 0; i < grp->stats_cnt; i++) + rtnl_hstat_dump(req, pairs[i].attr, + readq(port->eth_stats + pairs[i].offset)); + return 0; +} + +static struct rtnl_hstat_group nfp_hstat_mac_rx __ro_after_init = { + .qualifiers = { + RTNL_HSTATS_QUALS_BASIC(DEV, RX), + }, + + .get_stats = nfp_hstat_mac_get, +}; + +static struct rtnl_hstat_group nfp_hstat_mac_tx __ro_after_init = { + .qualifiers = { + RTNL_HSTATS_QUALS_BASIC(DEV, TX), + }, + + .get_stats = nfp_hstat_mac_get, +}; + +static const struct rtnl_hstat_group nfp_hstat_mac = { + .has_children = true, + .children = { + &nfp_hstat_mac_rx, + &nfp_hstat_mac_tx, + NULL, + }, +}; + +static int +nfp_hstat_mac_head_drop(struct net_device *netdev, struct rtnl_hstat_req *req, + const struct rtnl_hstat_group *grp) +{ + struct nfp_port *port; + unsigned int off, dir; + + port = nfp_port_from_netdev(netdev); + if (!__nfp_port_get_eth_port(port) || !port->eth_stats) + return -EINVAL; + + dir = rtnl_hstat_qual_get(req, RTNL_HSTATS_QUAL_DIRECTION); + off = dir == IFLA_HSTATS_QUAL_DIR_RX ? + NFP_MAC_STATS_RX_MAC_HEAD_DROP : NFP_MAC_STATS_TX_QUEUE_DROP; + + rtnl_hstat_dump(req, IFLA_HSTATS_STAT_RFC2819_etherStatsDropEvents, + readq(port->eth_stats + off)); + return 0; +} + +static const struct rtnl_hstat_group nfp_hstat_tm = { + .qualifiers = { + RTNL_HSTATS_QUALS_BASIC_BIDIR(DEV), + }, + + .get_stats = nfp_hstat_mac_head_drop, + .stats = { + [1] = RTNL_HSTATS_STAT_RFC2819_etherStatsDropEvents_BIT, + }, + .stats_cnt = 1, +}; /* NFD per-vNIC stats */ static int @@ -21,6 +232,10 @@ nfp_hstat_vnic_nfd_basic_get(struct net_device *netdev, nn_readq(nn, NFP_NET_CFG_STATS_RX_FRAMES + off)); rtnl_hstat_dump(req, IFLA_HSTATS_STAT_LINUX_BYTES, nn_readq(nn, NFP_NET_CFG_STATS_RX_OCTETS + off)); + rtnl_hstat_dump(req, IFLA_HSTATS_STAT_RFC2863_Errors, + nn_readq(nn, NFP_NET_CFG_STATS_RX_ERRORS + off)); + rtnl_hstat_dump(req, IFLA_HSTATS_STAT_RFC2863_Discards, + nn_readq(nn, NFP_NET_CFG_STATS_RX_DISCARDS + off)); return 0; } @@ -33,8 +248,10 @@ static const struct rtnl_hstat_group nfp_hstat_vnic_nfd = { .stats = { [0] = RTNL_HSTATS_STAT_LINUX_PKTS_BIT | RTNL_HSTATS_STAT_LINUX_BYTES_BIT, + [2] = RTNL_HSTATS_STAT_RFC2863_Errors_BIT | + RTNL_HSTATS_STAT_RFC2863_Discards_BIT, }, - .stats_cnt = 2, + .stats_cnt = 4, }; /* NFD per-Q stats */ @@ -99,6 +316,8 @@ nfp_hstat_vnic_sw_rx_get(struct net_device *dev, struct rtnl_hstat_req *req, r_vec->hw_csum_rx_complete); rtnl_hstat_dump(req, IFLA_HSTATS_STAT_LINUX_CSUM_UNNECESSARY, r_vec->hw_csum_rx_ok + r_vec->hw_csum_rx_inner_ok); + rtnl_hstat_dump(req, IFLA_HSTATS_STAT_RFC2819_etherStatsDropEvents, + r_vec->rx_drops); return 0; } @@ -116,9 +335,10 @@ static const struct rtnl_hstat_group nfp_hstat_vnic_sw_rx = { RTNL_HSTATS_STAT_LINUX_BYTES_BIT | RTNL_HSTATS_STAT_LINUX_CSUM_PARTIAL_BIT | RTNL_HSTATS_STAT_LINUX_CSUM_UNNECESSARY_BIT, + [1] = RTNL_HSTATS_STAT_RFC2819_etherStatsDropEvents_BIT, }, - .stats_cnt = 4, + .stats_cnt = 5, }; static int @@ -137,6 +357,7 @@ nfp_hstat_vnic_sw_tx_get(struct net_device *dev, struct rtnl_hstat_req *req, r_vec->hw_csum_tx + r_vec->hw_csum_tx_inner); rtnl_hstat_dump(req, IFLA_HSTATS_STAT_LINUX_SEGMENTATION_OFFLOAD_PKTS, r_vec->tx_lso); + rtnl_hstat_dump(req, IFLA_HSTATS_STAT_RFC2863_Errors, r_vec->tx_errors); return 0; } @@ -155,8 +376,9 @@ static const struct rtnl_hstat_group nfp_hstat_vnic_sw_tx = { RTNL_HSTATS_STAT_LINUX_BUSY_BIT | RTNL_HSTATS_STAT_LINUX_CSUM_PARTIAL_BIT | RTNL_HSTATS_STAT_LINUX_SEGMENTATION_OFFLOAD_PKTS_BIT, + [1] = RTNL_HSTATS_STAT_RFC2863_Errors_BIT, }, - .stats_cnt = 5, + .stats_cnt = 6, }; static const struct rtnl_hstat_group nfp_hstat_vnic_sw = { @@ -171,9 +393,38 @@ static const struct rtnl_hstat_group nfp_hstat_vnic_sw = { int nfp_net_hstat_get_groups(const struct net_device *netdev, struct rtnl_hstat_req *req) { + struct nfp_port *port; + rtnl_hstat_add_grp(req, &nfp_hstat_vnic_sw); rtnl_hstat_add_grp(req, &nfp_hstat_vnic_nfd_pq); rtnl_hstat_add_grp(req, &nfp_hstat_vnic_nfd); + port = nfp_port_from_netdev(netdev); + if (__nfp_port_get_eth_port(port) && port->eth_stats) { + rtnl_hstat_add_grp(req, &nfp_hstat_tm); + rtnl_hstat_add_grp(req, &nfp_hstat_mac); + } + return 0; } + +void __init nfp_net_hstat_init(void) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(nfp_mac_stats_rx); i++) { + unsigned int attr; + + attr = nfp_mac_stats_rx[i].attr; + nfp_hstat_mac_rx.stats[attr / 64] |= BIT_ULL(attr % 64); + } + nfp_hstat_mac_rx.stats_cnt = ARRAY_SIZE(nfp_mac_stats_rx); + + for (i = 0; i < ARRAY_SIZE(nfp_mac_stats_tx); i++) { + unsigned int attr; + + attr = nfp_mac_stats_tx[i].attr; + nfp_hstat_mac_tx.stats[attr / 64] |= BIT_ULL(attr % 64); + } + nfp_hstat_mac_tx.stats_cnt = ARRAY_SIZE(nfp_mac_stats_tx); +} diff --git a/drivers/net/ethernet/netronome/nfp/nfp_main.c b/drivers/net/ethernet/netronome/nfp/nfp_main.c index 6c10e8d119e4..4e366fde3478 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_main.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_main.c @@ -724,6 +724,7 @@ static int __init nfp_main_init(void) nfp_driver_name); nfp_net_debugfs_create(); + nfp_net_hstat_init(); err = pci_register_driver(&nfp_pci_driver); if (err < 0) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_main.h b/drivers/net/ethernet/netronome/nfp/nfp_main.h index a3613a2e0aa5..367afb869df6 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_main.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_main.h @@ -145,6 +145,8 @@ extern struct pci_driver nfp_netvf_pci_driver; extern const struct devlink_ops nfp_devlink_ops; +void nfp_net_hstat_init(void); + int nfp_net_pci_probe(struct nfp_pf *pf); void nfp_net_pci_remove(struct nfp_pf *pf); -- 2.19.2