717 lines · c
1// SPDX-License-Identifier: GPL-2.0+2 3#include <linux/netdevice.h>4 5#include "lan966x_main.h"6 7/* Number of traffic classes */8#define LAN966X_NUM_TC 89#define LAN966X_STATS_CHECK_DELAY (2 * HZ)10 11static const struct lan966x_stat_layout lan966x_stats_layout[] = {12 { .name = "rx_octets", .offset = 0x00, },13 { .name = "rx_unicast", .offset = 0x01, },14 { .name = "rx_multicast", .offset = 0x02 },15 { .name = "rx_broadcast", .offset = 0x03 },16 { .name = "rx_short", .offset = 0x04 },17 { .name = "rx_frag", .offset = 0x05 },18 { .name = "rx_jabber", .offset = 0x06 },19 { .name = "rx_crc", .offset = 0x07 },20 { .name = "rx_symbol_err", .offset = 0x08 },21 { .name = "rx_sz_64", .offset = 0x09 },22 { .name = "rx_sz_65_127", .offset = 0x0a},23 { .name = "rx_sz_128_255", .offset = 0x0b},24 { .name = "rx_sz_256_511", .offset = 0x0c },25 { .name = "rx_sz_512_1023", .offset = 0x0d },26 { .name = "rx_sz_1024_1526", .offset = 0x0e },27 { .name = "rx_sz_jumbo", .offset = 0x0f },28 { .name = "rx_pause", .offset = 0x10 },29 { .name = "rx_control", .offset = 0x11 },30 { .name = "rx_long", .offset = 0x12 },31 { .name = "rx_cat_drop", .offset = 0x13 },32 { .name = "rx_red_prio_0", .offset = 0x14 },33 { .name = "rx_red_prio_1", .offset = 0x15 },34 { .name = "rx_red_prio_2", .offset = 0x16 },35 { .name = "rx_red_prio_3", .offset = 0x17 },36 { .name = "rx_red_prio_4", .offset = 0x18 },37 { .name = "rx_red_prio_5", .offset = 0x19 },38 { .name = "rx_red_prio_6", .offset = 0x1a },39 { .name = "rx_red_prio_7", .offset = 0x1b },40 { .name = "rx_yellow_prio_0", .offset = 0x1c },41 { .name = "rx_yellow_prio_1", .offset = 0x1d },42 { .name = "rx_yellow_prio_2", .offset = 0x1e },43 { .name = "rx_yellow_prio_3", .offset = 0x1f },44 { .name = "rx_yellow_prio_4", .offset = 0x20 },45 { .name = "rx_yellow_prio_5", .offset = 0x21 },46 { .name = "rx_yellow_prio_6", .offset = 0x22 },47 { .name = "rx_yellow_prio_7", .offset = 0x23 },48 { .name = "rx_green_prio_0", .offset = 0x24 },49 { .name = "rx_green_prio_1", .offset = 0x25 },50 { .name = "rx_green_prio_2", .offset = 0x26 },51 { .name = "rx_green_prio_3", .offset = 0x27 },52 { .name = "rx_green_prio_4", .offset = 0x28 },53 { .name = "rx_green_prio_5", .offset = 0x29 },54 { .name = "rx_green_prio_6", .offset = 0x2a },55 { .name = "rx_green_prio_7", .offset = 0x2b },56 { .name = "rx_assembly_err", .offset = 0x2c },57 { .name = "rx_smd_err", .offset = 0x2d },58 { .name = "rx_assembly_ok", .offset = 0x2e },59 { .name = "rx_merge_frag", .offset = 0x2f },60 { .name = "rx_pmac_octets", .offset = 0x30, },61 { .name = "rx_pmac_unicast", .offset = 0x31, },62 { .name = "rx_pmac_multicast", .offset = 0x32 },63 { .name = "rx_pmac_broadcast", .offset = 0x33 },64 { .name = "rx_pmac_short", .offset = 0x34 },65 { .name = "rx_pmac_frag", .offset = 0x35 },66 { .name = "rx_pmac_jabber", .offset = 0x36 },67 { .name = "rx_pmac_crc", .offset = 0x37 },68 { .name = "rx_pmac_symbol_err", .offset = 0x38 },69 { .name = "rx_pmac_sz_64", .offset = 0x39 },70 { .name = "rx_pmac_sz_65_127", .offset = 0x3a },71 { .name = "rx_pmac_sz_128_255", .offset = 0x3b },72 { .name = "rx_pmac_sz_256_511", .offset = 0x3c },73 { .name = "rx_pmac_sz_512_1023", .offset = 0x3d },74 { .name = "rx_pmac_sz_1024_1526", .offset = 0x3e },75 { .name = "rx_pmac_sz_jumbo", .offset = 0x3f },76 { .name = "rx_pmac_pause", .offset = 0x40 },77 { .name = "rx_pmac_control", .offset = 0x41 },78 { .name = "rx_pmac_long", .offset = 0x42 },79 80 { .name = "tx_octets", .offset = 0x80, },81 { .name = "tx_unicast", .offset = 0x81, },82 { .name = "tx_multicast", .offset = 0x82 },83 { .name = "tx_broadcast", .offset = 0x83 },84 { .name = "tx_col", .offset = 0x84 },85 { .name = "tx_drop", .offset = 0x85 },86 { .name = "tx_pause", .offset = 0x86 },87 { .name = "tx_sz_64", .offset = 0x87 },88 { .name = "tx_sz_65_127", .offset = 0x88 },89 { .name = "tx_sz_128_255", .offset = 0x89 },90 { .name = "tx_sz_256_511", .offset = 0x8a },91 { .name = "tx_sz_512_1023", .offset = 0x8b },92 { .name = "tx_sz_1024_1526", .offset = 0x8c },93 { .name = "tx_sz_jumbo", .offset = 0x8d },94 { .name = "tx_yellow_prio_0", .offset = 0x8e },95 { .name = "tx_yellow_prio_1", .offset = 0x8f },96 { .name = "tx_yellow_prio_2", .offset = 0x90 },97 { .name = "tx_yellow_prio_3", .offset = 0x91 },98 { .name = "tx_yellow_prio_4", .offset = 0x92 },99 { .name = "tx_yellow_prio_5", .offset = 0x93 },100 { .name = "tx_yellow_prio_6", .offset = 0x94 },101 { .name = "tx_yellow_prio_7", .offset = 0x95 },102 { .name = "tx_green_prio_0", .offset = 0x96 },103 { .name = "tx_green_prio_1", .offset = 0x97 },104 { .name = "tx_green_prio_2", .offset = 0x98 },105 { .name = "tx_green_prio_3", .offset = 0x99 },106 { .name = "tx_green_prio_4", .offset = 0x9a },107 { .name = "tx_green_prio_5", .offset = 0x9b },108 { .name = "tx_green_prio_6", .offset = 0x9c },109 { .name = "tx_green_prio_7", .offset = 0x9d },110 { .name = "tx_aged", .offset = 0x9e },111 { .name = "tx_llct", .offset = 0x9f },112 { .name = "tx_ct", .offset = 0xa0 },113 { .name = "tx_mm_hold", .offset = 0xa1 },114 { .name = "tx_merge_frag", .offset = 0xa2 },115 { .name = "tx_pmac_octets", .offset = 0xa3, },116 { .name = "tx_pmac_unicast", .offset = 0xa4, },117 { .name = "tx_pmac_multicast", .offset = 0xa5 },118 { .name = "tx_pmac_broadcast", .offset = 0xa6 },119 { .name = "tx_pmac_pause", .offset = 0xa7 },120 { .name = "tx_pmac_sz_64", .offset = 0xa8 },121 { .name = "tx_pmac_sz_65_127", .offset = 0xa9 },122 { .name = "tx_pmac_sz_128_255", .offset = 0xaa },123 { .name = "tx_pmac_sz_256_511", .offset = 0xab },124 { .name = "tx_pmac_sz_512_1023", .offset = 0xac },125 { .name = "tx_pmac_sz_1024_1526", .offset = 0xad },126 { .name = "tx_pmac_sz_jumbo", .offset = 0xae },127 128 { .name = "dr_local", .offset = 0x100 },129 { .name = "dr_tail", .offset = 0x101 },130 { .name = "dr_yellow_prio_0", .offset = 0x102 },131 { .name = "dr_yellow_prio_1", .offset = 0x103 },132 { .name = "dr_yellow_prio_2", .offset = 0x104 },133 { .name = "dr_yellow_prio_3", .offset = 0x105 },134 { .name = "dr_yellow_prio_4", .offset = 0x106 },135 { .name = "dr_yellow_prio_5", .offset = 0x107 },136 { .name = "dr_yellow_prio_6", .offset = 0x108 },137 { .name = "dr_yellow_prio_7", .offset = 0x109 },138 { .name = "dr_green_prio_0", .offset = 0x10a },139 { .name = "dr_green_prio_1", .offset = 0x10b },140 { .name = "dr_green_prio_2", .offset = 0x10c },141 { .name = "dr_green_prio_3", .offset = 0x10d },142 { .name = "dr_green_prio_4", .offset = 0x10e },143 { .name = "dr_green_prio_5", .offset = 0x10f },144 { .name = "dr_green_prio_6", .offset = 0x110 },145 { .name = "dr_green_prio_7", .offset = 0x111 },146};147 148/* The following numbers are indexes into lan966x_stats_layout[] */149#define SYS_COUNT_RX_OCT 0150#define SYS_COUNT_RX_UC 1151#define SYS_COUNT_RX_MC 2152#define SYS_COUNT_RX_BC 3153#define SYS_COUNT_RX_SHORT 4154#define SYS_COUNT_RX_FRAG 5155#define SYS_COUNT_RX_JABBER 6156#define SYS_COUNT_RX_CRC 7157#define SYS_COUNT_RX_SYMBOL_ERR 8158#define SYS_COUNT_RX_SZ_64 9159#define SYS_COUNT_RX_SZ_65_127 10160#define SYS_COUNT_RX_SZ_128_255 11161#define SYS_COUNT_RX_SZ_256_511 12162#define SYS_COUNT_RX_SZ_512_1023 13163#define SYS_COUNT_RX_SZ_1024_1526 14164#define SYS_COUNT_RX_SZ_JUMBO 15165#define SYS_COUNT_RX_PAUSE 16166#define SYS_COUNT_RX_CONTROL 17167#define SYS_COUNT_RX_LONG 18168#define SYS_COUNT_RX_CAT_DROP 19169#define SYS_COUNT_RX_RED_PRIO_0 20170#define SYS_COUNT_RX_RED_PRIO_1 21171#define SYS_COUNT_RX_RED_PRIO_2 22172#define SYS_COUNT_RX_RED_PRIO_3 23173#define SYS_COUNT_RX_RED_PRIO_4 24174#define SYS_COUNT_RX_RED_PRIO_5 25175#define SYS_COUNT_RX_RED_PRIO_6 26176#define SYS_COUNT_RX_RED_PRIO_7 27177#define SYS_COUNT_RX_YELLOW_PRIO_0 28178#define SYS_COUNT_RX_YELLOW_PRIO_1 29179#define SYS_COUNT_RX_YELLOW_PRIO_2 30180#define SYS_COUNT_RX_YELLOW_PRIO_3 31181#define SYS_COUNT_RX_YELLOW_PRIO_4 32182#define SYS_COUNT_RX_YELLOW_PRIO_5 33183#define SYS_COUNT_RX_YELLOW_PRIO_6 34184#define SYS_COUNT_RX_YELLOW_PRIO_7 35185#define SYS_COUNT_RX_GREEN_PRIO_0 36186#define SYS_COUNT_RX_GREEN_PRIO_1 37187#define SYS_COUNT_RX_GREEN_PRIO_2 38188#define SYS_COUNT_RX_GREEN_PRIO_3 39189#define SYS_COUNT_RX_GREEN_PRIO_4 40190#define SYS_COUNT_RX_GREEN_PRIO_5 41191#define SYS_COUNT_RX_GREEN_PRIO_6 42192#define SYS_COUNT_RX_GREEN_PRIO_7 43193#define SYS_COUNT_RX_ASSEMBLY_ERR 44194#define SYS_COUNT_RX_SMD_ERR 45195#define SYS_COUNT_RX_ASSEMBLY_OK 46196#define SYS_COUNT_RX_MERGE_FRAG 47197#define SYS_COUNT_RX_PMAC_OCT 48198#define SYS_COUNT_RX_PMAC_UC 49199#define SYS_COUNT_RX_PMAC_MC 50200#define SYS_COUNT_RX_PMAC_BC 51201#define SYS_COUNT_RX_PMAC_SHORT 52202#define SYS_COUNT_RX_PMAC_FRAG 53203#define SYS_COUNT_RX_PMAC_JABBER 54204#define SYS_COUNT_RX_PMAC_CRC 55205#define SYS_COUNT_RX_PMAC_SYMBOL_ERR 56206#define SYS_COUNT_RX_PMAC_SZ_64 57207#define SYS_COUNT_RX_PMAC_SZ_65_127 58208#define SYS_COUNT_RX_PMAC_SZ_128_255 59209#define SYS_COUNT_RX_PMAC_SZ_256_511 60210#define SYS_COUNT_RX_PMAC_SZ_512_1023 61211#define SYS_COUNT_RX_PMAC_SZ_1024_1526 62212#define SYS_COUNT_RX_PMAC_SZ_JUMBO 63213#define SYS_COUNT_RX_PMAC_PAUSE 64214#define SYS_COUNT_RX_PMAC_CONTROL 65215#define SYS_COUNT_RX_PMAC_LONG 66216 217#define SYS_COUNT_TX_OCT 67218#define SYS_COUNT_TX_UC 68219#define SYS_COUNT_TX_MC 69220#define SYS_COUNT_TX_BC 70221#define SYS_COUNT_TX_COL 71222#define SYS_COUNT_TX_DROP 72223#define SYS_COUNT_TX_PAUSE 73224#define SYS_COUNT_TX_SZ_64 74225#define SYS_COUNT_TX_SZ_65_127 75226#define SYS_COUNT_TX_SZ_128_255 76227#define SYS_COUNT_TX_SZ_256_511 77228#define SYS_COUNT_TX_SZ_512_1023 78229#define SYS_COUNT_TX_SZ_1024_1526 79230#define SYS_COUNT_TX_SZ_JUMBO 80231#define SYS_COUNT_TX_YELLOW_PRIO_0 81232#define SYS_COUNT_TX_YELLOW_PRIO_1 82233#define SYS_COUNT_TX_YELLOW_PRIO_2 83234#define SYS_COUNT_TX_YELLOW_PRIO_3 84235#define SYS_COUNT_TX_YELLOW_PRIO_4 85236#define SYS_COUNT_TX_YELLOW_PRIO_5 86237#define SYS_COUNT_TX_YELLOW_PRIO_6 87238#define SYS_COUNT_TX_YELLOW_PRIO_7 88239#define SYS_COUNT_TX_GREEN_PRIO_0 89240#define SYS_COUNT_TX_GREEN_PRIO_1 90241#define SYS_COUNT_TX_GREEN_PRIO_2 91242#define SYS_COUNT_TX_GREEN_PRIO_3 92243#define SYS_COUNT_TX_GREEN_PRIO_4 93244#define SYS_COUNT_TX_GREEN_PRIO_5 94245#define SYS_COUNT_TX_GREEN_PRIO_6 95246#define SYS_COUNT_TX_GREEN_PRIO_7 96247#define SYS_COUNT_TX_AGED 97248#define SYS_COUNT_TX_LLCT 98249#define SYS_COUNT_TX_CT 99250#define SYS_COUNT_TX_MM_HOLD 100251#define SYS_COUNT_TX_MERGE_FRAG 101252#define SYS_COUNT_TX_PMAC_OCT 102253#define SYS_COUNT_TX_PMAC_UC 103254#define SYS_COUNT_TX_PMAC_MC 104255#define SYS_COUNT_TX_PMAC_BC 105256#define SYS_COUNT_TX_PMAC_PAUSE 106257#define SYS_COUNT_TX_PMAC_SZ_64 107258#define SYS_COUNT_TX_PMAC_SZ_65_127 108259#define SYS_COUNT_TX_PMAC_SZ_128_255 109260#define SYS_COUNT_TX_PMAC_SZ_256_511 110261#define SYS_COUNT_TX_PMAC_SZ_512_1023 111262#define SYS_COUNT_TX_PMAC_SZ_1024_1526 112263#define SYS_COUNT_TX_PMAC_SZ_JUMBO 113264 265#define SYS_COUNT_DR_LOCAL 114266#define SYS_COUNT_DR_TAIL 115267#define SYS_COUNT_DR_YELLOW_PRIO_0 116268#define SYS_COUNT_DR_YELLOW_PRIO_1 117269#define SYS_COUNT_DR_YELLOW_PRIO_2 118270#define SYS_COUNT_DR_YELLOW_PRIO_3 119271#define SYS_COUNT_DR_YELLOW_PRIO_4 120272#define SYS_COUNT_DR_YELLOW_PRIO_5 121273#define SYS_COUNT_DR_YELLOW_PRIO_6 122274#define SYS_COUNT_DR_YELLOW_PRIO_7 123275#define SYS_COUNT_DR_GREEN_PRIO_0 124276#define SYS_COUNT_DR_GREEN_PRIO_1 125277#define SYS_COUNT_DR_GREEN_PRIO_2 126278#define SYS_COUNT_DR_GREEN_PRIO_3 127279#define SYS_COUNT_DR_GREEN_PRIO_4 128280#define SYS_COUNT_DR_GREEN_PRIO_5 129281#define SYS_COUNT_DR_GREEN_PRIO_6 130282#define SYS_COUNT_DR_GREEN_PRIO_7 131283 284/* Add a possibly wrapping 32 bit value to a 64 bit counter */285static void lan966x_add_cnt(u64 *cnt, u32 val)286{287 if (val < (*cnt & U32_MAX))288 *cnt += (u64)1 << 32; /* value has wrapped */289 290 *cnt = (*cnt & ~(u64)U32_MAX) + val;291}292 293static void lan966x_stats_update(struct lan966x *lan966x)294{295 int i, j;296 297 mutex_lock(&lan966x->stats_lock);298 299 for (i = 0; i < lan966x->num_phys_ports; i++) {300 uint idx = i * lan966x->num_stats;301 302 lan_wr(SYS_STAT_CFG_STAT_VIEW_SET(i),303 lan966x, SYS_STAT_CFG);304 305 for (j = 0; j < lan966x->num_stats; j++) {306 u32 offset = lan966x->stats_layout[j].offset;307 308 lan966x_add_cnt(&lan966x->stats[idx++],309 lan_rd(lan966x, SYS_CNT(offset)));310 }311 }312 313 mutex_unlock(&lan966x->stats_lock);314}315 316static int lan966x_get_sset_count(struct net_device *dev, int sset)317{318 struct lan966x_port *port = netdev_priv(dev);319 struct lan966x *lan966x = port->lan966x;320 321 if (sset != ETH_SS_STATS)322 return -EOPNOTSUPP;323 324 return lan966x->num_stats;325}326 327static void lan966x_get_strings(struct net_device *netdev, u32 sset, u8 *data)328{329 struct lan966x_port *port = netdev_priv(netdev);330 struct lan966x *lan966x = port->lan966x;331 int i;332 333 if (sset != ETH_SS_STATS)334 return;335 336 for (i = 0; i < lan966x->num_stats; i++)337 memcpy(data + i * ETH_GSTRING_LEN,338 lan966x->stats_layout[i].name, ETH_GSTRING_LEN);339}340 341static void lan966x_get_ethtool_stats(struct net_device *dev,342 struct ethtool_stats *stats, u64 *data)343{344 struct lan966x_port *port = netdev_priv(dev);345 struct lan966x *lan966x = port->lan966x;346 int i;347 348 /* check and update now */349 lan966x_stats_update(lan966x);350 351 /* Copy all counters */352 for (i = 0; i < lan966x->num_stats; i++)353 *data++ = lan966x->stats[port->chip_port *354 lan966x->num_stats + i];355}356 357static void lan966x_get_eth_mac_stats(struct net_device *dev,358 struct ethtool_eth_mac_stats *mac_stats)359{360 struct lan966x_port *port = netdev_priv(dev);361 struct lan966x *lan966x = port->lan966x;362 u32 idx;363 364 lan966x_stats_update(lan966x);365 366 idx = port->chip_port * lan966x->num_stats;367 368 mutex_lock(&lan966x->stats_lock);369 370 mac_stats->FramesTransmittedOK =371 lan966x->stats[idx + SYS_COUNT_TX_UC] +372 lan966x->stats[idx + SYS_COUNT_TX_MC] +373 lan966x->stats[idx + SYS_COUNT_TX_BC] +374 lan966x->stats[idx + SYS_COUNT_TX_PMAC_UC] +375 lan966x->stats[idx + SYS_COUNT_TX_PMAC_MC] +376 lan966x->stats[idx + SYS_COUNT_TX_PMAC_BC];377 mac_stats->SingleCollisionFrames =378 lan966x->stats[idx + SYS_COUNT_TX_COL];379 mac_stats->FramesReceivedOK =380 lan966x->stats[idx + SYS_COUNT_RX_UC] +381 lan966x->stats[idx + SYS_COUNT_RX_MC] +382 lan966x->stats[idx + SYS_COUNT_RX_BC];383 mac_stats->FrameCheckSequenceErrors =384 lan966x->stats[idx + SYS_COUNT_RX_CRC] +385 lan966x->stats[idx + SYS_COUNT_RX_CRC];386 mac_stats->OctetsTransmittedOK =387 lan966x->stats[idx + SYS_COUNT_TX_OCT] +388 lan966x->stats[idx + SYS_COUNT_TX_PMAC_OCT];389 mac_stats->FramesWithDeferredXmissions =390 lan966x->stats[idx + SYS_COUNT_TX_MM_HOLD];391 mac_stats->OctetsReceivedOK =392 lan966x->stats[idx + SYS_COUNT_RX_OCT];393 mac_stats->MulticastFramesXmittedOK =394 lan966x->stats[idx + SYS_COUNT_TX_MC] +395 lan966x->stats[idx + SYS_COUNT_TX_PMAC_MC];396 mac_stats->BroadcastFramesXmittedOK =397 lan966x->stats[idx + SYS_COUNT_TX_BC] +398 lan966x->stats[idx + SYS_COUNT_TX_PMAC_BC];399 mac_stats->MulticastFramesReceivedOK =400 lan966x->stats[idx + SYS_COUNT_RX_MC];401 mac_stats->BroadcastFramesReceivedOK =402 lan966x->stats[idx + SYS_COUNT_RX_BC];403 mac_stats->InRangeLengthErrors =404 lan966x->stats[idx + SYS_COUNT_RX_FRAG] +405 lan966x->stats[idx + SYS_COUNT_RX_JABBER] +406 lan966x->stats[idx + SYS_COUNT_RX_CRC] +407 lan966x->stats[idx + SYS_COUNT_RX_PMAC_FRAG] +408 lan966x->stats[idx + SYS_COUNT_RX_PMAC_JABBER] +409 lan966x->stats[idx + SYS_COUNT_RX_PMAC_CRC];410 mac_stats->OutOfRangeLengthField =411 lan966x->stats[idx + SYS_COUNT_RX_SHORT] +412 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SHORT] +413 lan966x->stats[idx + SYS_COUNT_RX_LONG] +414 lan966x->stats[idx + SYS_COUNT_RX_PMAC_LONG];415 mac_stats->FrameTooLongErrors =416 lan966x->stats[idx + SYS_COUNT_RX_LONG] +417 lan966x->stats[idx + SYS_COUNT_RX_PMAC_LONG];418 419 mutex_unlock(&lan966x->stats_lock);420}421 422static const struct ethtool_rmon_hist_range lan966x_rmon_ranges[] = {423 { 0, 64 },424 { 65, 127 },425 { 128, 255 },426 { 256, 511 },427 { 512, 1023 },428 { 1024, 1518 },429 { 1519, 10239 },430 {}431};432 433static void lan966x_get_eth_rmon_stats(struct net_device *dev,434 struct ethtool_rmon_stats *rmon_stats,435 const struct ethtool_rmon_hist_range **ranges)436{437 struct lan966x_port *port = netdev_priv(dev);438 struct lan966x *lan966x = port->lan966x;439 u32 idx;440 441 lan966x_stats_update(lan966x);442 443 idx = port->chip_port * lan966x->num_stats;444 445 mutex_lock(&lan966x->stats_lock);446 447 rmon_stats->undersize_pkts =448 lan966x->stats[idx + SYS_COUNT_RX_SHORT] +449 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SHORT];450 rmon_stats->oversize_pkts =451 lan966x->stats[idx + SYS_COUNT_RX_LONG] +452 lan966x->stats[idx + SYS_COUNT_RX_PMAC_LONG];453 rmon_stats->fragments =454 lan966x->stats[idx + SYS_COUNT_RX_FRAG] +455 lan966x->stats[idx + SYS_COUNT_RX_PMAC_FRAG];456 rmon_stats->jabbers =457 lan966x->stats[idx + SYS_COUNT_RX_JABBER] +458 lan966x->stats[idx + SYS_COUNT_RX_PMAC_JABBER];459 rmon_stats->hist[0] =460 lan966x->stats[idx + SYS_COUNT_RX_SZ_64] +461 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_64];462 rmon_stats->hist[1] =463 lan966x->stats[idx + SYS_COUNT_RX_SZ_65_127] +464 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_65_127];465 rmon_stats->hist[2] =466 lan966x->stats[idx + SYS_COUNT_RX_SZ_128_255] +467 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_128_255];468 rmon_stats->hist[3] =469 lan966x->stats[idx + SYS_COUNT_RX_SZ_256_511] +470 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_256_511];471 rmon_stats->hist[4] =472 lan966x->stats[idx + SYS_COUNT_RX_SZ_512_1023] +473 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_512_1023];474 rmon_stats->hist[5] =475 lan966x->stats[idx + SYS_COUNT_RX_SZ_1024_1526] +476 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_1024_1526];477 rmon_stats->hist[6] =478 lan966x->stats[idx + SYS_COUNT_RX_SZ_1024_1526] +479 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_1024_1526];480 481 rmon_stats->hist_tx[0] =482 lan966x->stats[idx + SYS_COUNT_TX_SZ_64] +483 lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_64];484 rmon_stats->hist_tx[1] =485 lan966x->stats[idx + SYS_COUNT_TX_SZ_65_127] +486 lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_65_127];487 rmon_stats->hist_tx[2] =488 lan966x->stats[idx + SYS_COUNT_TX_SZ_128_255] +489 lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_128_255];490 rmon_stats->hist_tx[3] =491 lan966x->stats[idx + SYS_COUNT_TX_SZ_256_511] +492 lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_256_511];493 rmon_stats->hist_tx[4] =494 lan966x->stats[idx + SYS_COUNT_TX_SZ_512_1023] +495 lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_512_1023];496 rmon_stats->hist_tx[5] =497 lan966x->stats[idx + SYS_COUNT_TX_SZ_1024_1526] +498 lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_1024_1526];499 rmon_stats->hist_tx[6] =500 lan966x->stats[idx + SYS_COUNT_TX_SZ_1024_1526] +501 lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_1024_1526];502 503 mutex_unlock(&lan966x->stats_lock);504 505 *ranges = lan966x_rmon_ranges;506}507 508static int lan966x_get_link_ksettings(struct net_device *ndev,509 struct ethtool_link_ksettings *cmd)510{511 struct lan966x_port *port = netdev_priv(ndev);512 513 return phylink_ethtool_ksettings_get(port->phylink, cmd);514}515 516static int lan966x_set_link_ksettings(struct net_device *ndev,517 const struct ethtool_link_ksettings *cmd)518{519 struct lan966x_port *port = netdev_priv(ndev);520 521 return phylink_ethtool_ksettings_set(port->phylink, cmd);522}523 524static void lan966x_get_pauseparam(struct net_device *dev,525 struct ethtool_pauseparam *pause)526{527 struct lan966x_port *port = netdev_priv(dev);528 529 phylink_ethtool_get_pauseparam(port->phylink, pause);530}531 532static int lan966x_set_pauseparam(struct net_device *dev,533 struct ethtool_pauseparam *pause)534{535 struct lan966x_port *port = netdev_priv(dev);536 537 return phylink_ethtool_set_pauseparam(port->phylink, pause);538}539 540static int lan966x_get_ts_info(struct net_device *dev,541 struct kernel_ethtool_ts_info *info)542{543 struct lan966x_port *port = netdev_priv(dev);544 struct lan966x *lan966x = port->lan966x;545 struct lan966x_phc *phc;546 547 if (!lan966x->ptp)548 return ethtool_op_get_ts_info(dev, info);549 550 phc = &lan966x->phc[LAN966X_PHC_PORT];551 552 if (phc->clock) {553 info->phc_index = ptp_clock_index(phc->clock);554 } else {555 info->so_timestamping |= SOF_TIMESTAMPING_TX_SOFTWARE;556 return 0;557 }558 info->so_timestamping |= SOF_TIMESTAMPING_TX_SOFTWARE |559 SOF_TIMESTAMPING_TX_HARDWARE |560 SOF_TIMESTAMPING_RX_HARDWARE |561 SOF_TIMESTAMPING_RAW_HARDWARE;562 info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON) |563 BIT(HWTSTAMP_TX_ONESTEP_SYNC);564 info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |565 BIT(HWTSTAMP_FILTER_ALL);566 567 return 0;568}569 570const struct ethtool_ops lan966x_ethtool_ops = {571 .get_link_ksettings = lan966x_get_link_ksettings,572 .set_link_ksettings = lan966x_set_link_ksettings,573 .get_pauseparam = lan966x_get_pauseparam,574 .set_pauseparam = lan966x_set_pauseparam,575 .get_sset_count = lan966x_get_sset_count,576 .get_strings = lan966x_get_strings,577 .get_ethtool_stats = lan966x_get_ethtool_stats,578 .get_eth_mac_stats = lan966x_get_eth_mac_stats,579 .get_rmon_stats = lan966x_get_eth_rmon_stats,580 .get_link = ethtool_op_get_link,581 .get_ts_info = lan966x_get_ts_info,582};583 584static void lan966x_check_stats_work(struct work_struct *work)585{586 struct delayed_work *del_work = to_delayed_work(work);587 struct lan966x *lan966x = container_of(del_work, struct lan966x,588 stats_work);589 590 lan966x_stats_update(lan966x);591 592 queue_delayed_work(lan966x->stats_queue, &lan966x->stats_work,593 LAN966X_STATS_CHECK_DELAY);594}595 596void lan966x_stats_get(struct net_device *dev,597 struct rtnl_link_stats64 *stats)598{599 struct lan966x_port *port = netdev_priv(dev);600 struct lan966x *lan966x = port->lan966x;601 u32 idx;602 int i;603 604 idx = port->chip_port * lan966x->num_stats;605 606 mutex_lock(&lan966x->stats_lock);607 608 stats->rx_bytes = lan966x->stats[idx + SYS_COUNT_RX_OCT] +609 lan966x->stats[idx + SYS_COUNT_RX_PMAC_OCT];610 611 stats->rx_packets = lan966x->stats[idx + SYS_COUNT_RX_SHORT] +612 lan966x->stats[idx + SYS_COUNT_RX_FRAG] +613 lan966x->stats[idx + SYS_COUNT_RX_JABBER] +614 lan966x->stats[idx + SYS_COUNT_RX_CRC] +615 lan966x->stats[idx + SYS_COUNT_RX_SYMBOL_ERR] +616 lan966x->stats[idx + SYS_COUNT_RX_SZ_64] +617 lan966x->stats[idx + SYS_COUNT_RX_SZ_65_127] +618 lan966x->stats[idx + SYS_COUNT_RX_SZ_128_255] +619 lan966x->stats[idx + SYS_COUNT_RX_SZ_256_511] +620 lan966x->stats[idx + SYS_COUNT_RX_SZ_512_1023] +621 lan966x->stats[idx + SYS_COUNT_RX_SZ_1024_1526] +622 lan966x->stats[idx + SYS_COUNT_RX_SZ_JUMBO] +623 lan966x->stats[idx + SYS_COUNT_RX_LONG] +624 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SHORT] +625 lan966x->stats[idx + SYS_COUNT_RX_PMAC_FRAG] +626 lan966x->stats[idx + SYS_COUNT_RX_PMAC_JABBER] +627 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_64] +628 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_65_127] +629 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_128_255] +630 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_256_511] +631 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_512_1023] +632 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_1024_1526] +633 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_JUMBO];634 635 stats->multicast = lan966x->stats[idx + SYS_COUNT_RX_MC] +636 lan966x->stats[idx + SYS_COUNT_RX_PMAC_MC];637 638 stats->rx_errors = lan966x->stats[idx + SYS_COUNT_RX_SHORT] +639 lan966x->stats[idx + SYS_COUNT_RX_FRAG] +640 lan966x->stats[idx + SYS_COUNT_RX_JABBER] +641 lan966x->stats[idx + SYS_COUNT_RX_CRC] +642 lan966x->stats[idx + SYS_COUNT_RX_SYMBOL_ERR] +643 lan966x->stats[idx + SYS_COUNT_RX_LONG];644 645 stats->rx_dropped = dev->stats.rx_dropped +646 lan966x->stats[idx + SYS_COUNT_RX_LONG] +647 lan966x->stats[idx + SYS_COUNT_DR_LOCAL] +648 lan966x->stats[idx + SYS_COUNT_DR_TAIL] +649 lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_0] +650 lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_1] +651 lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_2] +652 lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_3] +653 lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_4] +654 lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_5] +655 lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_6] +656 lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_7];657 658 for (i = 0; i < LAN966X_NUM_TC; i++) {659 stats->rx_dropped +=660 (lan966x->stats[idx + SYS_COUNT_DR_YELLOW_PRIO_0 + i] +661 lan966x->stats[idx + SYS_COUNT_DR_GREEN_PRIO_0 + i]);662 }663 664 /* Get Tx stats */665 stats->tx_bytes = lan966x->stats[idx + SYS_COUNT_TX_OCT] +666 lan966x->stats[idx + SYS_COUNT_TX_PMAC_OCT];667 668 stats->tx_packets = lan966x->stats[idx + SYS_COUNT_TX_SZ_64] +669 lan966x->stats[idx + SYS_COUNT_TX_SZ_65_127] +670 lan966x->stats[idx + SYS_COUNT_TX_SZ_128_255] +671 lan966x->stats[idx + SYS_COUNT_TX_SZ_256_511] +672 lan966x->stats[idx + SYS_COUNT_TX_SZ_512_1023] +673 lan966x->stats[idx + SYS_COUNT_TX_SZ_1024_1526] +674 lan966x->stats[idx + SYS_COUNT_TX_SZ_JUMBO] +675 lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_64] +676 lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_65_127] +677 lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_128_255] +678 lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_256_511] +679 lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_512_1023] +680 lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_1024_1526] +681 lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_JUMBO];682 683 stats->tx_dropped = lan966x->stats[idx + SYS_COUNT_TX_DROP] +684 lan966x->stats[idx + SYS_COUNT_TX_AGED];685 686 stats->collisions = lan966x->stats[idx + SYS_COUNT_TX_COL];687 688 mutex_unlock(&lan966x->stats_lock);689}690 691int lan966x_stats_init(struct lan966x *lan966x)692{693 char queue_name[32];694 695 lan966x->stats_layout = lan966x_stats_layout;696 lan966x->num_stats = ARRAY_SIZE(lan966x_stats_layout);697 lan966x->stats = devm_kcalloc(lan966x->dev, lan966x->num_phys_ports *698 lan966x->num_stats,699 sizeof(u64), GFP_KERNEL);700 if (!lan966x->stats)701 return -ENOMEM;702 703 /* Init stats worker */704 mutex_init(&lan966x->stats_lock);705 snprintf(queue_name, sizeof(queue_name), "%s-stats",706 dev_name(lan966x->dev));707 lan966x->stats_queue = create_singlethread_workqueue(queue_name);708 if (!lan966x->stats_queue)709 return -ENOMEM;710 711 INIT_DELAYED_WORK(&lan966x->stats_work, lan966x_check_stats_work);712 queue_delayed_work(lan966x->stats_queue, &lan966x->stats_work,713 LAN966X_STATS_CHECK_DELAY);714 715 return 0;716}717