1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright(c) 2017 - 2019 Pensando Systems, Inc */ 3 4 #include <linux/ethtool.h> 5 #include <linux/kernel.h> 6 #include <linux/mutex.h> 7 #include <linux/netdevice.h> 8 9 #include "ionic.h" 10 #include "ionic_lif.h" 11 #include "ionic_stats.h" 12 13 static const struct ionic_stat_desc ionic_lif_stats_desc[] = { 14 IONIC_LIF_STAT_DESC(tx_packets), 15 IONIC_LIF_STAT_DESC(tx_bytes), 16 IONIC_LIF_STAT_DESC(rx_packets), 17 IONIC_LIF_STAT_DESC(rx_bytes), 18 IONIC_LIF_STAT_DESC(tx_tso), 19 IONIC_LIF_STAT_DESC(tx_tso_bytes), 20 IONIC_LIF_STAT_DESC(tx_csum_none), 21 IONIC_LIF_STAT_DESC(tx_csum), 22 IONIC_LIF_STAT_DESC(rx_csum_none), 23 IONIC_LIF_STAT_DESC(rx_csum_complete), 24 IONIC_LIF_STAT_DESC(rx_csum_error), 25 IONIC_LIF_STAT_DESC(hw_tx_dropped), 26 IONIC_LIF_STAT_DESC(hw_rx_dropped), 27 IONIC_LIF_STAT_DESC(hw_rx_over_errors), 28 IONIC_LIF_STAT_DESC(hw_rx_missed_errors), 29 IONIC_LIF_STAT_DESC(hw_tx_aborted_errors), 30 IONIC_LIF_STAT_DESC(xdp_drop), 31 IONIC_LIF_STAT_DESC(xdp_aborted), 32 IONIC_LIF_STAT_DESC(xdp_pass), 33 IONIC_LIF_STAT_DESC(xdp_tx), 34 IONIC_LIF_STAT_DESC(xdp_redirect), 35 IONIC_LIF_STAT_DESC(xdp_frames), 36 }; 37 38 static const struct ionic_stat_desc ionic_port_stats_desc[] = { 39 IONIC_PORT_STAT_DESC(frames_rx_ok), 40 IONIC_PORT_STAT_DESC(frames_rx_all), 41 IONIC_PORT_STAT_DESC(frames_rx_bad_fcs), 42 IONIC_PORT_STAT_DESC(frames_rx_bad_all), 43 IONIC_PORT_STAT_DESC(octets_rx_ok), 44 IONIC_PORT_STAT_DESC(octets_rx_all), 45 IONIC_PORT_STAT_DESC(frames_rx_unicast), 46 IONIC_PORT_STAT_DESC(frames_rx_multicast), 47 IONIC_PORT_STAT_DESC(frames_rx_broadcast), 48 IONIC_PORT_STAT_DESC(frames_rx_pause), 49 IONIC_PORT_STAT_DESC(frames_rx_bad_length), 50 IONIC_PORT_STAT_DESC(frames_rx_undersized), 51 IONIC_PORT_STAT_DESC(frames_rx_oversized), 52 IONIC_PORT_STAT_DESC(frames_rx_fragments), 53 IONIC_PORT_STAT_DESC(frames_rx_jabber), 54 IONIC_PORT_STAT_DESC(frames_rx_pripause), 55 IONIC_PORT_STAT_DESC(frames_rx_stomped_crc), 56 IONIC_PORT_STAT_DESC(frames_rx_too_long), 57 IONIC_PORT_STAT_DESC(frames_rx_vlan_good), 58 IONIC_PORT_STAT_DESC(frames_rx_dropped), 59 IONIC_PORT_STAT_DESC(frames_rx_less_than_64b), 60 IONIC_PORT_STAT_DESC(frames_rx_64b), 61 IONIC_PORT_STAT_DESC(frames_rx_65b_127b), 62 IONIC_PORT_STAT_DESC(frames_rx_128b_255b), 63 IONIC_PORT_STAT_DESC(frames_rx_256b_511b), 64 IONIC_PORT_STAT_DESC(frames_rx_512b_1023b), 65 IONIC_PORT_STAT_DESC(frames_rx_1024b_1518b), 66 IONIC_PORT_STAT_DESC(frames_rx_1519b_2047b), 67 IONIC_PORT_STAT_DESC(frames_rx_2048b_4095b), 68 IONIC_PORT_STAT_DESC(frames_rx_4096b_8191b), 69 IONIC_PORT_STAT_DESC(frames_rx_8192b_9215b), 70 IONIC_PORT_STAT_DESC(frames_rx_other), 71 IONIC_PORT_STAT_DESC(frames_tx_ok), 72 IONIC_PORT_STAT_DESC(frames_tx_all), 73 IONIC_PORT_STAT_DESC(frames_tx_bad), 74 IONIC_PORT_STAT_DESC(octets_tx_ok), 75 IONIC_PORT_STAT_DESC(octets_tx_total), 76 IONIC_PORT_STAT_DESC(frames_tx_unicast), 77 IONIC_PORT_STAT_DESC(frames_tx_multicast), 78 IONIC_PORT_STAT_DESC(frames_tx_broadcast), 79 IONIC_PORT_STAT_DESC(frames_tx_pause), 80 IONIC_PORT_STAT_DESC(frames_tx_pripause), 81 IONIC_PORT_STAT_DESC(frames_tx_vlan), 82 IONIC_PORT_STAT_DESC(frames_tx_less_than_64b), 83 IONIC_PORT_STAT_DESC(frames_tx_64b), 84 IONIC_PORT_STAT_DESC(frames_tx_65b_127b), 85 IONIC_PORT_STAT_DESC(frames_tx_128b_255b), 86 IONIC_PORT_STAT_DESC(frames_tx_256b_511b), 87 IONIC_PORT_STAT_DESC(frames_tx_512b_1023b), 88 IONIC_PORT_STAT_DESC(frames_tx_1024b_1518b), 89 IONIC_PORT_STAT_DESC(frames_tx_1519b_2047b), 90 IONIC_PORT_STAT_DESC(frames_tx_2048b_4095b), 91 IONIC_PORT_STAT_DESC(frames_tx_4096b_8191b), 92 IONIC_PORT_STAT_DESC(frames_tx_8192b_9215b), 93 IONIC_PORT_STAT_DESC(frames_tx_other), 94 IONIC_PORT_STAT_DESC(frames_tx_pri_0), 95 IONIC_PORT_STAT_DESC(frames_tx_pri_1), 96 IONIC_PORT_STAT_DESC(frames_tx_pri_2), 97 IONIC_PORT_STAT_DESC(frames_tx_pri_3), 98 IONIC_PORT_STAT_DESC(frames_tx_pri_4), 99 IONIC_PORT_STAT_DESC(frames_tx_pri_5), 100 IONIC_PORT_STAT_DESC(frames_tx_pri_6), 101 IONIC_PORT_STAT_DESC(frames_tx_pri_7), 102 IONIC_PORT_STAT_DESC(frames_rx_pri_0), 103 IONIC_PORT_STAT_DESC(frames_rx_pri_1), 104 IONIC_PORT_STAT_DESC(frames_rx_pri_2), 105 IONIC_PORT_STAT_DESC(frames_rx_pri_3), 106 IONIC_PORT_STAT_DESC(frames_rx_pri_4), 107 IONIC_PORT_STAT_DESC(frames_rx_pri_5), 108 IONIC_PORT_STAT_DESC(frames_rx_pri_6), 109 IONIC_PORT_STAT_DESC(frames_rx_pri_7), 110 IONIC_PORT_STAT_DESC(tx_pripause_0_1us_count), 111 IONIC_PORT_STAT_DESC(tx_pripause_1_1us_count), 112 IONIC_PORT_STAT_DESC(tx_pripause_2_1us_count), 113 IONIC_PORT_STAT_DESC(tx_pripause_3_1us_count), 114 IONIC_PORT_STAT_DESC(tx_pripause_4_1us_count), 115 IONIC_PORT_STAT_DESC(tx_pripause_5_1us_count), 116 IONIC_PORT_STAT_DESC(tx_pripause_6_1us_count), 117 IONIC_PORT_STAT_DESC(tx_pripause_7_1us_count), 118 IONIC_PORT_STAT_DESC(rx_pripause_0_1us_count), 119 IONIC_PORT_STAT_DESC(rx_pripause_1_1us_count), 120 IONIC_PORT_STAT_DESC(rx_pripause_2_1us_count), 121 IONIC_PORT_STAT_DESC(rx_pripause_3_1us_count), 122 IONIC_PORT_STAT_DESC(rx_pripause_4_1us_count), 123 IONIC_PORT_STAT_DESC(rx_pripause_5_1us_count), 124 IONIC_PORT_STAT_DESC(rx_pripause_6_1us_count), 125 IONIC_PORT_STAT_DESC(rx_pripause_7_1us_count), 126 IONIC_PORT_STAT_DESC(rx_pause_1us_count), 127 IONIC_PORT_STAT_DESC(frames_tx_truncated), 128 }; 129 130 static const struct ionic_stat_desc ionic_tx_stats_desc[] = { 131 IONIC_TX_STAT_DESC(pkts), 132 IONIC_TX_STAT_DESC(bytes), 133 IONIC_TX_STAT_DESC(clean), 134 IONIC_TX_STAT_DESC(dma_map_err), 135 IONIC_TX_STAT_DESC(linearize), 136 IONIC_TX_STAT_DESC(frags), 137 IONIC_TX_STAT_DESC(tso), 138 IONIC_TX_STAT_DESC(tso_bytes), 139 IONIC_TX_STAT_DESC(hwstamp_valid), 140 IONIC_TX_STAT_DESC(hwstamp_invalid), 141 IONIC_TX_STAT_DESC(csum_none), 142 IONIC_TX_STAT_DESC(csum), 143 IONIC_TX_STAT_DESC(vlan_inserted), 144 IONIC_TX_STAT_DESC(xdp_frames), 145 }; 146 147 static const struct ionic_stat_desc ionic_rx_stats_desc[] = { 148 IONIC_RX_STAT_DESC(pkts), 149 IONIC_RX_STAT_DESC(bytes), 150 IONIC_RX_STAT_DESC(dma_map_err), 151 IONIC_RX_STAT_DESC(alloc_err), 152 IONIC_RX_STAT_DESC(csum_none), 153 IONIC_RX_STAT_DESC(csum_complete), 154 IONIC_RX_STAT_DESC(csum_error), 155 IONIC_RX_STAT_DESC(hwstamp_valid), 156 IONIC_RX_STAT_DESC(hwstamp_invalid), 157 IONIC_RX_STAT_DESC(dropped), 158 IONIC_RX_STAT_DESC(vlan_stripped), 159 IONIC_RX_STAT_DESC(xdp_drop), 160 IONIC_RX_STAT_DESC(xdp_aborted), 161 IONIC_RX_STAT_DESC(xdp_pass), 162 IONIC_RX_STAT_DESC(xdp_tx), 163 IONIC_RX_STAT_DESC(xdp_redirect), 164 }; 165 166 #define IONIC_NUM_LIF_STATS ARRAY_SIZE(ionic_lif_stats_desc) 167 #define IONIC_NUM_PORT_STATS ARRAY_SIZE(ionic_port_stats_desc) 168 #define IONIC_NUM_TX_STATS ARRAY_SIZE(ionic_tx_stats_desc) 169 #define IONIC_NUM_RX_STATS ARRAY_SIZE(ionic_rx_stats_desc) 170 #define IONIC_NUM_EXTRA_PORT_STATS 1 171 172 #define MAX_Q(lif) ((lif)->netdev->real_num_tx_queues) 173 174 static void ionic_add_lif_txq_stats(struct ionic_lif *lif, int q_num, 175 struct ionic_lif_sw_stats *stats) 176 { 177 struct ionic_tx_stats *txstats = &lif->txqstats[q_num]; 178 179 stats->tx_packets += txstats->pkts; 180 stats->tx_bytes += txstats->bytes; 181 stats->tx_tso += txstats->tso; 182 stats->tx_tso_bytes += txstats->tso_bytes; 183 stats->tx_csum_none += txstats->csum_none; 184 stats->tx_csum += txstats->csum; 185 stats->tx_hwstamp_valid += txstats->hwstamp_valid; 186 stats->tx_hwstamp_invalid += txstats->hwstamp_invalid; 187 stats->xdp_frames += txstats->xdp_frames; 188 } 189 190 static void ionic_add_lif_rxq_stats(struct ionic_lif *lif, int q_num, 191 struct ionic_lif_sw_stats *stats) 192 { 193 struct ionic_rx_stats *rxstats = &lif->rxqstats[q_num]; 194 195 stats->rx_packets += rxstats->pkts; 196 stats->rx_bytes += rxstats->bytes; 197 stats->rx_csum_none += rxstats->csum_none; 198 stats->rx_csum_complete += rxstats->csum_complete; 199 stats->rx_csum_error += rxstats->csum_error; 200 stats->rx_hwstamp_valid += rxstats->hwstamp_valid; 201 stats->rx_hwstamp_invalid += rxstats->hwstamp_invalid; 202 stats->xdp_drop += rxstats->xdp_drop; 203 stats->xdp_aborted += rxstats->xdp_aborted; 204 stats->xdp_pass += rxstats->xdp_pass; 205 stats->xdp_tx += rxstats->xdp_tx; 206 stats->xdp_redirect += rxstats->xdp_redirect; 207 } 208 209 static void ionic_get_lif_stats(struct ionic_lif *lif, 210 struct ionic_lif_sw_stats *stats) 211 { 212 struct rtnl_link_stats64 ns; 213 int q_num; 214 215 memset(stats, 0, sizeof(*stats)); 216 217 for (q_num = 0; q_num < MAX_Q(lif); q_num++) { 218 ionic_add_lif_txq_stats(lif, q_num, stats); 219 ionic_add_lif_rxq_stats(lif, q_num, stats); 220 } 221 222 if (lif->hwstamp_txq) 223 ionic_add_lif_txq_stats(lif, lif->hwstamp_txq->q.index, stats); 224 225 if (lif->hwstamp_rxq) 226 ionic_add_lif_rxq_stats(lif, lif->hwstamp_rxq->q.index, stats); 227 228 ionic_get_stats64(lif->netdev, &ns); 229 stats->hw_tx_dropped = ns.tx_dropped; 230 stats->hw_rx_dropped = ns.rx_dropped; 231 stats->hw_rx_over_errors = ns.rx_over_errors; 232 stats->hw_rx_missed_errors = ns.rx_missed_errors; 233 stats->hw_tx_aborted_errors = ns.tx_aborted_errors; 234 } 235 236 static u32 ionic_extra_port_stats_get_count(struct ionic_lif *lif) 237 { 238 struct ionic_dev *idev = &lif->ionic->idev; 239 struct ionic_port_extra_stats *pes_cache; 240 u32 count = 0; 241 242 if (!(lif->ionic->ident.dev.capabilities & 243 cpu_to_le64(IONIC_DEV_CAP_EXTRA_STATS))) 244 return count; 245 246 pes_cache = &idev->port_extra_stats_cache; 247 /* Treat all of the extra port stats as invalid in subsequent calls if 248 * port_info isn't set; otherwise cache a valid snapshot for them. 249 */ 250 if (!idev->port_info) { 251 memset(pes_cache, 0xff, sizeof(*pes_cache)); 252 return count; 253 } 254 255 *pes_cache = idev->port_info->extra_stats; 256 257 if (pes_cache->rx_bits_phy != IONIC_STAT_INVALID) 258 count++; 259 260 return count; 261 } 262 263 static u64 ionic_sw_stats_get_count(struct ionic_lif *lif) 264 { 265 u64 total = 0, tx_queues = MAX_Q(lif), rx_queues = MAX_Q(lif); 266 267 if (lif->hwstamp_txq) 268 tx_queues += 1; 269 270 if (lif->hwstamp_rxq) 271 rx_queues += 1; 272 273 total += IONIC_NUM_LIF_STATS; 274 total += IONIC_NUM_PORT_STATS + ionic_extra_port_stats_get_count(lif); 275 276 total += tx_queues * IONIC_NUM_TX_STATS; 277 total += rx_queues * IONIC_NUM_RX_STATS; 278 279 return total; 280 } 281 282 static void ionic_sw_stats_get_tx_strings(struct ionic_lif *lif, u8 **buf, 283 int q_num) 284 { 285 int i; 286 287 for (i = 0; i < IONIC_NUM_TX_STATS; i++) 288 ethtool_sprintf(buf, "tx_%d_%s", q_num, 289 ionic_tx_stats_desc[i].name); 290 } 291 292 static void ionic_sw_stats_get_rx_strings(struct ionic_lif *lif, u8 **buf, 293 int q_num) 294 { 295 int i; 296 297 for (i = 0; i < IONIC_NUM_RX_STATS; i++) 298 ethtool_sprintf(buf, "rx_%d_%s", q_num, 299 ionic_rx_stats_desc[i].name); 300 } 301 302 static void ionic_extra_port_stats_get_strings(struct ionic_lif *lif, u8 **buf) 303 { 304 struct ionic_port_extra_stats *pes_cache; 305 306 if (!(lif->ionic->ident.dev.capabilities & 307 cpu_to_le64(IONIC_DEV_CAP_EXTRA_STATS))) 308 return; 309 310 pes_cache = &lif->ionic->idev.port_extra_stats_cache; 311 312 if (pes_cache->rx_bits_phy != IONIC_STAT_INVALID) 313 ethtool_puts(buf, "rx_bits_phy"); 314 } 315 316 static void ionic_sw_stats_get_strings(struct ionic_lif *lif, u8 **buf) 317 { 318 int i, q_num; 319 320 for (i = 0; i < IONIC_NUM_LIF_STATS; i++) 321 ethtool_puts(buf, ionic_lif_stats_desc[i].name); 322 323 for (i = 0; i < IONIC_NUM_PORT_STATS; i++) 324 ethtool_puts(buf, ionic_port_stats_desc[i].name); 325 ionic_extra_port_stats_get_strings(lif, buf); 326 327 for (q_num = 0; q_num < MAX_Q(lif); q_num++) 328 ionic_sw_stats_get_tx_strings(lif, buf, q_num); 329 330 if (lif->hwstamp_txq) 331 ionic_sw_stats_get_tx_strings(lif, buf, lif->hwstamp_txq->q.index); 332 333 for (q_num = 0; q_num < MAX_Q(lif); q_num++) 334 ionic_sw_stats_get_rx_strings(lif, buf, q_num); 335 336 if (lif->hwstamp_rxq) 337 ionic_sw_stats_get_rx_strings(lif, buf, lif->hwstamp_rxq->q.index); 338 } 339 340 static void ionic_sw_stats_get_txq_values(struct ionic_lif *lif, u64 **buf, 341 int q_num) 342 { 343 struct ionic_tx_stats *txstats; 344 int i; 345 346 txstats = &lif->txqstats[q_num]; 347 348 for (i = 0; i < IONIC_NUM_TX_STATS; i++) { 349 **buf = IONIC_READ_STAT64(txstats, &ionic_tx_stats_desc[i]); 350 (*buf)++; 351 } 352 } 353 354 static void ionic_sw_stats_get_rxq_values(struct ionic_lif *lif, u64 **buf, 355 int q_num) 356 { 357 struct ionic_rx_stats *rxstats; 358 int i; 359 360 rxstats = &lif->rxqstats[q_num]; 361 362 for (i = 0; i < IONIC_NUM_RX_STATS; i++) { 363 **buf = IONIC_READ_STAT64(rxstats, &ionic_rx_stats_desc[i]); 364 (*buf)++; 365 } 366 } 367 368 static void ionic_extra_port_stats_get_values(struct ionic_lif *lif, u64 **buf) 369 { 370 struct ionic_port_extra_stats *pes_cache; 371 372 if (!(lif->ionic->ident.dev.capabilities & 373 cpu_to_le64(IONIC_DEV_CAP_EXTRA_STATS))) 374 return; 375 376 /* The number of statistics added to @buf here must equal 377 * ionic_extra_port_stats_get_count(). 378 */ 379 pes_cache = &lif->ionic->idev.port_extra_stats_cache; 380 381 if (pes_cache->rx_bits_phy != IONIC_STAT_INVALID) { 382 **buf = le64_to_cpu(pes_cache->rx_bits_phy); 383 (*buf)++; 384 } 385 } 386 387 static void ionic_sw_stats_get_values(struct ionic_lif *lif, u64 **buf) 388 { 389 struct ionic_port_stats *port_stats; 390 struct ionic_lif_sw_stats lif_stats; 391 int i, q_num; 392 393 ionic_get_lif_stats(lif, &lif_stats); 394 395 for (i = 0; i < IONIC_NUM_LIF_STATS; i++) { 396 **buf = IONIC_READ_STAT64(&lif_stats, &ionic_lif_stats_desc[i]); 397 (*buf)++; 398 } 399 400 port_stats = &lif->ionic->idev.port_info->stats; 401 for (i = 0; i < IONIC_NUM_PORT_STATS; i++) { 402 **buf = IONIC_READ_STAT_LE64(port_stats, 403 &ionic_port_stats_desc[i]); 404 (*buf)++; 405 } 406 ionic_extra_port_stats_get_values(lif, buf); 407 408 for (q_num = 0; q_num < MAX_Q(lif); q_num++) 409 ionic_sw_stats_get_txq_values(lif, buf, q_num); 410 411 if (lif->hwstamp_txq) 412 ionic_sw_stats_get_txq_values(lif, buf, lif->hwstamp_txq->q.index); 413 414 for (q_num = 0; q_num < MAX_Q(lif); q_num++) 415 ionic_sw_stats_get_rxq_values(lif, buf, q_num); 416 417 if (lif->hwstamp_rxq) 418 ionic_sw_stats_get_rxq_values(lif, buf, lif->hwstamp_rxq->q.index); 419 } 420 421 const struct ionic_stats_group_intf ionic_stats_groups[] = { 422 /* SW Stats group */ 423 { 424 .get_strings = ionic_sw_stats_get_strings, 425 .get_values = ionic_sw_stats_get_values, 426 .get_count = ionic_sw_stats_get_count, 427 }, 428 /* Add more stat groups here */ 429 }; 430 431 const int ionic_num_stats_grps = ARRAY_SIZE(ionic_stats_groups); 432