0001
0002
0003 #include <linux/netdevice.h>
0004
0005 #include "lan966x_main.h"
0006
0007
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
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
0285 static void lan966x_add_cnt(u64 *cnt, u32 val)
0286 {
0287 if (val < (*cnt & U32_MAX))
0288 *cnt += (u64)1 << 32;
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
0349 lan966x_stats_update(lan966x);
0350
0351
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
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
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 }