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 11 static 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 */ 285 static 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 293 static 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 316 static 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 327 static 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 341 static 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 357 static void lan966x_get_eth_mac_stats(struct net_device *dev, 358 struct ethtool_eth_mac_stats *mac_stats) 359 { 360 struct lan966x_port *port = netdev_priv(dev); 361 struct lan966x *lan966x = port->lan966x; 362 u32 idx; 363 364 lan966x_stats_update(lan966x); 365 366 idx = port->chip_port * lan966x->num_stats; 367 368 mutex_lock(&lan966x->stats_lock); 369 370 mac_stats->FramesTransmittedOK = 371 lan966x->stats[idx + SYS_COUNT_TX_UC] + 372 lan966x->stats[idx + SYS_COUNT_TX_MC] + 373 lan966x->stats[idx + SYS_COUNT_TX_BC] + 374 lan966x->stats[idx + SYS_COUNT_TX_PMAC_UC] + 375 lan966x->stats[idx + SYS_COUNT_TX_PMAC_MC] + 376 lan966x->stats[idx + SYS_COUNT_TX_PMAC_BC]; 377 mac_stats->SingleCollisionFrames = 378 lan966x->stats[idx + SYS_COUNT_TX_COL]; 379 mac_stats->FramesReceivedOK = 380 lan966x->stats[idx + SYS_COUNT_RX_UC] + 381 lan966x->stats[idx + SYS_COUNT_RX_MC] + 382 lan966x->stats[idx + SYS_COUNT_RX_BC]; 383 mac_stats->FrameCheckSequenceErrors = 384 lan966x->stats[idx + SYS_COUNT_RX_CRC] + 385 lan966x->stats[idx + SYS_COUNT_RX_CRC]; 386 mac_stats->OctetsTransmittedOK = 387 lan966x->stats[idx + SYS_COUNT_TX_OCT] + 388 lan966x->stats[idx + SYS_COUNT_TX_PMAC_OCT]; 389 mac_stats->FramesWithDeferredXmissions = 390 lan966x->stats[idx + SYS_COUNT_TX_MM_HOLD]; 391 mac_stats->OctetsReceivedOK = 392 lan966x->stats[idx + SYS_COUNT_RX_OCT]; 393 mac_stats->MulticastFramesXmittedOK = 394 lan966x->stats[idx + SYS_COUNT_TX_MC] + 395 lan966x->stats[idx + SYS_COUNT_TX_PMAC_MC]; 396 mac_stats->BroadcastFramesXmittedOK = 397 lan966x->stats[idx + SYS_COUNT_TX_BC] + 398 lan966x->stats[idx + SYS_COUNT_TX_PMAC_BC]; 399 mac_stats->MulticastFramesReceivedOK = 400 lan966x->stats[idx + SYS_COUNT_RX_MC]; 401 mac_stats->BroadcastFramesReceivedOK = 402 lan966x->stats[idx + SYS_COUNT_RX_BC]; 403 mac_stats->InRangeLengthErrors = 404 lan966x->stats[idx + SYS_COUNT_RX_FRAG] + 405 lan966x->stats[idx + SYS_COUNT_RX_JABBER] + 406 lan966x->stats[idx + SYS_COUNT_RX_CRC] + 407 lan966x->stats[idx + SYS_COUNT_RX_PMAC_FRAG] + 408 lan966x->stats[idx + SYS_COUNT_RX_PMAC_JABBER] + 409 lan966x->stats[idx + SYS_COUNT_RX_PMAC_CRC]; 410 mac_stats->OutOfRangeLengthField = 411 lan966x->stats[idx + SYS_COUNT_RX_SHORT] + 412 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SHORT] + 413 lan966x->stats[idx + SYS_COUNT_RX_LONG] + 414 lan966x->stats[idx + SYS_COUNT_RX_PMAC_LONG]; 415 mac_stats->FrameTooLongErrors = 416 lan966x->stats[idx + SYS_COUNT_RX_LONG] + 417 lan966x->stats[idx + SYS_COUNT_RX_PMAC_LONG]; 418 419 mutex_unlock(&lan966x->stats_lock); 420 } 421 422 static const struct ethtool_rmon_hist_range lan966x_rmon_ranges[] = { 423 { 0, 64 }, 424 { 65, 127 }, 425 { 128, 255 }, 426 { 256, 511 }, 427 { 512, 1023 }, 428 { 1024, 1518 }, 429 { 1519, 10239 }, 430 {} 431 }; 432 433 static void lan966x_get_eth_rmon_stats(struct net_device *dev, 434 struct ethtool_rmon_stats *rmon_stats, 435 const struct ethtool_rmon_hist_range **ranges) 436 { 437 struct lan966x_port *port = netdev_priv(dev); 438 struct lan966x *lan966x = port->lan966x; 439 u32 idx; 440 441 lan966x_stats_update(lan966x); 442 443 idx = port->chip_port * lan966x->num_stats; 444 445 mutex_lock(&lan966x->stats_lock); 446 447 rmon_stats->undersize_pkts = 448 lan966x->stats[idx + SYS_COUNT_RX_SHORT] + 449 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SHORT]; 450 rmon_stats->oversize_pkts = 451 lan966x->stats[idx + SYS_COUNT_RX_LONG] + 452 lan966x->stats[idx + SYS_COUNT_RX_PMAC_LONG]; 453 rmon_stats->fragments = 454 lan966x->stats[idx + SYS_COUNT_RX_FRAG] + 455 lan966x->stats[idx + SYS_COUNT_RX_PMAC_FRAG]; 456 rmon_stats->jabbers = 457 lan966x->stats[idx + SYS_COUNT_RX_JABBER] + 458 lan966x->stats[idx + SYS_COUNT_RX_PMAC_JABBER]; 459 rmon_stats->hist[0] = 460 lan966x->stats[idx + SYS_COUNT_RX_SZ_64] + 461 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_64]; 462 rmon_stats->hist[1] = 463 lan966x->stats[idx + SYS_COUNT_RX_SZ_65_127] + 464 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_65_127]; 465 rmon_stats->hist[2] = 466 lan966x->stats[idx + SYS_COUNT_RX_SZ_128_255] + 467 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_128_255]; 468 rmon_stats->hist[3] = 469 lan966x->stats[idx + SYS_COUNT_RX_SZ_256_511] + 470 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_256_511]; 471 rmon_stats->hist[4] = 472 lan966x->stats[idx + SYS_COUNT_RX_SZ_512_1023] + 473 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_512_1023]; 474 rmon_stats->hist[5] = 475 lan966x->stats[idx + SYS_COUNT_RX_SZ_1024_1526] + 476 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_1024_1526]; 477 rmon_stats->hist[6] = 478 lan966x->stats[idx + SYS_COUNT_RX_SZ_1024_1526] + 479 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_1024_1526]; 480 481 rmon_stats->hist_tx[0] = 482 lan966x->stats[idx + SYS_COUNT_TX_SZ_64] + 483 lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_64]; 484 rmon_stats->hist_tx[1] = 485 lan966x->stats[idx + SYS_COUNT_TX_SZ_65_127] + 486 lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_65_127]; 487 rmon_stats->hist_tx[2] = 488 lan966x->stats[idx + SYS_COUNT_TX_SZ_128_255] + 489 lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_128_255]; 490 rmon_stats->hist_tx[3] = 491 lan966x->stats[idx + SYS_COUNT_TX_SZ_256_511] + 492 lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_256_511]; 493 rmon_stats->hist_tx[4] = 494 lan966x->stats[idx + SYS_COUNT_TX_SZ_512_1023] + 495 lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_512_1023]; 496 rmon_stats->hist_tx[5] = 497 lan966x->stats[idx + SYS_COUNT_TX_SZ_1024_1526] + 498 lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_1024_1526]; 499 rmon_stats->hist_tx[6] = 500 lan966x->stats[idx + SYS_COUNT_TX_SZ_1024_1526] + 501 lan966x->stats[idx + SYS_COUNT_TX_PMAC_SZ_1024_1526]; 502 503 mutex_unlock(&lan966x->stats_lock); 504 505 *ranges = lan966x_rmon_ranges; 506 } 507 508 static int lan966x_get_link_ksettings(struct net_device *ndev, 509 struct ethtool_link_ksettings *cmd) 510 { 511 struct lan966x_port *port = netdev_priv(ndev); 512 513 return phylink_ethtool_ksettings_get(port->phylink, cmd); 514 } 515 516 static int lan966x_set_link_ksettings(struct net_device *ndev, 517 const struct ethtool_link_ksettings *cmd) 518 { 519 struct lan966x_port *port = netdev_priv(ndev); 520 521 return phylink_ethtool_ksettings_set(port->phylink, cmd); 522 } 523 524 static void lan966x_get_pauseparam(struct net_device *dev, 525 struct ethtool_pauseparam *pause) 526 { 527 struct lan966x_port *port = netdev_priv(dev); 528 529 phylink_ethtool_get_pauseparam(port->phylink, pause); 530 } 531 532 static int lan966x_set_pauseparam(struct net_device *dev, 533 struct ethtool_pauseparam *pause) 534 { 535 struct lan966x_port *port = netdev_priv(dev); 536 537 return phylink_ethtool_set_pauseparam(port->phylink, pause); 538 } 539 540 static int lan966x_get_ts_info(struct net_device *dev, 541 struct kernel_ethtool_ts_info *info) 542 { 543 struct lan966x_port *port = netdev_priv(dev); 544 struct lan966x *lan966x = port->lan966x; 545 struct lan966x_phc *phc; 546 547 if (!lan966x->ptp) 548 return ethtool_op_get_ts_info(dev, info); 549 550 phc = &lan966x->phc[LAN966X_PHC_PORT]; 551 552 info->phc_index = phc->clock ? ptp_clock_index(phc->clock) : -1; 553 if (info->phc_index == -1) { 554 info->so_timestamping |= SOF_TIMESTAMPING_TX_SOFTWARE | 555 SOF_TIMESTAMPING_RX_SOFTWARE | 556 SOF_TIMESTAMPING_SOFTWARE; 557 return 0; 558 } 559 info->so_timestamping |= SOF_TIMESTAMPING_TX_SOFTWARE | 560 SOF_TIMESTAMPING_RX_SOFTWARE | 561 SOF_TIMESTAMPING_SOFTWARE | 562 SOF_TIMESTAMPING_TX_HARDWARE | 563 SOF_TIMESTAMPING_RX_HARDWARE | 564 SOF_TIMESTAMPING_RAW_HARDWARE; 565 info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON) | 566 BIT(HWTSTAMP_TX_ONESTEP_SYNC); 567 info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | 568 BIT(HWTSTAMP_FILTER_ALL); 569 570 return 0; 571 } 572 573 const struct ethtool_ops lan966x_ethtool_ops = { 574 .get_link_ksettings = lan966x_get_link_ksettings, 575 .set_link_ksettings = lan966x_set_link_ksettings, 576 .get_pauseparam = lan966x_get_pauseparam, 577 .set_pauseparam = lan966x_set_pauseparam, 578 .get_sset_count = lan966x_get_sset_count, 579 .get_strings = lan966x_get_strings, 580 .get_ethtool_stats = lan966x_get_ethtool_stats, 581 .get_eth_mac_stats = lan966x_get_eth_mac_stats, 582 .get_rmon_stats = lan966x_get_eth_rmon_stats, 583 .get_link = ethtool_op_get_link, 584 .get_ts_info = lan966x_get_ts_info, 585 }; 586 587 static void lan966x_check_stats_work(struct work_struct *work) 588 { 589 struct delayed_work *del_work = to_delayed_work(work); 590 struct lan966x *lan966x = container_of(del_work, struct lan966x, 591 stats_work); 592 593 lan966x_stats_update(lan966x); 594 595 queue_delayed_work(lan966x->stats_queue, &lan966x->stats_work, 596 LAN966X_STATS_CHECK_DELAY); 597 } 598 599 void lan966x_stats_get(struct net_device *dev, 600 struct rtnl_link_stats64 *stats) 601 { 602 struct lan966x_port *port = netdev_priv(dev); 603 struct lan966x *lan966x = port->lan966x; 604 u32 idx; 605 int i; 606 607 idx = port->chip_port * lan966x->num_stats; 608 609 mutex_lock(&lan966x->stats_lock); 610 611 stats->rx_bytes = lan966x->stats[idx + SYS_COUNT_RX_OCT] + 612 lan966x->stats[idx + SYS_COUNT_RX_PMAC_OCT]; 613 614 stats->rx_packets = lan966x->stats[idx + SYS_COUNT_RX_SHORT] + 615 lan966x->stats[idx + SYS_COUNT_RX_FRAG] + 616 lan966x->stats[idx + SYS_COUNT_RX_JABBER] + 617 lan966x->stats[idx + SYS_COUNT_RX_CRC] + 618 lan966x->stats[idx + SYS_COUNT_RX_SYMBOL_ERR] + 619 lan966x->stats[idx + SYS_COUNT_RX_SZ_64] + 620 lan966x->stats[idx + SYS_COUNT_RX_SZ_65_127] + 621 lan966x->stats[idx + SYS_COUNT_RX_SZ_128_255] + 622 lan966x->stats[idx + SYS_COUNT_RX_SZ_256_511] + 623 lan966x->stats[idx + SYS_COUNT_RX_SZ_512_1023] + 624 lan966x->stats[idx + SYS_COUNT_RX_SZ_1024_1526] + 625 lan966x->stats[idx + SYS_COUNT_RX_SZ_JUMBO] + 626 lan966x->stats[idx + SYS_COUNT_RX_LONG] + 627 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SHORT] + 628 lan966x->stats[idx + SYS_COUNT_RX_PMAC_FRAG] + 629 lan966x->stats[idx + SYS_COUNT_RX_PMAC_JABBER] + 630 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_64] + 631 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_65_127] + 632 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_128_255] + 633 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_256_511] + 634 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_512_1023] + 635 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_1024_1526] + 636 lan966x->stats[idx + SYS_COUNT_RX_PMAC_SZ_JUMBO]; 637 638 stats->multicast = lan966x->stats[idx + SYS_COUNT_RX_MC] + 639 lan966x->stats[idx + SYS_COUNT_RX_PMAC_MC]; 640 641 stats->rx_errors = lan966x->stats[idx + SYS_COUNT_RX_SHORT] + 642 lan966x->stats[idx + SYS_COUNT_RX_FRAG] + 643 lan966x->stats[idx + SYS_COUNT_RX_JABBER] + 644 lan966x->stats[idx + SYS_COUNT_RX_CRC] + 645 lan966x->stats[idx + SYS_COUNT_RX_SYMBOL_ERR] + 646 lan966x->stats[idx + SYS_COUNT_RX_LONG]; 647 648 stats->rx_dropped = dev->stats.rx_dropped + 649 lan966x->stats[idx + SYS_COUNT_RX_LONG] + 650 lan966x->stats[idx + SYS_COUNT_DR_LOCAL] + 651 lan966x->stats[idx + SYS_COUNT_DR_TAIL] + 652 lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_0] + 653 lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_1] + 654 lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_2] + 655 lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_3] + 656 lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_4] + 657 lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_5] + 658 lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_6] + 659 lan966x->stats[idx + SYS_COUNT_RX_RED_PRIO_7]; 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 694 int 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 if (!lan966x->stats_queue) 712 return -ENOMEM; 713 714 INIT_DELAYED_WORK(&lan966x->stats_work, lan966x_check_stats_work); 715 queue_delayed_work(lan966x->stats_queue, &lan966x->stats_work, 716 LAN966X_STATS_CHECK_DELAY); 717 718 return 0; 719 } 720