1fe90104cSVladimir Oltean // SPDX-License-Identifier: (GPL-2.0 OR MIT) 2fe90104cSVladimir Oltean /* Statistics for Ocelot switch family 3fe90104cSVladimir Oltean * 4fe90104cSVladimir Oltean * Copyright (c) 2017 Microsemi Corporation 5e32036e1SVladimir Oltean * Copyright 2022 NXP 6fe90104cSVladimir Oltean */ 7fe90104cSVladimir Oltean #include <linux/spinlock.h> 8fe90104cSVladimir Oltean #include <linux/mutex.h> 9fe90104cSVladimir Oltean #include <linux/workqueue.h> 10fe90104cSVladimir Oltean #include "ocelot.h" 11fe90104cSVladimir Oltean 12*a3bb8f52SColin Foster enum ocelot_stat { 13*a3bb8f52SColin Foster OCELOT_STAT_RX_OCTETS, 14*a3bb8f52SColin Foster OCELOT_STAT_RX_UNICAST, 15*a3bb8f52SColin Foster OCELOT_STAT_RX_MULTICAST, 16*a3bb8f52SColin Foster OCELOT_STAT_RX_BROADCAST, 17*a3bb8f52SColin Foster OCELOT_STAT_RX_SHORTS, 18*a3bb8f52SColin Foster OCELOT_STAT_RX_FRAGMENTS, 19*a3bb8f52SColin Foster OCELOT_STAT_RX_JABBERS, 20*a3bb8f52SColin Foster OCELOT_STAT_RX_CRC_ALIGN_ERRS, 21*a3bb8f52SColin Foster OCELOT_STAT_RX_SYM_ERRS, 22*a3bb8f52SColin Foster OCELOT_STAT_RX_64, 23*a3bb8f52SColin Foster OCELOT_STAT_RX_65_127, 24*a3bb8f52SColin Foster OCELOT_STAT_RX_128_255, 25*a3bb8f52SColin Foster OCELOT_STAT_RX_256_511, 26*a3bb8f52SColin Foster OCELOT_STAT_RX_512_1023, 27*a3bb8f52SColin Foster OCELOT_STAT_RX_1024_1526, 28*a3bb8f52SColin Foster OCELOT_STAT_RX_1527_MAX, 29*a3bb8f52SColin Foster OCELOT_STAT_RX_PAUSE, 30*a3bb8f52SColin Foster OCELOT_STAT_RX_CONTROL, 31*a3bb8f52SColin Foster OCELOT_STAT_RX_LONGS, 32*a3bb8f52SColin Foster OCELOT_STAT_RX_CLASSIFIED_DROPS, 33*a3bb8f52SColin Foster OCELOT_STAT_RX_RED_PRIO_0, 34*a3bb8f52SColin Foster OCELOT_STAT_RX_RED_PRIO_1, 35*a3bb8f52SColin Foster OCELOT_STAT_RX_RED_PRIO_2, 36*a3bb8f52SColin Foster OCELOT_STAT_RX_RED_PRIO_3, 37*a3bb8f52SColin Foster OCELOT_STAT_RX_RED_PRIO_4, 38*a3bb8f52SColin Foster OCELOT_STAT_RX_RED_PRIO_5, 39*a3bb8f52SColin Foster OCELOT_STAT_RX_RED_PRIO_6, 40*a3bb8f52SColin Foster OCELOT_STAT_RX_RED_PRIO_7, 41*a3bb8f52SColin Foster OCELOT_STAT_RX_YELLOW_PRIO_0, 42*a3bb8f52SColin Foster OCELOT_STAT_RX_YELLOW_PRIO_1, 43*a3bb8f52SColin Foster OCELOT_STAT_RX_YELLOW_PRIO_2, 44*a3bb8f52SColin Foster OCELOT_STAT_RX_YELLOW_PRIO_3, 45*a3bb8f52SColin Foster OCELOT_STAT_RX_YELLOW_PRIO_4, 46*a3bb8f52SColin Foster OCELOT_STAT_RX_YELLOW_PRIO_5, 47*a3bb8f52SColin Foster OCELOT_STAT_RX_YELLOW_PRIO_6, 48*a3bb8f52SColin Foster OCELOT_STAT_RX_YELLOW_PRIO_7, 49*a3bb8f52SColin Foster OCELOT_STAT_RX_GREEN_PRIO_0, 50*a3bb8f52SColin Foster OCELOT_STAT_RX_GREEN_PRIO_1, 51*a3bb8f52SColin Foster OCELOT_STAT_RX_GREEN_PRIO_2, 52*a3bb8f52SColin Foster OCELOT_STAT_RX_GREEN_PRIO_3, 53*a3bb8f52SColin Foster OCELOT_STAT_RX_GREEN_PRIO_4, 54*a3bb8f52SColin Foster OCELOT_STAT_RX_GREEN_PRIO_5, 55*a3bb8f52SColin Foster OCELOT_STAT_RX_GREEN_PRIO_6, 56*a3bb8f52SColin Foster OCELOT_STAT_RX_GREEN_PRIO_7, 57*a3bb8f52SColin Foster OCELOT_STAT_TX_OCTETS, 58*a3bb8f52SColin Foster OCELOT_STAT_TX_UNICAST, 59*a3bb8f52SColin Foster OCELOT_STAT_TX_MULTICAST, 60*a3bb8f52SColin Foster OCELOT_STAT_TX_BROADCAST, 61*a3bb8f52SColin Foster OCELOT_STAT_TX_COLLISION, 62*a3bb8f52SColin Foster OCELOT_STAT_TX_DROPS, 63*a3bb8f52SColin Foster OCELOT_STAT_TX_PAUSE, 64*a3bb8f52SColin Foster OCELOT_STAT_TX_64, 65*a3bb8f52SColin Foster OCELOT_STAT_TX_65_127, 66*a3bb8f52SColin Foster OCELOT_STAT_TX_128_255, 67*a3bb8f52SColin Foster OCELOT_STAT_TX_256_511, 68*a3bb8f52SColin Foster OCELOT_STAT_TX_512_1023, 69*a3bb8f52SColin Foster OCELOT_STAT_TX_1024_1526, 70*a3bb8f52SColin Foster OCELOT_STAT_TX_1527_MAX, 71*a3bb8f52SColin Foster OCELOT_STAT_TX_YELLOW_PRIO_0, 72*a3bb8f52SColin Foster OCELOT_STAT_TX_YELLOW_PRIO_1, 73*a3bb8f52SColin Foster OCELOT_STAT_TX_YELLOW_PRIO_2, 74*a3bb8f52SColin Foster OCELOT_STAT_TX_YELLOW_PRIO_3, 75*a3bb8f52SColin Foster OCELOT_STAT_TX_YELLOW_PRIO_4, 76*a3bb8f52SColin Foster OCELOT_STAT_TX_YELLOW_PRIO_5, 77*a3bb8f52SColin Foster OCELOT_STAT_TX_YELLOW_PRIO_6, 78*a3bb8f52SColin Foster OCELOT_STAT_TX_YELLOW_PRIO_7, 79*a3bb8f52SColin Foster OCELOT_STAT_TX_GREEN_PRIO_0, 80*a3bb8f52SColin Foster OCELOT_STAT_TX_GREEN_PRIO_1, 81*a3bb8f52SColin Foster OCELOT_STAT_TX_GREEN_PRIO_2, 82*a3bb8f52SColin Foster OCELOT_STAT_TX_GREEN_PRIO_3, 83*a3bb8f52SColin Foster OCELOT_STAT_TX_GREEN_PRIO_4, 84*a3bb8f52SColin Foster OCELOT_STAT_TX_GREEN_PRIO_5, 85*a3bb8f52SColin Foster OCELOT_STAT_TX_GREEN_PRIO_6, 86*a3bb8f52SColin Foster OCELOT_STAT_TX_GREEN_PRIO_7, 87*a3bb8f52SColin Foster OCELOT_STAT_TX_AGED, 88*a3bb8f52SColin Foster OCELOT_STAT_DROP_LOCAL, 89*a3bb8f52SColin Foster OCELOT_STAT_DROP_TAIL, 90*a3bb8f52SColin Foster OCELOT_STAT_DROP_YELLOW_PRIO_0, 91*a3bb8f52SColin Foster OCELOT_STAT_DROP_YELLOW_PRIO_1, 92*a3bb8f52SColin Foster OCELOT_STAT_DROP_YELLOW_PRIO_2, 93*a3bb8f52SColin Foster OCELOT_STAT_DROP_YELLOW_PRIO_3, 94*a3bb8f52SColin Foster OCELOT_STAT_DROP_YELLOW_PRIO_4, 95*a3bb8f52SColin Foster OCELOT_STAT_DROP_YELLOW_PRIO_5, 96*a3bb8f52SColin Foster OCELOT_STAT_DROP_YELLOW_PRIO_6, 97*a3bb8f52SColin Foster OCELOT_STAT_DROP_YELLOW_PRIO_7, 98*a3bb8f52SColin Foster OCELOT_STAT_DROP_GREEN_PRIO_0, 99*a3bb8f52SColin Foster OCELOT_STAT_DROP_GREEN_PRIO_1, 100*a3bb8f52SColin Foster OCELOT_STAT_DROP_GREEN_PRIO_2, 101*a3bb8f52SColin Foster OCELOT_STAT_DROP_GREEN_PRIO_3, 102*a3bb8f52SColin Foster OCELOT_STAT_DROP_GREEN_PRIO_4, 103*a3bb8f52SColin Foster OCELOT_STAT_DROP_GREEN_PRIO_5, 104*a3bb8f52SColin Foster OCELOT_STAT_DROP_GREEN_PRIO_6, 105*a3bb8f52SColin Foster OCELOT_STAT_DROP_GREEN_PRIO_7, 106*a3bb8f52SColin Foster OCELOT_NUM_STATS, 107*a3bb8f52SColin Foster }; 108*a3bb8f52SColin Foster 109*a3bb8f52SColin Foster struct ocelot_stat_layout { 110*a3bb8f52SColin Foster u32 reg; 111*a3bb8f52SColin Foster char name[ETH_GSTRING_LEN]; 112*a3bb8f52SColin Foster }; 113*a3bb8f52SColin Foster 114*a3bb8f52SColin Foster /* 32-bit counter checked for wraparound by ocelot_port_update_stats() 115*a3bb8f52SColin Foster * and copied to ocelot->stats. 116*a3bb8f52SColin Foster */ 117*a3bb8f52SColin Foster #define OCELOT_STAT(kind) \ 118*a3bb8f52SColin Foster [OCELOT_STAT_ ## kind] = { .reg = SYS_COUNT_ ## kind } 119*a3bb8f52SColin Foster /* Same as above, except also exported to ethtool -S. Standard counters should 120*a3bb8f52SColin Foster * only be exposed to more specific interfaces rather than by their string name. 121*a3bb8f52SColin Foster */ 122*a3bb8f52SColin Foster #define OCELOT_STAT_ETHTOOL(kind, ethtool_name) \ 123*a3bb8f52SColin Foster [OCELOT_STAT_ ## kind] = { .reg = SYS_COUNT_ ## kind, .name = ethtool_name } 124*a3bb8f52SColin Foster 125*a3bb8f52SColin Foster #define OCELOT_COMMON_STATS \ 126*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_OCTETS, "rx_octets"), \ 127*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_UNICAST, "rx_unicast"), \ 128*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_MULTICAST, "rx_multicast"), \ 129*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_BROADCAST, "rx_broadcast"), \ 130*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_SHORTS, "rx_shorts"), \ 131*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_FRAGMENTS, "rx_fragments"), \ 132*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_JABBERS, "rx_jabbers"), \ 133*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_CRC_ALIGN_ERRS, "rx_crc_align_errs"), \ 134*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_SYM_ERRS, "rx_sym_errs"), \ 135*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_64, "rx_frames_below_65_octets"), \ 136*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_65_127, "rx_frames_65_to_127_octets"), \ 137*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_128_255, "rx_frames_128_to_255_octets"), \ 138*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_256_511, "rx_frames_256_to_511_octets"), \ 139*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_512_1023, "rx_frames_512_to_1023_octets"), \ 140*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_1024_1526, "rx_frames_1024_to_1526_octets"), \ 141*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_1527_MAX, "rx_frames_over_1526_octets"), \ 142*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_PAUSE, "rx_pause"), \ 143*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_CONTROL, "rx_control"), \ 144*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_LONGS, "rx_longs"), \ 145*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_CLASSIFIED_DROPS, "rx_classified_drops"), \ 146*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_RED_PRIO_0, "rx_red_prio_0"), \ 147*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_RED_PRIO_1, "rx_red_prio_1"), \ 148*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_RED_PRIO_2, "rx_red_prio_2"), \ 149*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_RED_PRIO_3, "rx_red_prio_3"), \ 150*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_RED_PRIO_4, "rx_red_prio_4"), \ 151*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_RED_PRIO_5, "rx_red_prio_5"), \ 152*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_RED_PRIO_6, "rx_red_prio_6"), \ 153*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_RED_PRIO_7, "rx_red_prio_7"), \ 154*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_0, "rx_yellow_prio_0"), \ 155*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_1, "rx_yellow_prio_1"), \ 156*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_2, "rx_yellow_prio_2"), \ 157*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_3, "rx_yellow_prio_3"), \ 158*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_4, "rx_yellow_prio_4"), \ 159*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_5, "rx_yellow_prio_5"), \ 160*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_6, "rx_yellow_prio_6"), \ 161*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_YELLOW_PRIO_7, "rx_yellow_prio_7"), \ 162*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_0, "rx_green_prio_0"), \ 163*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_1, "rx_green_prio_1"), \ 164*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_2, "rx_green_prio_2"), \ 165*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_3, "rx_green_prio_3"), \ 166*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_4, "rx_green_prio_4"), \ 167*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_5, "rx_green_prio_5"), \ 168*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_6, "rx_green_prio_6"), \ 169*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(RX_GREEN_PRIO_7, "rx_green_prio_7"), \ 170*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(TX_OCTETS, "tx_octets"), \ 171*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(TX_UNICAST, "tx_unicast"), \ 172*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(TX_MULTICAST, "tx_multicast"), \ 173*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(TX_BROADCAST, "tx_broadcast"), \ 174*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(TX_COLLISION, "tx_collision"), \ 175*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(TX_DROPS, "tx_drops"), \ 176*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(TX_PAUSE, "tx_pause"), \ 177*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(TX_64, "tx_frames_below_65_octets"), \ 178*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(TX_65_127, "tx_frames_65_to_127_octets"), \ 179*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(TX_128_255, "tx_frames_128_255_octets"), \ 180*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(TX_256_511, "tx_frames_256_511_octets"), \ 181*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(TX_512_1023, "tx_frames_512_1023_octets"), \ 182*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(TX_1024_1526, "tx_frames_1024_1526_octets"), \ 183*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(TX_1527_MAX, "tx_frames_over_1526_octets"), \ 184*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_0, "tx_yellow_prio_0"), \ 185*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_1, "tx_yellow_prio_1"), \ 186*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_2, "tx_yellow_prio_2"), \ 187*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_3, "tx_yellow_prio_3"), \ 188*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_4, "tx_yellow_prio_4"), \ 189*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_5, "tx_yellow_prio_5"), \ 190*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_6, "tx_yellow_prio_6"), \ 191*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(TX_YELLOW_PRIO_7, "tx_yellow_prio_7"), \ 192*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_0, "tx_green_prio_0"), \ 193*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_1, "tx_green_prio_1"), \ 194*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_2, "tx_green_prio_2"), \ 195*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_3, "tx_green_prio_3"), \ 196*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_4, "tx_green_prio_4"), \ 197*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_5, "tx_green_prio_5"), \ 198*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_6, "tx_green_prio_6"), \ 199*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(TX_GREEN_PRIO_7, "tx_green_prio_7"), \ 200*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(TX_AGED, "tx_aged"), \ 201*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(DROP_LOCAL, "drop_local"), \ 202*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(DROP_TAIL, "drop_tail"), \ 203*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_0, "drop_yellow_prio_0"), \ 204*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_1, "drop_yellow_prio_1"), \ 205*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_2, "drop_yellow_prio_2"), \ 206*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_3, "drop_yellow_prio_3"), \ 207*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_4, "drop_yellow_prio_4"), \ 208*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_5, "drop_yellow_prio_5"), \ 209*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_6, "drop_yellow_prio_6"), \ 210*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(DROP_YELLOW_PRIO_7, "drop_yellow_prio_7"), \ 211*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_0, "drop_green_prio_0"), \ 212*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_1, "drop_green_prio_1"), \ 213*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_2, "drop_green_prio_2"), \ 214*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_3, "drop_green_prio_3"), \ 215*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_4, "drop_green_prio_4"), \ 216*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_5, "drop_green_prio_5"), \ 217*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_6, "drop_green_prio_6"), \ 218*a3bb8f52SColin Foster OCELOT_STAT_ETHTOOL(DROP_GREEN_PRIO_7, "drop_green_prio_7") 219*a3bb8f52SColin Foster 220*a3bb8f52SColin Foster struct ocelot_stats_region { 221*a3bb8f52SColin Foster struct list_head node; 222*a3bb8f52SColin Foster u32 base; 223*a3bb8f52SColin Foster int count; 224*a3bb8f52SColin Foster u32 *buf; 225*a3bb8f52SColin Foster }; 226*a3bb8f52SColin Foster 22733d5eeb9SColin Foster static const struct ocelot_stat_layout ocelot_stats_layout[OCELOT_NUM_STATS] = { 22833d5eeb9SColin Foster OCELOT_COMMON_STATS, 22933d5eeb9SColin Foster }; 23033d5eeb9SColin Foster 231fe90104cSVladimir Oltean /* Read the counters from hardware and keep them in region->buf. 232fe90104cSVladimir Oltean * Caller must hold &ocelot->stat_view_lock. 233fe90104cSVladimir Oltean */ 234fe90104cSVladimir Oltean static int ocelot_port_update_stats(struct ocelot *ocelot, int port) 235fe90104cSVladimir Oltean { 236fe90104cSVladimir Oltean struct ocelot_stats_region *region; 237fe90104cSVladimir Oltean int err; 238fe90104cSVladimir Oltean 239fe90104cSVladimir Oltean /* Configure the port to read the stats from */ 240fe90104cSVladimir Oltean ocelot_write(ocelot, SYS_STAT_CFG_STAT_VIEW(port), SYS_STAT_CFG); 241fe90104cSVladimir Oltean 242fe90104cSVladimir Oltean list_for_each_entry(region, &ocelot->stats_regions, node) { 243fe90104cSVladimir Oltean err = ocelot_bulk_read(ocelot, region->base, region->buf, 244fe90104cSVladimir Oltean region->count); 245fe90104cSVladimir Oltean if (err) 246fe90104cSVladimir Oltean return err; 247fe90104cSVladimir Oltean } 248fe90104cSVladimir Oltean 249fe90104cSVladimir Oltean return 0; 250fe90104cSVladimir Oltean } 251fe90104cSVladimir Oltean 252fe90104cSVladimir Oltean /* Transfer the counters from region->buf to ocelot->stats. 253fe90104cSVladimir Oltean * Caller must hold &ocelot->stat_view_lock and &ocelot->stats_lock. 254fe90104cSVladimir Oltean */ 255fe90104cSVladimir Oltean static void ocelot_port_transfer_stats(struct ocelot *ocelot, int port) 256fe90104cSVladimir Oltean { 257fe90104cSVladimir Oltean unsigned int idx = port * OCELOT_NUM_STATS; 258fe90104cSVladimir Oltean struct ocelot_stats_region *region; 259fe90104cSVladimir Oltean int j; 260fe90104cSVladimir Oltean 261fe90104cSVladimir Oltean list_for_each_entry(region, &ocelot->stats_regions, node) { 262fe90104cSVladimir Oltean for (j = 0; j < region->count; j++) { 263fe90104cSVladimir Oltean u64 *stat = &ocelot->stats[idx + j]; 264fe90104cSVladimir Oltean u64 val = region->buf[j]; 265fe90104cSVladimir Oltean 266fe90104cSVladimir Oltean if (val < (*stat & U32_MAX)) 267fe90104cSVladimir Oltean *stat += (u64)1 << 32; 268fe90104cSVladimir Oltean 269fe90104cSVladimir Oltean *stat = (*stat & ~(u64)U32_MAX) + val; 270fe90104cSVladimir Oltean } 271fe90104cSVladimir Oltean 272fe90104cSVladimir Oltean idx += region->count; 273fe90104cSVladimir Oltean } 274fe90104cSVladimir Oltean } 275fe90104cSVladimir Oltean 276fe90104cSVladimir Oltean static void ocelot_check_stats_work(struct work_struct *work) 277fe90104cSVladimir Oltean { 278fe90104cSVladimir Oltean struct delayed_work *del_work = to_delayed_work(work); 279fe90104cSVladimir Oltean struct ocelot *ocelot = container_of(del_work, struct ocelot, 280fe90104cSVladimir Oltean stats_work); 281fe90104cSVladimir Oltean int port, err; 282fe90104cSVladimir Oltean 283fe90104cSVladimir Oltean mutex_lock(&ocelot->stat_view_lock); 284fe90104cSVladimir Oltean 285fe90104cSVladimir Oltean for (port = 0; port < ocelot->num_phys_ports; port++) { 286fe90104cSVladimir Oltean err = ocelot_port_update_stats(ocelot, port); 287fe90104cSVladimir Oltean if (err) 288fe90104cSVladimir Oltean break; 289fe90104cSVladimir Oltean 290fe90104cSVladimir Oltean spin_lock(&ocelot->stats_lock); 291fe90104cSVladimir Oltean ocelot_port_transfer_stats(ocelot, port); 292fe90104cSVladimir Oltean spin_unlock(&ocelot->stats_lock); 293fe90104cSVladimir Oltean } 294fe90104cSVladimir Oltean 295fe90104cSVladimir Oltean if (!err && ocelot->ops->update_stats) 296fe90104cSVladimir Oltean ocelot->ops->update_stats(ocelot); 297fe90104cSVladimir Oltean 298fe90104cSVladimir Oltean mutex_unlock(&ocelot->stat_view_lock); 299fe90104cSVladimir Oltean 300fe90104cSVladimir Oltean if (err) 301fe90104cSVladimir Oltean dev_err(ocelot->dev, "Error %d updating ethtool stats\n", err); 302fe90104cSVladimir Oltean 303fe90104cSVladimir Oltean queue_delayed_work(ocelot->stats_queue, &ocelot->stats_work, 304fe90104cSVladimir Oltean OCELOT_STATS_CHECK_DELAY); 305fe90104cSVladimir Oltean } 306fe90104cSVladimir Oltean 307fe90104cSVladimir Oltean void ocelot_get_strings(struct ocelot *ocelot, int port, u32 sset, u8 *data) 308fe90104cSVladimir Oltean { 309fe90104cSVladimir Oltean int i; 310fe90104cSVladimir Oltean 311fe90104cSVladimir Oltean if (sset != ETH_SS_STATS) 312fe90104cSVladimir Oltean return; 313fe90104cSVladimir Oltean 314fe90104cSVladimir Oltean for (i = 0; i < OCELOT_NUM_STATS; i++) { 31533d5eeb9SColin Foster if (ocelot_stats_layout[i].name[0] == '\0') 316fe90104cSVladimir Oltean continue; 317fe90104cSVladimir Oltean 31833d5eeb9SColin Foster memcpy(data + i * ETH_GSTRING_LEN, ocelot_stats_layout[i].name, 319fe90104cSVladimir Oltean ETH_GSTRING_LEN); 320fe90104cSVladimir Oltean } 321fe90104cSVladimir Oltean } 322fe90104cSVladimir Oltean EXPORT_SYMBOL(ocelot_get_strings); 323fe90104cSVladimir Oltean 324e32036e1SVladimir Oltean /* Update ocelot->stats for the given port and run the given callback */ 325e32036e1SVladimir Oltean static void ocelot_port_stats_run(struct ocelot *ocelot, int port, void *priv, 326e32036e1SVladimir Oltean void (*cb)(struct ocelot *ocelot, int port, 327e32036e1SVladimir Oltean void *priv)) 328fe90104cSVladimir Oltean { 329e32036e1SVladimir Oltean int err; 330fe90104cSVladimir Oltean 331fe90104cSVladimir Oltean mutex_lock(&ocelot->stat_view_lock); 332fe90104cSVladimir Oltean 333fe90104cSVladimir Oltean err = ocelot_port_update_stats(ocelot, port); 334e32036e1SVladimir Oltean if (err) { 335e32036e1SVladimir Oltean dev_err(ocelot->dev, "Failed to update port %d stats: %pe\n", 336e32036e1SVladimir Oltean port, ERR_PTR(err)); 337e32036e1SVladimir Oltean goto out_unlock; 338e32036e1SVladimir Oltean } 339fe90104cSVladimir Oltean 340fe90104cSVladimir Oltean spin_lock(&ocelot->stats_lock); 341fe90104cSVladimir Oltean 342fe90104cSVladimir Oltean ocelot_port_transfer_stats(ocelot, port); 343e32036e1SVladimir Oltean cb(ocelot, port, priv); 344fe90104cSVladimir Oltean 345fe90104cSVladimir Oltean spin_unlock(&ocelot->stats_lock); 346fe90104cSVladimir Oltean 347e32036e1SVladimir Oltean out_unlock: 348fe90104cSVladimir Oltean mutex_unlock(&ocelot->stat_view_lock); 349fe90104cSVladimir Oltean } 350fe90104cSVladimir Oltean 351fe90104cSVladimir Oltean int ocelot_get_sset_count(struct ocelot *ocelot, int port, int sset) 352fe90104cSVladimir Oltean { 353fe90104cSVladimir Oltean int i, num_stats = 0; 354fe90104cSVladimir Oltean 355fe90104cSVladimir Oltean if (sset != ETH_SS_STATS) 356fe90104cSVladimir Oltean return -EOPNOTSUPP; 357fe90104cSVladimir Oltean 358fe90104cSVladimir Oltean for (i = 0; i < OCELOT_NUM_STATS; i++) 35933d5eeb9SColin Foster if (ocelot_stats_layout[i].name[0] != '\0') 360fe90104cSVladimir Oltean num_stats++; 361fe90104cSVladimir Oltean 362fe90104cSVladimir Oltean return num_stats; 363fe90104cSVladimir Oltean } 364fe90104cSVladimir Oltean EXPORT_SYMBOL(ocelot_get_sset_count); 365fe90104cSVladimir Oltean 366e32036e1SVladimir Oltean static void ocelot_port_ethtool_stats_cb(struct ocelot *ocelot, int port, 367e32036e1SVladimir Oltean void *priv) 368e32036e1SVladimir Oltean { 369e32036e1SVladimir Oltean u64 *data = priv; 370e32036e1SVladimir Oltean int i; 371e32036e1SVladimir Oltean 372e32036e1SVladimir Oltean /* Copy all supported counters */ 373e32036e1SVladimir Oltean for (i = 0; i < OCELOT_NUM_STATS; i++) { 374e32036e1SVladimir Oltean int index = port * OCELOT_NUM_STATS + i; 375e32036e1SVladimir Oltean 37633d5eeb9SColin Foster if (ocelot_stats_layout[i].name[0] == '\0') 377e32036e1SVladimir Oltean continue; 378e32036e1SVladimir Oltean 379e32036e1SVladimir Oltean *data++ = ocelot->stats[index]; 380e32036e1SVladimir Oltean } 381e32036e1SVladimir Oltean } 382e32036e1SVladimir Oltean 383e32036e1SVladimir Oltean void ocelot_get_ethtool_stats(struct ocelot *ocelot, int port, u64 *data) 384e32036e1SVladimir Oltean { 385e32036e1SVladimir Oltean ocelot_port_stats_run(ocelot, port, data, ocelot_port_ethtool_stats_cb); 386e32036e1SVladimir Oltean } 387e32036e1SVladimir Oltean EXPORT_SYMBOL(ocelot_get_ethtool_stats); 388e32036e1SVladimir Oltean 389e32036e1SVladimir Oltean static void ocelot_port_pause_stats_cb(struct ocelot *ocelot, int port, void *priv) 390e32036e1SVladimir Oltean { 391e32036e1SVladimir Oltean u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS]; 392e32036e1SVladimir Oltean struct ethtool_pause_stats *pause_stats = priv; 393e32036e1SVladimir Oltean 394e32036e1SVladimir Oltean pause_stats->tx_pause_frames = s[OCELOT_STAT_TX_PAUSE]; 395e32036e1SVladimir Oltean pause_stats->rx_pause_frames = s[OCELOT_STAT_RX_PAUSE]; 396e32036e1SVladimir Oltean } 397e32036e1SVladimir Oltean 398e32036e1SVladimir Oltean void ocelot_port_get_pause_stats(struct ocelot *ocelot, int port, 399e32036e1SVladimir Oltean struct ethtool_pause_stats *pause_stats) 400e32036e1SVladimir Oltean { 401e32036e1SVladimir Oltean ocelot_port_stats_run(ocelot, port, pause_stats, 402e32036e1SVladimir Oltean ocelot_port_pause_stats_cb); 403e32036e1SVladimir Oltean } 404e32036e1SVladimir Oltean EXPORT_SYMBOL_GPL(ocelot_port_get_pause_stats); 405e32036e1SVladimir Oltean 406e32036e1SVladimir Oltean static const struct ethtool_rmon_hist_range ocelot_rmon_ranges[] = { 407e32036e1SVladimir Oltean { 64, 64 }, 408e32036e1SVladimir Oltean { 65, 127 }, 409e32036e1SVladimir Oltean { 128, 255 }, 410e32036e1SVladimir Oltean { 256, 511 }, 411e32036e1SVladimir Oltean { 512, 1023 }, 412e32036e1SVladimir Oltean { 1024, 1526 }, 413e32036e1SVladimir Oltean { 1527, 65535 }, 414e32036e1SVladimir Oltean {}, 415e32036e1SVladimir Oltean }; 416e32036e1SVladimir Oltean 417e32036e1SVladimir Oltean static void ocelot_port_rmon_stats_cb(struct ocelot *ocelot, int port, void *priv) 418e32036e1SVladimir Oltean { 419e32036e1SVladimir Oltean u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS]; 420e32036e1SVladimir Oltean struct ethtool_rmon_stats *rmon_stats = priv; 421e32036e1SVladimir Oltean 422e32036e1SVladimir Oltean rmon_stats->undersize_pkts = s[OCELOT_STAT_RX_SHORTS]; 423e32036e1SVladimir Oltean rmon_stats->oversize_pkts = s[OCELOT_STAT_RX_LONGS]; 424e32036e1SVladimir Oltean rmon_stats->fragments = s[OCELOT_STAT_RX_FRAGMENTS]; 425e32036e1SVladimir Oltean rmon_stats->jabbers = s[OCELOT_STAT_RX_JABBERS]; 426e32036e1SVladimir Oltean 427e32036e1SVladimir Oltean rmon_stats->hist[0] = s[OCELOT_STAT_RX_64]; 428e32036e1SVladimir Oltean rmon_stats->hist[1] = s[OCELOT_STAT_RX_65_127]; 429e32036e1SVladimir Oltean rmon_stats->hist[2] = s[OCELOT_STAT_RX_128_255]; 430e32036e1SVladimir Oltean rmon_stats->hist[3] = s[OCELOT_STAT_RX_256_511]; 431e32036e1SVladimir Oltean rmon_stats->hist[4] = s[OCELOT_STAT_RX_512_1023]; 432e32036e1SVladimir Oltean rmon_stats->hist[5] = s[OCELOT_STAT_RX_1024_1526]; 433e32036e1SVladimir Oltean rmon_stats->hist[6] = s[OCELOT_STAT_RX_1527_MAX]; 434e32036e1SVladimir Oltean 435e32036e1SVladimir Oltean rmon_stats->hist_tx[0] = s[OCELOT_STAT_TX_64]; 436e32036e1SVladimir Oltean rmon_stats->hist_tx[1] = s[OCELOT_STAT_TX_65_127]; 437e32036e1SVladimir Oltean rmon_stats->hist_tx[2] = s[OCELOT_STAT_TX_128_255]; 438e32036e1SVladimir Oltean rmon_stats->hist_tx[3] = s[OCELOT_STAT_TX_128_255]; 439e32036e1SVladimir Oltean rmon_stats->hist_tx[4] = s[OCELOT_STAT_TX_256_511]; 440e32036e1SVladimir Oltean rmon_stats->hist_tx[5] = s[OCELOT_STAT_TX_512_1023]; 441e32036e1SVladimir Oltean rmon_stats->hist_tx[6] = s[OCELOT_STAT_TX_1024_1526]; 442e32036e1SVladimir Oltean } 443e32036e1SVladimir Oltean 444e32036e1SVladimir Oltean void ocelot_port_get_rmon_stats(struct ocelot *ocelot, int port, 445e32036e1SVladimir Oltean struct ethtool_rmon_stats *rmon_stats, 446e32036e1SVladimir Oltean const struct ethtool_rmon_hist_range **ranges) 447e32036e1SVladimir Oltean { 448e32036e1SVladimir Oltean *ranges = ocelot_rmon_ranges; 449e32036e1SVladimir Oltean 450e32036e1SVladimir Oltean ocelot_port_stats_run(ocelot, port, rmon_stats, 451e32036e1SVladimir Oltean ocelot_port_rmon_stats_cb); 452e32036e1SVladimir Oltean } 453e32036e1SVladimir Oltean EXPORT_SYMBOL_GPL(ocelot_port_get_rmon_stats); 454e32036e1SVladimir Oltean 455e32036e1SVladimir Oltean static void ocelot_port_ctrl_stats_cb(struct ocelot *ocelot, int port, void *priv) 456e32036e1SVladimir Oltean { 457e32036e1SVladimir Oltean u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS]; 458e32036e1SVladimir Oltean struct ethtool_eth_ctrl_stats *ctrl_stats = priv; 459e32036e1SVladimir Oltean 460e32036e1SVladimir Oltean ctrl_stats->MACControlFramesReceived = s[OCELOT_STAT_RX_CONTROL]; 461e32036e1SVladimir Oltean } 462e32036e1SVladimir Oltean 463e32036e1SVladimir Oltean void ocelot_port_get_eth_ctrl_stats(struct ocelot *ocelot, int port, 464e32036e1SVladimir Oltean struct ethtool_eth_ctrl_stats *ctrl_stats) 465e32036e1SVladimir Oltean { 466e32036e1SVladimir Oltean ocelot_port_stats_run(ocelot, port, ctrl_stats, 467e32036e1SVladimir Oltean ocelot_port_ctrl_stats_cb); 468e32036e1SVladimir Oltean } 469e32036e1SVladimir Oltean EXPORT_SYMBOL_GPL(ocelot_port_get_eth_ctrl_stats); 470e32036e1SVladimir Oltean 471e32036e1SVladimir Oltean static void ocelot_port_mac_stats_cb(struct ocelot *ocelot, int port, void *priv) 472e32036e1SVladimir Oltean { 473e32036e1SVladimir Oltean u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS]; 474e32036e1SVladimir Oltean struct ethtool_eth_mac_stats *mac_stats = priv; 475e32036e1SVladimir Oltean 476e32036e1SVladimir Oltean mac_stats->OctetsTransmittedOK = s[OCELOT_STAT_TX_OCTETS]; 477e32036e1SVladimir Oltean mac_stats->FramesTransmittedOK = s[OCELOT_STAT_TX_64] + 478e32036e1SVladimir Oltean s[OCELOT_STAT_TX_65_127] + 479e32036e1SVladimir Oltean s[OCELOT_STAT_TX_128_255] + 480e32036e1SVladimir Oltean s[OCELOT_STAT_TX_256_511] + 481e32036e1SVladimir Oltean s[OCELOT_STAT_TX_512_1023] + 482e32036e1SVladimir Oltean s[OCELOT_STAT_TX_1024_1526] + 483e32036e1SVladimir Oltean s[OCELOT_STAT_TX_1527_MAX]; 484e32036e1SVladimir Oltean mac_stats->OctetsReceivedOK = s[OCELOT_STAT_RX_OCTETS]; 485e32036e1SVladimir Oltean mac_stats->FramesReceivedOK = s[OCELOT_STAT_RX_GREEN_PRIO_0] + 486e32036e1SVladimir Oltean s[OCELOT_STAT_RX_GREEN_PRIO_1] + 487e32036e1SVladimir Oltean s[OCELOT_STAT_RX_GREEN_PRIO_2] + 488e32036e1SVladimir Oltean s[OCELOT_STAT_RX_GREEN_PRIO_3] + 489e32036e1SVladimir Oltean s[OCELOT_STAT_RX_GREEN_PRIO_4] + 490e32036e1SVladimir Oltean s[OCELOT_STAT_RX_GREEN_PRIO_5] + 491e32036e1SVladimir Oltean s[OCELOT_STAT_RX_GREEN_PRIO_6] + 492e32036e1SVladimir Oltean s[OCELOT_STAT_RX_GREEN_PRIO_7] + 493e32036e1SVladimir Oltean s[OCELOT_STAT_RX_YELLOW_PRIO_0] + 494e32036e1SVladimir Oltean s[OCELOT_STAT_RX_YELLOW_PRIO_1] + 495e32036e1SVladimir Oltean s[OCELOT_STAT_RX_YELLOW_PRIO_2] + 496e32036e1SVladimir Oltean s[OCELOT_STAT_RX_YELLOW_PRIO_3] + 497e32036e1SVladimir Oltean s[OCELOT_STAT_RX_YELLOW_PRIO_4] + 498e32036e1SVladimir Oltean s[OCELOT_STAT_RX_YELLOW_PRIO_5] + 499e32036e1SVladimir Oltean s[OCELOT_STAT_RX_YELLOW_PRIO_6] + 500e32036e1SVladimir Oltean s[OCELOT_STAT_RX_YELLOW_PRIO_7]; 501e32036e1SVladimir Oltean mac_stats->MulticastFramesXmittedOK = s[OCELOT_STAT_TX_MULTICAST]; 502e32036e1SVladimir Oltean mac_stats->BroadcastFramesXmittedOK = s[OCELOT_STAT_TX_BROADCAST]; 503e32036e1SVladimir Oltean mac_stats->MulticastFramesReceivedOK = s[OCELOT_STAT_RX_MULTICAST]; 504e32036e1SVladimir Oltean mac_stats->BroadcastFramesReceivedOK = s[OCELOT_STAT_RX_BROADCAST]; 505e32036e1SVladimir Oltean mac_stats->FrameTooLongErrors = s[OCELOT_STAT_RX_LONGS]; 506e32036e1SVladimir Oltean /* Sadly, C_RX_CRC is the sum of FCS and alignment errors, they are not 507e32036e1SVladimir Oltean * counted individually. 508e32036e1SVladimir Oltean */ 509e32036e1SVladimir Oltean mac_stats->FrameCheckSequenceErrors = s[OCELOT_STAT_RX_CRC_ALIGN_ERRS]; 510e32036e1SVladimir Oltean mac_stats->AlignmentErrors = s[OCELOT_STAT_RX_CRC_ALIGN_ERRS]; 511e32036e1SVladimir Oltean } 512e32036e1SVladimir Oltean 513e32036e1SVladimir Oltean void ocelot_port_get_eth_mac_stats(struct ocelot *ocelot, int port, 514e32036e1SVladimir Oltean struct ethtool_eth_mac_stats *mac_stats) 515e32036e1SVladimir Oltean { 516e32036e1SVladimir Oltean ocelot_port_stats_run(ocelot, port, mac_stats, 517e32036e1SVladimir Oltean ocelot_port_mac_stats_cb); 518e32036e1SVladimir Oltean } 519e32036e1SVladimir Oltean EXPORT_SYMBOL_GPL(ocelot_port_get_eth_mac_stats); 520e32036e1SVladimir Oltean 521e32036e1SVladimir Oltean static void ocelot_port_phy_stats_cb(struct ocelot *ocelot, int port, void *priv) 522e32036e1SVladimir Oltean { 523e32036e1SVladimir Oltean u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS]; 524e32036e1SVladimir Oltean struct ethtool_eth_phy_stats *phy_stats = priv; 525e32036e1SVladimir Oltean 526e32036e1SVladimir Oltean phy_stats->SymbolErrorDuringCarrier = s[OCELOT_STAT_RX_SYM_ERRS]; 527e32036e1SVladimir Oltean } 528e32036e1SVladimir Oltean 529e32036e1SVladimir Oltean void ocelot_port_get_eth_phy_stats(struct ocelot *ocelot, int port, 530e32036e1SVladimir Oltean struct ethtool_eth_phy_stats *phy_stats) 531e32036e1SVladimir Oltean { 532e32036e1SVladimir Oltean ocelot_port_stats_run(ocelot, port, phy_stats, 533e32036e1SVladimir Oltean ocelot_port_phy_stats_cb); 534e32036e1SVladimir Oltean } 535e32036e1SVladimir Oltean EXPORT_SYMBOL_GPL(ocelot_port_get_eth_phy_stats); 536e32036e1SVladimir Oltean 537776b71e5SVladimir Oltean void ocelot_port_get_stats64(struct ocelot *ocelot, int port, 538776b71e5SVladimir Oltean struct rtnl_link_stats64 *stats) 539776b71e5SVladimir Oltean { 540776b71e5SVladimir Oltean u64 *s = &ocelot->stats[port * OCELOT_NUM_STATS]; 541776b71e5SVladimir Oltean 542776b71e5SVladimir Oltean spin_lock(&ocelot->stats_lock); 543776b71e5SVladimir Oltean 544776b71e5SVladimir Oltean /* Get Rx stats */ 545776b71e5SVladimir Oltean stats->rx_bytes = s[OCELOT_STAT_RX_OCTETS]; 546776b71e5SVladimir Oltean stats->rx_packets = s[OCELOT_STAT_RX_SHORTS] + 547776b71e5SVladimir Oltean s[OCELOT_STAT_RX_FRAGMENTS] + 548776b71e5SVladimir Oltean s[OCELOT_STAT_RX_JABBERS] + 549776b71e5SVladimir Oltean s[OCELOT_STAT_RX_LONGS] + 550776b71e5SVladimir Oltean s[OCELOT_STAT_RX_64] + 551776b71e5SVladimir Oltean s[OCELOT_STAT_RX_65_127] + 552776b71e5SVladimir Oltean s[OCELOT_STAT_RX_128_255] + 553776b71e5SVladimir Oltean s[OCELOT_STAT_RX_256_511] + 554776b71e5SVladimir Oltean s[OCELOT_STAT_RX_512_1023] + 555776b71e5SVladimir Oltean s[OCELOT_STAT_RX_1024_1526] + 556776b71e5SVladimir Oltean s[OCELOT_STAT_RX_1527_MAX]; 557776b71e5SVladimir Oltean stats->multicast = s[OCELOT_STAT_RX_MULTICAST]; 558776b71e5SVladimir Oltean stats->rx_missed_errors = s[OCELOT_STAT_DROP_TAIL]; 559776b71e5SVladimir Oltean stats->rx_dropped = s[OCELOT_STAT_RX_RED_PRIO_0] + 560776b71e5SVladimir Oltean s[OCELOT_STAT_RX_RED_PRIO_1] + 561776b71e5SVladimir Oltean s[OCELOT_STAT_RX_RED_PRIO_2] + 562776b71e5SVladimir Oltean s[OCELOT_STAT_RX_RED_PRIO_3] + 563776b71e5SVladimir Oltean s[OCELOT_STAT_RX_RED_PRIO_4] + 564776b71e5SVladimir Oltean s[OCELOT_STAT_RX_RED_PRIO_5] + 565776b71e5SVladimir Oltean s[OCELOT_STAT_RX_RED_PRIO_6] + 566776b71e5SVladimir Oltean s[OCELOT_STAT_RX_RED_PRIO_7] + 567776b71e5SVladimir Oltean s[OCELOT_STAT_DROP_LOCAL] + 568776b71e5SVladimir Oltean s[OCELOT_STAT_DROP_YELLOW_PRIO_0] + 569776b71e5SVladimir Oltean s[OCELOT_STAT_DROP_YELLOW_PRIO_1] + 570776b71e5SVladimir Oltean s[OCELOT_STAT_DROP_YELLOW_PRIO_2] + 571776b71e5SVladimir Oltean s[OCELOT_STAT_DROP_YELLOW_PRIO_3] + 572776b71e5SVladimir Oltean s[OCELOT_STAT_DROP_YELLOW_PRIO_4] + 573776b71e5SVladimir Oltean s[OCELOT_STAT_DROP_YELLOW_PRIO_5] + 574776b71e5SVladimir Oltean s[OCELOT_STAT_DROP_YELLOW_PRIO_6] + 575776b71e5SVladimir Oltean s[OCELOT_STAT_DROP_YELLOW_PRIO_7] + 576776b71e5SVladimir Oltean s[OCELOT_STAT_DROP_GREEN_PRIO_0] + 577776b71e5SVladimir Oltean s[OCELOT_STAT_DROP_GREEN_PRIO_1] + 578776b71e5SVladimir Oltean s[OCELOT_STAT_DROP_GREEN_PRIO_2] + 579776b71e5SVladimir Oltean s[OCELOT_STAT_DROP_GREEN_PRIO_3] + 580776b71e5SVladimir Oltean s[OCELOT_STAT_DROP_GREEN_PRIO_4] + 581776b71e5SVladimir Oltean s[OCELOT_STAT_DROP_GREEN_PRIO_5] + 582776b71e5SVladimir Oltean s[OCELOT_STAT_DROP_GREEN_PRIO_6] + 583776b71e5SVladimir Oltean s[OCELOT_STAT_DROP_GREEN_PRIO_7]; 584776b71e5SVladimir Oltean 585776b71e5SVladimir Oltean /* Get Tx stats */ 586776b71e5SVladimir Oltean stats->tx_bytes = s[OCELOT_STAT_TX_OCTETS]; 587776b71e5SVladimir Oltean stats->tx_packets = s[OCELOT_STAT_TX_64] + 588776b71e5SVladimir Oltean s[OCELOT_STAT_TX_65_127] + 589776b71e5SVladimir Oltean s[OCELOT_STAT_TX_128_255] + 590776b71e5SVladimir Oltean s[OCELOT_STAT_TX_256_511] + 591776b71e5SVladimir Oltean s[OCELOT_STAT_TX_512_1023] + 592776b71e5SVladimir Oltean s[OCELOT_STAT_TX_1024_1526] + 593776b71e5SVladimir Oltean s[OCELOT_STAT_TX_1527_MAX]; 594776b71e5SVladimir Oltean stats->tx_dropped = s[OCELOT_STAT_TX_DROPS] + 595776b71e5SVladimir Oltean s[OCELOT_STAT_TX_AGED]; 596776b71e5SVladimir Oltean stats->collisions = s[OCELOT_STAT_TX_COLLISION]; 597776b71e5SVladimir Oltean 598776b71e5SVladimir Oltean spin_unlock(&ocelot->stats_lock); 599776b71e5SVladimir Oltean } 600776b71e5SVladimir Oltean EXPORT_SYMBOL(ocelot_port_get_stats64); 601776b71e5SVladimir Oltean 602fe90104cSVladimir Oltean static int ocelot_prepare_stats_regions(struct ocelot *ocelot) 603fe90104cSVladimir Oltean { 604fe90104cSVladimir Oltean struct ocelot_stats_region *region = NULL; 605fe90104cSVladimir Oltean unsigned int last; 606fe90104cSVladimir Oltean int i; 607fe90104cSVladimir Oltean 608fe90104cSVladimir Oltean INIT_LIST_HEAD(&ocelot->stats_regions); 609fe90104cSVladimir Oltean 610fe90104cSVladimir Oltean for (i = 0; i < OCELOT_NUM_STATS; i++) { 61133d5eeb9SColin Foster if (!ocelot_stats_layout[i].reg) 612fe90104cSVladimir Oltean continue; 613fe90104cSVladimir Oltean 61433d5eeb9SColin Foster if (region && ocelot_stats_layout[i].reg == last + 4) { 615fe90104cSVladimir Oltean region->count++; 616fe90104cSVladimir Oltean } else { 617fe90104cSVladimir Oltean region = devm_kzalloc(ocelot->dev, sizeof(*region), 618fe90104cSVladimir Oltean GFP_KERNEL); 619fe90104cSVladimir Oltean if (!region) 620fe90104cSVladimir Oltean return -ENOMEM; 621fe90104cSVladimir Oltean 62233d5eeb9SColin Foster region->base = ocelot_stats_layout[i].reg; 623fe90104cSVladimir Oltean region->count = 1; 624fe90104cSVladimir Oltean list_add_tail(®ion->node, &ocelot->stats_regions); 625fe90104cSVladimir Oltean } 626fe90104cSVladimir Oltean 62733d5eeb9SColin Foster last = ocelot_stats_layout[i].reg; 628fe90104cSVladimir Oltean } 629fe90104cSVladimir Oltean 630fe90104cSVladimir Oltean list_for_each_entry(region, &ocelot->stats_regions, node) { 631fe90104cSVladimir Oltean region->buf = devm_kcalloc(ocelot->dev, region->count, 632fe90104cSVladimir Oltean sizeof(*region->buf), GFP_KERNEL); 633fe90104cSVladimir Oltean if (!region->buf) 634fe90104cSVladimir Oltean return -ENOMEM; 635fe90104cSVladimir Oltean } 636fe90104cSVladimir Oltean 637fe90104cSVladimir Oltean return 0; 638fe90104cSVladimir Oltean } 639fe90104cSVladimir Oltean 640fe90104cSVladimir Oltean int ocelot_stats_init(struct ocelot *ocelot) 641fe90104cSVladimir Oltean { 642fe90104cSVladimir Oltean char queue_name[32]; 643fe90104cSVladimir Oltean int ret; 644fe90104cSVladimir Oltean 645fe90104cSVladimir Oltean ocelot->stats = devm_kcalloc(ocelot->dev, 646fe90104cSVladimir Oltean ocelot->num_phys_ports * OCELOT_NUM_STATS, 647fe90104cSVladimir Oltean sizeof(u64), GFP_KERNEL); 648fe90104cSVladimir Oltean if (!ocelot->stats) 649fe90104cSVladimir Oltean return -ENOMEM; 650fe90104cSVladimir Oltean 651fe90104cSVladimir Oltean snprintf(queue_name, sizeof(queue_name), "%s-stats", 652fe90104cSVladimir Oltean dev_name(ocelot->dev)); 653fe90104cSVladimir Oltean ocelot->stats_queue = create_singlethread_workqueue(queue_name); 654fe90104cSVladimir Oltean if (!ocelot->stats_queue) 655fe90104cSVladimir Oltean return -ENOMEM; 656fe90104cSVladimir Oltean 657fe90104cSVladimir Oltean spin_lock_init(&ocelot->stats_lock); 658fe90104cSVladimir Oltean mutex_init(&ocelot->stat_view_lock); 659fe90104cSVladimir Oltean 660fe90104cSVladimir Oltean ret = ocelot_prepare_stats_regions(ocelot); 661fe90104cSVladimir Oltean if (ret) { 662fe90104cSVladimir Oltean destroy_workqueue(ocelot->stats_queue); 663fe90104cSVladimir Oltean return ret; 664fe90104cSVladimir Oltean } 665fe90104cSVladimir Oltean 666fe90104cSVladimir Oltean INIT_DELAYED_WORK(&ocelot->stats_work, ocelot_check_stats_work); 667fe90104cSVladimir Oltean queue_delayed_work(ocelot->stats_queue, &ocelot->stats_work, 668fe90104cSVladimir Oltean OCELOT_STATS_CHECK_DELAY); 669fe90104cSVladimir Oltean 670fe90104cSVladimir Oltean return 0; 671fe90104cSVladimir Oltean } 672fe90104cSVladimir Oltean 673fe90104cSVladimir Oltean void ocelot_stats_deinit(struct ocelot *ocelot) 674fe90104cSVladimir Oltean { 675fe90104cSVladimir Oltean cancel_delayed_work(&ocelot->stats_work); 676fe90104cSVladimir Oltean destroy_workqueue(ocelot->stats_queue); 677fe90104cSVladimir Oltean } 678*a3bb8f52SColin Foster 679