cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

lan966x_ethtool.c (25652B)


      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			8
      9#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		  0
    150#define SYS_COUNT_RX_UC			  1
    151#define SYS_COUNT_RX_MC			  2
    152#define SYS_COUNT_RX_BC			  3
    153#define SYS_COUNT_RX_SHORT		  4
    154#define SYS_COUNT_RX_FRAG		  5
    155#define SYS_COUNT_RX_JABBER		  6
    156#define SYS_COUNT_RX_CRC		  7
    157#define SYS_COUNT_RX_SYMBOL_ERR		  8
    158#define SYS_COUNT_RX_SZ_64		  9
    159#define SYS_COUNT_RX_SZ_65_127		 10
    160#define SYS_COUNT_RX_SZ_128_255		 11
    161#define SYS_COUNT_RX_SZ_256_511		 12
    162#define SYS_COUNT_RX_SZ_512_1023	 13
    163#define SYS_COUNT_RX_SZ_1024_1526	 14
    164#define SYS_COUNT_RX_SZ_JUMBO		 15
    165#define SYS_COUNT_RX_PAUSE		 16
    166#define SYS_COUNT_RX_CONTROL		 17
    167#define SYS_COUNT_RX_LONG		 18
    168#define SYS_COUNT_RX_CAT_DROP		 19
    169#define SYS_COUNT_RX_RED_PRIO_0		 20
    170#define SYS_COUNT_RX_RED_PRIO_1		 21
    171#define SYS_COUNT_RX_RED_PRIO_2		 22
    172#define SYS_COUNT_RX_RED_PRIO_3		 23
    173#define SYS_COUNT_RX_RED_PRIO_4		 24
    174#define SYS_COUNT_RX_RED_PRIO_5		 25
    175#define SYS_COUNT_RX_RED_PRIO_6		 26
    176#define SYS_COUNT_RX_RED_PRIO_7		 27
    177#define SYS_COUNT_RX_YELLOW_PRIO_0	 28
    178#define SYS_COUNT_RX_YELLOW_PRIO_1	 29
    179#define SYS_COUNT_RX_YELLOW_PRIO_2	 30
    180#define SYS_COUNT_RX_YELLOW_PRIO_3	 31
    181#define SYS_COUNT_RX_YELLOW_PRIO_4	 32
    182#define SYS_COUNT_RX_YELLOW_PRIO_5	 33
    183#define SYS_COUNT_RX_YELLOW_PRIO_6	 34
    184#define SYS_COUNT_RX_YELLOW_PRIO_7	 35
    185#define SYS_COUNT_RX_GREEN_PRIO_0	 36
    186#define SYS_COUNT_RX_GREEN_PRIO_1	 37
    187#define SYS_COUNT_RX_GREEN_PRIO_2	 38
    188#define SYS_COUNT_RX_GREEN_PRIO_3	 39
    189#define SYS_COUNT_RX_GREEN_PRIO_4	 40
    190#define SYS_COUNT_RX_GREEN_PRIO_5	 41
    191#define SYS_COUNT_RX_GREEN_PRIO_6	 42
    192#define SYS_COUNT_RX_GREEN_PRIO_7	 43
    193#define SYS_COUNT_RX_ASSEMBLY_ERR	 44
    194#define SYS_COUNT_RX_SMD_ERR		 45
    195#define SYS_COUNT_RX_ASSEMBLY_OK	 46
    196#define SYS_COUNT_RX_MERGE_FRAG		 47
    197#define SYS_COUNT_RX_PMAC_OCT		 48
    198#define SYS_COUNT_RX_PMAC_UC		 49
    199#define SYS_COUNT_RX_PMAC_MC		 50
    200#define SYS_COUNT_RX_PMAC_BC		 51
    201#define SYS_COUNT_RX_PMAC_SHORT		 52
    202#define SYS_COUNT_RX_PMAC_FRAG		 53
    203#define SYS_COUNT_RX_PMAC_JABBER	 54
    204#define SYS_COUNT_RX_PMAC_CRC		 55
    205#define SYS_COUNT_RX_PMAC_SYMBOL_ERR	 56
    206#define SYS_COUNT_RX_PMAC_SZ_64		 57
    207#define SYS_COUNT_RX_PMAC_SZ_65_127	 58
    208#define SYS_COUNT_RX_PMAC_SZ_128_255	 59
    209#define SYS_COUNT_RX_PMAC_SZ_256_511	 60
    210#define SYS_COUNT_RX_PMAC_SZ_512_1023	 61
    211#define SYS_COUNT_RX_PMAC_SZ_1024_1526	 62
    212#define SYS_COUNT_RX_PMAC_SZ_JUMBO	 63
    213#define SYS_COUNT_RX_PMAC_PAUSE		 64
    214#define SYS_COUNT_RX_PMAC_CONTROL	 65
    215#define SYS_COUNT_RX_PMAC_LONG		 66
    216
    217#define SYS_COUNT_TX_OCT		 67
    218#define SYS_COUNT_TX_UC			 68
    219#define SYS_COUNT_TX_MC			 69
    220#define SYS_COUNT_TX_BC			 70
    221#define SYS_COUNT_TX_COL		 71
    222#define SYS_COUNT_TX_DROP		 72
    223#define SYS_COUNT_TX_PAUSE		 73
    224#define SYS_COUNT_TX_SZ_64		 74
    225#define SYS_COUNT_TX_SZ_65_127		 75
    226#define SYS_COUNT_TX_SZ_128_255		 76
    227#define SYS_COUNT_TX_SZ_256_511		 77
    228#define SYS_COUNT_TX_SZ_512_1023	 78
    229#define SYS_COUNT_TX_SZ_1024_1526	 79
    230#define SYS_COUNT_TX_SZ_JUMBO		 80
    231#define SYS_COUNT_TX_YELLOW_PRIO_0	 81
    232#define SYS_COUNT_TX_YELLOW_PRIO_1	 82
    233#define SYS_COUNT_TX_YELLOW_PRIO_2	 83
    234#define SYS_COUNT_TX_YELLOW_PRIO_3	 84
    235#define SYS_COUNT_TX_YELLOW_PRIO_4	 85
    236#define SYS_COUNT_TX_YELLOW_PRIO_5	 86
    237#define SYS_COUNT_TX_YELLOW_PRIO_6	 87
    238#define SYS_COUNT_TX_YELLOW_PRIO_7	 88
    239#define SYS_COUNT_TX_GREEN_PRIO_0	 89
    240#define SYS_COUNT_TX_GREEN_PRIO_1	 90
    241#define SYS_COUNT_TX_GREEN_PRIO_2	 91
    242#define SYS_COUNT_TX_GREEN_PRIO_3	 92
    243#define SYS_COUNT_TX_GREEN_PRIO_4	 93
    244#define SYS_COUNT_TX_GREEN_PRIO_5	 94
    245#define SYS_COUNT_TX_GREEN_PRIO_6	 95
    246#define SYS_COUNT_TX_GREEN_PRIO_7	 96
    247#define SYS_COUNT_TX_AGED		 97
    248#define SYS_COUNT_TX_LLCT		 98
    249#define SYS_COUNT_TX_CT			 99
    250#define SYS_COUNT_TX_MM_HOLD		100
    251#define SYS_COUNT_TX_MERGE_FRAG		101
    252#define SYS_COUNT_TX_PMAC_OCT		102
    253#define SYS_COUNT_TX_PMAC_UC		103
    254#define SYS_COUNT_TX_PMAC_MC		104
    255#define SYS_COUNT_TX_PMAC_BC		105
    256#define SYS_COUNT_TX_PMAC_PAUSE		106
    257#define SYS_COUNT_TX_PMAC_SZ_64		107
    258#define SYS_COUNT_TX_PMAC_SZ_65_127	108
    259#define SYS_COUNT_TX_PMAC_SZ_128_255	109
    260#define SYS_COUNT_TX_PMAC_SZ_256_511	110
    261#define SYS_COUNT_TX_PMAC_SZ_512_1023	111
    262#define SYS_COUNT_TX_PMAC_SZ_1024_1526	112
    263#define SYS_COUNT_TX_PMAC_SZ_JUMBO	113
    264
    265#define SYS_COUNT_DR_LOCAL		114
    266#define SYS_COUNT_DR_TAIL		115
    267#define SYS_COUNT_DR_YELLOW_PRIO_0	116
    268#define SYS_COUNT_DR_YELLOW_PRIO_1	117
    269#define SYS_COUNT_DR_YELLOW_PRIO_2	118
    270#define SYS_COUNT_DR_YELLOW_PRIO_3	119
    271#define SYS_COUNT_DR_YELLOW_PRIO_4	120
    272#define SYS_COUNT_DR_YELLOW_PRIO_5	121
    273#define SYS_COUNT_DR_YELLOW_PRIO_6	122
    274#define SYS_COUNT_DR_YELLOW_PRIO_7	123
    275#define SYS_COUNT_DR_GREEN_PRIO_0	124
    276#define SYS_COUNT_DR_GREEN_PRIO_1	125
    277#define SYS_COUNT_DR_GREEN_PRIO_2	126
    278#define SYS_COUNT_DR_GREEN_PRIO_3	127
    279#define SYS_COUNT_DR_GREEN_PRIO_4	128
    280#define SYS_COUNT_DR_GREEN_PRIO_5	129
    281#define SYS_COUNT_DR_GREEN_PRIO_6	130
    282#define SYS_COUNT_DR_GREEN_PRIO_7	131
    283
    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->MultipleCollisionFrames = 0;
    380	mac_stats->FramesReceivedOK =
    381		lan966x->stats[idx + SYS_COUNT_RX_UC] +
    382		lan966x->stats[idx + SYS_COUNT_RX_MC] +
    383		lan966x->stats[idx + SYS_COUNT_RX_BC];
    384	mac_stats->FrameCheckSequenceErrors =
    385		lan966x->stats[idx + SYS_COUNT_RX_CRC] +
    386		lan966x->stats[idx + SYS_COUNT_RX_CRC];
    387	mac_stats->AlignmentErrors = 0;
    388	mac_stats->OctetsTransmittedOK =
    389		lan966x->stats[idx + SYS_COUNT_TX_OCT] +
    390		lan966x->stats[idx + SYS_COUNT_TX_PMAC_OCT];
    391	mac_stats->FramesWithDeferredXmissions =
    392		lan966x->stats[idx + SYS_COUNT_TX_MM_HOLD];
    393	mac_stats->LateCollisions = 0;
    394	mac_stats->FramesAbortedDueToXSColls = 0;
    395	mac_stats->FramesLostDueToIntMACXmitError = 0;
    396	mac_stats->CarrierSenseErrors = 0;
    397	mac_stats->OctetsReceivedOK =
    398		lan966x->stats[idx + SYS_COUNT_RX_OCT];
    399	mac_stats->FramesLostDueToIntMACRcvError = 0;
    400	mac_stats->MulticastFramesXmittedOK =
    401		lan966x->stats[idx + SYS_COUNT_TX_MC] +
    402		lan966x->stats[idx + SYS_COUNT_TX_PMAC_MC];
    403	mac_stats->BroadcastFramesXmittedOK =
    404		lan966x->stats[idx + SYS_COUNT_TX_BC] +
    405		lan966x->stats[idx + SYS_COUNT_TX_PMAC_BC];
    406	mac_stats->FramesWithExcessiveDeferral = 0;
    407	mac_stats->MulticastFramesReceivedOK =
    408		lan966x->stats[idx + SYS_COUNT_RX_MC];
    409	mac_stats->BroadcastFramesReceivedOK =
    410		lan966x->stats[idx + SYS_COUNT_RX_BC];
    411	mac_stats->InRangeLengthErrors =
    412		lan966x->stats[idx + SYS_COUNT_RX_FRAG] +
    413		lan966x->stats[idx + SYS_COUNT_RX_JABBER] +
    414		lan966x->stats[idx + SYS_COUNT_RX_CRC] +
    415		lan966x->stats[idx + SYS_COUNT_RX_PMAC_FRAG] +
    416		lan966x->stats[idx + SYS_COUNT_RX_PMAC_JABBER] +
    417		lan966x->stats[idx + SYS_COUNT_RX_PMAC_CRC];
    418	mac_stats->OutOfRangeLengthField =
    419		lan966x->stats[idx + SYS_COUNT_RX_SHORT] +
    420		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SHORT] +
    421		lan966x->stats[idx + SYS_COUNT_RX_LONG] +
    422		lan966x->stats[idx + SYS_COUNT_RX_PMAC_LONG];
    423	mac_stats->FrameTooLongErrors =
    424		lan966x->stats[idx + SYS_COUNT_RX_LONG] +
    425		lan966x->stats[idx + SYS_COUNT_RX_PMAC_LONG];
    426
    427	mutex_unlock(&lan966x->stats_lock);
    428}
    429
    430static const struct ethtool_rmon_hist_range lan966x_rmon_ranges[] = {
    431	{    0,    64 },
    432	{   65,   127 },
    433	{  128,   255 },
    434	{  256,   511 },
    435	{  512,  1023 },
    436	{ 1024,  1518 },
    437	{ 1519, 10239 },
    438	{}
    439};
    440
    441static void lan966x_get_eth_rmon_stats(struct net_device *dev,
    442				       struct ethtool_rmon_stats *rmon_stats,
    443				       const struct ethtool_rmon_hist_range **ranges)
    444{
    445	struct lan966x_port *port = netdev_priv(dev);
    446	struct lan966x *lan966x = port->lan966x;
    447	u32 idx;
    448
    449	lan966x_stats_update(lan966x);
    450
    451	idx = port->chip_port * lan966x->num_stats;
    452
    453	mutex_lock(&lan966x->stats_lock);
    454
    455	rmon_stats->undersize_pkts =
    456		lan966x->stats[idx + SYS_COUNT_RX_SHORT] +
    457		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SHORT];
    458	rmon_stats->oversize_pkts =
    459		lan966x->stats[idx + SYS_COUNT_RX_LONG] +
    460		lan966x->stats[idx + SYS_COUNT_RX_PMAC_LONG];
    461	rmon_stats->fragments =
    462		lan966x->stats[idx + SYS_COUNT_RX_FRAG] +
    463		lan966x->stats[idx + SYS_COUNT_RX_PMAC_FRAG];
    464	rmon_stats->jabbers =
    465		lan966x->stats[idx + SYS_COUNT_RX_JABBER] +
    466		lan966x->stats[idx + SYS_COUNT_RX_PMAC_JABBER];
    467	rmon_stats->hist[0] =
    468		lan966x->stats[idx + SYS_COUNT_RX_SZ_64] +
    469		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_64];
    470	rmon_stats->hist[1] =
    471		lan966x->stats[idx + SYS_COUNT_RX_SZ_65_127] +
    472		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_65_127];
    473	rmon_stats->hist[2] =
    474		lan966x->stats[idx + SYS_COUNT_RX_SZ_128_255] +
    475		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_128_255];
    476	rmon_stats->hist[3] =
    477		lan966x->stats[idx + SYS_COUNT_RX_SZ_256_511] +
    478		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_256_511];
    479	rmon_stats->hist[4] =
    480		lan966x->stats[idx + SYS_COUNT_RX_SZ_512_1023] +
    481		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_512_1023];
    482	rmon_stats->hist[5] =
    483		lan966x->stats[idx + SYS_COUNT_RX_SZ_1024_1526] +
    484		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_1024_1526];
    485	rmon_stats->hist[6] =
    486		lan966x->stats[idx + SYS_COUNT_RX_SZ_1024_1526] +
    487		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_1024_1526];
    488
    489	rmon_stats->hist_tx[0] =
    490		lan966x->stats[idx + SYS_COUNT_TX_SZ_64] +
    491		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_64];
    492	rmon_stats->hist_tx[1] =
    493		lan966x->stats[idx + SYS_COUNT_TX_SZ_65_127] +
    494		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_65_127];
    495	rmon_stats->hist_tx[2] =
    496		lan966x->stats[idx + SYS_COUNT_TX_SZ_128_255] +
    497		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_128_255];
    498	rmon_stats->hist_tx[3] =
    499		lan966x->stats[idx + SYS_COUNT_TX_SZ_256_511] +
    500		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_256_511];
    501	rmon_stats->hist_tx[4] =
    502		lan966x->stats[idx + SYS_COUNT_TX_SZ_512_1023] +
    503		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_512_1023];
    504	rmon_stats->hist_tx[5] =
    505		lan966x->stats[idx + SYS_COUNT_TX_SZ_1024_1526] +
    506		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_1024_1526];
    507	rmon_stats->hist_tx[6] =
    508		lan966x->stats[idx + SYS_COUNT_TX_SZ_1024_1526] +
    509		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_1024_1526];
    510
    511	mutex_unlock(&lan966x->stats_lock);
    512
    513	*ranges = lan966x_rmon_ranges;
    514}
    515
    516static int lan966x_get_link_ksettings(struct net_device *ndev,
    517				      struct ethtool_link_ksettings *cmd)
    518{
    519	struct lan966x_port *port = netdev_priv(ndev);
    520
    521	return phylink_ethtool_ksettings_get(port->phylink, cmd);
    522}
    523
    524static int lan966x_set_link_ksettings(struct net_device *ndev,
    525				      const struct ethtool_link_ksettings *cmd)
    526{
    527	struct lan966x_port *port = netdev_priv(ndev);
    528
    529	return phylink_ethtool_ksettings_set(port->phylink, cmd);
    530}
    531
    532static void lan966x_get_pauseparam(struct net_device *dev,
    533				   struct ethtool_pauseparam *pause)
    534{
    535	struct lan966x_port *port = netdev_priv(dev);
    536
    537	phylink_ethtool_get_pauseparam(port->phylink, pause);
    538}
    539
    540static int lan966x_set_pauseparam(struct net_device *dev,
    541				  struct ethtool_pauseparam *pause)
    542{
    543	struct lan966x_port *port = netdev_priv(dev);
    544
    545	return phylink_ethtool_set_pauseparam(port->phylink, pause);
    546}
    547
    548static int lan966x_get_ts_info(struct net_device *dev,
    549			       struct ethtool_ts_info *info)
    550{
    551	struct lan966x_port *port = netdev_priv(dev);
    552	struct lan966x *lan966x = port->lan966x;
    553	struct lan966x_phc *phc;
    554
    555	if (!lan966x->ptp)
    556		return ethtool_op_get_ts_info(dev, info);
    557
    558	phc = &lan966x->phc[LAN966X_PHC_PORT];
    559
    560	info->phc_index = phc->clock ? ptp_clock_index(phc->clock) : -1;
    561	if (info->phc_index == -1) {
    562		info->so_timestamping |= SOF_TIMESTAMPING_TX_SOFTWARE |
    563					 SOF_TIMESTAMPING_RX_SOFTWARE |
    564					 SOF_TIMESTAMPING_SOFTWARE;
    565		return 0;
    566	}
    567	info->so_timestamping |= SOF_TIMESTAMPING_TX_SOFTWARE |
    568				 SOF_TIMESTAMPING_RX_SOFTWARE |
    569				 SOF_TIMESTAMPING_SOFTWARE |
    570				 SOF_TIMESTAMPING_TX_HARDWARE |
    571				 SOF_TIMESTAMPING_RX_HARDWARE |
    572				 SOF_TIMESTAMPING_RAW_HARDWARE;
    573	info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON) |
    574			 BIT(HWTSTAMP_TX_ONESTEP_SYNC);
    575	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
    576			   BIT(HWTSTAMP_FILTER_ALL);
    577
    578	return 0;
    579}
    580
    581const struct ethtool_ops lan966x_ethtool_ops = {
    582	.get_link_ksettings     = lan966x_get_link_ksettings,
    583	.set_link_ksettings     = lan966x_set_link_ksettings,
    584	.get_pauseparam		= lan966x_get_pauseparam,
    585	.set_pauseparam		= lan966x_set_pauseparam,
    586	.get_sset_count		= lan966x_get_sset_count,
    587	.get_strings		= lan966x_get_strings,
    588	.get_ethtool_stats	= lan966x_get_ethtool_stats,
    589	.get_eth_mac_stats      = lan966x_get_eth_mac_stats,
    590	.get_rmon_stats		= lan966x_get_eth_rmon_stats,
    591	.get_link		= ethtool_op_get_link,
    592	.get_ts_info		= lan966x_get_ts_info,
    593};
    594
    595static void lan966x_check_stats_work(struct work_struct *work)
    596{
    597	struct delayed_work *del_work = to_delayed_work(work);
    598	struct lan966x *lan966x = container_of(del_work, struct lan966x,
    599					       stats_work);
    600
    601	lan966x_stats_update(lan966x);
    602
    603	queue_delayed_work(lan966x->stats_queue, &lan966x->stats_work,
    604			   LAN966X_STATS_CHECK_DELAY);
    605}
    606
    607void lan966x_stats_get(struct net_device *dev,
    608		       struct rtnl_link_stats64 *stats)
    609{
    610	struct lan966x_port *port = netdev_priv(dev);
    611	struct lan966x *lan966x = port->lan966x;
    612	u32 idx;
    613	int i;
    614
    615	idx = port->chip_port * lan966x->num_stats;
    616
    617	mutex_lock(&lan966x->stats_lock);
    618
    619	stats->rx_bytes = lan966x->stats[idx + SYS_COUNT_RX_OCT] +
    620		lan966x->stats[idx + SYS_COUNT_RX_PMAC_OCT];
    621
    622	stats->rx_packets = lan966x->stats[idx + SYS_COUNT_RX_SHORT] +
    623		lan966x->stats[idx + SYS_COUNT_RX_FRAG] +
    624		lan966x->stats[idx + SYS_COUNT_RX_JABBER] +
    625		lan966x->stats[idx + SYS_COUNT_RX_CRC] +
    626		lan966x->stats[idx + SYS_COUNT_RX_SYMBOL_ERR] +
    627		lan966x->stats[idx + SYS_COUNT_RX_SZ_64] +
    628		lan966x->stats[idx + SYS_COUNT_RX_SZ_65_127] +
    629		lan966x->stats[idx + SYS_COUNT_RX_SZ_128_255] +
    630		lan966x->stats[idx + SYS_COUNT_RX_SZ_256_511] +
    631		lan966x->stats[idx + SYS_COUNT_RX_SZ_512_1023] +
    632		lan966x->stats[idx + SYS_COUNT_RX_SZ_1024_1526] +
    633		lan966x->stats[idx + SYS_COUNT_RX_SZ_JUMBO] +
    634		lan966x->stats[idx + SYS_COUNT_RX_LONG] +
    635		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SHORT] +
    636		lan966x->stats[idx + SYS_COUNT_RX_PMAC_FRAG] +
    637		lan966x->stats[idx + SYS_COUNT_RX_PMAC_JABBER] +
    638		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_64] +
    639		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_65_127] +
    640		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_128_255] +
    641		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_256_511] +
    642		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_512_1023] +
    643		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_1024_1526] +
    644		lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_JUMBO];
    645
    646	stats->multicast = lan966x->stats[idx + SYS_COUNT_RX_MC] +
    647		lan966x->stats[idx + SYS_COUNT_RX_PMAC_MC];
    648
    649	stats->rx_errors = lan966x->stats[idx + SYS_COUNT_RX_SHORT] +
    650		lan966x->stats[idx + SYS_COUNT_RX_FRAG] +
    651		lan966x->stats[idx + SYS_COUNT_RX_JABBER] +
    652		lan966x->stats[idx + SYS_COUNT_RX_CRC] +
    653		lan966x->stats[idx + SYS_COUNT_RX_SYMBOL_ERR] +
    654		lan966x->stats[idx + SYS_COUNT_RX_LONG];
    655
    656	stats->rx_dropped = dev->stats.rx_dropped +
    657		lan966x->stats[idx + SYS_COUNT_RX_LONG] +
    658		lan966x->stats[idx + SYS_COUNT_DR_LOCAL] +
    659		lan966x->stats[idx + SYS_COUNT_DR_TAIL];
    660
    661	for (i = 0; i < LAN966X_NUM_TC; i++) {
    662		stats->rx_dropped +=
    663			(lan966x->stats[idx + SYS_COUNT_DR_YELLOW_PRIO_0 + i] +
    664			 lan966x->stats[idx + SYS_COUNT_DR_GREEN_PRIO_0 + i]);
    665	}
    666
    667	/* Get Tx stats */
    668	stats->tx_bytes = lan966x->stats[idx + SYS_COUNT_TX_OCT] +
    669		lan966x->stats[idx + SYS_COUNT_TX_PMAC_OCT];
    670
    671	stats->tx_packets = lan966x->stats[idx + SYS_COUNT_TX_SZ_64] +
    672		lan966x->stats[idx + SYS_COUNT_TX_SZ_65_127] +
    673		lan966x->stats[idx + SYS_COUNT_TX_SZ_128_255] +
    674		lan966x->stats[idx + SYS_COUNT_TX_SZ_256_511] +
    675		lan966x->stats[idx + SYS_COUNT_TX_SZ_512_1023] +
    676		lan966x->stats[idx + SYS_COUNT_TX_SZ_1024_1526] +
    677		lan966x->stats[idx + SYS_COUNT_TX_SZ_JUMBO] +
    678		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_64] +
    679		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_65_127] +
    680		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_128_255] +
    681		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_256_511] +
    682		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_512_1023] +
    683		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_1024_1526] +
    684		lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_JUMBO];
    685
    686	stats->tx_dropped = lan966x->stats[idx + SYS_COUNT_TX_DROP] +
    687		lan966x->stats[idx + SYS_COUNT_TX_AGED];
    688
    689	stats->collisions = lan966x->stats[idx + SYS_COUNT_TX_COL];
    690
    691	mutex_unlock(&lan966x->stats_lock);
    692}
    693
    694int lan966x_stats_init(struct lan966x *lan966x)
    695{
    696	char queue_name[32];
    697
    698	lan966x->stats_layout = lan966x_stats_layout;
    699	lan966x->num_stats = ARRAY_SIZE(lan966x_stats_layout);
    700	lan966x->stats = devm_kcalloc(lan966x->dev, lan966x->num_phys_ports *
    701				      lan966x->num_stats,
    702				      sizeof(u64), GFP_KERNEL);
    703	if (!lan966x->stats)
    704		return -ENOMEM;
    705
    706	/* Init stats worker */
    707	mutex_init(&lan966x->stats_lock);
    708	snprintf(queue_name, sizeof(queue_name), "%s-stats",
    709		 dev_name(lan966x->dev));
    710	lan966x->stats_queue = create_singlethread_workqueue(queue_name);
    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}