Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 
0003 #include <linux/netdevice.h>
0004 
0005 #include "lan966x_main.h"
0006 
0007 /* Number of traffic classes */
0008 #define LAN966X_NUM_TC          8
0009 #define LAN966X_STATS_CHECK_DELAY   (2 * HZ)
0010 
0011 static const struct lan966x_stat_layout lan966x_stats_layout[] = {
0012     { .name = "rx_octets", .offset = 0x00, },
0013     { .name = "rx_unicast", .offset = 0x01, },
0014     { .name = "rx_multicast", .offset = 0x02 },
0015     { .name = "rx_broadcast", .offset = 0x03 },
0016     { .name = "rx_short", .offset = 0x04 },
0017     { .name = "rx_frag", .offset = 0x05 },
0018     { .name = "rx_jabber", .offset = 0x06 },
0019     { .name = "rx_crc", .offset = 0x07 },
0020     { .name = "rx_symbol_err", .offset = 0x08 },
0021     { .name = "rx_sz_64", .offset = 0x09 },
0022     { .name = "rx_sz_65_127", .offset = 0x0a},
0023     { .name = "rx_sz_128_255", .offset = 0x0b},
0024     { .name = "rx_sz_256_511", .offset = 0x0c },
0025     { .name = "rx_sz_512_1023", .offset = 0x0d },
0026     { .name = "rx_sz_1024_1526", .offset = 0x0e },
0027     { .name = "rx_sz_jumbo", .offset = 0x0f },
0028     { .name = "rx_pause", .offset = 0x10 },
0029     { .name = "rx_control", .offset = 0x11 },
0030     { .name = "rx_long", .offset = 0x12 },
0031     { .name = "rx_cat_drop", .offset = 0x13 },
0032     { .name = "rx_red_prio_0", .offset = 0x14 },
0033     { .name = "rx_red_prio_1", .offset = 0x15 },
0034     { .name = "rx_red_prio_2", .offset = 0x16 },
0035     { .name = "rx_red_prio_3", .offset = 0x17 },
0036     { .name = "rx_red_prio_4", .offset = 0x18 },
0037     { .name = "rx_red_prio_5", .offset = 0x19 },
0038     { .name = "rx_red_prio_6", .offset = 0x1a },
0039     { .name = "rx_red_prio_7", .offset = 0x1b },
0040     { .name = "rx_yellow_prio_0", .offset = 0x1c },
0041     { .name = "rx_yellow_prio_1", .offset = 0x1d },
0042     { .name = "rx_yellow_prio_2", .offset = 0x1e },
0043     { .name = "rx_yellow_prio_3", .offset = 0x1f },
0044     { .name = "rx_yellow_prio_4", .offset = 0x20 },
0045     { .name = "rx_yellow_prio_5", .offset = 0x21 },
0046     { .name = "rx_yellow_prio_6", .offset = 0x22 },
0047     { .name = "rx_yellow_prio_7", .offset = 0x23 },
0048     { .name = "rx_green_prio_0", .offset = 0x24 },
0049     { .name = "rx_green_prio_1", .offset = 0x25 },
0050     { .name = "rx_green_prio_2", .offset = 0x26 },
0051     { .name = "rx_green_prio_3", .offset = 0x27 },
0052     { .name = "rx_green_prio_4", .offset = 0x28 },
0053     { .name = "rx_green_prio_5", .offset = 0x29 },
0054     { .name = "rx_green_prio_6", .offset = 0x2a },
0055     { .name = "rx_green_prio_7", .offset = 0x2b },
0056     { .name = "rx_assembly_err", .offset = 0x2c },
0057     { .name = "rx_smd_err", .offset = 0x2d },
0058     { .name = "rx_assembly_ok", .offset = 0x2e },
0059     { .name = "rx_merge_frag", .offset = 0x2f },
0060     { .name = "rx_pmac_octets", .offset = 0x30, },
0061     { .name = "rx_pmac_unicast", .offset = 0x31, },
0062     { .name = "rx_pmac_multicast", .offset = 0x32 },
0063     { .name = "rx_pmac_broadcast", .offset = 0x33 },
0064     { .name = "rx_pmac_short", .offset = 0x34 },
0065     { .name = "rx_pmac_frag", .offset = 0x35 },
0066     { .name = "rx_pmac_jabber", .offset = 0x36 },
0067     { .name = "rx_pmac_crc", .offset = 0x37 },
0068     { .name = "rx_pmac_symbol_err", .offset = 0x38 },
0069     { .name = "rx_pmac_sz_64", .offset = 0x39 },
0070     { .name = "rx_pmac_sz_65_127", .offset = 0x3a },
0071     { .name = "rx_pmac_sz_128_255", .offset = 0x3b },
0072     { .name = "rx_pmac_sz_256_511", .offset = 0x3c },
0073     { .name = "rx_pmac_sz_512_1023", .offset = 0x3d },
0074     { .name = "rx_pmac_sz_1024_1526", .offset = 0x3e },
0075     { .name = "rx_pmac_sz_jumbo", .offset = 0x3f },
0076     { .name = "rx_pmac_pause", .offset = 0x40 },
0077     { .name = "rx_pmac_control", .offset = 0x41 },
0078     { .name = "rx_pmac_long", .offset = 0x42 },
0079 
0080     { .name = "tx_octets", .offset = 0x80, },
0081     { .name = "tx_unicast", .offset = 0x81, },
0082     { .name = "tx_multicast", .offset = 0x82 },
0083     { .name = "tx_broadcast", .offset = 0x83 },
0084     { .name = "tx_col", .offset = 0x84 },
0085     { .name = "tx_drop", .offset = 0x85 },
0086     { .name = "tx_pause", .offset = 0x86 },
0087     { .name = "tx_sz_64", .offset = 0x87 },
0088     { .name = "tx_sz_65_127", .offset = 0x88 },
0089     { .name = "tx_sz_128_255", .offset = 0x89 },
0090     { .name = "tx_sz_256_511", .offset = 0x8a },
0091     { .name = "tx_sz_512_1023", .offset = 0x8b },
0092     { .name = "tx_sz_1024_1526", .offset = 0x8c },
0093     { .name = "tx_sz_jumbo", .offset = 0x8d },
0094     { .name = "tx_yellow_prio_0", .offset = 0x8e },
0095     { .name = "tx_yellow_prio_1", .offset = 0x8f },
0096     { .name = "tx_yellow_prio_2", .offset = 0x90 },
0097     { .name = "tx_yellow_prio_3", .offset = 0x91 },
0098     { .name = "tx_yellow_prio_4", .offset = 0x92 },
0099     { .name = "tx_yellow_prio_5", .offset = 0x93 },
0100     { .name = "tx_yellow_prio_6", .offset = 0x94 },
0101     { .name = "tx_yellow_prio_7", .offset = 0x95 },
0102     { .name = "tx_green_prio_0", .offset = 0x96 },
0103     { .name = "tx_green_prio_1", .offset = 0x97 },
0104     { .name = "tx_green_prio_2", .offset = 0x98 },
0105     { .name = "tx_green_prio_3", .offset = 0x99 },
0106     { .name = "tx_green_prio_4", .offset = 0x9a },
0107     { .name = "tx_green_prio_5", .offset = 0x9b },
0108     { .name = "tx_green_prio_6", .offset = 0x9c },
0109     { .name = "tx_green_prio_7", .offset = 0x9d },
0110     { .name = "tx_aged", .offset = 0x9e },
0111     { .name = "tx_llct", .offset = 0x9f },
0112     { .name = "tx_ct", .offset = 0xa0 },
0113     { .name = "tx_mm_hold", .offset = 0xa1 },
0114     { .name = "tx_merge_frag", .offset = 0xa2 },
0115     { .name = "tx_pmac_octets", .offset = 0xa3, },
0116     { .name = "tx_pmac_unicast", .offset = 0xa4, },
0117     { .name = "tx_pmac_multicast", .offset = 0xa5 },
0118     { .name = "tx_pmac_broadcast", .offset = 0xa6 },
0119     { .name = "tx_pmac_pause", .offset = 0xa7 },
0120     { .name = "tx_pmac_sz_64", .offset = 0xa8 },
0121     { .name = "tx_pmac_sz_65_127", .offset = 0xa9 },
0122     { .name = "tx_pmac_sz_128_255", .offset = 0xaa },
0123     { .name = "tx_pmac_sz_256_511", .offset = 0xab },
0124     { .name = "tx_pmac_sz_512_1023", .offset = 0xac },
0125     { .name = "tx_pmac_sz_1024_1526", .offset = 0xad },
0126     { .name = "tx_pmac_sz_jumbo", .offset = 0xae },
0127 
0128     { .name = "dr_local", .offset = 0x100 },
0129     { .name = "dr_tail", .offset = 0x101 },
0130     { .name = "dr_yellow_prio_0", .offset = 0x102 },
0131     { .name = "dr_yellow_prio_1", .offset = 0x103 },
0132     { .name = "dr_yellow_prio_2", .offset = 0x104 },
0133     { .name = "dr_yellow_prio_3", .offset = 0x105 },
0134     { .name = "dr_yellow_prio_4", .offset = 0x106 },
0135     { .name = "dr_yellow_prio_5", .offset = 0x107 },
0136     { .name = "dr_yellow_prio_6", .offset = 0x108 },
0137     { .name = "dr_yellow_prio_7", .offset = 0x109 },
0138     { .name = "dr_green_prio_0", .offset = 0x10a },
0139     { .name = "dr_green_prio_1", .offset = 0x10b },
0140     { .name = "dr_green_prio_2", .offset = 0x10c },
0141     { .name = "dr_green_prio_3", .offset = 0x10d },
0142     { .name = "dr_green_prio_4", .offset = 0x10e },
0143     { .name = "dr_green_prio_5", .offset = 0x10f },
0144     { .name = "dr_green_prio_6", .offset = 0x110 },
0145     { .name = "dr_green_prio_7", .offset = 0x111 },
0146 };
0147 
0148 /* The following numbers are indexes into lan966x_stats_layout[] */
0149 #define SYS_COUNT_RX_OCT          0
0150 #define SYS_COUNT_RX_UC           1
0151 #define SYS_COUNT_RX_MC           2
0152 #define SYS_COUNT_RX_BC           3
0153 #define SYS_COUNT_RX_SHORT        4
0154 #define SYS_COUNT_RX_FRAG         5
0155 #define SYS_COUNT_RX_JABBER       6
0156 #define SYS_COUNT_RX_CRC          7
0157 #define SYS_COUNT_RX_SYMBOL_ERR       8
0158 #define SYS_COUNT_RX_SZ_64        9
0159 #define SYS_COUNT_RX_SZ_65_127       10
0160 #define SYS_COUNT_RX_SZ_128_255      11
0161 #define SYS_COUNT_RX_SZ_256_511      12
0162 #define SYS_COUNT_RX_SZ_512_1023     13
0163 #define SYS_COUNT_RX_SZ_1024_1526    14
0164 #define SYS_COUNT_RX_SZ_JUMBO        15
0165 #define SYS_COUNT_RX_PAUSE       16
0166 #define SYS_COUNT_RX_CONTROL         17
0167 #define SYS_COUNT_RX_LONG        18
0168 #define SYS_COUNT_RX_CAT_DROP        19
0169 #define SYS_COUNT_RX_RED_PRIO_0      20
0170 #define SYS_COUNT_RX_RED_PRIO_1      21
0171 #define SYS_COUNT_RX_RED_PRIO_2      22
0172 #define SYS_COUNT_RX_RED_PRIO_3      23
0173 #define SYS_COUNT_RX_RED_PRIO_4      24
0174 #define SYS_COUNT_RX_RED_PRIO_5      25
0175 #define SYS_COUNT_RX_RED_PRIO_6      26
0176 #define SYS_COUNT_RX_RED_PRIO_7      27
0177 #define SYS_COUNT_RX_YELLOW_PRIO_0   28
0178 #define SYS_COUNT_RX_YELLOW_PRIO_1   29
0179 #define SYS_COUNT_RX_YELLOW_PRIO_2   30
0180 #define SYS_COUNT_RX_YELLOW_PRIO_3   31
0181 #define SYS_COUNT_RX_YELLOW_PRIO_4   32
0182 #define SYS_COUNT_RX_YELLOW_PRIO_5   33
0183 #define SYS_COUNT_RX_YELLOW_PRIO_6   34
0184 #define SYS_COUNT_RX_YELLOW_PRIO_7   35
0185 #define SYS_COUNT_RX_GREEN_PRIO_0    36
0186 #define SYS_COUNT_RX_GREEN_PRIO_1    37
0187 #define SYS_COUNT_RX_GREEN_PRIO_2    38
0188 #define SYS_COUNT_RX_GREEN_PRIO_3    39
0189 #define SYS_COUNT_RX_GREEN_PRIO_4    40
0190 #define SYS_COUNT_RX_GREEN_PRIO_5    41
0191 #define SYS_COUNT_RX_GREEN_PRIO_6    42
0192 #define SYS_COUNT_RX_GREEN_PRIO_7    43
0193 #define SYS_COUNT_RX_ASSEMBLY_ERR    44
0194 #define SYS_COUNT_RX_SMD_ERR         45
0195 #define SYS_COUNT_RX_ASSEMBLY_OK     46
0196 #define SYS_COUNT_RX_MERGE_FRAG      47
0197 #define SYS_COUNT_RX_PMAC_OCT        48
0198 #define SYS_COUNT_RX_PMAC_UC         49
0199 #define SYS_COUNT_RX_PMAC_MC         50
0200 #define SYS_COUNT_RX_PMAC_BC         51
0201 #define SYS_COUNT_RX_PMAC_SHORT      52
0202 #define SYS_COUNT_RX_PMAC_FRAG       53
0203 #define SYS_COUNT_RX_PMAC_JABBER     54
0204 #define SYS_COUNT_RX_PMAC_CRC        55
0205 #define SYS_COUNT_RX_PMAC_SYMBOL_ERR     56
0206 #define SYS_COUNT_RX_PMAC_SZ_64      57
0207 #define SYS_COUNT_RX_PMAC_SZ_65_127  58
0208 #define SYS_COUNT_RX_PMAC_SZ_128_255     59
0209 #define SYS_COUNT_RX_PMAC_SZ_256_511     60
0210 #define SYS_COUNT_RX_PMAC_SZ_512_1023    61
0211 #define SYS_COUNT_RX_PMAC_SZ_1024_1526   62
0212 #define SYS_COUNT_RX_PMAC_SZ_JUMBO   63
0213 #define SYS_COUNT_RX_PMAC_PAUSE      64
0214 #define SYS_COUNT_RX_PMAC_CONTROL    65
0215 #define SYS_COUNT_RX_PMAC_LONG       66
0216 
0217 #define SYS_COUNT_TX_OCT         67
0218 #define SYS_COUNT_TX_UC          68
0219 #define SYS_COUNT_TX_MC          69
0220 #define SYS_COUNT_TX_BC          70
0221 #define SYS_COUNT_TX_COL         71
0222 #define SYS_COUNT_TX_DROP        72
0223 #define SYS_COUNT_TX_PAUSE       73
0224 #define SYS_COUNT_TX_SZ_64       74
0225 #define SYS_COUNT_TX_SZ_65_127       75
0226 #define SYS_COUNT_TX_SZ_128_255      76
0227 #define SYS_COUNT_TX_SZ_256_511      77
0228 #define SYS_COUNT_TX_SZ_512_1023     78
0229 #define SYS_COUNT_TX_SZ_1024_1526    79
0230 #define SYS_COUNT_TX_SZ_JUMBO        80
0231 #define SYS_COUNT_TX_YELLOW_PRIO_0   81
0232 #define SYS_COUNT_TX_YELLOW_PRIO_1   82
0233 #define SYS_COUNT_TX_YELLOW_PRIO_2   83
0234 #define SYS_COUNT_TX_YELLOW_PRIO_3   84
0235 #define SYS_COUNT_TX_YELLOW_PRIO_4   85
0236 #define SYS_COUNT_TX_YELLOW_PRIO_5   86
0237 #define SYS_COUNT_TX_YELLOW_PRIO_6   87
0238 #define SYS_COUNT_TX_YELLOW_PRIO_7   88
0239 #define SYS_COUNT_TX_GREEN_PRIO_0    89
0240 #define SYS_COUNT_TX_GREEN_PRIO_1    90
0241 #define SYS_COUNT_TX_GREEN_PRIO_2    91
0242 #define SYS_COUNT_TX_GREEN_PRIO_3    92
0243 #define SYS_COUNT_TX_GREEN_PRIO_4    93
0244 #define SYS_COUNT_TX_GREEN_PRIO_5    94
0245 #define SYS_COUNT_TX_GREEN_PRIO_6    95
0246 #define SYS_COUNT_TX_GREEN_PRIO_7    96
0247 #define SYS_COUNT_TX_AGED        97
0248 #define SYS_COUNT_TX_LLCT        98
0249 #define SYS_COUNT_TX_CT          99
0250 #define SYS_COUNT_TX_MM_HOLD        100
0251 #define SYS_COUNT_TX_MERGE_FRAG     101
0252 #define SYS_COUNT_TX_PMAC_OCT       102
0253 #define SYS_COUNT_TX_PMAC_UC        103
0254 #define SYS_COUNT_TX_PMAC_MC        104
0255 #define SYS_COUNT_TX_PMAC_BC        105
0256 #define SYS_COUNT_TX_PMAC_PAUSE     106
0257 #define SYS_COUNT_TX_PMAC_SZ_64     107
0258 #define SYS_COUNT_TX_PMAC_SZ_65_127 108
0259 #define SYS_COUNT_TX_PMAC_SZ_128_255    109
0260 #define SYS_COUNT_TX_PMAC_SZ_256_511    110
0261 #define SYS_COUNT_TX_PMAC_SZ_512_1023   111
0262 #define SYS_COUNT_TX_PMAC_SZ_1024_1526  112
0263 #define SYS_COUNT_TX_PMAC_SZ_JUMBO  113
0264 
0265 #define SYS_COUNT_DR_LOCAL      114
0266 #define SYS_COUNT_DR_TAIL       115
0267 #define SYS_COUNT_DR_YELLOW_PRIO_0  116
0268 #define SYS_COUNT_DR_YELLOW_PRIO_1  117
0269 #define SYS_COUNT_DR_YELLOW_PRIO_2  118
0270 #define SYS_COUNT_DR_YELLOW_PRIO_3  119
0271 #define SYS_COUNT_DR_YELLOW_PRIO_4  120
0272 #define SYS_COUNT_DR_YELLOW_PRIO_5  121
0273 #define SYS_COUNT_DR_YELLOW_PRIO_6  122
0274 #define SYS_COUNT_DR_YELLOW_PRIO_7  123
0275 #define SYS_COUNT_DR_GREEN_PRIO_0   124
0276 #define SYS_COUNT_DR_GREEN_PRIO_1   125
0277 #define SYS_COUNT_DR_GREEN_PRIO_2   126
0278 #define SYS_COUNT_DR_GREEN_PRIO_3   127
0279 #define SYS_COUNT_DR_GREEN_PRIO_4   128
0280 #define SYS_COUNT_DR_GREEN_PRIO_5   129
0281 #define SYS_COUNT_DR_GREEN_PRIO_6   130
0282 #define SYS_COUNT_DR_GREEN_PRIO_7   131
0283 
0284 /* Add a possibly wrapping 32 bit value to a 64 bit counter */
0285 static void lan966x_add_cnt(u64 *cnt, u32 val)
0286 {
0287     if (val < (*cnt & U32_MAX))
0288         *cnt += (u64)1 << 32; /* value has wrapped */
0289 
0290     *cnt = (*cnt & ~(u64)U32_MAX) + val;
0291 }
0292 
0293 static void lan966x_stats_update(struct lan966x *lan966x)
0294 {
0295     int i, j;
0296 
0297     mutex_lock(&lan966x->stats_lock);
0298 
0299     for (i = 0; i < lan966x->num_phys_ports; i++) {
0300         uint idx = i * lan966x->num_stats;
0301 
0302         lan_wr(SYS_STAT_CFG_STAT_VIEW_SET(i),
0303                lan966x, SYS_STAT_CFG);
0304 
0305         for (j = 0; j < lan966x->num_stats; j++) {
0306             u32 offset = lan966x->stats_layout[j].offset;
0307 
0308             lan966x_add_cnt(&lan966x->stats[idx++],
0309                     lan_rd(lan966x, SYS_CNT(offset)));
0310         }
0311     }
0312 
0313     mutex_unlock(&lan966x->stats_lock);
0314 }
0315 
0316 static int lan966x_get_sset_count(struct net_device *dev, int sset)
0317 {
0318     struct lan966x_port *port = netdev_priv(dev);
0319     struct lan966x *lan966x = port->lan966x;
0320 
0321     if (sset != ETH_SS_STATS)
0322         return -EOPNOTSUPP;
0323 
0324     return lan966x->num_stats;
0325 }
0326 
0327 static void lan966x_get_strings(struct net_device *netdev, u32 sset, u8 *data)
0328 {
0329     struct lan966x_port *port = netdev_priv(netdev);
0330     struct lan966x *lan966x = port->lan966x;
0331     int i;
0332 
0333     if (sset != ETH_SS_STATS)
0334         return;
0335 
0336     for (i = 0; i < lan966x->num_stats; i++)
0337         memcpy(data + i * ETH_GSTRING_LEN,
0338                lan966x->stats_layout[i].name, ETH_GSTRING_LEN);
0339 }
0340 
0341 static void lan966x_get_ethtool_stats(struct net_device *dev,
0342                       struct ethtool_stats *stats, u64 *data)
0343 {
0344     struct lan966x_port *port = netdev_priv(dev);
0345     struct lan966x *lan966x = port->lan966x;
0346     int i;
0347 
0348     /* check and update now */
0349     lan966x_stats_update(lan966x);
0350 
0351     /* Copy all counters */
0352     for (i = 0; i < lan966x->num_stats; i++)
0353         *data++ = lan966x->stats[port->chip_port *
0354                      lan966x->num_stats + i];
0355 }
0356 
0357 static void lan966x_get_eth_mac_stats(struct net_device *dev,
0358                       struct ethtool_eth_mac_stats *mac_stats)
0359 {
0360     struct lan966x_port *port = netdev_priv(dev);
0361     struct lan966x *lan966x = port->lan966x;
0362     u32 idx;
0363 
0364     lan966x_stats_update(lan966x);
0365 
0366     idx = port->chip_port * lan966x->num_stats;
0367 
0368     mutex_lock(&lan966x->stats_lock);
0369 
0370     mac_stats->FramesTransmittedOK =
0371         lan966x->stats[idx + SYS_COUNT_TX_UC] +
0372         lan966x->stats[idx + SYS_COUNT_TX_MC] +
0373         lan966x->stats[idx + SYS_COUNT_TX_BC] +
0374         lan966x->stats[idx + SYS_COUNT_TX_PMAC_UC] +
0375         lan966x->stats[idx + SYS_COUNT_TX_PMAC_MC] +
0376         lan966x->stats[idx + SYS_COUNT_TX_PMAC_BC];
0377     mac_stats->SingleCollisionFrames =
0378         lan966x->stats[idx + SYS_COUNT_TX_COL];
0379     mac_stats->MultipleCollisionFrames = 0;
0380     mac_stats->FramesReceivedOK =
0381         lan966x->stats[idx + SYS_COUNT_RX_UC] +
0382         lan966x->stats[idx + SYS_COUNT_RX_MC] +
0383         lan966x->stats[idx + SYS_COUNT_RX_BC];
0384     mac_stats->FrameCheckSequenceErrors =
0385         lan966x->stats[idx + SYS_COUNT_RX_CRC] +
0386         lan966x->stats[idx + SYS_COUNT_RX_CRC];
0387     mac_stats->AlignmentErrors = 0;
0388     mac_stats->OctetsTransmittedOK =
0389         lan966x->stats[idx + SYS_COUNT_TX_OCT] +
0390         lan966x->stats[idx + SYS_COUNT_TX_PMAC_OCT];
0391     mac_stats->FramesWithDeferredXmissions =
0392         lan966x->stats[idx + SYS_COUNT_TX_MM_HOLD];
0393     mac_stats->LateCollisions = 0;
0394     mac_stats->FramesAbortedDueToXSColls = 0;
0395     mac_stats->FramesLostDueToIntMACXmitError = 0;
0396     mac_stats->CarrierSenseErrors = 0;
0397     mac_stats->OctetsReceivedOK =
0398         lan966x->stats[idx + SYS_COUNT_RX_OCT];
0399     mac_stats->FramesLostDueToIntMACRcvError = 0;
0400     mac_stats->MulticastFramesXmittedOK =
0401         lan966x->stats[idx + SYS_COUNT_TX_MC] +
0402         lan966x->stats[idx + SYS_COUNT_TX_PMAC_MC];
0403     mac_stats->BroadcastFramesXmittedOK =
0404         lan966x->stats[idx + SYS_COUNT_TX_BC] +
0405         lan966x->stats[idx + SYS_COUNT_TX_PMAC_BC];
0406     mac_stats->FramesWithExcessiveDeferral = 0;
0407     mac_stats->MulticastFramesReceivedOK =
0408         lan966x->stats[idx + SYS_COUNT_RX_MC];
0409     mac_stats->BroadcastFramesReceivedOK =
0410         lan966x->stats[idx + SYS_COUNT_RX_BC];
0411     mac_stats->InRangeLengthErrors =
0412         lan966x->stats[idx + SYS_COUNT_RX_FRAG] +
0413         lan966x->stats[idx + SYS_COUNT_RX_JABBER] +
0414         lan966x->stats[idx + SYS_COUNT_RX_CRC] +
0415         lan966x->stats[idx + SYS_COUNT_RX_PMAC_FRAG] +
0416         lan966x->stats[idx + SYS_COUNT_RX_PMAC_JABBER] +
0417         lan966x->stats[idx + SYS_COUNT_RX_PMAC_CRC];
0418     mac_stats->OutOfRangeLengthField =
0419         lan966x->stats[idx + SYS_COUNT_RX_SHORT] +
0420         lan966x->stats[idx + SYS_COUNT_RX_PMAC_SHORT] +
0421         lan966x->stats[idx + SYS_COUNT_RX_LONG] +
0422         lan966x->stats[idx + SYS_COUNT_RX_PMAC_LONG];
0423     mac_stats->FrameTooLongErrors =
0424         lan966x->stats[idx + SYS_COUNT_RX_LONG] +
0425         lan966x->stats[idx + SYS_COUNT_RX_PMAC_LONG];
0426 
0427     mutex_unlock(&lan966x->stats_lock);
0428 }
0429 
0430 static const struct ethtool_rmon_hist_range lan966x_rmon_ranges[] = {
0431     {    0,    64 },
0432     {   65,   127 },
0433     {  128,   255 },
0434     {  256,   511 },
0435     {  512,  1023 },
0436     { 1024,  1518 },
0437     { 1519, 10239 },
0438     {}
0439 };
0440 
0441 static void lan966x_get_eth_rmon_stats(struct net_device *dev,
0442                        struct ethtool_rmon_stats *rmon_stats,
0443                        const struct ethtool_rmon_hist_range **ranges)
0444 {
0445     struct lan966x_port *port = netdev_priv(dev);
0446     struct lan966x *lan966x = port->lan966x;
0447     u32 idx;
0448 
0449     lan966x_stats_update(lan966x);
0450 
0451     idx = port->chip_port * lan966x->num_stats;
0452 
0453     mutex_lock(&lan966x->stats_lock);
0454 
0455     rmon_stats->undersize_pkts =
0456         lan966x->stats[idx + SYS_COUNT_RX_SHORT] +
0457         lan966x->stats[idx + SYS_COUNT_RX_PMAC_SHORT];
0458     rmon_stats->oversize_pkts =
0459         lan966x->stats[idx + SYS_COUNT_RX_LONG] +
0460         lan966x->stats[idx + SYS_COUNT_RX_PMAC_LONG];
0461     rmon_stats->fragments =
0462         lan966x->stats[idx + SYS_COUNT_RX_FRAG] +
0463         lan966x->stats[idx + SYS_COUNT_RX_PMAC_FRAG];
0464     rmon_stats->jabbers =
0465         lan966x->stats[idx + SYS_COUNT_RX_JABBER] +
0466         lan966x->stats[idx + SYS_COUNT_RX_PMAC_JABBER];
0467     rmon_stats->hist[0] =
0468         lan966x->stats[idx + SYS_COUNT_RX_SZ_64] +
0469         lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_64];
0470     rmon_stats->hist[1] =
0471         lan966x->stats[idx + SYS_COUNT_RX_SZ_65_127] +
0472         lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_65_127];
0473     rmon_stats->hist[2] =
0474         lan966x->stats[idx + SYS_COUNT_RX_SZ_128_255] +
0475         lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_128_255];
0476     rmon_stats->hist[3] =
0477         lan966x->stats[idx + SYS_COUNT_RX_SZ_256_511] +
0478         lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_256_511];
0479     rmon_stats->hist[4] =
0480         lan966x->stats[idx + SYS_COUNT_RX_SZ_512_1023] +
0481         lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_512_1023];
0482     rmon_stats->hist[5] =
0483         lan966x->stats[idx + SYS_COUNT_RX_SZ_1024_1526] +
0484         lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_1024_1526];
0485     rmon_stats->hist[6] =
0486         lan966x->stats[idx + SYS_COUNT_RX_SZ_1024_1526] +
0487         lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_1024_1526];
0488 
0489     rmon_stats->hist_tx[0] =
0490         lan966x->stats[idx + SYS_COUNT_TX_SZ_64] +
0491         lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_64];
0492     rmon_stats->hist_tx[1] =
0493         lan966x->stats[idx + SYS_COUNT_TX_SZ_65_127] +
0494         lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_65_127];
0495     rmon_stats->hist_tx[2] =
0496         lan966x->stats[idx + SYS_COUNT_TX_SZ_128_255] +
0497         lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_128_255];
0498     rmon_stats->hist_tx[3] =
0499         lan966x->stats[idx + SYS_COUNT_TX_SZ_256_511] +
0500         lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_256_511];
0501     rmon_stats->hist_tx[4] =
0502         lan966x->stats[idx + SYS_COUNT_TX_SZ_512_1023] +
0503         lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_512_1023];
0504     rmon_stats->hist_tx[5] =
0505         lan966x->stats[idx + SYS_COUNT_TX_SZ_1024_1526] +
0506         lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_1024_1526];
0507     rmon_stats->hist_tx[6] =
0508         lan966x->stats[idx + SYS_COUNT_TX_SZ_1024_1526] +
0509         lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_1024_1526];
0510 
0511     mutex_unlock(&lan966x->stats_lock);
0512 
0513     *ranges = lan966x_rmon_ranges;
0514 }
0515 
0516 static int lan966x_get_link_ksettings(struct net_device *ndev,
0517                       struct ethtool_link_ksettings *cmd)
0518 {
0519     struct lan966x_port *port = netdev_priv(ndev);
0520 
0521     return phylink_ethtool_ksettings_get(port->phylink, cmd);
0522 }
0523 
0524 static int lan966x_set_link_ksettings(struct net_device *ndev,
0525                       const struct ethtool_link_ksettings *cmd)
0526 {
0527     struct lan966x_port *port = netdev_priv(ndev);
0528 
0529     return phylink_ethtool_ksettings_set(port->phylink, cmd);
0530 }
0531 
0532 static void lan966x_get_pauseparam(struct net_device *dev,
0533                    struct ethtool_pauseparam *pause)
0534 {
0535     struct lan966x_port *port = netdev_priv(dev);
0536 
0537     phylink_ethtool_get_pauseparam(port->phylink, pause);
0538 }
0539 
0540 static int lan966x_set_pauseparam(struct net_device *dev,
0541                   struct ethtool_pauseparam *pause)
0542 {
0543     struct lan966x_port *port = netdev_priv(dev);
0544 
0545     return phylink_ethtool_set_pauseparam(port->phylink, pause);
0546 }
0547 
0548 static int lan966x_get_ts_info(struct net_device *dev,
0549                    struct ethtool_ts_info *info)
0550 {
0551     struct lan966x_port *port = netdev_priv(dev);
0552     struct lan966x *lan966x = port->lan966x;
0553     struct lan966x_phc *phc;
0554 
0555     if (!lan966x->ptp)
0556         return ethtool_op_get_ts_info(dev, info);
0557 
0558     phc = &lan966x->phc[LAN966X_PHC_PORT];
0559 
0560     info->phc_index = phc->clock ? ptp_clock_index(phc->clock) : -1;
0561     if (info->phc_index == -1) {
0562         info->so_timestamping |= SOF_TIMESTAMPING_TX_SOFTWARE |
0563                      SOF_TIMESTAMPING_RX_SOFTWARE |
0564                      SOF_TIMESTAMPING_SOFTWARE;
0565         return 0;
0566     }
0567     info->so_timestamping |= SOF_TIMESTAMPING_TX_SOFTWARE |
0568                  SOF_TIMESTAMPING_RX_SOFTWARE |
0569                  SOF_TIMESTAMPING_SOFTWARE |
0570                  SOF_TIMESTAMPING_TX_HARDWARE |
0571                  SOF_TIMESTAMPING_RX_HARDWARE |
0572                  SOF_TIMESTAMPING_RAW_HARDWARE;
0573     info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON) |
0574              BIT(HWTSTAMP_TX_ONESTEP_SYNC);
0575     info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
0576                BIT(HWTSTAMP_FILTER_ALL);
0577 
0578     return 0;
0579 }
0580 
0581 const struct ethtool_ops lan966x_ethtool_ops = {
0582     .get_link_ksettings     = lan966x_get_link_ksettings,
0583     .set_link_ksettings     = lan966x_set_link_ksettings,
0584     .get_pauseparam     = lan966x_get_pauseparam,
0585     .set_pauseparam     = lan966x_set_pauseparam,
0586     .get_sset_count     = lan966x_get_sset_count,
0587     .get_strings        = lan966x_get_strings,
0588     .get_ethtool_stats  = lan966x_get_ethtool_stats,
0589     .get_eth_mac_stats      = lan966x_get_eth_mac_stats,
0590     .get_rmon_stats     = lan966x_get_eth_rmon_stats,
0591     .get_link       = ethtool_op_get_link,
0592     .get_ts_info        = lan966x_get_ts_info,
0593 };
0594 
0595 static void lan966x_check_stats_work(struct work_struct *work)
0596 {
0597     struct delayed_work *del_work = to_delayed_work(work);
0598     struct lan966x *lan966x = container_of(del_work, struct lan966x,
0599                            stats_work);
0600 
0601     lan966x_stats_update(lan966x);
0602 
0603     queue_delayed_work(lan966x->stats_queue, &lan966x->stats_work,
0604                LAN966X_STATS_CHECK_DELAY);
0605 }
0606 
0607 void lan966x_stats_get(struct net_device *dev,
0608                struct rtnl_link_stats64 *stats)
0609 {
0610     struct lan966x_port *port = netdev_priv(dev);
0611     struct lan966x *lan966x = port->lan966x;
0612     u32 idx;
0613     int i;
0614 
0615     idx = port->chip_port * lan966x->num_stats;
0616 
0617     mutex_lock(&lan966x->stats_lock);
0618 
0619     stats->rx_bytes = lan966x->stats[idx + SYS_COUNT_RX_OCT] +
0620         lan966x->stats[idx + SYS_COUNT_RX_PMAC_OCT];
0621 
0622     stats->rx_packets = lan966x->stats[idx + SYS_COUNT_RX_SHORT] +
0623         lan966x->stats[idx + SYS_COUNT_RX_FRAG] +
0624         lan966x->stats[idx + SYS_COUNT_RX_JABBER] +
0625         lan966x->stats[idx + SYS_COUNT_RX_CRC] +
0626         lan966x->stats[idx + SYS_COUNT_RX_SYMBOL_ERR] +
0627         lan966x->stats[idx + SYS_COUNT_RX_SZ_64] +
0628         lan966x->stats[idx + SYS_COUNT_RX_SZ_65_127] +
0629         lan966x->stats[idx + SYS_COUNT_RX_SZ_128_255] +
0630         lan966x->stats[idx + SYS_COUNT_RX_SZ_256_511] +
0631         lan966x->stats[idx + SYS_COUNT_RX_SZ_512_1023] +
0632         lan966x->stats[idx + SYS_COUNT_RX_SZ_1024_1526] +
0633         lan966x->stats[idx + SYS_COUNT_RX_SZ_JUMBO] +
0634         lan966x->stats[idx + SYS_COUNT_RX_LONG] +
0635         lan966x->stats[idx + SYS_COUNT_RX_PMAC_SHORT] +
0636         lan966x->stats[idx + SYS_COUNT_RX_PMAC_FRAG] +
0637         lan966x->stats[idx + SYS_COUNT_RX_PMAC_JABBER] +
0638         lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_64] +
0639         lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_65_127] +
0640         lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_128_255] +
0641         lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_256_511] +
0642         lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_512_1023] +
0643         lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_1024_1526] +
0644         lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_JUMBO];
0645 
0646     stats->multicast = lan966x->stats[idx + SYS_COUNT_RX_MC] +
0647         lan966x->stats[idx + SYS_COUNT_RX_PMAC_MC];
0648 
0649     stats->rx_errors = lan966x->stats[idx + SYS_COUNT_RX_SHORT] +
0650         lan966x->stats[idx + SYS_COUNT_RX_FRAG] +
0651         lan966x->stats[idx + SYS_COUNT_RX_JABBER] +
0652         lan966x->stats[idx + SYS_COUNT_RX_CRC] +
0653         lan966x->stats[idx + SYS_COUNT_RX_SYMBOL_ERR] +
0654         lan966x->stats[idx + SYS_COUNT_RX_LONG];
0655 
0656     stats->rx_dropped = dev->stats.rx_dropped +
0657         lan966x->stats[idx + SYS_COUNT_RX_LONG] +
0658         lan966x->stats[idx + SYS_COUNT_DR_LOCAL] +
0659         lan966x->stats[idx + SYS_COUNT_DR_TAIL];
0660 
0661     for (i = 0; i < LAN966X_NUM_TC; i++) {
0662         stats->rx_dropped +=
0663             (lan966x->stats[idx + SYS_COUNT_DR_YELLOW_PRIO_0 + i] +
0664              lan966x->stats[idx + SYS_COUNT_DR_GREEN_PRIO_0 + i]);
0665     }
0666 
0667     /* Get Tx stats */
0668     stats->tx_bytes = lan966x->stats[idx + SYS_COUNT_TX_OCT] +
0669         lan966x->stats[idx + SYS_COUNT_TX_PMAC_OCT];
0670 
0671     stats->tx_packets = lan966x->stats[idx + SYS_COUNT_TX_SZ_64] +
0672         lan966x->stats[idx + SYS_COUNT_TX_SZ_65_127] +
0673         lan966x->stats[idx + SYS_COUNT_TX_SZ_128_255] +
0674         lan966x->stats[idx + SYS_COUNT_TX_SZ_256_511] +
0675         lan966x->stats[idx + SYS_COUNT_TX_SZ_512_1023] +
0676         lan966x->stats[idx + SYS_COUNT_TX_SZ_1024_1526] +
0677         lan966x->stats[idx + SYS_COUNT_TX_SZ_JUMBO] +
0678         lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_64] +
0679         lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_65_127] +
0680         lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_128_255] +
0681         lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_256_511] +
0682         lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_512_1023] +
0683         lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_1024_1526] +
0684         lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_JUMBO];
0685 
0686     stats->tx_dropped = lan966x->stats[idx + SYS_COUNT_TX_DROP] +
0687         lan966x->stats[idx + SYS_COUNT_TX_AGED];
0688 
0689     stats->collisions = lan966x->stats[idx + SYS_COUNT_TX_COL];
0690 
0691     mutex_unlock(&lan966x->stats_lock);
0692 }
0693 
0694 int lan966x_stats_init(struct lan966x *lan966x)
0695 {
0696     char queue_name[32];
0697 
0698     lan966x->stats_layout = lan966x_stats_layout;
0699     lan966x->num_stats = ARRAY_SIZE(lan966x_stats_layout);
0700     lan966x->stats = devm_kcalloc(lan966x->dev, lan966x->num_phys_ports *
0701                       lan966x->num_stats,
0702                       sizeof(u64), GFP_KERNEL);
0703     if (!lan966x->stats)
0704         return -ENOMEM;
0705 
0706     /* Init stats worker */
0707     mutex_init(&lan966x->stats_lock);
0708     snprintf(queue_name, sizeof(queue_name), "%s-stats",
0709          dev_name(lan966x->dev));
0710     lan966x->stats_queue = create_singlethread_workqueue(queue_name);
0711     INIT_DELAYED_WORK(&lan966x->stats_work, lan966x_check_stats_work);
0712     queue_delayed_work(lan966x->stats_queue, &lan966x->stats_work,
0713                LAN966X_STATS_CHECK_DELAY);
0714 
0715     return 0;
0716 }