162306a36Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0 OR MIT) 262306a36Sopenharmony_ci/* Statistics for Ocelot switch family 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (c) 2017 Microsemi Corporation 562306a36Sopenharmony_ci * Copyright 2022 NXP 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci#include <linux/ethtool_netlink.h> 862306a36Sopenharmony_ci#include <linux/spinlock.h> 962306a36Sopenharmony_ci#include <linux/mutex.h> 1062306a36Sopenharmony_ci#include <linux/workqueue.h> 1162306a36Sopenharmony_ci#include "ocelot.h" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_cienum ocelot_stat { 1462306a36Sopenharmony_ci OCELOT_STAT_RX_OCTETS, 1562306a36Sopenharmony_ci OCELOT_STAT_RX_UNICAST, 1662306a36Sopenharmony_ci OCELOT_STAT_RX_MULTICAST, 1762306a36Sopenharmony_ci OCELOT_STAT_RX_BROADCAST, 1862306a36Sopenharmony_ci OCELOT_STAT_RX_SHORTS, 1962306a36Sopenharmony_ci OCELOT_STAT_RX_FRAGMENTS, 2062306a36Sopenharmony_ci OCELOT_STAT_RX_JABBERS, 2162306a36Sopenharmony_ci OCELOT_STAT_RX_CRC_ALIGN_ERRS, 2262306a36Sopenharmony_ci OCELOT_STAT_RX_SYM_ERRS, 2362306a36Sopenharmony_ci OCELOT_STAT_RX_64, 2462306a36Sopenharmony_ci OCELOT_STAT_RX_65_127, 2562306a36Sopenharmony_ci OCELOT_STAT_RX_128_255, 2662306a36Sopenharmony_ci OCELOT_STAT_RX_256_511, 2762306a36Sopenharmony_ci OCELOT_STAT_RX_512_1023, 2862306a36Sopenharmony_ci OCELOT_STAT_RX_1024_1526, 2962306a36Sopenharmony_ci OCELOT_STAT_RX_1527_MAX, 3062306a36Sopenharmony_ci OCELOT_STAT_RX_PAUSE, 3162306a36Sopenharmony_ci OCELOT_STAT_RX_CONTROL, 3262306a36Sopenharmony_ci OCELOT_STAT_RX_LONGS, 3362306a36Sopenharmony_ci OCELOT_STAT_RX_CLASSIFIED_DROPS, 3462306a36Sopenharmony_ci OCELOT_STAT_RX_RED_PRIO_0, 3562306a36Sopenharmony_ci OCELOT_STAT_RX_RED_PRIO_1, 3662306a36Sopenharmony_ci OCELOT_STAT_RX_RED_PRIO_2, 3762306a36Sopenharmony_ci OCELOT_STAT_RX_RED_PRIO_3, 3862306a36Sopenharmony_ci OCELOT_STAT_RX_RED_PRIO_4, 3962306a36Sopenharmony_ci OCELOT_STAT_RX_RED_PRIO_5, 4062306a36Sopenharmony_ci OCELOT_STAT_RX_RED_PRIO_6, 4162306a36Sopenharmony_ci OCELOT_STAT_RX_RED_PRIO_7, 4262306a36Sopenharmony_ci OCELOT_STAT_RX_YELLOW_PRIO_0, 4362306a36Sopenharmony_ci OCELOT_STAT_RX_YELLOW_PRIO_1, 4462306a36Sopenharmony_ci OCELOT_STAT_RX_YELLOW_PRIO_2, 4562306a36Sopenharmony_ci OCELOT_STAT_RX_YELLOW_PRIO_3, 4662306a36Sopenharmony_ci OCELOT_STAT_RX_YELLOW_PRIO_4, 4762306a36Sopenharmony_ci OCELOT_STAT_RX_YELLOW_PRIO_5, 4862306a36Sopenharmony_ci OCELOT_STAT_RX_YELLOW_PRIO_6, 4962306a36Sopenharmony_ci OCELOT_STAT_RX_YELLOW_PRIO_7, 5062306a36Sopenharmony_ci OCELOT_STAT_RX_GREEN_PRIO_0, 5162306a36Sopenharmony_ci OCELOT_STAT_RX_GREEN_PRIO_1, 5262306a36Sopenharmony_ci OCELOT_STAT_RX_GREEN_PRIO_2, 5362306a36Sopenharmony_ci OCELOT_STAT_RX_GREEN_PRIO_3, 5462306a36Sopenharmony_ci OCELOT_STAT_RX_GREEN_PRIO_4, 5562306a36Sopenharmony_ci OCELOT_STAT_RX_GREEN_PRIO_5, 5662306a36Sopenharmony_ci OCELOT_STAT_RX_GREEN_PRIO_6, 5762306a36Sopenharmony_ci OCELOT_STAT_RX_GREEN_PRIO_7, 5862306a36Sopenharmony_ci OCELOT_STAT_RX_ASSEMBLY_ERRS, 5962306a36Sopenharmony_ci OCELOT_STAT_RX_SMD_ERRS, 6062306a36Sopenharmony_ci OCELOT_STAT_RX_ASSEMBLY_OK, 6162306a36Sopenharmony_ci OCELOT_STAT_RX_MERGE_FRAGMENTS, 6262306a36Sopenharmony_ci OCELOT_STAT_RX_PMAC_OCTETS, 6362306a36Sopenharmony_ci OCELOT_STAT_RX_PMAC_UNICAST, 6462306a36Sopenharmony_ci OCELOT_STAT_RX_PMAC_MULTICAST, 6562306a36Sopenharmony_ci OCELOT_STAT_RX_PMAC_BROADCAST, 6662306a36Sopenharmony_ci OCELOT_STAT_RX_PMAC_SHORTS, 6762306a36Sopenharmony_ci OCELOT_STAT_RX_PMAC_FRAGMENTS, 6862306a36Sopenharmony_ci OCELOT_STAT_RX_PMAC_JABBERS, 6962306a36Sopenharmony_ci OCELOT_STAT_RX_PMAC_CRC_ALIGN_ERRS, 7062306a36Sopenharmony_ci OCELOT_STAT_RX_PMAC_SYM_ERRS, 7162306a36Sopenharmony_ci OCELOT_STAT_RX_PMAC_64, 7262306a36Sopenharmony_ci OCELOT_STAT_RX_PMAC_65_127, 7362306a36Sopenharmony_ci OCELOT_STAT_RX_PMAC_128_255, 7462306a36Sopenharmony_ci OCELOT_STAT_RX_PMAC_256_511, 7562306a36Sopenharmony_ci OCELOT_STAT_RX_PMAC_512_1023, 7662306a36Sopenharmony_ci OCELOT_STAT_RX_PMAC_1024_1526, 7762306a36Sopenharmony_ci OCELOT_STAT_RX_PMAC_1527_MAX, 7862306a36Sopenharmony_ci OCELOT_STAT_RX_PMAC_PAUSE, 7962306a36Sopenharmony_ci OCELOT_STAT_RX_PMAC_CONTROL, 8062306a36Sopenharmony_ci OCELOT_STAT_RX_PMAC_LONGS, 8162306a36Sopenharmony_ci OCELOT_STAT_TX_OCTETS, 8262306a36Sopenharmony_ci OCELOT_STAT_TX_UNICAST, 8362306a36Sopenharmony_ci OCELOT_STAT_TX_MULTICAST, 8462306a36Sopenharmony_ci OCELOT_STAT_TX_BROADCAST, 8562306a36Sopenharmony_ci OCELOT_STAT_TX_COLLISION, 8662306a36Sopenharmony_ci OCELOT_STAT_TX_DROPS, 8762306a36Sopenharmony_ci OCELOT_STAT_TX_PAUSE, 8862306a36Sopenharmony_ci OCELOT_STAT_TX_64, 8962306a36Sopenharmony_ci OCELOT_STAT_TX_65_127, 9062306a36Sopenharmony_ci OCELOT_STAT_TX_128_255, 9162306a36Sopenharmony_ci OCELOT_STAT_TX_256_511, 9262306a36Sopenharmony_ci OCELOT_STAT_TX_512_1023, 9362306a36Sopenharmony_ci OCELOT_STAT_TX_1024_1526, 9462306a36Sopenharmony_ci OCELOT_STAT_TX_1527_MAX, 9562306a36Sopenharmony_ci OCELOT_STAT_TX_YELLOW_PRIO_0, 9662306a36Sopenharmony_ci OCELOT_STAT_TX_YELLOW_PRIO_1, 9762306a36Sopenharmony_ci OCELOT_STAT_TX_YELLOW_PRIO_2, 9862306a36Sopenharmony_ci OCELOT_STAT_TX_YELLOW_PRIO_3, 9962306a36Sopenharmony_ci OCELOT_STAT_TX_YELLOW_PRIO_4, 10062306a36Sopenharmony_ci OCELOT_STAT_TX_YELLOW_PRIO_5, 10162306a36Sopenharmony_ci OCELOT_STAT_TX_YELLOW_PRIO_6, 10262306a36Sopenharmony_ci OCELOT_STAT_TX_YELLOW_PRIO_7, 10362306a36Sopenharmony_ci OCELOT_STAT_TX_GREEN_PRIO_0, 10462306a36Sopenharmony_ci OCELOT_STAT_TX_GREEN_PRIO_1, 10562306a36Sopenharmony_ci OCELOT_STAT_TX_GREEN_PRIO_2, 10662306a36Sopenharmony_ci OCELOT_STAT_TX_GREEN_PRIO_3, 10762306a36Sopenharmony_ci OCELOT_STAT_TX_GREEN_PRIO_4, 10862306a36Sopenharmony_ci OCELOT_STAT_TX_GREEN_PRIO_5, 10962306a36Sopenharmony_ci OCELOT_STAT_TX_GREEN_PRIO_6, 11062306a36Sopenharmony_ci OCELOT_STAT_TX_GREEN_PRIO_7, 11162306a36Sopenharmony_ci OCELOT_STAT_TX_AGED, 11262306a36Sopenharmony_ci OCELOT_STAT_TX_MM_HOLD, 11362306a36Sopenharmony_ci OCELOT_STAT_TX_MERGE_FRAGMENTS, 11462306a36Sopenharmony_ci OCELOT_STAT_TX_PMAC_OCTETS, 11562306a36Sopenharmony_ci OCELOT_STAT_TX_PMAC_UNICAST, 11662306a36Sopenharmony_ci OCELOT_STAT_TX_PMAC_MULTICAST, 11762306a36Sopenharmony_ci OCELOT_STAT_TX_PMAC_BROADCAST, 11862306a36Sopenharmony_ci OCELOT_STAT_TX_PMAC_PAUSE, 11962306a36Sopenharmony_ci OCELOT_STAT_TX_PMAC_64, 12062306a36Sopenharmony_ci OCELOT_STAT_TX_PMAC_65_127, 12162306a36Sopenharmony_ci OCELOT_STAT_TX_PMAC_128_255, 12262306a36Sopenharmony_ci OCELOT_STAT_TX_PMAC_256_511, 12362306a36Sopenharmony_ci OCELOT_STAT_TX_PMAC_512_1023, 12462306a36Sopenharmony_ci OCELOT_STAT_TX_PMAC_1024_1526, 12562306a36Sopenharmony_ci OCELOT_STAT_TX_PMAC_1527_MAX, 12662306a36Sopenharmony_ci OCELOT_STAT_DROP_LOCAL, 12762306a36Sopenharmony_ci OCELOT_STAT_DROP_TAIL, 12862306a36Sopenharmony_ci OCELOT_STAT_DROP_YELLOW_PRIO_0, 12962306a36Sopenharmony_ci OCELOT_STAT_DROP_YELLOW_PRIO_1, 13062306a36Sopenharmony_ci OCELOT_STAT_DROP_YELLOW_PRIO_2, 13162306a36Sopenharmony_ci OCELOT_STAT_DROP_YELLOW_PRIO_3, 13262306a36Sopenharmony_ci OCELOT_STAT_DROP_YELLOW_PRIO_4, 13362306a36Sopenharmony_ci OCELOT_STAT_DROP_YELLOW_PRIO_5, 13462306a36Sopenharmony_ci OCELOT_STAT_DROP_YELLOW_PRIO_6, 13562306a36Sopenharmony_ci OCELOT_STAT_DROP_YELLOW_PRIO_7, 13662306a36Sopenharmony_ci OCELOT_STAT_DROP_GREEN_PRIO_0, 13762306a36Sopenharmony_ci OCELOT_STAT_DROP_GREEN_PRIO_1, 13862306a36Sopenharmony_ci OCELOT_STAT_DROP_GREEN_PRIO_2, 13962306a36Sopenharmony_ci OCELOT_STAT_DROP_GREEN_PRIO_3, 14062306a36Sopenharmony_ci OCELOT_STAT_DROP_GREEN_PRIO_4, 14162306a36Sopenharmony_ci OCELOT_STAT_DROP_GREEN_PRIO_5, 14262306a36Sopenharmony_ci OCELOT_STAT_DROP_GREEN_PRIO_6, 14362306a36Sopenharmony_ci OCELOT_STAT_DROP_GREEN_PRIO_7, 14462306a36Sopenharmony_ci OCELOT_NUM_STATS, 14562306a36Sopenharmony_ci}; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cistruct ocelot_stat_layout { 14862306a36Sopenharmony_ci enum ocelot_reg reg; 14962306a36Sopenharmony_ci char name[ETH_GSTRING_LEN]; 15062306a36Sopenharmony_ci}; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci/* 32-bit counter checked for wraparound by ocelot_port_update_stats() 15362306a36Sopenharmony_ci * and copied to ocelot->stats. 15462306a36Sopenharmony_ci */ 15562306a36Sopenharmony_ci#define OCELOT_STAT(kind) \ 15662306a36Sopenharmony_ci [OCELOT_STAT_ ## kind] = { .reg = SYS_COUNT_ ## kind } 15762306a36Sopenharmony_ci/* Same as above, except also exported to ethtool -S. Standard counters should 15862306a36Sopenharmony_ci * only be exposed to more specific interfaces rather than by their string name. 15962306a36Sopenharmony_ci */ 16062306a36Sopenharmony_ci#define OCELOT_STAT_ETHTOOL(kind, ethtool_name) \ 16162306a36Sopenharmony_ci [OCELOT_STAT_ ## kind] = { .reg = SYS_COUNT_ ## kind, .name = ethtool_name } 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci#define OCELOT_COMMON_STATS \ 16462306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_OCTETS, "rx_octets"), \ 16562306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_UNICAST, "rx_unicast"), \ 16662306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_MULTICAST, "rx_multicast"), \ 16762306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_BROADCAST, "rx_broadcast"), \ 16862306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_SHORTS, "rx_shorts"), \ 16962306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_FRAGMENTS, "rx_fragments"), \ 17062306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_JABBERS, "rx_jabbers"), \ 17162306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_CRC_ALIGN_ERRS, "rx_crc_align_errs"), \ 17262306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_SYM_ERRS, "rx_sym_errs"), \ 17362306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_64, "rx_frames_below_65_octets"), \ 17462306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_65_127, "rx_frames_65_to_127_octets"), \ 17562306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_128_255, "rx_frames_128_to_255_octets"), \ 17662306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_256_511, "rx_frames_256_to_511_octets"), \ 17762306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_512_1023, "rx_frames_512_to_1023_octets"), \ 17862306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_1024_1526, "rx_frames_1024_to_1526_octets"), \ 17962306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_1527_MAX, "rx_frames_over_1526_octets"), \ 18062306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_PAUSE, "rx_pause"), \ 18162306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_CONTROL, "rx_control"), \ 18262306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_LONGS, "rx_longs"), \ 18362306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_CLASSIFIED_DROPS, "rx_classified_drops"), \ 18462306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_RED_PRIO_0, "rx_red_prio_0"), \ 18562306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_RED_PRIO_1, "rx_red_prio_1"), \ 18662306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_RED_PRIO_2, "rx_red_prio_2"), \ 18762306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_RED_PRIO_3, "rx_red_prio_3"), \ 18862306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_RED_PRIO_4, "rx_red_prio_4"), \ 18962306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_RED_PRIO_5, "rx_red_prio_5"), \ 19062306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_RED_PRIO_6, "rx_red_prio_6"), \ 19162306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_RED_PRIO_7, "rx_red_prio_7"), \ 19262306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_0, "rx_yellow_prio_0"), \ 19362306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_1, "rx_yellow_prio_1"), \ 19462306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_2, "rx_yellow_prio_2"), \ 19562306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_3, "rx_yellow_prio_3"), \ 19662306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_4, "rx_yellow_prio_4"), \ 19762306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_5, "rx_yellow_prio_5"), \ 19862306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_6, "rx_yellow_prio_6"), \ 19962306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_7, "rx_yellow_prio_7"), \ 20062306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_0, "rx_green_prio_0"), \ 20162306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_1, "rx_green_prio_1"), \ 20262306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_2, "rx_green_prio_2"), \ 20362306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_3, "rx_green_prio_3"), \ 20462306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_4, "rx_green_prio_4"), \ 20562306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_5, "rx_green_prio_5"), \ 20662306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_6, "rx_green_prio_6"), \ 20762306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_7, "rx_green_prio_7"), \ 20862306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(TX_OCTETS, "tx_octets"), \ 20962306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(TX_UNICAST, "tx_unicast"), \ 21062306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(TX_MULTICAST, "tx_multicast"), \ 21162306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(TX_BROADCAST, "tx_broadcast"), \ 21262306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(TX_COLLISION, "tx_collision"), \ 21362306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(TX_DROPS, "tx_drops"), \ 21462306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(TX_PAUSE, "tx_pause"), \ 21562306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(TX_64, "tx_frames_below_65_octets"), \ 21662306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(TX_65_127, "tx_frames_65_to_127_octets"), \ 21762306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(TX_128_255, "tx_frames_128_255_octets"), \ 21862306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(TX_256_511, "tx_frames_256_511_octets"), \ 21962306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(TX_512_1023, "tx_frames_512_1023_octets"), \ 22062306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(TX_1024_1526, "tx_frames_1024_1526_octets"), \ 22162306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(TX_1527_MAX, "tx_frames_over_1526_octets"), \ 22262306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_0, "tx_yellow_prio_0"), \ 22362306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_1, "tx_yellow_prio_1"), \ 22462306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_2, "tx_yellow_prio_2"), \ 22562306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_3, "tx_yellow_prio_3"), \ 22662306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_4, "tx_yellow_prio_4"), \ 22762306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_5, "tx_yellow_prio_5"), \ 22862306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_6, "tx_yellow_prio_6"), \ 22962306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_7, "tx_yellow_prio_7"), \ 23062306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_0, "tx_green_prio_0"), \ 23162306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_1, "tx_green_prio_1"), \ 23262306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_2, "tx_green_prio_2"), \ 23362306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_3, "tx_green_prio_3"), \ 23462306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_4, "tx_green_prio_4"), \ 23562306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_5, "tx_green_prio_5"), \ 23662306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_6, "tx_green_prio_6"), \ 23762306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_7, "tx_green_prio_7"), \ 23862306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(TX_AGED, "tx_aged"), \ 23962306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(DROP_LOCAL, "drop_local"), \ 24062306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(DROP_TAIL, "drop_tail"), \ 24162306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_0, "drop_yellow_prio_0"), \ 24262306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_1, "drop_yellow_prio_1"), \ 24362306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_2, "drop_yellow_prio_2"), \ 24462306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_3, "drop_yellow_prio_3"), \ 24562306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_4, "drop_yellow_prio_4"), \ 24662306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_5, "drop_yellow_prio_5"), \ 24762306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_6, "drop_yellow_prio_6"), \ 24862306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_7, "drop_yellow_prio_7"), \ 24962306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_0, "drop_green_prio_0"), \ 25062306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_1, "drop_green_prio_1"), \ 25162306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_2, "drop_green_prio_2"), \ 25262306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_3, "drop_green_prio_3"), \ 25362306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_4, "drop_green_prio_4"), \ 25462306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_5, "drop_green_prio_5"), \ 25562306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_6, "drop_green_prio_6"), \ 25662306a36Sopenharmony_ci OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_7, "drop_green_prio_7") 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_cistruct ocelot_stats_region { 25962306a36Sopenharmony_ci struct list_head node; 26062306a36Sopenharmony_ci enum ocelot_reg base; 26162306a36Sopenharmony_ci enum ocelot_stat first_stat; 26262306a36Sopenharmony_ci int count; 26362306a36Sopenharmony_ci u32 *buf; 26462306a36Sopenharmony_ci}; 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_cistatic const struct ocelot_stat_layout ocelot_stats_layout[OCELOT_NUM_STATS] = { 26762306a36Sopenharmony_ci OCELOT_COMMON_STATS, 26862306a36Sopenharmony_ci}; 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_cistatic const struct ocelot_stat_layout ocelot_mm_stats_layout[OCELOT_NUM_STATS] = { 27162306a36Sopenharmony_ci OCELOT_COMMON_STATS, 27262306a36Sopenharmony_ci OCELOT_STAT(RX_ASSEMBLY_ERRS), 27362306a36Sopenharmony_ci OCELOT_STAT(RX_SMD_ERRS), 27462306a36Sopenharmony_ci OCELOT_STAT(RX_ASSEMBLY_OK), 27562306a36Sopenharmony_ci OCELOT_STAT(RX_MERGE_FRAGMENTS), 27662306a36Sopenharmony_ci OCELOT_STAT(TX_MERGE_FRAGMENTS), 27762306a36Sopenharmony_ci OCELOT_STAT(TX_MM_HOLD), 27862306a36Sopenharmony_ci OCELOT_STAT(RX_PMAC_OCTETS), 27962306a36Sopenharmony_ci OCELOT_STAT(RX_PMAC_UNICAST), 28062306a36Sopenharmony_ci OCELOT_STAT(RX_PMAC_MULTICAST), 28162306a36Sopenharmony_ci OCELOT_STAT(RX_PMAC_BROADCAST), 28262306a36Sopenharmony_ci OCELOT_STAT(RX_PMAC_SHORTS), 28362306a36Sopenharmony_ci OCELOT_STAT(RX_PMAC_FRAGMENTS), 28462306a36Sopenharmony_ci OCELOT_STAT(RX_PMAC_JABBERS), 28562306a36Sopenharmony_ci OCELOT_STAT(RX_PMAC_CRC_ALIGN_ERRS), 28662306a36Sopenharmony_ci OCELOT_STAT(RX_PMAC_SYM_ERRS), 28762306a36Sopenharmony_ci OCELOT_STAT(RX_PMAC_64), 28862306a36Sopenharmony_ci OCELOT_STAT(RX_PMAC_65_127), 28962306a36Sopenharmony_ci OCELOT_STAT(RX_PMAC_128_255), 29062306a36Sopenharmony_ci OCELOT_STAT(RX_PMAC_256_511), 29162306a36Sopenharmony_ci OCELOT_STAT(RX_PMAC_512_1023), 29262306a36Sopenharmony_ci OCELOT_STAT(RX_PMAC_1024_1526), 29362306a36Sopenharmony_ci OCELOT_STAT(RX_PMAC_1527_MAX), 29462306a36Sopenharmony_ci OCELOT_STAT(RX_PMAC_PAUSE), 29562306a36Sopenharmony_ci OCELOT_STAT(RX_PMAC_CONTROL), 29662306a36Sopenharmony_ci OCELOT_STAT(RX_PMAC_LONGS), 29762306a36Sopenharmony_ci OCELOT_STAT(TX_PMAC_OCTETS), 29862306a36Sopenharmony_ci OCELOT_STAT(TX_PMAC_UNICAST), 29962306a36Sopenharmony_ci OCELOT_STAT(TX_PMAC_MULTICAST), 30062306a36Sopenharmony_ci OCELOT_STAT(TX_PMAC_BROADCAST), 30162306a36Sopenharmony_ci OCELOT_STAT(TX_PMAC_PAUSE), 30262306a36Sopenharmony_ci OCELOT_STAT(TX_PMAC_64), 30362306a36Sopenharmony_ci OCELOT_STAT(TX_PMAC_65_127), 30462306a36Sopenharmony_ci OCELOT_STAT(TX_PMAC_128_255), 30562306a36Sopenharmony_ci OCELOT_STAT(TX_PMAC_256_511), 30662306a36Sopenharmony_ci OCELOT_STAT(TX_PMAC_512_1023), 30762306a36Sopenharmony_ci OCELOT_STAT(TX_PMAC_1024_1526), 30862306a36Sopenharmony_ci OCELOT_STAT(TX_PMAC_1527_MAX), 30962306a36Sopenharmony_ci}; 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_cistatic const struct ocelot_stat_layout * 31262306a36Sopenharmony_ciocelot_get_stats_layout(struct ocelot *ocelot) 31362306a36Sopenharmony_ci{ 31462306a36Sopenharmony_ci if (ocelot->mm_supported) 31562306a36Sopenharmony_ci return ocelot_mm_stats_layout; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci return ocelot_stats_layout; 31862306a36Sopenharmony_ci} 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci/* Read the counters from hardware and keep them in region->buf. 32162306a36Sopenharmony_ci * Caller must hold &ocelot->stat_view_lock. 32262306a36Sopenharmony_ci */ 32362306a36Sopenharmony_cistatic int ocelot_port_update_stats(struct ocelot *ocelot, int port) 32462306a36Sopenharmony_ci{ 32562306a36Sopenharmony_ci struct ocelot_stats_region *region; 32662306a36Sopenharmony_ci int err; 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci /* Configure the port to read the stats from */ 32962306a36Sopenharmony_ci ocelot_write(ocelot, SYS_STAT_CFG_STAT_VIEW(port), SYS_STAT_CFG); 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci list_for_each_entry(region, &ocelot->stats_regions, node) { 33262306a36Sopenharmony_ci err = ocelot_bulk_read(ocelot, region->base, region->buf, 33362306a36Sopenharmony_ci region->count); 33462306a36Sopenharmony_ci if (err) 33562306a36Sopenharmony_ci return err; 33662306a36Sopenharmony_ci } 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci return 0; 33962306a36Sopenharmony_ci} 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci/* Transfer the counters from region->buf to ocelot->stats. 34262306a36Sopenharmony_ci * Caller must hold &ocelot->stat_view_lock and &ocelot->stats_lock. 34362306a36Sopenharmony_ci */ 34462306a36Sopenharmony_cistatic void ocelot_port_transfer_stats(struct ocelot *ocelot, int port) 34562306a36Sopenharmony_ci{ 34662306a36Sopenharmony_ci struct ocelot_stats_region *region; 34762306a36Sopenharmony_ci int j; 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci list_for_each_entry(region, &ocelot->stats_regions, node) { 35062306a36Sopenharmony_ci unsigned int idx = port * OCELOT_NUM_STATS + region->first_stat; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci for (j = 0; j < region->count; j++) { 35362306a36Sopenharmony_ci u64 *stat = &ocelot->stats[idx + j]; 35462306a36Sopenharmony_ci u64 val = region->buf[j]; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci if (val < (*stat & U32_MAX)) 35762306a36Sopenharmony_ci *stat += (u64)1 << 32; 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci *stat = (*stat & ~(u64)U32_MAX) + val; 36062306a36Sopenharmony_ci } 36162306a36Sopenharmony_ci } 36262306a36Sopenharmony_ci} 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_cistatic void ocelot_check_stats_work(struct work_struct *work) 36562306a36Sopenharmony_ci{ 36662306a36Sopenharmony_ci struct delayed_work *del_work = to_delayed_work(work); 36762306a36Sopenharmony_ci struct ocelot *ocelot = container_of(del_work, struct ocelot, 36862306a36Sopenharmony_ci stats_work); 36962306a36Sopenharmony_ci int port, err; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci mutex_lock(&ocelot->stat_view_lock); 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci for (port = 0; port < ocelot->num_phys_ports; port++) { 37462306a36Sopenharmony_ci err = ocelot_port_update_stats(ocelot, port); 37562306a36Sopenharmony_ci if (err) 37662306a36Sopenharmony_ci break; 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci spin_lock(&ocelot->stats_lock); 37962306a36Sopenharmony_ci ocelot_port_transfer_stats(ocelot, port); 38062306a36Sopenharmony_ci spin_unlock(&ocelot->stats_lock); 38162306a36Sopenharmony_ci } 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci if (!err && ocelot->ops->update_stats) 38462306a36Sopenharmony_ci ocelot->ops->update_stats(ocelot); 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci mutex_unlock(&ocelot->stat_view_lock); 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci if (err) 38962306a36Sopenharmony_ci dev_err(ocelot->dev, "Error %d updating ethtool stats\n", err); 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci queue_delayed_work(ocelot->stats_queue, &ocelot->stats_work, 39262306a36Sopenharmony_ci OCELOT_STATS_CHECK_DELAY); 39362306a36Sopenharmony_ci} 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_civoid ocelot_get_strings(struct ocelot *ocelot, int port, u32 sset, u8 *data) 39662306a36Sopenharmony_ci{ 39762306a36Sopenharmony_ci const struct ocelot_stat_layout *layout; 39862306a36Sopenharmony_ci enum ocelot_stat i; 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci if (sset != ETH_SS_STATS) 40162306a36Sopenharmony_ci return; 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci layout = ocelot_get_stats_layout(ocelot); 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci for (i = 0; i < OCELOT_NUM_STATS; i++) { 40662306a36Sopenharmony_ci if (layout[i].name[0] == '\0') 40762306a36Sopenharmony_ci continue; 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci memcpy(data, layout[i].name, ETH_GSTRING_LEN); 41062306a36Sopenharmony_ci data += ETH_GSTRING_LEN; 41162306a36Sopenharmony_ci } 41262306a36Sopenharmony_ci} 41362306a36Sopenharmony_ciEXPORT_SYMBOL(ocelot_get_strings); 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci/* Update ocelot->stats for the given port and run the given callback */ 41662306a36Sopenharmony_cistatic void ocelot_port_stats_run(struct ocelot *ocelot, int port, void *priv, 41762306a36Sopenharmony_ci void (*cb)(struct ocelot *ocelot, int port, 41862306a36Sopenharmony_ci void *priv)) 41962306a36Sopenharmony_ci{ 42062306a36Sopenharmony_ci int err; 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci mutex_lock(&ocelot->stat_view_lock); 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci err = ocelot_port_update_stats(ocelot, port); 42562306a36Sopenharmony_ci if (err) { 42662306a36Sopenharmony_ci dev_err(ocelot->dev, "Failed to update port %d stats: %pe\n", 42762306a36Sopenharmony_ci port, ERR_PTR(err)); 42862306a36Sopenharmony_ci goto out_unlock; 42962306a36Sopenharmony_ci } 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci spin_lock(&ocelot->stats_lock); 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci ocelot_port_transfer_stats(ocelot, port); 43462306a36Sopenharmony_ci cb(ocelot, port, priv); 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci spin_unlock(&ocelot->stats_lock); 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ciout_unlock: 43962306a36Sopenharmony_ci mutex_unlock(&ocelot->stat_view_lock); 44062306a36Sopenharmony_ci} 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ciint ocelot_get_sset_count(struct ocelot *ocelot, int port, int sset) 44362306a36Sopenharmony_ci{ 44462306a36Sopenharmony_ci const struct ocelot_stat_layout *layout; 44562306a36Sopenharmony_ci enum ocelot_stat i; 44662306a36Sopenharmony_ci int num_stats = 0; 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci if (sset != ETH_SS_STATS) 44962306a36Sopenharmony_ci return -EOPNOTSUPP; 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci layout = ocelot_get_stats_layout(ocelot); 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci for (i = 0; i < OCELOT_NUM_STATS; i++) 45462306a36Sopenharmony_ci if (layout[i].name[0] != '\0') 45562306a36Sopenharmony_ci num_stats++; 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci return num_stats; 45862306a36Sopenharmony_ci} 45962306a36Sopenharmony_ciEXPORT_SYMBOL(ocelot_get_sset_count); 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_cistatic void ocelot_port_ethtool_stats_cb(struct ocelot *ocelot, int port, 46262306a36Sopenharmony_ci void *priv) 46362306a36Sopenharmony_ci{ 46462306a36Sopenharmony_ci const struct ocelot_stat_layout *layout; 46562306a36Sopenharmony_ci enum ocelot_stat i; 46662306a36Sopenharmony_ci u64 *data = priv; 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci layout = ocelot_get_stats_layout(ocelot); 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci /* Copy all supported counters */ 47162306a36Sopenharmony_ci for (i = 0; i < OCELOT_NUM_STATS; i++) { 47262306a36Sopenharmony_ci int index = port * OCELOT_NUM_STATS + i; 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci if (layout[i].name[0] == '\0') 47562306a36Sopenharmony_ci continue; 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci *data++ = ocelot->stats[index]; 47862306a36Sopenharmony_ci } 47962306a36Sopenharmony_ci} 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_civoid ocelot_get_ethtool_stats(struct ocelot *ocelot, int port, u64 *data) 48262306a36Sopenharmony_ci{ 48362306a36Sopenharmony_ci ocelot_port_stats_run(ocelot, port, data, ocelot_port_ethtool_stats_cb); 48462306a36Sopenharmony_ci} 48562306a36Sopenharmony_ciEXPORT_SYMBOL(ocelot_get_ethtool_stats); 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_cistatic void ocelot_port_pause_stats_cb(struct ocelot *ocelot, int port, void *priv) 48862306a36Sopenharmony_ci{ 48962306a36Sopenharmony_ci u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS]; 49062306a36Sopenharmony_ci struct ethtool_pause_stats *pause_stats = priv; 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci pause_stats->tx_pause_frames = s[OCELOT_STAT_TX_PAUSE]; 49362306a36Sopenharmony_ci pause_stats->rx_pause_frames = s[OCELOT_STAT_RX_PAUSE]; 49462306a36Sopenharmony_ci} 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_cistatic void ocelot_port_pmac_pause_stats_cb(struct ocelot *ocelot, int port, 49762306a36Sopenharmony_ci void *priv) 49862306a36Sopenharmony_ci{ 49962306a36Sopenharmony_ci u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS]; 50062306a36Sopenharmony_ci struct ethtool_pause_stats *pause_stats = priv; 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci pause_stats->tx_pause_frames = s[OCELOT_STAT_TX_PMAC_PAUSE]; 50362306a36Sopenharmony_ci pause_stats->rx_pause_frames = s[OCELOT_STAT_RX_PMAC_PAUSE]; 50462306a36Sopenharmony_ci} 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_cistatic void ocelot_port_mm_stats_cb(struct ocelot *ocelot, int port, 50762306a36Sopenharmony_ci void *priv) 50862306a36Sopenharmony_ci{ 50962306a36Sopenharmony_ci u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS]; 51062306a36Sopenharmony_ci struct ethtool_mm_stats *stats = priv; 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci stats->MACMergeFrameAssErrorCount = s[OCELOT_STAT_RX_ASSEMBLY_ERRS]; 51362306a36Sopenharmony_ci stats->MACMergeFrameSmdErrorCount = s[OCELOT_STAT_RX_SMD_ERRS]; 51462306a36Sopenharmony_ci stats->MACMergeFrameAssOkCount = s[OCELOT_STAT_RX_ASSEMBLY_OK]; 51562306a36Sopenharmony_ci stats->MACMergeFragCountRx = s[OCELOT_STAT_RX_MERGE_FRAGMENTS]; 51662306a36Sopenharmony_ci stats->MACMergeFragCountTx = s[OCELOT_STAT_TX_MERGE_FRAGMENTS]; 51762306a36Sopenharmony_ci stats->MACMergeHoldCount = s[OCELOT_STAT_TX_MM_HOLD]; 51862306a36Sopenharmony_ci} 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_civoid ocelot_port_get_pause_stats(struct ocelot *ocelot, int port, 52162306a36Sopenharmony_ci struct ethtool_pause_stats *pause_stats) 52262306a36Sopenharmony_ci{ 52362306a36Sopenharmony_ci struct net_device *dev; 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci switch (pause_stats->src) { 52662306a36Sopenharmony_ci case ETHTOOL_MAC_STATS_SRC_EMAC: 52762306a36Sopenharmony_ci ocelot_port_stats_run(ocelot, port, pause_stats, 52862306a36Sopenharmony_ci ocelot_port_pause_stats_cb); 52962306a36Sopenharmony_ci break; 53062306a36Sopenharmony_ci case ETHTOOL_MAC_STATS_SRC_PMAC: 53162306a36Sopenharmony_ci if (ocelot->mm_supported) 53262306a36Sopenharmony_ci ocelot_port_stats_run(ocelot, port, pause_stats, 53362306a36Sopenharmony_ci ocelot_port_pmac_pause_stats_cb); 53462306a36Sopenharmony_ci break; 53562306a36Sopenharmony_ci case ETHTOOL_MAC_STATS_SRC_AGGREGATE: 53662306a36Sopenharmony_ci dev = ocelot->ops->port_to_netdev(ocelot, port); 53762306a36Sopenharmony_ci ethtool_aggregate_pause_stats(dev, pause_stats); 53862306a36Sopenharmony_ci break; 53962306a36Sopenharmony_ci } 54062306a36Sopenharmony_ci} 54162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ocelot_port_get_pause_stats); 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_civoid ocelot_port_get_mm_stats(struct ocelot *ocelot, int port, 54462306a36Sopenharmony_ci struct ethtool_mm_stats *stats) 54562306a36Sopenharmony_ci{ 54662306a36Sopenharmony_ci if (!ocelot->mm_supported) 54762306a36Sopenharmony_ci return; 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci ocelot_port_stats_run(ocelot, port, stats, ocelot_port_mm_stats_cb); 55062306a36Sopenharmony_ci} 55162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ocelot_port_get_mm_stats); 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_cistatic const struct ethtool_rmon_hist_range ocelot_rmon_ranges[] = { 55462306a36Sopenharmony_ci { 64, 64 }, 55562306a36Sopenharmony_ci { 65, 127 }, 55662306a36Sopenharmony_ci { 128, 255 }, 55762306a36Sopenharmony_ci { 256, 511 }, 55862306a36Sopenharmony_ci { 512, 1023 }, 55962306a36Sopenharmony_ci { 1024, 1526 }, 56062306a36Sopenharmony_ci { 1527, 65535 }, 56162306a36Sopenharmony_ci {}, 56262306a36Sopenharmony_ci}; 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_cistatic void ocelot_port_rmon_stats_cb(struct ocelot *ocelot, int port, void *priv) 56562306a36Sopenharmony_ci{ 56662306a36Sopenharmony_ci u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS]; 56762306a36Sopenharmony_ci struct ethtool_rmon_stats *rmon_stats = priv; 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci rmon_stats->undersize_pkts = s[OCELOT_STAT_RX_SHORTS]; 57062306a36Sopenharmony_ci rmon_stats->oversize_pkts = s[OCELOT_STAT_RX_LONGS]; 57162306a36Sopenharmony_ci rmon_stats->fragments = s[OCELOT_STAT_RX_FRAGMENTS]; 57262306a36Sopenharmony_ci rmon_stats->jabbers = s[OCELOT_STAT_RX_JABBERS]; 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci rmon_stats->hist[0] = s[OCELOT_STAT_RX_64]; 57562306a36Sopenharmony_ci rmon_stats->hist[1] = s[OCELOT_STAT_RX_65_127]; 57662306a36Sopenharmony_ci rmon_stats->hist[2] = s[OCELOT_STAT_RX_128_255]; 57762306a36Sopenharmony_ci rmon_stats->hist[3] = s[OCELOT_STAT_RX_256_511]; 57862306a36Sopenharmony_ci rmon_stats->hist[4] = s[OCELOT_STAT_RX_512_1023]; 57962306a36Sopenharmony_ci rmon_stats->hist[5] = s[OCELOT_STAT_RX_1024_1526]; 58062306a36Sopenharmony_ci rmon_stats->hist[6] = s[OCELOT_STAT_RX_1527_MAX]; 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci rmon_stats->hist_tx[0] = s[OCELOT_STAT_TX_64]; 58362306a36Sopenharmony_ci rmon_stats->hist_tx[1] = s[OCELOT_STAT_TX_65_127]; 58462306a36Sopenharmony_ci rmon_stats->hist_tx[2] = s[OCELOT_STAT_TX_128_255]; 58562306a36Sopenharmony_ci rmon_stats->hist_tx[3] = s[OCELOT_STAT_TX_256_511]; 58662306a36Sopenharmony_ci rmon_stats->hist_tx[4] = s[OCELOT_STAT_TX_512_1023]; 58762306a36Sopenharmony_ci rmon_stats->hist_tx[5] = s[OCELOT_STAT_TX_1024_1526]; 58862306a36Sopenharmony_ci rmon_stats->hist_tx[6] = s[OCELOT_STAT_TX_1527_MAX]; 58962306a36Sopenharmony_ci} 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_cistatic void ocelot_port_pmac_rmon_stats_cb(struct ocelot *ocelot, int port, 59262306a36Sopenharmony_ci void *priv) 59362306a36Sopenharmony_ci{ 59462306a36Sopenharmony_ci u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS]; 59562306a36Sopenharmony_ci struct ethtool_rmon_stats *rmon_stats = priv; 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci rmon_stats->undersize_pkts = s[OCELOT_STAT_RX_PMAC_SHORTS]; 59862306a36Sopenharmony_ci rmon_stats->oversize_pkts = s[OCELOT_STAT_RX_PMAC_LONGS]; 59962306a36Sopenharmony_ci rmon_stats->fragments = s[OCELOT_STAT_RX_PMAC_FRAGMENTS]; 60062306a36Sopenharmony_ci rmon_stats->jabbers = s[OCELOT_STAT_RX_PMAC_JABBERS]; 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci rmon_stats->hist[0] = s[OCELOT_STAT_RX_PMAC_64]; 60362306a36Sopenharmony_ci rmon_stats->hist[1] = s[OCELOT_STAT_RX_PMAC_65_127]; 60462306a36Sopenharmony_ci rmon_stats->hist[2] = s[OCELOT_STAT_RX_PMAC_128_255]; 60562306a36Sopenharmony_ci rmon_stats->hist[3] = s[OCELOT_STAT_RX_PMAC_256_511]; 60662306a36Sopenharmony_ci rmon_stats->hist[4] = s[OCELOT_STAT_RX_PMAC_512_1023]; 60762306a36Sopenharmony_ci rmon_stats->hist[5] = s[OCELOT_STAT_RX_PMAC_1024_1526]; 60862306a36Sopenharmony_ci rmon_stats->hist[6] = s[OCELOT_STAT_RX_PMAC_1527_MAX]; 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci rmon_stats->hist_tx[0] = s[OCELOT_STAT_TX_PMAC_64]; 61162306a36Sopenharmony_ci rmon_stats->hist_tx[1] = s[OCELOT_STAT_TX_PMAC_65_127]; 61262306a36Sopenharmony_ci rmon_stats->hist_tx[2] = s[OCELOT_STAT_TX_PMAC_128_255]; 61362306a36Sopenharmony_ci rmon_stats->hist_tx[3] = s[OCELOT_STAT_TX_PMAC_256_511]; 61462306a36Sopenharmony_ci rmon_stats->hist_tx[4] = s[OCELOT_STAT_TX_PMAC_512_1023]; 61562306a36Sopenharmony_ci rmon_stats->hist_tx[5] = s[OCELOT_STAT_TX_PMAC_1024_1526]; 61662306a36Sopenharmony_ci rmon_stats->hist_tx[6] = s[OCELOT_STAT_TX_PMAC_1527_MAX]; 61762306a36Sopenharmony_ci} 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_civoid ocelot_port_get_rmon_stats(struct ocelot *ocelot, int port, 62062306a36Sopenharmony_ci struct ethtool_rmon_stats *rmon_stats, 62162306a36Sopenharmony_ci const struct ethtool_rmon_hist_range **ranges) 62262306a36Sopenharmony_ci{ 62362306a36Sopenharmony_ci struct net_device *dev; 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci *ranges = ocelot_rmon_ranges; 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci switch (rmon_stats->src) { 62862306a36Sopenharmony_ci case ETHTOOL_MAC_STATS_SRC_EMAC: 62962306a36Sopenharmony_ci ocelot_port_stats_run(ocelot, port, rmon_stats, 63062306a36Sopenharmony_ci ocelot_port_rmon_stats_cb); 63162306a36Sopenharmony_ci break; 63262306a36Sopenharmony_ci case ETHTOOL_MAC_STATS_SRC_PMAC: 63362306a36Sopenharmony_ci if (ocelot->mm_supported) 63462306a36Sopenharmony_ci ocelot_port_stats_run(ocelot, port, rmon_stats, 63562306a36Sopenharmony_ci ocelot_port_pmac_rmon_stats_cb); 63662306a36Sopenharmony_ci break; 63762306a36Sopenharmony_ci case ETHTOOL_MAC_STATS_SRC_AGGREGATE: 63862306a36Sopenharmony_ci dev = ocelot->ops->port_to_netdev(ocelot, port); 63962306a36Sopenharmony_ci ethtool_aggregate_rmon_stats(dev, rmon_stats); 64062306a36Sopenharmony_ci break; 64162306a36Sopenharmony_ci } 64262306a36Sopenharmony_ci} 64362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ocelot_port_get_rmon_stats); 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_cistatic void ocelot_port_ctrl_stats_cb(struct ocelot *ocelot, int port, void *priv) 64662306a36Sopenharmony_ci{ 64762306a36Sopenharmony_ci u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS]; 64862306a36Sopenharmony_ci struct ethtool_eth_ctrl_stats *ctrl_stats = priv; 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci ctrl_stats->MACControlFramesReceived = s[OCELOT_STAT_RX_CONTROL]; 65162306a36Sopenharmony_ci} 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_cistatic void ocelot_port_pmac_ctrl_stats_cb(struct ocelot *ocelot, int port, 65462306a36Sopenharmony_ci void *priv) 65562306a36Sopenharmony_ci{ 65662306a36Sopenharmony_ci u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS]; 65762306a36Sopenharmony_ci struct ethtool_eth_ctrl_stats *ctrl_stats = priv; 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_ci ctrl_stats->MACControlFramesReceived = s[OCELOT_STAT_RX_PMAC_CONTROL]; 66062306a36Sopenharmony_ci} 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_civoid ocelot_port_get_eth_ctrl_stats(struct ocelot *ocelot, int port, 66362306a36Sopenharmony_ci struct ethtool_eth_ctrl_stats *ctrl_stats) 66462306a36Sopenharmony_ci{ 66562306a36Sopenharmony_ci struct net_device *dev; 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci switch (ctrl_stats->src) { 66862306a36Sopenharmony_ci case ETHTOOL_MAC_STATS_SRC_EMAC: 66962306a36Sopenharmony_ci ocelot_port_stats_run(ocelot, port, ctrl_stats, 67062306a36Sopenharmony_ci ocelot_port_ctrl_stats_cb); 67162306a36Sopenharmony_ci break; 67262306a36Sopenharmony_ci case ETHTOOL_MAC_STATS_SRC_PMAC: 67362306a36Sopenharmony_ci if (ocelot->mm_supported) 67462306a36Sopenharmony_ci ocelot_port_stats_run(ocelot, port, ctrl_stats, 67562306a36Sopenharmony_ci ocelot_port_pmac_ctrl_stats_cb); 67662306a36Sopenharmony_ci break; 67762306a36Sopenharmony_ci case ETHTOOL_MAC_STATS_SRC_AGGREGATE: 67862306a36Sopenharmony_ci dev = ocelot->ops->port_to_netdev(ocelot, port); 67962306a36Sopenharmony_ci ethtool_aggregate_ctrl_stats(dev, ctrl_stats); 68062306a36Sopenharmony_ci break; 68162306a36Sopenharmony_ci } 68262306a36Sopenharmony_ci} 68362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ocelot_port_get_eth_ctrl_stats); 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_cistatic void ocelot_port_mac_stats_cb(struct ocelot *ocelot, int port, void *priv) 68662306a36Sopenharmony_ci{ 68762306a36Sopenharmony_ci u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS]; 68862306a36Sopenharmony_ci struct ethtool_eth_mac_stats *mac_stats = priv; 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci mac_stats->OctetsTransmittedOK = s[OCELOT_STAT_TX_OCTETS]; 69162306a36Sopenharmony_ci mac_stats->FramesTransmittedOK = s[OCELOT_STAT_TX_64] + 69262306a36Sopenharmony_ci s[OCELOT_STAT_TX_65_127] + 69362306a36Sopenharmony_ci s[OCELOT_STAT_TX_128_255] + 69462306a36Sopenharmony_ci s[OCELOT_STAT_TX_256_511] + 69562306a36Sopenharmony_ci s[OCELOT_STAT_TX_512_1023] + 69662306a36Sopenharmony_ci s[OCELOT_STAT_TX_1024_1526] + 69762306a36Sopenharmony_ci s[OCELOT_STAT_TX_1527_MAX]; 69862306a36Sopenharmony_ci mac_stats->OctetsReceivedOK = s[OCELOT_STAT_RX_OCTETS]; 69962306a36Sopenharmony_ci mac_stats->FramesReceivedOK = s[OCELOT_STAT_RX_GREEN_PRIO_0] + 70062306a36Sopenharmony_ci s[OCELOT_STAT_RX_GREEN_PRIO_1] + 70162306a36Sopenharmony_ci s[OCELOT_STAT_RX_GREEN_PRIO_2] + 70262306a36Sopenharmony_ci s[OCELOT_STAT_RX_GREEN_PRIO_3] + 70362306a36Sopenharmony_ci s[OCELOT_STAT_RX_GREEN_PRIO_4] + 70462306a36Sopenharmony_ci s[OCELOT_STAT_RX_GREEN_PRIO_5] + 70562306a36Sopenharmony_ci s[OCELOT_STAT_RX_GREEN_PRIO_6] + 70662306a36Sopenharmony_ci s[OCELOT_STAT_RX_GREEN_PRIO_7] + 70762306a36Sopenharmony_ci s[OCELOT_STAT_RX_YELLOW_PRIO_0] + 70862306a36Sopenharmony_ci s[OCELOT_STAT_RX_YELLOW_PRIO_1] + 70962306a36Sopenharmony_ci s[OCELOT_STAT_RX_YELLOW_PRIO_2] + 71062306a36Sopenharmony_ci s[OCELOT_STAT_RX_YELLOW_PRIO_3] + 71162306a36Sopenharmony_ci s[OCELOT_STAT_RX_YELLOW_PRIO_4] + 71262306a36Sopenharmony_ci s[OCELOT_STAT_RX_YELLOW_PRIO_5] + 71362306a36Sopenharmony_ci s[OCELOT_STAT_RX_YELLOW_PRIO_6] + 71462306a36Sopenharmony_ci s[OCELOT_STAT_RX_YELLOW_PRIO_7]; 71562306a36Sopenharmony_ci mac_stats->MulticastFramesXmittedOK = s[OCELOT_STAT_TX_MULTICAST]; 71662306a36Sopenharmony_ci mac_stats->BroadcastFramesXmittedOK = s[OCELOT_STAT_TX_BROADCAST]; 71762306a36Sopenharmony_ci mac_stats->MulticastFramesReceivedOK = s[OCELOT_STAT_RX_MULTICAST]; 71862306a36Sopenharmony_ci mac_stats->BroadcastFramesReceivedOK = s[OCELOT_STAT_RX_BROADCAST]; 71962306a36Sopenharmony_ci mac_stats->FrameTooLongErrors = s[OCELOT_STAT_RX_LONGS]; 72062306a36Sopenharmony_ci /* Sadly, C_RX_CRC is the sum of FCS and alignment errors, they are not 72162306a36Sopenharmony_ci * counted individually. 72262306a36Sopenharmony_ci */ 72362306a36Sopenharmony_ci mac_stats->FrameCheckSequenceErrors = s[OCELOT_STAT_RX_CRC_ALIGN_ERRS]; 72462306a36Sopenharmony_ci mac_stats->AlignmentErrors = s[OCELOT_STAT_RX_CRC_ALIGN_ERRS]; 72562306a36Sopenharmony_ci} 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_cistatic void ocelot_port_pmac_mac_stats_cb(struct ocelot *ocelot, int port, 72862306a36Sopenharmony_ci void *priv) 72962306a36Sopenharmony_ci{ 73062306a36Sopenharmony_ci u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS]; 73162306a36Sopenharmony_ci struct ethtool_eth_mac_stats *mac_stats = priv; 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci mac_stats->OctetsTransmittedOK = s[OCELOT_STAT_TX_PMAC_OCTETS]; 73462306a36Sopenharmony_ci mac_stats->FramesTransmittedOK = s[OCELOT_STAT_TX_PMAC_64] + 73562306a36Sopenharmony_ci s[OCELOT_STAT_TX_PMAC_65_127] + 73662306a36Sopenharmony_ci s[OCELOT_STAT_TX_PMAC_128_255] + 73762306a36Sopenharmony_ci s[OCELOT_STAT_TX_PMAC_256_511] + 73862306a36Sopenharmony_ci s[OCELOT_STAT_TX_PMAC_512_1023] + 73962306a36Sopenharmony_ci s[OCELOT_STAT_TX_PMAC_1024_1526] + 74062306a36Sopenharmony_ci s[OCELOT_STAT_TX_PMAC_1527_MAX]; 74162306a36Sopenharmony_ci mac_stats->OctetsReceivedOK = s[OCELOT_STAT_RX_PMAC_OCTETS]; 74262306a36Sopenharmony_ci mac_stats->FramesReceivedOK = s[OCELOT_STAT_RX_PMAC_64] + 74362306a36Sopenharmony_ci s[OCELOT_STAT_RX_PMAC_65_127] + 74462306a36Sopenharmony_ci s[OCELOT_STAT_RX_PMAC_128_255] + 74562306a36Sopenharmony_ci s[OCELOT_STAT_RX_PMAC_256_511] + 74662306a36Sopenharmony_ci s[OCELOT_STAT_RX_PMAC_512_1023] + 74762306a36Sopenharmony_ci s[OCELOT_STAT_RX_PMAC_1024_1526] + 74862306a36Sopenharmony_ci s[OCELOT_STAT_RX_PMAC_1527_MAX]; 74962306a36Sopenharmony_ci mac_stats->MulticastFramesXmittedOK = s[OCELOT_STAT_TX_PMAC_MULTICAST]; 75062306a36Sopenharmony_ci mac_stats->BroadcastFramesXmittedOK = s[OCELOT_STAT_TX_PMAC_BROADCAST]; 75162306a36Sopenharmony_ci mac_stats->MulticastFramesReceivedOK = s[OCELOT_STAT_RX_PMAC_MULTICAST]; 75262306a36Sopenharmony_ci mac_stats->BroadcastFramesReceivedOK = s[OCELOT_STAT_RX_PMAC_BROADCAST]; 75362306a36Sopenharmony_ci mac_stats->FrameTooLongErrors = s[OCELOT_STAT_RX_PMAC_LONGS]; 75462306a36Sopenharmony_ci /* Sadly, C_RX_CRC is the sum of FCS and alignment errors, they are not 75562306a36Sopenharmony_ci * counted individually. 75662306a36Sopenharmony_ci */ 75762306a36Sopenharmony_ci mac_stats->FrameCheckSequenceErrors = s[OCELOT_STAT_RX_PMAC_CRC_ALIGN_ERRS]; 75862306a36Sopenharmony_ci mac_stats->AlignmentErrors = s[OCELOT_STAT_RX_PMAC_CRC_ALIGN_ERRS]; 75962306a36Sopenharmony_ci} 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_civoid ocelot_port_get_eth_mac_stats(struct ocelot *ocelot, int port, 76262306a36Sopenharmony_ci struct ethtool_eth_mac_stats *mac_stats) 76362306a36Sopenharmony_ci{ 76462306a36Sopenharmony_ci struct net_device *dev; 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_ci switch (mac_stats->src) { 76762306a36Sopenharmony_ci case ETHTOOL_MAC_STATS_SRC_EMAC: 76862306a36Sopenharmony_ci ocelot_port_stats_run(ocelot, port, mac_stats, 76962306a36Sopenharmony_ci ocelot_port_mac_stats_cb); 77062306a36Sopenharmony_ci break; 77162306a36Sopenharmony_ci case ETHTOOL_MAC_STATS_SRC_PMAC: 77262306a36Sopenharmony_ci if (ocelot->mm_supported) 77362306a36Sopenharmony_ci ocelot_port_stats_run(ocelot, port, mac_stats, 77462306a36Sopenharmony_ci ocelot_port_pmac_mac_stats_cb); 77562306a36Sopenharmony_ci break; 77662306a36Sopenharmony_ci case ETHTOOL_MAC_STATS_SRC_AGGREGATE: 77762306a36Sopenharmony_ci dev = ocelot->ops->port_to_netdev(ocelot, port); 77862306a36Sopenharmony_ci ethtool_aggregate_mac_stats(dev, mac_stats); 77962306a36Sopenharmony_ci break; 78062306a36Sopenharmony_ci } 78162306a36Sopenharmony_ci} 78262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ocelot_port_get_eth_mac_stats); 78362306a36Sopenharmony_ci 78462306a36Sopenharmony_cistatic void ocelot_port_phy_stats_cb(struct ocelot *ocelot, int port, void *priv) 78562306a36Sopenharmony_ci{ 78662306a36Sopenharmony_ci u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS]; 78762306a36Sopenharmony_ci struct ethtool_eth_phy_stats *phy_stats = priv; 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci phy_stats->SymbolErrorDuringCarrier = s[OCELOT_STAT_RX_SYM_ERRS]; 79062306a36Sopenharmony_ci} 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_cistatic void ocelot_port_pmac_phy_stats_cb(struct ocelot *ocelot, int port, 79362306a36Sopenharmony_ci void *priv) 79462306a36Sopenharmony_ci{ 79562306a36Sopenharmony_ci u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS]; 79662306a36Sopenharmony_ci struct ethtool_eth_phy_stats *phy_stats = priv; 79762306a36Sopenharmony_ci 79862306a36Sopenharmony_ci phy_stats->SymbolErrorDuringCarrier = s[OCELOT_STAT_RX_PMAC_SYM_ERRS]; 79962306a36Sopenharmony_ci} 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_civoid ocelot_port_get_eth_phy_stats(struct ocelot *ocelot, int port, 80262306a36Sopenharmony_ci struct ethtool_eth_phy_stats *phy_stats) 80362306a36Sopenharmony_ci{ 80462306a36Sopenharmony_ci struct net_device *dev; 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci switch (phy_stats->src) { 80762306a36Sopenharmony_ci case ETHTOOL_MAC_STATS_SRC_EMAC: 80862306a36Sopenharmony_ci ocelot_port_stats_run(ocelot, port, phy_stats, 80962306a36Sopenharmony_ci ocelot_port_phy_stats_cb); 81062306a36Sopenharmony_ci break; 81162306a36Sopenharmony_ci case ETHTOOL_MAC_STATS_SRC_PMAC: 81262306a36Sopenharmony_ci if (ocelot->mm_supported) 81362306a36Sopenharmony_ci ocelot_port_stats_run(ocelot, port, phy_stats, 81462306a36Sopenharmony_ci ocelot_port_pmac_phy_stats_cb); 81562306a36Sopenharmony_ci break; 81662306a36Sopenharmony_ci case ETHTOOL_MAC_STATS_SRC_AGGREGATE: 81762306a36Sopenharmony_ci dev = ocelot->ops->port_to_netdev(ocelot, port); 81862306a36Sopenharmony_ci ethtool_aggregate_phy_stats(dev, phy_stats); 81962306a36Sopenharmony_ci break; 82062306a36Sopenharmony_ci } 82162306a36Sopenharmony_ci} 82262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ocelot_port_get_eth_phy_stats); 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_civoid ocelot_port_get_stats64(struct ocelot *ocelot, int port, 82562306a36Sopenharmony_ci struct rtnl_link_stats64 *stats) 82662306a36Sopenharmony_ci{ 82762306a36Sopenharmony_ci u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS]; 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ci spin_lock(&ocelot->stats_lock); 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci /* Get Rx stats */ 83262306a36Sopenharmony_ci stats->rx_bytes = s[OCELOT_STAT_RX_OCTETS]; 83362306a36Sopenharmony_ci stats->rx_packets = s[OCELOT_STAT_RX_SHORTS] + 83462306a36Sopenharmony_ci s[OCELOT_STAT_RX_FRAGMENTS] + 83562306a36Sopenharmony_ci s[OCELOT_STAT_RX_JABBERS] + 83662306a36Sopenharmony_ci s[OCELOT_STAT_RX_LONGS] + 83762306a36Sopenharmony_ci s[OCELOT_STAT_RX_64] + 83862306a36Sopenharmony_ci s[OCELOT_STAT_RX_65_127] + 83962306a36Sopenharmony_ci s[OCELOT_STAT_RX_128_255] + 84062306a36Sopenharmony_ci s[OCELOT_STAT_RX_256_511] + 84162306a36Sopenharmony_ci s[OCELOT_STAT_RX_512_1023] + 84262306a36Sopenharmony_ci s[OCELOT_STAT_RX_1024_1526] + 84362306a36Sopenharmony_ci s[OCELOT_STAT_RX_1527_MAX]; 84462306a36Sopenharmony_ci stats->multicast = s[OCELOT_STAT_RX_MULTICAST]; 84562306a36Sopenharmony_ci stats->rx_missed_errors = s[OCELOT_STAT_DROP_TAIL]; 84662306a36Sopenharmony_ci stats->rx_dropped = s[OCELOT_STAT_RX_RED_PRIO_0] + 84762306a36Sopenharmony_ci s[OCELOT_STAT_RX_RED_PRIO_1] + 84862306a36Sopenharmony_ci s[OCELOT_STAT_RX_RED_PRIO_2] + 84962306a36Sopenharmony_ci s[OCELOT_STAT_RX_RED_PRIO_3] + 85062306a36Sopenharmony_ci s[OCELOT_STAT_RX_RED_PRIO_4] + 85162306a36Sopenharmony_ci s[OCELOT_STAT_RX_RED_PRIO_5] + 85262306a36Sopenharmony_ci s[OCELOT_STAT_RX_RED_PRIO_6] + 85362306a36Sopenharmony_ci s[OCELOT_STAT_RX_RED_PRIO_7] + 85462306a36Sopenharmony_ci s[OCELOT_STAT_DROP_LOCAL] + 85562306a36Sopenharmony_ci s[OCELOT_STAT_DROP_YELLOW_PRIO_0] + 85662306a36Sopenharmony_ci s[OCELOT_STAT_DROP_YELLOW_PRIO_1] + 85762306a36Sopenharmony_ci s[OCELOT_STAT_DROP_YELLOW_PRIO_2] + 85862306a36Sopenharmony_ci s[OCELOT_STAT_DROP_YELLOW_PRIO_3] + 85962306a36Sopenharmony_ci s[OCELOT_STAT_DROP_YELLOW_PRIO_4] + 86062306a36Sopenharmony_ci s[OCELOT_STAT_DROP_YELLOW_PRIO_5] + 86162306a36Sopenharmony_ci s[OCELOT_STAT_DROP_YELLOW_PRIO_6] + 86262306a36Sopenharmony_ci s[OCELOT_STAT_DROP_YELLOW_PRIO_7] + 86362306a36Sopenharmony_ci s[OCELOT_STAT_DROP_GREEN_PRIO_0] + 86462306a36Sopenharmony_ci s[OCELOT_STAT_DROP_GREEN_PRIO_1] + 86562306a36Sopenharmony_ci s[OCELOT_STAT_DROP_GREEN_PRIO_2] + 86662306a36Sopenharmony_ci s[OCELOT_STAT_DROP_GREEN_PRIO_3] + 86762306a36Sopenharmony_ci s[OCELOT_STAT_DROP_GREEN_PRIO_4] + 86862306a36Sopenharmony_ci s[OCELOT_STAT_DROP_GREEN_PRIO_5] + 86962306a36Sopenharmony_ci s[OCELOT_STAT_DROP_GREEN_PRIO_6] + 87062306a36Sopenharmony_ci s[OCELOT_STAT_DROP_GREEN_PRIO_7]; 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci /* Get Tx stats */ 87362306a36Sopenharmony_ci stats->tx_bytes = s[OCELOT_STAT_TX_OCTETS]; 87462306a36Sopenharmony_ci stats->tx_packets = s[OCELOT_STAT_TX_64] + 87562306a36Sopenharmony_ci s[OCELOT_STAT_TX_65_127] + 87662306a36Sopenharmony_ci s[OCELOT_STAT_TX_128_255] + 87762306a36Sopenharmony_ci s[OCELOT_STAT_TX_256_511] + 87862306a36Sopenharmony_ci s[OCELOT_STAT_TX_512_1023] + 87962306a36Sopenharmony_ci s[OCELOT_STAT_TX_1024_1526] + 88062306a36Sopenharmony_ci s[OCELOT_STAT_TX_1527_MAX]; 88162306a36Sopenharmony_ci stats->tx_dropped = s[OCELOT_STAT_TX_DROPS] + 88262306a36Sopenharmony_ci s[OCELOT_STAT_TX_AGED]; 88362306a36Sopenharmony_ci stats->collisions = s[OCELOT_STAT_TX_COLLISION]; 88462306a36Sopenharmony_ci 88562306a36Sopenharmony_ci spin_unlock(&ocelot->stats_lock); 88662306a36Sopenharmony_ci} 88762306a36Sopenharmony_ciEXPORT_SYMBOL(ocelot_port_get_stats64); 88862306a36Sopenharmony_ci 88962306a36Sopenharmony_cistatic int ocelot_prepare_stats_regions(struct ocelot *ocelot) 89062306a36Sopenharmony_ci{ 89162306a36Sopenharmony_ci struct ocelot_stats_region *region = NULL; 89262306a36Sopenharmony_ci const struct ocelot_stat_layout *layout; 89362306a36Sopenharmony_ci enum ocelot_reg last = 0; 89462306a36Sopenharmony_ci enum ocelot_stat i; 89562306a36Sopenharmony_ci 89662306a36Sopenharmony_ci INIT_LIST_HEAD(&ocelot->stats_regions); 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_ci layout = ocelot_get_stats_layout(ocelot); 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_ci for (i = 0; i < OCELOT_NUM_STATS; i++) { 90162306a36Sopenharmony_ci if (!layout[i].reg) 90262306a36Sopenharmony_ci continue; 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_ci /* enum ocelot_stat must be kept sorted in the same order 90562306a36Sopenharmony_ci * as the addresses behind layout[i].reg in order to have 90662306a36Sopenharmony_ci * efficient bulking 90762306a36Sopenharmony_ci */ 90862306a36Sopenharmony_ci if (last) { 90962306a36Sopenharmony_ci WARN(ocelot->map[SYS][last & REG_MASK] >= ocelot->map[SYS][layout[i].reg & REG_MASK], 91062306a36Sopenharmony_ci "reg 0x%x had address 0x%x but reg 0x%x has address 0x%x, bulking broken!", 91162306a36Sopenharmony_ci last, ocelot->map[SYS][last & REG_MASK], 91262306a36Sopenharmony_ci layout[i].reg, ocelot->map[SYS][layout[i].reg & REG_MASK]); 91362306a36Sopenharmony_ci } 91462306a36Sopenharmony_ci 91562306a36Sopenharmony_ci if (region && ocelot->map[SYS][layout[i].reg & REG_MASK] == 91662306a36Sopenharmony_ci ocelot->map[SYS][last & REG_MASK] + 4) { 91762306a36Sopenharmony_ci region->count++; 91862306a36Sopenharmony_ci } else { 91962306a36Sopenharmony_ci region = devm_kzalloc(ocelot->dev, sizeof(*region), 92062306a36Sopenharmony_ci GFP_KERNEL); 92162306a36Sopenharmony_ci if (!region) 92262306a36Sopenharmony_ci return -ENOMEM; 92362306a36Sopenharmony_ci 92462306a36Sopenharmony_ci region->base = layout[i].reg; 92562306a36Sopenharmony_ci region->first_stat = i; 92662306a36Sopenharmony_ci region->count = 1; 92762306a36Sopenharmony_ci list_add_tail(®ion->node, &ocelot->stats_regions); 92862306a36Sopenharmony_ci } 92962306a36Sopenharmony_ci 93062306a36Sopenharmony_ci last = layout[i].reg; 93162306a36Sopenharmony_ci } 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_ci list_for_each_entry(region, &ocelot->stats_regions, node) { 93462306a36Sopenharmony_ci enum ocelot_target target; 93562306a36Sopenharmony_ci u32 addr; 93662306a36Sopenharmony_ci 93762306a36Sopenharmony_ci ocelot_reg_to_target_addr(ocelot, region->base, &target, 93862306a36Sopenharmony_ci &addr); 93962306a36Sopenharmony_ci 94062306a36Sopenharmony_ci dev_dbg(ocelot->dev, 94162306a36Sopenharmony_ci "region of %d contiguous counters starting with SYS:STAT:CNT[0x%03x]\n", 94262306a36Sopenharmony_ci region->count, addr / 4); 94362306a36Sopenharmony_ci region->buf = devm_kcalloc(ocelot->dev, region->count, 94462306a36Sopenharmony_ci sizeof(*region->buf), GFP_KERNEL); 94562306a36Sopenharmony_ci if (!region->buf) 94662306a36Sopenharmony_ci return -ENOMEM; 94762306a36Sopenharmony_ci } 94862306a36Sopenharmony_ci 94962306a36Sopenharmony_ci return 0; 95062306a36Sopenharmony_ci} 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_ciint ocelot_stats_init(struct ocelot *ocelot) 95362306a36Sopenharmony_ci{ 95462306a36Sopenharmony_ci char queue_name[32]; 95562306a36Sopenharmony_ci int ret; 95662306a36Sopenharmony_ci 95762306a36Sopenharmony_ci ocelot->stats = devm_kcalloc(ocelot->dev, 95862306a36Sopenharmony_ci ocelot->num_phys_ports * OCELOT_NUM_STATS, 95962306a36Sopenharmony_ci sizeof(u64), GFP_KERNEL); 96062306a36Sopenharmony_ci if (!ocelot->stats) 96162306a36Sopenharmony_ci return -ENOMEM; 96262306a36Sopenharmony_ci 96362306a36Sopenharmony_ci snprintf(queue_name, sizeof(queue_name), "%s-stats", 96462306a36Sopenharmony_ci dev_name(ocelot->dev)); 96562306a36Sopenharmony_ci ocelot->stats_queue = create_singlethread_workqueue(queue_name); 96662306a36Sopenharmony_ci if (!ocelot->stats_queue) 96762306a36Sopenharmony_ci return -ENOMEM; 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_ci spin_lock_init(&ocelot->stats_lock); 97062306a36Sopenharmony_ci mutex_init(&ocelot->stat_view_lock); 97162306a36Sopenharmony_ci 97262306a36Sopenharmony_ci ret = ocelot_prepare_stats_regions(ocelot); 97362306a36Sopenharmony_ci if (ret) { 97462306a36Sopenharmony_ci destroy_workqueue(ocelot->stats_queue); 97562306a36Sopenharmony_ci return ret; 97662306a36Sopenharmony_ci } 97762306a36Sopenharmony_ci 97862306a36Sopenharmony_ci INIT_DELAYED_WORK(&ocelot->stats_work, ocelot_check_stats_work); 97962306a36Sopenharmony_ci queue_delayed_work(ocelot->stats_queue, &ocelot->stats_work, 98062306a36Sopenharmony_ci OCELOT_STATS_CHECK_DELAY); 98162306a36Sopenharmony_ci 98262306a36Sopenharmony_ci return 0; 98362306a36Sopenharmony_ci} 98462306a36Sopenharmony_ci 98562306a36Sopenharmony_civoid ocelot_stats_deinit(struct ocelot *ocelot) 98662306a36Sopenharmony_ci{ 98762306a36Sopenharmony_ci cancel_delayed_work(&ocelot->stats_work); 98862306a36Sopenharmony_ci destroy_workqueue(ocelot->stats_queue); 98962306a36Sopenharmony_ci} 990