1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (c) 2026 David Yang 4 */ 5 6 #include "chip.h" 7 #include "mib.h" 8 #include "smi.h" 9 10 struct yt921x_mib_desc { 11 unsigned int size; 12 unsigned int offset; 13 const char *name; 14 }; 15 16 #define MIB_DESC(_size, _offset, _name) \ 17 {_size, _offset, _name} 18 19 /* Must agree with yt921x_mib_stats 20 * 21 * Unstructured fields (name != NULL) will appear in get_ethtool_stats(), 22 * structured go to their *_stats() methods, but we need their sizes and offsets 23 * to perform 32bit MIB overflow wraparound. 24 */ 25 static const struct yt921x_mib_desc yt921x_mib_descs[] = { 26 MIB_DESC(1, YT921X_MIB_DATA_RX_BROADCAST, NULL), 27 MIB_DESC(1, YT921X_MIB_DATA_RX_PAUSE, NULL), 28 MIB_DESC(1, YT921X_MIB_DATA_RX_MULTICAST, NULL), 29 MIB_DESC(1, YT921X_MIB_DATA_RX_CRC_ERR, NULL), 30 31 MIB_DESC(1, YT921X_MIB_DATA_RX_ALIGN_ERR, NULL), 32 MIB_DESC(1, YT921X_MIB_DATA_RX_UNDERSIZE_ERR, NULL), 33 MIB_DESC(1, YT921X_MIB_DATA_RX_FRAG_ERR, NULL), 34 MIB_DESC(1, YT921X_MIB_DATA_RX_PKT_SZ_64, NULL), 35 36 MIB_DESC(1, YT921X_MIB_DATA_RX_PKT_SZ_65_TO_127, NULL), 37 MIB_DESC(1, YT921X_MIB_DATA_RX_PKT_SZ_128_TO_255, NULL), 38 MIB_DESC(1, YT921X_MIB_DATA_RX_PKT_SZ_256_TO_511, NULL), 39 MIB_DESC(1, YT921X_MIB_DATA_RX_PKT_SZ_512_TO_1023, NULL), 40 41 MIB_DESC(1, YT921X_MIB_DATA_RX_PKT_SZ_1024_TO_1518, NULL), 42 MIB_DESC(1, YT921X_MIB_DATA_RX_PKT_SZ_1519_TO_MAX, NULL), 43 MIB_DESC(2, YT921X_MIB_DATA_RX_GOOD_BYTES, NULL), 44 45 MIB_DESC(2, YT921X_MIB_DATA_RX_BAD_BYTES, "RxBadBytes"), 46 MIB_DESC(1, YT921X_MIB_DATA_RX_OVERSIZE_ERR, NULL), 47 48 MIB_DESC(1, YT921X_MIB_DATA_RX_DROPPED, NULL), 49 MIB_DESC(1, YT921X_MIB_DATA_TX_BROADCAST, NULL), 50 MIB_DESC(1, YT921X_MIB_DATA_TX_PAUSE, NULL), 51 MIB_DESC(1, YT921X_MIB_DATA_TX_MULTICAST, NULL), 52 53 MIB_DESC(1, YT921X_MIB_DATA_TX_UNDERSIZE_ERR, NULL), 54 MIB_DESC(1, YT921X_MIB_DATA_TX_PKT_SZ_64, NULL), 55 MIB_DESC(1, YT921X_MIB_DATA_TX_PKT_SZ_65_TO_127, NULL), 56 MIB_DESC(1, YT921X_MIB_DATA_TX_PKT_SZ_128_TO_255, NULL), 57 58 MIB_DESC(1, YT921X_MIB_DATA_TX_PKT_SZ_256_TO_511, NULL), 59 MIB_DESC(1, YT921X_MIB_DATA_TX_PKT_SZ_512_TO_1023, NULL), 60 MIB_DESC(1, YT921X_MIB_DATA_TX_PKT_SZ_1024_TO_1518, NULL), 61 MIB_DESC(1, YT921X_MIB_DATA_TX_PKT_SZ_1519_TO_MAX, NULL), 62 63 MIB_DESC(2, YT921X_MIB_DATA_TX_GOOD_BYTES, NULL), 64 MIB_DESC(1, YT921X_MIB_DATA_TX_COLLISION, NULL), 65 66 MIB_DESC(1, YT921X_MIB_DATA_TX_EXCESSIVE_COLLISION, NULL), 67 MIB_DESC(1, YT921X_MIB_DATA_TX_MULTIPLE_COLLISION, NULL), 68 MIB_DESC(1, YT921X_MIB_DATA_TX_SINGLE_COLLISION, NULL), 69 MIB_DESC(1, YT921X_MIB_DATA_TX_PKT, NULL), 70 71 MIB_DESC(1, YT921X_MIB_DATA_TX_DEFERRED, NULL), 72 MIB_DESC(1, YT921X_MIB_DATA_TX_LATE_COLLISION, NULL), 73 MIB_DESC(1, YT921X_MIB_DATA_RX_OAM, "RxOAM"), 74 MIB_DESC(1, YT921X_MIB_DATA_TX_OAM, "TxOAM"), 75 }; 76 77 static_assert(ARRAY_SIZE(yt921x_mib_descs) == YT921X_MIB_STAT_NUM); 78 79 /* The interval should be small enough to avoid overflow of 32bit MIBs. 80 * 81 * Until we can read MIBs from stats64 call directly (i.e. sleep 82 * there), we have to poll stats more frequently then it is actually needed. 83 * For overflow protection, normally, 100 sec interval should have been OK. 84 */ 85 #define YT921X_STATS_INTERVAL_JIFFIES (3 * HZ) 86 87 /* Read and handle overflow of 32bit MIBs. MIB buffer must be zeroed before. */ 88 static int yt921x_mib_read(struct yt921x_priv *priv, int port) 89 { 90 struct device *dev = yt921x_priv_to_device(priv); 91 struct yt921x_port *pp = &priv->ports[port]; 92 struct yt921x_mib *pm = pp->mib; 93 struct yt921x_mib_stats *mib; 94 u64 *buf = pm->data; 95 unsigned long flags; 96 u64 rx_frames; 97 u64 tx_frames; 98 int res = 0; 99 100 mib = &pm->stats; 101 102 for (size_t i = 0; i < ARRAY_SIZE(yt921x_mib_descs); i++) { 103 const struct yt921x_mib_desc *desc = &yt921x_mib_descs[i]; 104 u32 reg = YT921X_MIBn_DATA0(port) + desc->offset; 105 u32 val0; 106 u64 val; 107 108 res = yt921x_reg_read(priv, reg, &val0); 109 if (res) 110 break; 111 112 if (desc->size <= 1) { 113 u64 old_val = buf[i]; 114 115 val = (old_val & ~(u64)U32_MAX) | val0; 116 if (val < old_val) 117 val += 1ull << 32; 118 } else { 119 u32 val1; 120 121 res = yt921x_reg_read(priv, reg + 4, &val1); 122 if (res) 123 break; 124 val = ((u64)val1 << 32) | val0; 125 } 126 127 buf[i] = val; 128 } 129 130 flags = u64_stats_update_begin_irqsave(&pm->syncp); 131 for (size_t i = 0; i < ARRAY_SIZE(yt921x_mib_descs); i++) 132 u64_stats_set(&((u64_stats_t *)mib)[i], buf[i]); 133 rx_frames = u64_stats_read(&mib->rx_64byte) + 134 u64_stats_read(&mib->rx_65_127byte) + 135 u64_stats_read(&mib->rx_128_255byte) + 136 u64_stats_read(&mib->rx_256_511byte) + 137 u64_stats_read(&mib->rx_512_1023byte) + 138 u64_stats_read(&mib->rx_1024_1518byte) + 139 u64_stats_read(&mib->rx_jumbo); 140 tx_frames = u64_stats_read(&mib->tx_64byte) + 141 u64_stats_read(&mib->tx_65_127byte) + 142 u64_stats_read(&mib->tx_128_255byte) + 143 u64_stats_read(&mib->tx_256_511byte) + 144 u64_stats_read(&mib->tx_512_1023byte) + 145 u64_stats_read(&mib->tx_1024_1518byte) + 146 u64_stats_read(&mib->tx_jumbo); 147 u64_stats_set(&pm->rx_frames, rx_frames); 148 u64_stats_set(&pm->tx_frames, tx_frames); 149 u64_stats_update_end_irqrestore(&pm->syncp, flags); 150 151 if (res) 152 dev_err(dev, "Failed to %s port %d: %i\n", "read stats for", 153 port, res); 154 return res; 155 } 156 157 void yt921x_mib_poll(struct work_struct *work) 158 { 159 struct yt921x_mib *pm = container_of_const(work, struct yt921x_mib, 160 work.work); 161 struct yt921x_port *pp = pm->port; 162 unsigned long delay = YT921X_STATS_INTERVAL_JIFFIES; 163 struct yt921x_priv *priv = yt921x_port_to_priv(pp); 164 int port = pp->index; 165 int res; 166 167 mutex_lock(&priv->reg_lock); 168 res = yt921x_mib_read(priv, port); 169 mutex_unlock(&priv->reg_lock); 170 if (res) 171 delay *= 4; 172 173 schedule_delayed_work(&pm->work, delay); 174 } 175 176 void 177 yt921x_dsa_get_strings(struct dsa_switch *ds, int port, u32 stringset, 178 uint8_t *data) 179 { 180 if (stringset != ETH_SS_STATS) 181 return; 182 183 for (size_t i = 0; i < ARRAY_SIZE(yt921x_mib_descs); i++) { 184 const struct yt921x_mib_desc *desc = &yt921x_mib_descs[i]; 185 186 if (desc->name) 187 ethtool_puts(&data, desc->name); 188 } 189 } 190 191 void 192 yt921x_dsa_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data) 193 { 194 struct yt921x_priv *priv = dsa_to_yt921x_priv(ds); 195 struct yt921x_port *pp = &priv->ports[port]; 196 struct yt921x_mib *pm = pp->mib; 197 u64 *buf; 198 size_t j; 199 200 if (!pm) 201 return; 202 buf = pm->data; 203 204 mutex_lock(&priv->reg_lock); 205 206 yt921x_mib_read(priv, port); 207 208 j = 0; 209 for (size_t i = 0; i < ARRAY_SIZE(yt921x_mib_descs); i++) { 210 const struct yt921x_mib_desc *desc = &yt921x_mib_descs[i]; 211 212 if (!desc->name) 213 continue; 214 215 data[j] = buf[i]; 216 j++; 217 } 218 219 mutex_unlock(&priv->reg_lock); 220 } 221 222 int yt921x_dsa_get_sset_count(struct dsa_switch *ds, int port, int sset) 223 { 224 int cnt = 0; 225 226 if (sset != ETH_SS_STATS) 227 return 0; 228 229 for (size_t i = 0; i < ARRAY_SIZE(yt921x_mib_descs); i++) { 230 const struct yt921x_mib_desc *desc = &yt921x_mib_descs[i]; 231 232 if (desc->name) 233 cnt++; 234 } 235 236 return cnt; 237 } 238 239 void 240 yt921x_dsa_get_eth_mac_stats(struct dsa_switch *ds, int port, 241 struct ethtool_eth_mac_stats *mac_stats) 242 { 243 struct yt921x_priv *priv = dsa_to_yt921x_priv(ds); 244 struct yt921x_port *pp = &priv->ports[port]; 245 struct yt921x_mib *pm = pp->mib; 246 struct yt921x_mib_stats *mib; 247 248 if (!pm) 249 return; 250 mib = &pm->stats; 251 252 mutex_lock(&priv->reg_lock); 253 254 yt921x_mib_read(priv, port); 255 256 mac_stats->FramesTransmittedOK = u64_stats_read(&pm->tx_frames); 257 mac_stats->SingleCollisionFrames = u64_stats_read(&mib->tx_single_collisions); 258 mac_stats->MultipleCollisionFrames = u64_stats_read(&mib->tx_multiple_collisions); 259 mac_stats->FramesReceivedOK = u64_stats_read(&pm->rx_frames); 260 mac_stats->FrameCheckSequenceErrors = u64_stats_read(&mib->rx_crc_errors); 261 mac_stats->AlignmentErrors = u64_stats_read(&mib->rx_alignment_errors); 262 mac_stats->OctetsTransmittedOK = u64_stats_read(&mib->tx_good_bytes); 263 mac_stats->FramesWithDeferredXmissions = u64_stats_read(&mib->tx_deferred); 264 mac_stats->LateCollisions = u64_stats_read(&mib->tx_late_collisions); 265 mac_stats->FramesAbortedDueToXSColls = u64_stats_read(&mib->tx_aborted_errors); 266 /* mac_stats->FramesLostDueToIntMACXmitError */ 267 /* mac_stats->CarrierSenseErrors */ 268 mac_stats->OctetsReceivedOK = u64_stats_read(&mib->rx_good_bytes); 269 /* mac_stats->FramesLostDueToIntMACRcvError */ 270 mac_stats->MulticastFramesXmittedOK = u64_stats_read(&mib->tx_multicast); 271 mac_stats->BroadcastFramesXmittedOK = u64_stats_read(&mib->tx_broadcast); 272 /* mac_stats->FramesWithExcessiveDeferral */ 273 mac_stats->MulticastFramesReceivedOK = u64_stats_read(&mib->rx_multicast); 274 mac_stats->BroadcastFramesReceivedOK = u64_stats_read(&mib->rx_broadcast); 275 /* mac_stats->InRangeLengthErrors */ 276 /* mac_stats->OutOfRangeLengthField */ 277 mac_stats->FrameTooLongErrors = u64_stats_read(&mib->rx_oversize_errors); 278 279 mutex_unlock(&priv->reg_lock); 280 } 281 282 void 283 yt921x_dsa_get_eth_ctrl_stats(struct dsa_switch *ds, int port, 284 struct ethtool_eth_ctrl_stats *ctrl_stats) 285 { 286 struct yt921x_priv *priv = dsa_to_yt921x_priv(ds); 287 struct yt921x_port *pp = &priv->ports[port]; 288 struct yt921x_mib *pm = pp->mib; 289 struct yt921x_mib_stats *mib; 290 291 if (!pm) 292 return; 293 mib = &pm->stats; 294 295 mutex_lock(&priv->reg_lock); 296 297 yt921x_mib_read(priv, port); 298 299 ctrl_stats->MACControlFramesTransmitted = u64_stats_read(&mib->tx_pause); 300 ctrl_stats->MACControlFramesReceived = u64_stats_read(&mib->rx_pause); 301 /* ctrl_stats->UnsupportedOpcodesReceived */ 302 303 mutex_unlock(&priv->reg_lock); 304 } 305 306 static const struct ethtool_rmon_hist_range yt921x_rmon_ranges[] = { 307 { 0, 64 }, 308 { 65, 127 }, 309 { 128, 255 }, 310 { 256, 511 }, 311 { 512, 1023 }, 312 { 1024, 1518 }, 313 { 1519, YT921X_FRAME_SIZE_MAX }, 314 {} 315 }; 316 317 void 318 yt921x_dsa_get_rmon_stats(struct dsa_switch *ds, int port, 319 struct ethtool_rmon_stats *rmon_stats, 320 const struct ethtool_rmon_hist_range **ranges) 321 { 322 struct yt921x_priv *priv = dsa_to_yt921x_priv(ds); 323 struct yt921x_port *pp = &priv->ports[port]; 324 struct yt921x_mib *pm = pp->mib; 325 struct yt921x_mib_stats *mib; 326 327 if (!pm) 328 return; 329 mib = &pm->stats; 330 331 mutex_lock(&priv->reg_lock); 332 333 yt921x_mib_read(priv, port); 334 335 *ranges = yt921x_rmon_ranges; 336 337 rmon_stats->undersize_pkts = u64_stats_read(&mib->rx_undersize_errors); 338 rmon_stats->oversize_pkts = u64_stats_read(&mib->rx_oversize_errors); 339 rmon_stats->fragments = u64_stats_read(&mib->rx_alignment_errors); 340 /* rmon_stats->jabbers */ 341 342 rmon_stats->hist[0] = u64_stats_read(&mib->rx_64byte); 343 rmon_stats->hist[1] = u64_stats_read(&mib->rx_65_127byte); 344 rmon_stats->hist[2] = u64_stats_read(&mib->rx_128_255byte); 345 rmon_stats->hist[3] = u64_stats_read(&mib->rx_256_511byte); 346 rmon_stats->hist[4] = u64_stats_read(&mib->rx_512_1023byte); 347 rmon_stats->hist[5] = u64_stats_read(&mib->rx_1024_1518byte); 348 rmon_stats->hist[6] = u64_stats_read(&mib->rx_jumbo); 349 350 rmon_stats->hist_tx[0] = u64_stats_read(&mib->tx_64byte); 351 rmon_stats->hist_tx[1] = u64_stats_read(&mib->tx_65_127byte); 352 rmon_stats->hist_tx[2] = u64_stats_read(&mib->tx_128_255byte); 353 rmon_stats->hist_tx[3] = u64_stats_read(&mib->tx_256_511byte); 354 rmon_stats->hist_tx[4] = u64_stats_read(&mib->tx_512_1023byte); 355 rmon_stats->hist_tx[5] = u64_stats_read(&mib->tx_1024_1518byte); 356 rmon_stats->hist_tx[6] = u64_stats_read(&mib->tx_jumbo); 357 358 mutex_unlock(&priv->reg_lock); 359 } 360 361 void 362 yt921x_dsa_get_stats64(struct dsa_switch *ds, int port, 363 struct rtnl_link_stats64 *stats) 364 { 365 struct yt921x_priv *priv = dsa_to_yt921x_priv(ds); 366 struct yt921x_port *pp = &priv->ports[port]; 367 struct yt921x_mib *pm = pp->mib; 368 struct yt921x_mib_stats *mib; 369 unsigned int start; 370 371 if (!pm) 372 return; 373 mib = &pm->stats; 374 375 do { 376 start = u64_stats_fetch_begin(&pm->syncp); 377 378 stats->rx_length_errors = u64_stats_read(&mib->rx_undersize_errors) + 379 u64_stats_read(&mib->rx_fragment_errors); 380 stats->rx_over_errors = u64_stats_read(&mib->rx_oversize_errors); 381 stats->rx_crc_errors = u64_stats_read(&mib->rx_crc_errors); 382 stats->rx_frame_errors = u64_stats_read(&mib->rx_alignment_errors); 383 /* stats->rx_fifo_errors */ 384 /* stats->rx_missed_errors */ 385 386 stats->tx_aborted_errors = u64_stats_read(&mib->tx_aborted_errors); 387 /* stats->tx_carrier_errors */ 388 stats->tx_fifo_errors = u64_stats_read(&mib->tx_undersize_errors); 389 /* stats->tx_heartbeat_errors */ 390 stats->tx_window_errors = u64_stats_read(&mib->tx_late_collisions); 391 392 stats->rx_packets = u64_stats_read(&pm->rx_frames); 393 stats->tx_packets = u64_stats_read(&pm->tx_frames); 394 stats->rx_bytes = u64_stats_read(&mib->rx_good_bytes) - 395 ETH_FCS_LEN * stats->rx_packets; 396 stats->tx_bytes = u64_stats_read(&mib->tx_good_bytes) - 397 ETH_FCS_LEN * stats->tx_packets; 398 stats->rx_dropped = u64_stats_read(&mib->rx_dropped); 399 /* stats->tx_dropped */ 400 stats->multicast = u64_stats_read(&mib->rx_multicast); 401 stats->collisions = u64_stats_read(&mib->tx_collisions); 402 } while (u64_stats_fetch_retry(&pm->syncp, start)); 403 404 stats->rx_errors = stats->rx_length_errors + stats->rx_over_errors + 405 stats->rx_crc_errors + stats->rx_frame_errors; 406 stats->tx_errors = stats->tx_aborted_errors + stats->tx_fifo_errors + 407 stats->tx_window_errors; 408 } 409 410 void 411 yt921x_dsa_get_pause_stats(struct dsa_switch *ds, int port, 412 struct ethtool_pause_stats *pause_stats) 413 { 414 struct yt921x_priv *priv = dsa_to_yt921x_priv(ds); 415 struct yt921x_port *pp = &priv->ports[port]; 416 struct yt921x_mib *pm = pp->mib; 417 struct yt921x_mib_stats *mib; 418 419 if (!pm) 420 return; 421 mib = &pm->stats; 422 423 mutex_lock(&priv->reg_lock); 424 425 yt921x_mib_read(priv, port); 426 427 pause_stats->tx_pause_frames = u64_stats_read(&mib->tx_pause); 428 pause_stats->rx_pause_frames = u64_stats_read(&mib->rx_pause); 429 430 mutex_unlock(&priv->reg_lock); 431 } 432