linux/drivers/net/ethernet/microchip/lan966x/lan966x_ethtool.c
<<
>>
Prefs
   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}
 717