// SPDX-License-Identifier: GPL-2.0+
/* Microchip Sparx5 Switch driver
*
* Copyright (c) 2021 Microchip Technology Inc. and its subsidiaries.
*/
#include <linux/ethtool.h>
#include "sparx5_main_regs.h"
#include "sparx5_main.h"
#include "sparx5_port.h"
/* Index of ANA_AC port counters */
#define SPX5_PORT_POLICER_DROPS 0
/* Add a potentially wrapping 32 bit value to a 64 bit counter */
static void sparx5_update_counter(u64 *cnt, u32 val)
{
if (val < (*cnt & U32_MAX))
*cnt += (u64)1 << 32 ; /* value has wrapped */
*cnt = (*cnt & ~(u64)U32_MAX) + val;
}
enum sparx5_stats_entry {
spx5_stats_rx_symbol_err_cnt = 0 ,
spx5_stats_pmac_rx_symbol_err_cnt = 1 ,
spx5_stats_tx_uc_cnt = 2 ,
spx5_stats_pmac_tx_uc_cnt = 3 ,
spx5_stats_tx_mc_cnt = 4 ,
spx5_stats_tx_bc_cnt = 5 ,
spx5_stats_tx_backoff1_cnt = 6 ,
spx5_stats_tx_multi_coll_cnt = 7 ,
spx5_stats_rx_uc_cnt = 8 ,
spx5_stats_pmac_rx_uc_cnt = 9 ,
spx5_stats_rx_mc_cnt = 10 ,
spx5_stats_rx_bc_cnt = 11 ,
spx5_stats_rx_crc_err_cnt = 12 ,
spx5_stats_pmac_rx_crc_err_cnt = 13 ,
spx5_stats_rx_alignment_lost_cnt = 14 ,
spx5_stats_pmac_rx_alignment_lost_cnt = 15 ,
spx5_stats_tx_ok_bytes_cnt = 16 ,
spx5_stats_pmac_tx_ok_bytes_cnt = 17 ,
spx5_stats_tx_defer_cnt = 18 ,
spx5_stats_tx_late_coll_cnt = 19 ,
spx5_stats_tx_xcoll_cnt = 20 ,
spx5_stats_tx_csense_cnt = 21 ,
spx5_stats_rx_ok_bytes_cnt = 22 ,
spx5_stats_pmac_rx_ok_bytes_cnt = 23 ,
spx5_stats_pmac_tx_mc_cnt = 24 ,
spx5_stats_pmac_tx_bc_cnt = 25 ,
spx5_stats_tx_xdefer_cnt = 26 ,
spx5_stats_pmac_rx_mc_cnt = 27 ,
spx5_stats_pmac_rx_bc_cnt = 28 ,
spx5_stats_rx_in_range_len_err_cnt = 29 ,
spx5_stats_pmac_rx_in_range_len_err_cnt = 30 ,
spx5_stats_rx_out_of_range_len_err_cnt = 31 ,
spx5_stats_pmac_rx_out_of_range_len_err_cnt = 32 ,
spx5_stats_rx_oversize_cnt = 33 ,
spx5_stats_pmac_rx_oversize_cnt = 34 ,
spx5_stats_tx_pause_cnt = 35 ,
spx5_stats_pmac_tx_pause_cnt = 36 ,
spx5_stats_rx_pause_cnt = 37 ,
spx5_stats_pmac_rx_pause_cnt = 38 ,
spx5_stats_rx_unsup_opcode_cnt = 39 ,
spx5_stats_pmac_rx_unsup_opcode_cnt = 40 ,
spx5_stats_rx_undersize_cnt = 41 ,
spx5_stats_pmac_rx_undersize_cnt = 42 ,
spx5_stats_rx_fragments_cnt = 43 ,
spx5_stats_pmac_rx_fragments_cnt = 44 ,
spx5_stats_rx_jabbers_cnt = 45 ,
spx5_stats_pmac_rx_jabbers_cnt = 46 ,
spx5_stats_rx_size64_cnt = 47 ,
spx5_stats_pmac_rx_size64_cnt = 48 ,
spx5_stats_rx_size65to127_cnt = 49 ,
spx5_stats_pmac_rx_size65to127_cnt = 50 ,
spx5_stats_rx_size128to255_cnt = 51 ,
spx5_stats_pmac_rx_size128to255_cnt = 52 ,
spx5_stats_rx_size256to511_cnt = 53 ,
spx5_stats_pmac_rx_size256to511_cnt = 54 ,
spx5_stats_rx_size512to1023_cnt = 55 ,
spx5_stats_pmac_rx_size512to1023_cnt = 56 ,
spx5_stats_rx_size1024to1518_cnt = 57 ,
spx5_stats_pmac_rx_size1024to1518_cnt = 58 ,
spx5_stats_rx_size1519tomax_cnt = 59 ,
spx5_stats_pmac_rx_size1519tomax_cnt = 60 ,
spx5_stats_tx_size64_cnt = 61 ,
spx5_stats_pmac_tx_size64_cnt = 62 ,
spx5_stats_tx_size65to127_cnt = 63 ,
spx5_stats_pmac_tx_size65to127_cnt = 64 ,
spx5_stats_tx_size128to255_cnt = 65 ,
spx5_stats_pmac_tx_size128to255_cnt = 66 ,
spx5_stats_tx_size256to511_cnt = 67 ,
spx5_stats_pmac_tx_size256to511_cnt = 68 ,
spx5_stats_tx_size512to1023_cnt = 69 ,
spx5_stats_pmac_tx_size512to1023_cnt = 70 ,
spx5_stats_tx_size1024to1518_cnt = 71 ,
spx5_stats_pmac_tx_size1024to1518_cnt = 72 ,
spx5_stats_tx_size1519tomax_cnt = 73 ,
spx5_stats_pmac_tx_size1519tomax_cnt = 74 ,
spx5_stats_mm_rx_assembly_err_cnt = 75 ,
spx5_stats_mm_rx_assembly_ok_cnt = 76 ,
spx5_stats_mm_rx_merge_frag_cnt = 77 ,
spx5_stats_mm_rx_smd_err_cnt = 78 ,
spx5_stats_mm_tx_pfragment_cnt = 79 ,
spx5_stats_rx_bad_bytes_cnt = 80 ,
spx5_stats_pmac_rx_bad_bytes_cnt = 81 ,
spx5_stats_rx_in_bytes_cnt = 82 ,
spx5_stats_rx_ipg_shrink_cnt = 83 ,
spx5_stats_rx_sync_lost_err_cnt = 84 ,
spx5_stats_rx_tagged_frms_cnt = 85 ,
spx5_stats_rx_untagged_frms_cnt = 86 ,
spx5_stats_tx_out_bytes_cnt = 87 ,
spx5_stats_tx_tagged_frms_cnt = 88 ,
spx5_stats_tx_untagged_frms_cnt = 89 ,
spx5_stats_rx_hih_cksm_err_cnt = 90 ,
spx5_stats_pmac_rx_hih_cksm_err_cnt = 91 ,
spx5_stats_rx_xgmii_prot_err_cnt = 92 ,
spx5_stats_pmac_rx_xgmii_prot_err_cnt = 93 ,
spx5_stats_ana_ac_port_stat_lsb_cnt = 94 ,
spx5_stats_green_p0_rx_fwd = 95 ,
spx5_stats_green_p0_rx_port_drop = 111 ,
spx5_stats_green_p0_tx_port = 127 ,
spx5_stats_rx_local_drop = 143 ,
spx5_stats_tx_local_drop = 144 ,
spx5_stats_count = 145 ,
};
static const char *const sparx5_stats_layout[] = {
"mm_rx_assembly_err_cnt" ,
"mm_rx_assembly_ok_cnt" ,
"mm_rx_merge_frag_cnt" ,
"mm_rx_smd_err_cnt" ,
"mm_tx_pfragment_cnt" ,
"rx_bad_bytes_cnt" ,
"pmac_rx_bad_bytes_cnt" ,
"rx_in_bytes_cnt" ,
"rx_ipg_shrink_cnt" ,
"rx_sync_lost_err_cnt" ,
"rx_tagged_frms_cnt" ,
"rx_untagged_frms_cnt" ,
"tx_out_bytes_cnt" ,
"tx_tagged_frms_cnt" ,
"tx_untagged_frms_cnt" ,
"rx_hih_cksm_err_cnt" ,
"pmac_rx_hih_cksm_err_cnt" ,
"rx_xgmii_prot_err_cnt" ,
"pmac_rx_xgmii_prot_err_cnt" ,
"rx_port_policer_drop" ,
"rx_fwd_green_p0" ,
"rx_fwd_green_p1" ,
"rx_fwd_green_p2" ,
"rx_fwd_green_p3" ,
"rx_fwd_green_p4" ,
"rx_fwd_green_p5" ,
"rx_fwd_green_p6" ,
"rx_fwd_green_p7" ,
"rx_fwd_yellow_p0" ,
"rx_fwd_yellow_p1" ,
"rx_fwd_yellow_p2" ,
"rx_fwd_yellow_p3" ,
"rx_fwd_yellow_p4" ,
"rx_fwd_yellow_p5" ,
"rx_fwd_yellow_p6" ,
"rx_fwd_yellow_p7" ,
"rx_port_drop_green_p0" ,
"rx_port_drop_green_p1" ,
"rx_port_drop_green_p2" ,
"rx_port_drop_green_p3" ,
"rx_port_drop_green_p4" ,
"rx_port_drop_green_p5" ,
"rx_port_drop_green_p6" ,
"rx_port_drop_green_p7" ,
"rx_port_drop_yellow_p0" ,
"rx_port_drop_yellow_p1" ,
"rx_port_drop_yellow_p2" ,
"rx_port_drop_yellow_p3" ,
"rx_port_drop_yellow_p4" ,
"rx_port_drop_yellow_p5" ,
"rx_port_drop_yellow_p6" ,
"rx_port_drop_yellow_p7" ,
"tx_port_green_p0" ,
"tx_port_green_p1" ,
"tx_port_green_p2" ,
"tx_port_green_p3" ,
"tx_port_green_p4" ,
"tx_port_green_p5" ,
"tx_port_green_p6" ,
"tx_port_green_p7" ,
"tx_port_yellow_p0" ,
"tx_port_yellow_p1" ,
"tx_port_yellow_p2" ,
"tx_port_yellow_p3" ,
"tx_port_yellow_p4" ,
"tx_port_yellow_p5" ,
"tx_port_yellow_p6" ,
"tx_port_yellow_p7" ,
"rx_local_drop" ,
"tx_local_drop" ,
};
static void sparx5_get_queue_sys_stats(struct sparx5 *sparx5, int portno)
{
u64 *portstats;
u64 *stats;
u32 addr;
int idx;
portstats = &sparx5->stats[portno * sparx5->num_stats];
mutex_lock(&sparx5->queue_stats_lock);
spx5_wr(XQS_STAT_CFG_STAT_VIEW_SET(portno), sparx5, XQS_STAT_CFG);
addr = 0 ;
stats = &portstats[spx5_stats_green_p0_rx_fwd];
for (idx = 0 ; idx < 2 * SPX5_PRIOS; ++idx, ++addr, ++stats)
sparx5_update_counter(stats, spx5_rd(sparx5, XQS_CNT(addr)));
addr = 16 ;
stats = &portstats[spx5_stats_green_p0_rx_port_drop];
for (idx = 0 ; idx < 2 * SPX5_PRIOS; ++idx, ++addr, ++stats)
sparx5_update_counter(stats, spx5_rd(sparx5, XQS_CNT(addr)));
addr = 256 ;
stats = &portstats[spx5_stats_green_p0_tx_port];
for (idx = 0 ; idx < 2 * SPX5_PRIOS; ++idx, ++addr, ++stats)
sparx5_update_counter(stats, spx5_rd(sparx5, XQS_CNT(addr)));
sparx5_update_counter(&portstats[spx5_stats_rx_local_drop],
spx5_rd(sparx5, XQS_CNT(32 )));
sparx5_update_counter(&portstats[spx5_stats_tx_local_drop],
spx5_rd(sparx5, XQS_CNT(272 )));
mutex_unlock(&sparx5->queue_stats_lock);
}
static void sparx5_get_ana_ac_stats_stats(struct sparx5 *sparx5, int portno)
{
u64 *portstats = &sparx5->stats[portno * sparx5->num_stats];
sparx5_update_counter(&portstats[spx5_stats_ana_ac_port_stat_lsb_cnt],
spx5_rd(sparx5, ANA_AC_PORT_STAT_LSB_CNT(portno,
SPX5_PORT_POLICER_DROPS)));
}
static void sparx5_get_dev_phy_stats(u64 *portstats, void __iomem *inst, u32
tinst)
{
sparx5_update_counter(&portstats[spx5_stats_rx_symbol_err_cnt],
spx5_inst_rd(inst,
DEV5G_RX_SYMBOL_ERR_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_symbol_err_cnt],
spx5_inst_rd(inst,
DEV5G_PMAC_RX_SYMBOL_ERR_CNT(tinst)));
}
static void sparx5_get_dev_mac_stats(u64 *portstats, void __iomem *inst, u32
tinst)
{
sparx5_update_counter(&portstats[spx5_stats_tx_uc_cnt],
spx5_inst_rd(inst, DEV5G_TX_UC_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_tx_uc_cnt],
spx5_inst_rd(inst, DEV5G_PMAC_TX_UC_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_tx_mc_cnt],
spx5_inst_rd(inst, DEV5G_TX_MC_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_tx_bc_cnt],
spx5_inst_rd(inst, DEV5G_TX_BC_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_rx_uc_cnt],
spx5_inst_rd(inst, DEV5G_RX_UC_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_uc_cnt],
spx5_inst_rd(inst, DEV5G_PMAC_RX_UC_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_rx_mc_cnt],
spx5_inst_rd(inst, DEV5G_RX_MC_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_rx_bc_cnt],
spx5_inst_rd(inst, DEV5G_RX_BC_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_rx_crc_err_cnt],
spx5_inst_rd(inst, DEV5G_RX_CRC_ERR_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_crc_err_cnt],
spx5_inst_rd(inst,
DEV5G_PMAC_RX_CRC_ERR_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_rx_alignment_lost_cnt],
spx5_inst_rd(inst,
DEV5G_RX_ALIGNMENT_LOST_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_alignment_lost_cnt],
spx5_inst_rd(inst,
DEV5G_PMAC_RX_ALIGNMENT_LOST_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_tx_ok_bytes_cnt],
spx5_inst_rd(inst, DEV5G_TX_OK_BYTES_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_tx_ok_bytes_cnt],
spx5_inst_rd(inst,
DEV5G_PMAC_TX_OK_BYTES_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_rx_ok_bytes_cnt],
spx5_inst_rd(inst, DEV5G_RX_OK_BYTES_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_ok_bytes_cnt],
spx5_inst_rd(inst,
DEV5G_PMAC_RX_OK_BYTES_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_tx_mc_cnt],
spx5_inst_rd(inst, DEV5G_PMAC_TX_MC_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_tx_bc_cnt],
spx5_inst_rd(inst, DEV5G_PMAC_TX_BC_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_mc_cnt],
spx5_inst_rd(inst, DEV5G_PMAC_RX_MC_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_bc_cnt],
spx5_inst_rd(inst, DEV5G_PMAC_RX_BC_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_rx_in_range_len_err_cnt],
spx5_inst_rd(inst,
DEV5G_RX_IN_RANGE_LEN_ERR_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_in_range_len_err_cnt],
spx5_inst_rd(inst,
DEV5G_PMAC_RX_IN_RANGE_LEN_ERR_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_rx_out_of_range_len_err_cnt],
spx5_inst_rd(inst,
DEV5G_RX_OUT_OF_RANGE_LEN_ERR_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_out_of_range_len_err_cnt],
spx5_inst_rd(inst,
DEV5G_PMAC_RX_OUT_OF_RANGE_LEN_ERR_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_rx_oversize_cnt],
spx5_inst_rd(inst, DEV5G_RX_OVERSIZE_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_oversize_cnt],
spx5_inst_rd(inst,
DEV5G_PMAC_RX_OVERSIZE_CNT(tinst)));
}
static void sparx5_get_dev_mac_ctrl_stats(u64 *portstats, void __iomem *inst,
u32 tinst)
{
sparx5_update_counter(&portstats[spx5_stats_tx_pause_cnt],
spx5_inst_rd(inst, DEV5G_TX_PAUSE_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_tx_pause_cnt],
spx5_inst_rd(inst,
DEV5G_PMAC_TX_PAUSE_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_rx_pause_cnt],
spx5_inst_rd(inst, DEV5G_RX_PAUSE_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_pause_cnt],
spx5_inst_rd(inst,
DEV5G_PMAC_RX_PAUSE_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_rx_unsup_opcode_cnt],
spx5_inst_rd(inst,
DEV5G_RX_UNSUP_OPCODE_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_unsup_opcode_cnt],
spx5_inst_rd(inst,
DEV5G_PMAC_RX_UNSUP_OPCODE_CNT(tinst)));
}
static void sparx5_get_dev_rmon_stats(u64 *portstats, void __iomem *inst, u32
tinst)
{
sparx5_update_counter(&portstats[spx5_stats_rx_undersize_cnt],
spx5_inst_rd(inst,
DEV5G_RX_UNDERSIZE_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_undersize_cnt],
spx5_inst_rd(inst,
DEV5G_PMAC_RX_UNDERSIZE_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_rx_oversize_cnt],
spx5_inst_rd(inst, DEV5G_RX_OVERSIZE_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_oversize_cnt],
spx5_inst_rd(inst,
DEV5G_PMAC_RX_OVERSIZE_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_rx_fragments_cnt],
spx5_inst_rd(inst,
DEV5G_RX_FRAGMENTS_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_fragments_cnt],
spx5_inst_rd(inst,
DEV5G_PMAC_RX_FRAGMENTS_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_rx_jabbers_cnt],
spx5_inst_rd(inst, DEV5G_RX_JABBERS_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_jabbers_cnt],
spx5_inst_rd(inst,
DEV5G_PMAC_RX_JABBERS_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_rx_size64_cnt],
spx5_inst_rd(inst, DEV5G_RX_SIZE64_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size64_cnt],
spx5_inst_rd(inst,
DEV5G_PMAC_RX_SIZE64_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_rx_size65to127_cnt],
spx5_inst_rd(inst,
DEV5G_RX_SIZE65TO127_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size65to127_cnt],
spx5_inst_rd(inst,
DEV5G_PMAC_RX_SIZE65TO127_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_rx_size128to255_cnt],
spx5_inst_rd(inst,
DEV5G_RX_SIZE128TO255_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size128to255_cnt],
spx5_inst_rd(inst,
DEV5G_PMAC_RX_SIZE128TO255_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_rx_size256to511_cnt],
spx5_inst_rd(inst,
DEV5G_RX_SIZE256TO511_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size256to511_cnt],
spx5_inst_rd(inst,
DEV5G_PMAC_RX_SIZE256TO511_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_rx_size512to1023_cnt],
spx5_inst_rd(inst,
DEV5G_RX_SIZE512TO1023_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size512to1023_cnt],
spx5_inst_rd(inst,
DEV5G_PMAC_RX_SIZE512TO1023_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_rx_size1024to1518_cnt],
spx5_inst_rd(inst,
DEV5G_RX_SIZE1024TO1518_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size1024to1518_cnt],
spx5_inst_rd(inst,
DEV5G_PMAC_RX_SIZE1024TO1518_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_rx_size1519tomax_cnt],
spx5_inst_rd(inst,
DEV5G_RX_SIZE1519TOMAX_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size1519tomax_cnt],
spx5_inst_rd(inst,
DEV5G_PMAC_RX_SIZE1519TOMAX_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_tx_size64_cnt],
spx5_inst_rd(inst, DEV5G_TX_SIZE64_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size64_cnt],
spx5_inst_rd(inst,
DEV5G_PMAC_TX_SIZE64_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_tx_size65to127_cnt],
spx5_inst_rd(inst,
DEV5G_TX_SIZE65TO127_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size65to127_cnt],
spx5_inst_rd(inst,
DEV5G_PMAC_TX_SIZE65TO127_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_tx_size128to255_cnt],
spx5_inst_rd(inst,
DEV5G_TX_SIZE128TO255_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size128to255_cnt],
spx5_inst_rd(inst,
DEV5G_PMAC_TX_SIZE128TO255_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_tx_size256to511_cnt],
spx5_inst_rd(inst,
DEV5G_TX_SIZE256TO511_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size256to511_cnt],
spx5_inst_rd(inst,
DEV5G_PMAC_TX_SIZE256TO511_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_tx_size512to1023_cnt],
spx5_inst_rd(inst,
DEV5G_TX_SIZE512TO1023_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size512to1023_cnt],
spx5_inst_rd(inst,
DEV5G_PMAC_TX_SIZE512TO1023_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_tx_size1024to1518_cnt],
spx5_inst_rd(inst,
DEV5G_TX_SIZE1024TO1518_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size1024to1518_cnt],
spx5_inst_rd(inst,
DEV5G_PMAC_TX_SIZE1024TO1518_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_tx_size1519tomax_cnt],
spx5_inst_rd(inst,
DEV5G_TX_SIZE1519TOMAX_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size1519tomax_cnt],
spx5_inst_rd(inst,
DEV5G_PMAC_TX_SIZE1519TOMAX_CNT(tinst)));
}
static void sparx5_get_dev_misc_stats(u64 *portstats, void __iomem *inst, u32
tinst)
{
sparx5_update_counter(&portstats[spx5_stats_mm_rx_assembly_err_cnt],
spx5_inst_rd(inst,
DEV5G_MM_RX_ASSEMBLY_ERR_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_mm_rx_assembly_ok_cnt],
spx5_inst_rd(inst,
DEV5G_MM_RX_ASSEMBLY_OK_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_mm_rx_merge_frag_cnt],
spx5_inst_rd(inst,
DEV5G_MM_RX_MERGE_FRAG_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_mm_rx_smd_err_cnt],
spx5_inst_rd(inst,
DEV5G_MM_RX_SMD_ERR_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_mm_tx_pfragment_cnt],
spx5_inst_rd(inst,
DEV5G_MM_TX_PFRAGMENT_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_rx_bad_bytes_cnt],
spx5_inst_rd(inst,
DEV5G_RX_BAD_BYTES_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_bad_bytes_cnt],
spx5_inst_rd(inst,
DEV5G_PMAC_RX_BAD_BYTES_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_rx_in_bytes_cnt],
spx5_inst_rd(inst, DEV5G_RX_IN_BYTES_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_rx_ipg_shrink_cnt],
spx5_inst_rd(inst,
DEV5G_RX_IPG_SHRINK_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_rx_tagged_frms_cnt],
spx5_inst_rd(inst,
DEV5G_RX_TAGGED_FRMS_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_rx_untagged_frms_cnt],
spx5_inst_rd(inst,
DEV5G_RX_UNTAGGED_FRMS_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_tx_out_bytes_cnt],
spx5_inst_rd(inst,
DEV5G_TX_OUT_BYTES_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_tx_tagged_frms_cnt],
spx5_inst_rd(inst,
DEV5G_TX_TAGGED_FRMS_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_tx_untagged_frms_cnt],
spx5_inst_rd(inst,
DEV5G_TX_UNTAGGED_FRMS_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_rx_hih_cksm_err_cnt],
spx5_inst_rd(inst,
DEV5G_RX_HIH_CKSM_ERR_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_hih_cksm_err_cnt],
spx5_inst_rd(inst,
DEV5G_PMAC_RX_HIH_CKSM_ERR_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_rx_xgmii_prot_err_cnt],
spx5_inst_rd(inst,
DEV5G_RX_XGMII_PROT_ERR_CNT(tinst)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_xgmii_prot_err_cnt],
spx5_inst_rd(inst,
DEV5G_PMAC_RX_XGMII_PROT_ERR_CNT(tinst)));
}
static void sparx5_get_device_stats(struct sparx5 *sparx5, int portno)
{
u64 *portstats = &sparx5->stats[portno * sparx5->num_stats];
u32 tinst = sparx5_port_dev_index(sparx5, portno);
u32 dev = sparx5_to_high_dev(sparx5, portno);
void __iomem *inst;
inst = spx5_inst_get(sparx5, dev, tinst);
sparx5_get_dev_phy_stats(portstats, inst, tinst);
sparx5_get_dev_mac_stats(portstats, inst, tinst);
sparx5_get_dev_mac_ctrl_stats(portstats, inst, tinst);
sparx5_get_dev_rmon_stats(portstats, inst, tinst);
sparx5_get_dev_misc_stats(portstats, inst, tinst);
}
static void sparx5_get_asm_phy_stats(u64 *portstats, void __iomem *inst, int
portno)
{
sparx5_update_counter(&portstats[spx5_stats_rx_symbol_err_cnt],
spx5_inst_rd(inst,
ASM_RX_SYMBOL_ERR_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_symbol_err_cnt],
spx5_inst_rd(inst,
ASM_PMAC_RX_SYMBOL_ERR_CNT(portno)));
}
static void sparx5_get_asm_mac_stats(u64 *portstats, void __iomem *inst, int
portno)
{
sparx5_update_counter(&portstats[spx5_stats_tx_uc_cnt],
spx5_inst_rd(inst, ASM_TX_UC_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_tx_uc_cnt],
spx5_inst_rd(inst, ASM_PMAC_TX_UC_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_tx_mc_cnt],
spx5_inst_rd(inst, ASM_TX_MC_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_tx_bc_cnt],
spx5_inst_rd(inst, ASM_TX_BC_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_tx_backoff1_cnt],
spx5_inst_rd(inst, ASM_TX_BACKOFF1_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_tx_multi_coll_cnt],
spx5_inst_rd(inst,
ASM_TX_MULTI_COLL_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_rx_uc_cnt],
spx5_inst_rd(inst, ASM_RX_UC_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_uc_cnt],
spx5_inst_rd(inst, ASM_PMAC_RX_UC_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_rx_mc_cnt],
spx5_inst_rd(inst, ASM_RX_MC_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_rx_bc_cnt],
spx5_inst_rd(inst, ASM_RX_BC_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_rx_crc_err_cnt],
spx5_inst_rd(inst, ASM_RX_CRC_ERR_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_crc_err_cnt],
spx5_inst_rd(inst,
ASM_PMAC_RX_CRC_ERR_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_rx_alignment_lost_cnt],
spx5_inst_rd(inst,
ASM_RX_ALIGNMENT_LOST_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_alignment_lost_cnt],
spx5_inst_rd(inst,
ASM_PMAC_RX_ALIGNMENT_LOST_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_tx_ok_bytes_cnt],
spx5_inst_rd(inst, ASM_TX_OK_BYTES_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_tx_ok_bytes_cnt],
spx5_inst_rd(inst,
ASM_PMAC_TX_OK_BYTES_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_tx_defer_cnt],
spx5_inst_rd(inst, ASM_TX_DEFER_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_tx_late_coll_cnt],
spx5_inst_rd(inst, ASM_TX_LATE_COLL_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_tx_xcoll_cnt],
spx5_inst_rd(inst, ASM_TX_XCOLL_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_tx_csense_cnt],
spx5_inst_rd(inst, ASM_TX_CSENSE_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_rx_ok_bytes_cnt],
spx5_inst_rd(inst, ASM_RX_OK_BYTES_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_ok_bytes_cnt],
spx5_inst_rd(inst,
ASM_PMAC_RX_OK_BYTES_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_tx_mc_cnt],
spx5_inst_rd(inst, ASM_PMAC_TX_MC_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_tx_bc_cnt],
spx5_inst_rd(inst, ASM_PMAC_TX_BC_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_tx_xdefer_cnt],
spx5_inst_rd(inst, ASM_TX_XDEFER_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_mc_cnt],
spx5_inst_rd(inst, ASM_PMAC_RX_MC_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_bc_cnt],
spx5_inst_rd(inst, ASM_PMAC_RX_BC_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_rx_in_range_len_err_cnt],
spx5_inst_rd(inst,
ASM_RX_IN_RANGE_LEN_ERR_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_in_range_len_err_cnt],
spx5_inst_rd(inst,
ASM_PMAC_RX_IN_RANGE_LEN_ERR_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_rx_out_of_range_len_err_cnt],
spx5_inst_rd(inst,
ASM_RX_OUT_OF_RANGE_LEN_ERR_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_out_of_range_len_err_cnt],
spx5_inst_rd(inst,
ASM_PMAC_RX_OUT_OF_RANGE_LEN_ERR_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_rx_oversize_cnt],
spx5_inst_rd(inst, ASM_RX_OVERSIZE_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_oversize_cnt],
spx5_inst_rd(inst,
ASM_PMAC_RX_OVERSIZE_CNT(portno)));
}
static void sparx5_get_asm_mac_ctrl_stats(u64 *portstats, void __iomem *inst,
int portno)
{
sparx5_update_counter(&portstats[spx5_stats_tx_pause_cnt],
spx5_inst_rd(inst, ASM_TX_PAUSE_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_tx_pause_cnt],
spx5_inst_rd(inst,
ASM_PMAC_TX_PAUSE_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_rx_pause_cnt],
spx5_inst_rd(inst, ASM_RX_PAUSE_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_pause_cnt],
spx5_inst_rd(inst,
ASM_PMAC_RX_PAUSE_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_rx_unsup_opcode_cnt],
spx5_inst_rd(inst,
ASM_RX_UNSUP_OPCODE_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_unsup_opcode_cnt],
spx5_inst_rd(inst,
ASM_PMAC_RX_UNSUP_OPCODE_CNT(portno)));
}
static void sparx5_get_asm_rmon_stats(u64 *portstats, void __iomem *inst, int
portno)
{
sparx5_update_counter(&portstats[spx5_stats_rx_undersize_cnt],
spx5_inst_rd(inst, ASM_RX_UNDERSIZE_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_undersize_cnt],
spx5_inst_rd(inst,
ASM_PMAC_RX_UNDERSIZE_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_rx_oversize_cnt],
spx5_inst_rd(inst, ASM_RX_OVERSIZE_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_oversize_cnt],
spx5_inst_rd(inst,
ASM_PMAC_RX_OVERSIZE_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_rx_fragments_cnt],
spx5_inst_rd(inst, ASM_RX_FRAGMENTS_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_fragments_cnt],
spx5_inst_rd(inst,
ASM_PMAC_RX_FRAGMENTS_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_rx_jabbers_cnt],
spx5_inst_rd(inst, ASM_RX_JABBERS_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_jabbers_cnt],
spx5_inst_rd(inst,
ASM_PMAC_RX_JABBERS_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_rx_size64_cnt],
spx5_inst_rd(inst, ASM_RX_SIZE64_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size64_cnt],
spx5_inst_rd(inst,
ASM_PMAC_RX_SIZE64_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_rx_size65to127_cnt],
spx5_inst_rd(inst,
ASM_RX_SIZE65TO127_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size65to127_cnt],
spx5_inst_rd(inst,
ASM_PMAC_RX_SIZE65TO127_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_rx_size128to255_cnt],
spx5_inst_rd(inst,
ASM_RX_SIZE128TO255_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size128to255_cnt],
spx5_inst_rd(inst,
ASM_PMAC_RX_SIZE128TO255_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_rx_size256to511_cnt],
spx5_inst_rd(inst,
ASM_RX_SIZE256TO511_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size256to511_cnt],
spx5_inst_rd(inst,
ASM_PMAC_RX_SIZE256TO511_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_rx_size512to1023_cnt],
spx5_inst_rd(inst,
ASM_RX_SIZE512TO1023_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size512to1023_cnt],
spx5_inst_rd(inst,
ASM_PMAC_RX_SIZE512TO1023_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_rx_size1024to1518_cnt],
spx5_inst_rd(inst,
ASM_RX_SIZE1024TO1518_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size1024to1518_cnt],
spx5_inst_rd(inst,
ASM_PMAC_RX_SIZE1024TO1518_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_rx_size1519tomax_cnt],
spx5_inst_rd(inst,
ASM_RX_SIZE1519TOMAX_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_size1519tomax_cnt],
spx5_inst_rd(inst,
ASM_PMAC_RX_SIZE1519TOMAX_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_tx_size64_cnt],
spx5_inst_rd(inst, ASM_TX_SIZE64_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size64_cnt],
spx5_inst_rd(inst,
ASM_PMAC_TX_SIZE64_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_tx_size65to127_cnt],
spx5_inst_rd(inst,
ASM_TX_SIZE65TO127_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size65to127_cnt],
spx5_inst_rd(inst,
ASM_PMAC_TX_SIZE65TO127_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_tx_size128to255_cnt],
spx5_inst_rd(inst,
ASM_TX_SIZE128TO255_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size128to255_cnt],
spx5_inst_rd(inst,
ASM_PMAC_TX_SIZE128TO255_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_tx_size256to511_cnt],
spx5_inst_rd(inst,
ASM_TX_SIZE256TO511_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size256to511_cnt],
spx5_inst_rd(inst,
ASM_PMAC_TX_SIZE256TO511_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_tx_size512to1023_cnt],
spx5_inst_rd(inst,
ASM_TX_SIZE512TO1023_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size512to1023_cnt],
spx5_inst_rd(inst,
ASM_PMAC_TX_SIZE512TO1023_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_tx_size1024to1518_cnt],
spx5_inst_rd(inst,
ASM_TX_SIZE1024TO1518_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size1024to1518_cnt],
spx5_inst_rd(inst,
ASM_PMAC_TX_SIZE1024TO1518_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_tx_size1519tomax_cnt],
spx5_inst_rd(inst,
ASM_TX_SIZE1519TOMAX_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_tx_size1519tomax_cnt],
spx5_inst_rd(inst,
ASM_PMAC_TX_SIZE1519TOMAX_CNT(portno)));
}
static void sparx5_get_asm_misc_stats(u64 *portstats, void __iomem *inst, int
portno)
{
sparx5_update_counter(&portstats[spx5_stats_mm_rx_assembly_err_cnt],
spx5_inst_rd(inst,
ASM_MM_RX_ASSEMBLY_ERR_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_mm_rx_assembly_ok_cnt],
spx5_inst_rd(inst,
ASM_MM_RX_ASSEMBLY_OK_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_mm_rx_merge_frag_cnt],
spx5_inst_rd(inst,
ASM_MM_RX_MERGE_FRAG_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_mm_rx_smd_err_cnt],
spx5_inst_rd(inst,
ASM_MM_RX_SMD_ERR_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_mm_tx_pfragment_cnt],
spx5_inst_rd(inst,
ASM_MM_TX_PFRAGMENT_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_rx_bad_bytes_cnt],
spx5_inst_rd(inst, ASM_RX_BAD_BYTES_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_pmac_rx_bad_bytes_cnt],
spx5_inst_rd(inst,
ASM_PMAC_RX_BAD_BYTES_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_rx_in_bytes_cnt],
spx5_inst_rd(inst, ASM_RX_IN_BYTES_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_rx_ipg_shrink_cnt],
spx5_inst_rd(inst,
ASM_RX_IPG_SHRINK_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_rx_sync_lost_err_cnt],
spx5_inst_rd(inst,
ASM_RX_SYNC_LOST_ERR_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_rx_tagged_frms_cnt],
spx5_inst_rd(inst,
ASM_RX_TAGGED_FRMS_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_rx_untagged_frms_cnt],
spx5_inst_rd(inst,
ASM_RX_UNTAGGED_FRMS_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_tx_out_bytes_cnt],
spx5_inst_rd(inst, ASM_TX_OUT_BYTES_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_tx_tagged_frms_cnt],
spx5_inst_rd(inst,
ASM_TX_TAGGED_FRMS_CNT(portno)));
sparx5_update_counter(&portstats[spx5_stats_tx_untagged_frms_cnt],
spx5_inst_rd(inst,
ASM_TX_UNTAGGED_FRMS_CNT(portno)));
}
static void sparx5_get_asm_stats(struct sparx5 *sparx5, int portno)
{
u64 *portstats = &sparx5->stats[portno * sparx5->num_stats];
void __iomem *inst = spx5_inst_get(sparx5, TARGET_ASM, 0 );
sparx5_get_asm_phy_stats(portstats, inst, portno);
sparx5_get_asm_mac_stats(portstats, inst, portno);
sparx5_get_asm_mac_ctrl_stats(portstats, inst, portno);
sparx5_get_asm_rmon_stats(portstats, inst, portno);
sparx5_get_asm_misc_stats(portstats, inst, portno);
}
static const struct ethtool_rmon_hist_range sparx5_rmon_ranges[] = {
{ 0 , 64 },
{ 65 , 127 },
{ 128 , 255 },
{ 256 , 511 },
{ 512 , 1023 },
{ 1024 , 1518 },
{ 1519 , 10239 },
{}
};
static void sparx5_get_eth_phy_stats(struct net_device *ndev,
struct ethtool_eth_phy_stats *phy_stats)
{
struct sparx5_port *port = netdev_priv(ndev);
struct sparx5 *sparx5 = port->sparx5;
int portno = port->portno;
void __iomem *inst;
u64 *portstats;
portstats = &sparx5->stats[portno * sparx5->num_stats];
if (sparx5_is_baser(port->conf.portmode)) {
u32 tinst = sparx5_port_dev_index(sparx5, portno);
u32 dev = sparx5_to_high_dev(sparx5, portno);
inst = spx5_inst_get(sparx5, dev, tinst);
sparx5_get_dev_phy_stats(portstats, inst, tinst);
} else {
inst = spx5_inst_get(sparx5, TARGET_ASM, 0 );
sparx5_get_asm_phy_stats(portstats, inst, portno);
}
phy_stats->SymbolErrorDuringCarrier =
portstats[spx5_stats_rx_symbol_err_cnt] +
portstats[spx5_stats_pmac_rx_symbol_err_cnt];
}
static void sparx5_get_eth_mac_stats(struct net_device *ndev,
struct ethtool_eth_mac_stats *mac_stats)
{
struct sparx5_port *port = netdev_priv(ndev);
struct sparx5 *sparx5 = port->sparx5;
int portno = port->portno;
void __iomem *inst;
u64 *portstats;
portstats = &sparx5->stats[portno * sparx5->num_stats];
if (sparx5_is_baser(port->conf.portmode)) {
u32 tinst = sparx5_port_dev_index(sparx5, portno);
u32 dev = sparx5_to_high_dev(sparx5, portno);
inst = spx5_inst_get(sparx5, dev, tinst);
sparx5_get_dev_mac_stats(portstats, inst, tinst);
} else {
inst = spx5_inst_get(sparx5, TARGET_ASM, 0 );
sparx5_get_asm_mac_stats(portstats, inst, portno);
}
mac_stats->FramesTransmittedOK = portstats[spx5_stats_tx_uc_cnt] +
portstats[spx5_stats_pmac_tx_uc_cnt] +
portstats[spx5_stats_tx_mc_cnt] +
portstats[spx5_stats_tx_bc_cnt];
mac_stats->SingleCollisionFrames =
portstats[spx5_stats_tx_backoff1_cnt];
mac_stats->MultipleCollisionFrames =
portstats[spx5_stats_tx_multi_coll_cnt];
mac_stats->FramesReceivedOK = portstats[spx5_stats_rx_uc_cnt] +
portstats[spx5_stats_pmac_rx_uc_cnt] +
portstats[spx5_stats_rx_mc_cnt] +
portstats[spx5_stats_rx_bc_cnt];
mac_stats->FrameCheckSequenceErrors =
portstats[spx5_stats_rx_crc_err_cnt] +
portstats[spx5_stats_pmac_rx_crc_err_cnt];
mac_stats->AlignmentErrors = portstats[spx5_stats_rx_alignment_lost_cnt]
+ portstats[spx5_stats_pmac_rx_alignment_lost_cnt];
mac_stats->OctetsTransmittedOK = portstats[spx5_stats_tx_ok_bytes_cnt] +
portstats[spx5_stats_pmac_tx_ok_bytes_cnt];
mac_stats->FramesWithDeferredXmissions =
portstats[spx5_stats_tx_defer_cnt];
mac_stats->LateCollisions =
portstats[spx5_stats_tx_late_coll_cnt];
mac_stats->FramesAbortedDueToXSColls =
portstats[spx5_stats_tx_xcoll_cnt];
mac_stats->CarrierSenseErrors = portstats[spx5_stats_tx_csense_cnt];
mac_stats->OctetsReceivedOK = portstats[spx5_stats_rx_ok_bytes_cnt] +
portstats[spx5_stats_pmac_rx_ok_bytes_cnt];
mac_stats->MulticastFramesXmittedOK = portstats[spx5_stats_tx_mc_cnt] +
portstats[spx5_stats_pmac_tx_mc_cnt];
mac_stats->BroadcastFramesXmittedOK = portstats[spx5_stats_tx_bc_cnt] +
portstats[spx5_stats_pmac_tx_bc_cnt];
mac_stats->FramesWithExcessiveDeferral =
portstats[spx5_stats_tx_xdefer_cnt];
mac_stats->MulticastFramesReceivedOK = portstats[spx5_stats_rx_mc_cnt] +
portstats[spx5_stats_pmac_rx_mc_cnt];
mac_stats->BroadcastFramesReceivedOK = portstats[spx5_stats_rx_bc_cnt] +
portstats[spx5_stats_pmac_rx_bc_cnt];
mac_stats->InRangeLengthErrors =
portstats[spx5_stats_rx_in_range_len_err_cnt] +
portstats[spx5_stats_pmac_rx_in_range_len_err_cnt];
mac_stats->OutOfRangeLengthField =
portstats[spx5_stats_rx_out_of_range_len_err_cnt] +
portstats[spx5_stats_pmac_rx_out_of_range_len_err_cnt];
mac_stats->FrameTooLongErrors = portstats[spx5_stats_rx_oversize_cnt] +
portstats[spx5_stats_pmac_rx_oversize_cnt];
}
static void sparx5_get_eth_mac_ctrl_stats(struct net_device *ndev,
struct ethtool_eth_ctrl_stats *mac_ctrl_stats)
{
struct sparx5_port *port = netdev_priv(ndev);
struct sparx5 *sparx5 = port->sparx5;
int portno = port->portno;
void __iomem *inst;
u64 *portstats;
portstats = &sparx5->stats[portno * sparx5->num_stats];
if (sparx5_is_baser(port->conf.portmode)) {
u32 tinst = sparx5_port_dev_index(sparx5, portno);
u32 dev = sparx5_to_high_dev(sparx5, portno);
inst = spx5_inst_get(sparx5, dev, tinst);
sparx5_get_dev_mac_ctrl_stats(portstats, inst, tinst);
} else {
inst = spx5_inst_get(sparx5, TARGET_ASM, 0 );
sparx5_get_asm_mac_ctrl_stats(portstats, inst, portno);
}
mac_ctrl_stats->MACControlFramesTransmitted =
portstats[spx5_stats_tx_pause_cnt] +
portstats[spx5_stats_pmac_tx_pause_cnt];
mac_ctrl_stats->MACControlFramesReceived =
portstats[spx5_stats_rx_pause_cnt] +
portstats[spx5_stats_pmac_rx_pause_cnt];
mac_ctrl_stats->UnsupportedOpcodesReceived =
portstats[spx5_stats_rx_unsup_opcode_cnt] +
portstats[spx5_stats_pmac_rx_unsup_opcode_cnt];
}
static void sparx5_get_eth_rmon_stats(struct net_device *ndev,
struct ethtool_rmon_stats *rmon_stats,
const struct ethtool_rmon_hist_range **ranges)
{
struct sparx5_port *port = netdev_priv(ndev);
struct sparx5 *sparx5 = port->sparx5;
int portno = port->portno;
void __iomem *inst;
u64 *portstats;
portstats = &sparx5->stats[portno * sparx5->num_stats];
if (sparx5_is_baser(port->conf.portmode)) {
u32 tinst = sparx5_port_dev_index(sparx5, portno);
u32 dev = sparx5_to_high_dev(sparx5, portno);
inst = spx5_inst_get(sparx5, dev, tinst);
sparx5_get_dev_rmon_stats(portstats, inst, tinst);
} else {
inst = spx5_inst_get(sparx5, TARGET_ASM, 0 );
sparx5_get_asm_rmon_stats(portstats, inst, portno);
}
rmon_stats->undersize_pkts = portstats[spx5_stats_rx_undersize_cnt] +
portstats[spx5_stats_pmac_rx_undersize_cnt];
rmon_stats->oversize_pkts = portstats[spx5_stats_rx_oversize_cnt] +
portstats[spx5_stats_pmac_rx_oversize_cnt];
rmon_stats->fragments = portstats[spx5_stats_rx_fragments_cnt] +
portstats[spx5_stats_pmac_rx_fragments_cnt];
rmon_stats->jabbers = portstats[spx5_stats_rx_jabbers_cnt] +
portstats[spx5_stats_pmac_rx_jabbers_cnt];
rmon_stats->hist[0 ] = portstats[spx5_stats_rx_size64_cnt] +
portstats[spx5_stats_pmac_rx_size64_cnt];
rmon_stats->hist[1 ] = portstats[spx5_stats_rx_size65to127_cnt] +
portstats[spx5_stats_pmac_rx_size65to127_cnt];
rmon_stats->hist[2 ] = portstats[spx5_stats_rx_size128to255_cnt] +
portstats[spx5_stats_pmac_rx_size128to255_cnt];
rmon_stats->hist[3 ] = portstats[spx5_stats_rx_size256to511_cnt] +
portstats[spx5_stats_pmac_rx_size256to511_cnt];
rmon_stats->hist[4 ] = portstats[spx5_stats_rx_size512to1023_cnt] +
portstats[spx5_stats_pmac_rx_size512to1023_cnt];
rmon_stats->hist[5 ] = portstats[spx5_stats_rx_size1024to1518_cnt] +
portstats[spx5_stats_pmac_rx_size1024to1518_cnt];
rmon_stats->hist[6 ] = portstats[spx5_stats_rx_size1519tomax_cnt] +
portstats[spx5_stats_pmac_rx_size1519tomax_cnt];
rmon_stats->hist_tx[0 ] = portstats[spx5_stats_tx_size64_cnt] +
portstats[spx5_stats_pmac_tx_size64_cnt];
rmon_stats->hist_tx[1 ] = portstats[spx5_stats_tx_size65to127_cnt] +
portstats[spx5_stats_pmac_tx_size65to127_cnt];
rmon_stats->hist_tx[2 ] = portstats[spx5_stats_tx_size128to255_cnt] +
portstats[spx5_stats_pmac_tx_size128to255_cnt];
rmon_stats->hist_tx[3 ] = portstats[spx5_stats_tx_size256to511_cnt] +
portstats[spx5_stats_pmac_tx_size256to511_cnt];
rmon_stats->hist_tx[4 ] = portstats[spx5_stats_tx_size512to1023_cnt] +
portstats[spx5_stats_pmac_tx_size512to1023_cnt];
rmon_stats->hist_tx[5 ] = portstats[spx5_stats_tx_size1024to1518_cnt] +
portstats[spx5_stats_pmac_tx_size1024to1518_cnt];
rmon_stats->hist_tx[6 ] = portstats[spx5_stats_tx_size1519tomax_cnt] +
portstats[spx5_stats_pmac_tx_size1519tomax_cnt];
*ranges = sparx5_rmon_ranges;
}
static int sparx5_get_sset_count(struct net_device *ndev, int sset)
{
struct sparx5_port *port = netdev_priv(ndev);
struct sparx5 *sparx5 = port->sparx5;
if (sset != ETH_SS_STATS)
return -EOPNOTSUPP;
return sparx5->num_ethtool_stats;
}
static void sparx5_get_sset_strings(struct net_device *ndev, u32 sset, u8 *data)
{
struct sparx5_port *port = netdev_priv(ndev);
struct sparx5 *sparx5 = port->sparx5;
int idx;
if (sset != ETH_SS_STATS)
return ;
for (idx = 0 ; idx < sparx5->num_ethtool_stats; idx++)
ethtool_puts(&data, sparx5->stats_layout[idx]);
}
static void sparx5_get_sset_data(struct net_device *ndev,
struct ethtool_stats *stats, u64 *data)
{
struct sparx5_port *port = netdev_priv(ndev);
struct sparx5 *sparx5 = port->sparx5;
int portno = port->portno;
void __iomem *inst;
u64 *portstats;
int idx;
portstats = &sparx5->stats[portno * sparx5->num_stats];
if (sparx5_is_baser(port->conf.portmode)) {
u32 tinst = sparx5_port_dev_index(sparx5, portno);
u32 dev = sparx5_to_high_dev(sparx5, portno);
inst = spx5_inst_get(sparx5, dev, tinst);
sparx5_get_dev_misc_stats(portstats, inst, tinst);
} else {
inst = spx5_inst_get(sparx5, TARGET_ASM, 0 );
sparx5_get_asm_misc_stats(portstats, inst, portno);
}
sparx5_get_ana_ac_stats_stats(sparx5, portno);
sparx5_get_queue_sys_stats(sparx5, portno);
/* Copy port counters to the ethtool buffer */
for (idx = spx5_stats_mm_rx_assembly_err_cnt;
idx < spx5_stats_mm_rx_assembly_err_cnt +
sparx5->num_ethtool_stats; idx++)
*data++ = portstats[idx];
}
void sparx5_get_stats64(struct net_device *ndev,
struct rtnl_link_stats64 *stats)
{
struct sparx5_port *port = netdev_priv(ndev);
struct sparx5 *sparx5 = port->sparx5;
u64 *portstats;
int idx;
if (!sparx5->stats)
return ; /* Not initialized yet */
portstats = &sparx5->stats[port->portno * sparx5->num_stats];
stats->rx_packets = portstats[spx5_stats_rx_uc_cnt] +
portstats[spx5_stats_pmac_rx_uc_cnt] +
portstats[spx5_stats_rx_mc_cnt] +
portstats[spx5_stats_rx_bc_cnt];
stats->tx_packets = portstats[spx5_stats_tx_uc_cnt] +
portstats[spx5_stats_pmac_tx_uc_cnt] +
portstats[spx5_stats_tx_mc_cnt] +
portstats[spx5_stats_tx_bc_cnt];
stats->rx_bytes = portstats[spx5_stats_rx_ok_bytes_cnt] +
portstats[spx5_stats_pmac_rx_ok_bytes_cnt];
stats->tx_bytes = portstats[spx5_stats_tx_ok_bytes_cnt] +
portstats[spx5_stats_pmac_tx_ok_bytes_cnt];
stats->rx_errors = portstats[spx5_stats_rx_in_range_len_err_cnt] +
portstats[spx5_stats_pmac_rx_in_range_len_err_cnt] +
portstats[spx5_stats_rx_out_of_range_len_err_cnt] +
portstats[spx5_stats_pmac_rx_out_of_range_len_err_cnt] +
portstats[spx5_stats_rx_oversize_cnt] +
portstats[spx5_stats_pmac_rx_oversize_cnt] +
portstats[spx5_stats_rx_crc_err_cnt] +
portstats[spx5_stats_pmac_rx_crc_err_cnt] +
portstats[spx5_stats_rx_alignment_lost_cnt] +
portstats[spx5_stats_pmac_rx_alignment_lost_cnt];
stats->tx_errors = portstats[spx5_stats_tx_xcoll_cnt] +
portstats[spx5_stats_tx_csense_cnt] +
portstats[spx5_stats_tx_late_coll_cnt];
stats->multicast = portstats[spx5_stats_rx_mc_cnt] +
portstats[spx5_stats_pmac_rx_mc_cnt];
stats->collisions = portstats[spx5_stats_tx_late_coll_cnt] +
portstats[spx5_stats_tx_xcoll_cnt] +
portstats[spx5_stats_tx_backoff1_cnt];
stats->rx_length_errors = portstats[spx5_stats_rx_in_range_len_err_cnt] +
portstats[spx5_stats_pmac_rx_in_range_len_err_cnt] +
portstats[spx5_stats_rx_out_of_range_len_err_cnt] +
portstats[spx5_stats_pmac_rx_out_of_range_len_err_cnt] +
portstats[spx5_stats_rx_oversize_cnt] +
portstats[spx5_stats_pmac_rx_oversize_cnt];
stats->rx_crc_errors = portstats[spx5_stats_rx_crc_err_cnt] +
portstats[spx5_stats_pmac_rx_crc_err_cnt];
stats->rx_frame_errors = portstats[spx5_stats_rx_alignment_lost_cnt] +
portstats[spx5_stats_pmac_rx_alignment_lost_cnt];
stats->tx_aborted_errors = portstats[spx5_stats_tx_xcoll_cnt];
stats->tx_carrier_errors = portstats[spx5_stats_tx_csense_cnt];
stats->tx_window_errors = portstats[spx5_stats_tx_late_coll_cnt];
stats->rx_dropped = portstats[spx5_stats_ana_ac_port_stat_lsb_cnt];
for (idx = 0 ; idx < 2 * SPX5_PRIOS; ++idx)
stats->rx_dropped += portstats[spx5_stats_green_p0_rx_port_drop
+ idx];
stats->tx_dropped = portstats[spx5_stats_tx_local_drop];
}
static void sparx5_update_port_stats(struct sparx5 *sparx5, int portno)
{
if (sparx5_is_baser(sparx5->ports[portno]->conf.portmode))
sparx5_get_device_stats(sparx5, portno);
else
sparx5_get_asm_stats(sparx5, portno);
sparx5_get_ana_ac_stats_stats(sparx5, portno);
sparx5_get_queue_sys_stats(sparx5, portno);
}
static void sparx5_update_stats(struct sparx5 *sparx5)
{
int idx;
for (idx = 0 ; idx < sparx5->data->consts->n_ports; idx++)
if (sparx5->ports[idx])
sparx5_update_port_stats(sparx5, idx);
}
static void sparx5_check_stats_work(struct work_struct *work)
{
struct delayed_work *dwork = to_delayed_work(work);
struct sparx5 *sparx5 = container_of(dwork,
struct sparx5,
stats_work);
sparx5_update_stats(sparx5);
queue_delayed_work(sparx5->stats_queue, &sparx5->stats_work,
SPX5_STATS_CHECK_DELAY);
}
static int sparx5_get_link_settings(struct net_device *ndev,
struct ethtool_link_ksettings *cmd)
{
struct sparx5_port *port = netdev_priv(ndev);
return phylink_ethtool_ksettings_get(port->phylink, cmd);
}
static int sparx5_set_link_settings(struct net_device *ndev,
const struct ethtool_link_ksettings *cmd)
{
struct sparx5_port *port = netdev_priv(ndev);
return phylink_ethtool_ksettings_set(port->phylink, cmd);
}
static void sparx5_config_stats(struct sparx5 *sparx5)
{
/* Enable global events for port policer drops */
spx5_rmw(ANA_AC_PORT_SGE_CFG_MASK_SET(0 xf0f0),
ANA_AC_PORT_SGE_CFG_MASK,
sparx5,
ANA_AC_PORT_SGE_CFG(SPX5_PORT_POLICER_DROPS));
}
static void sparx5_config_port_stats(struct sparx5 *sparx5, int portno)
{
/* Clear Queue System counters */
spx5_wr(XQS_STAT_CFG_STAT_VIEW_SET(portno) |
XQS_STAT_CFG_STAT_CLEAR_SHOT_SET(3 ), sparx5,
XQS_STAT_CFG);
/* Use counter for port policer drop count */
spx5_rmw(ANA_AC_PORT_STAT_CFG_CFG_CNT_FRM_TYPE_SET(1 ) |
ANA_AC_PORT_STAT_CFG_CFG_CNT_BYTE_SET(0 ) |
ANA_AC_PORT_STAT_CFG_CFG_PRIO_MASK_SET(0 xff),
ANA_AC_PORT_STAT_CFG_CFG_CNT_FRM_TYPE |
ANA_AC_PORT_STAT_CFG_CFG_CNT_BYTE |
ANA_AC_PORT_STAT_CFG_CFG_PRIO_MASK,
sparx5, ANA_AC_PORT_STAT_CFG(portno, SPX5_PORT_POLICER_DROPS));
}
static int sparx5_get_ts_info(struct net_device *dev,
struct kernel_ethtool_ts_info *info)
{
struct sparx5_port *port = netdev_priv(dev);
struct sparx5 *sparx5 = port->sparx5;
struct sparx5_phc *phc;
if (!sparx5->ptp && is_sparx5(sparx5))
return ethtool_op_get_ts_info(dev, info);
phc = &sparx5->phc[SPARX5_PHC_PORT];
if (phc->clock) {
info->phc_index = ptp_clock_index(phc->clock);
} else {
info->so_timestamping |= SOF_TIMESTAMPING_TX_SOFTWARE;
return 0 ;
}
info->so_timestamping |= SOF_TIMESTAMPING_TX_SOFTWARE |
SOF_TIMESTAMPING_TX_HARDWARE |
SOF_TIMESTAMPING_RX_HARDWARE |
SOF_TIMESTAMPING_RAW_HARDWARE;
info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON) |
BIT(HWTSTAMP_TX_ONESTEP_SYNC);
info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
BIT(HWTSTAMP_FILTER_ALL);
return 0 ;
}
const struct ethtool_ops sparx5_ethtool_ops = {
.get_sset_count = sparx5_get_sset_count,
.get_strings = sparx5_get_sset_strings,
.get_ethtool_stats = sparx5_get_sset_data,
.get_link_ksettings = sparx5_get_link_settings,
.set_link_ksettings = sparx5_set_link_settings,
.get_link = ethtool_op_get_link,
.get_eth_phy_stats = sparx5_get_eth_phy_stats,
.get_eth_mac_stats = sparx5_get_eth_mac_stats,
.get_eth_ctrl_stats = sparx5_get_eth_mac_ctrl_stats,
.get_rmon_stats = sparx5_get_eth_rmon_stats,
.get_ts_info = sparx5_get_ts_info,
};
int sparx_stats_init(struct sparx5 *sparx5)
{
const struct sparx5_consts *consts = sparx5->data->consts;
char queue_name[32 ];
int portno;
sparx5->stats_layout = sparx5_stats_layout;
sparx5->num_stats = spx5_stats_count;
sparx5->num_ethtool_stats = ARRAY_SIZE(sparx5_stats_layout);
sparx5->stats = devm_kcalloc(sparx5->dev,
consts->n_ports_all *
sparx5->num_stats,
sizeof (u64), GFP_KERNEL);
if (!sparx5->stats)
return -ENOMEM;
mutex_init(&sparx5->queue_stats_lock);
sparx5_config_stats(sparx5);
for (portno = 0 ; portno < consts->n_ports; portno++)
if (sparx5->ports[portno])
sparx5_config_port_stats(sparx5, portno);
snprintf(queue_name, sizeof (queue_name), "%s-stats" ,
dev_name(sparx5->dev));
sparx5->stats_queue = create_singlethread_workqueue(queue_name);
if (!sparx5->stats_queue)
return -ENOMEM;
INIT_DELAYED_WORK(&sparx5->stats_work, sparx5_check_stats_work);
queue_delayed_work(sparx5->stats_queue, &sparx5->stats_work,
SPX5_STATS_CHECK_DELAY);
return 0 ;
}
Messung V0.5 in Prozent C=96 H=92 G=93
¤ Dauer der Verarbeitung: 0.21 Sekunden
(vorverarbeitet am 2026-06-07)
¤
*© Formatika GbR, Deutschland