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 171 #define MAX_Q(lif) ((lif)->netdev->real_num_tx_queues) 172 173 static void ionic_add_lif_txq_stats(struct ionic_lif *lif, int q_num, 174 struct ionic_lif_sw_stats *stats) 175 { 176 struct ionic_tx_stats *txstats = &lif->txqstats[q_num]; 177 178 stats->tx_packets += txstats->pkts; 179 stats->tx_bytes += txstats->bytes; 180 stats->tx_tso += txstats->tso; 181 stats->tx_tso_bytes += txstats->tso_bytes; 182 stats->tx_csum_none += txstats->csum_none; 183 stats->tx_csum += txstats->csum; 184 stats->tx_hwstamp_valid += txstats->hwstamp_valid; 185 stats->tx_hwstamp_invalid += txstats->hwstamp_invalid; 186 stats->xdp_frames += txstats->xdp_frames; 187 } 188 189 static void ionic_add_lif_rxq_stats(struct ionic_lif *lif, int q_num, 190 struct ionic_lif_sw_stats *stats) 191 { 192 struct ionic_rx_stats *rxstats = &lif->rxqstats[q_num]; 193 194 stats->rx_packets += rxstats->pkts; 195 stats->rx_bytes += rxstats->bytes; 196 stats->rx_csum_none += rxstats->csum_none; 197 stats->rx_csum_complete += rxstats->csum_complete; 198 stats->rx_csum_error += rxstats->csum_error; 199 stats->rx_hwstamp_valid += rxstats->hwstamp_valid; 200 stats->rx_hwstamp_invalid += rxstats->hwstamp_invalid; 201 stats->xdp_drop += rxstats->xdp_drop; 202 stats->xdp_aborted += rxstats->xdp_aborted; 203 stats->xdp_pass += rxstats->xdp_pass; 204 stats->xdp_tx += rxstats->xdp_tx; 205 stats->xdp_redirect += rxstats->xdp_redirect; 206 } 207 208 static void ionic_get_lif_stats(struct ionic_lif *lif, 209 struct ionic_lif_sw_stats *stats) 210 { 211 struct rtnl_link_stats64 ns; 212 int q_num; 213 214 memset(stats, 0, sizeof(*stats)); 215 216 for (q_num = 0; q_num < MAX_Q(lif); q_num++) { 217 ionic_add_lif_txq_stats(lif, q_num, stats); 218 ionic_add_lif_rxq_stats(lif, q_num, stats); 219 } 220 221 if (lif->hwstamp_txq) 222 ionic_add_lif_txq_stats(lif, lif->hwstamp_txq->q.index, stats); 223 224 if (lif->hwstamp_rxq) 225 ionic_add_lif_rxq_stats(lif, lif->hwstamp_rxq->q.index, stats); 226 227 ionic_get_stats64(lif->netdev, &ns); 228 stats->hw_tx_dropped = ns.tx_dropped; 229 stats->hw_rx_dropped = ns.rx_dropped; 230 stats->hw_rx_over_errors = ns.rx_over_errors; 231 stats->hw_rx_missed_errors = ns.rx_missed_errors; 232 stats->hw_tx_aborted_errors = ns.tx_aborted_errors; 233 } 234 235 static u64 ionic_sw_stats_get_count(struct ionic_lif *lif) 236 { 237 u64 total = 0, tx_queues = MAX_Q(lif), rx_queues = MAX_Q(lif); 238 239 if (lif->hwstamp_txq) 240 tx_queues += 1; 241 242 if (lif->hwstamp_rxq) 243 rx_queues += 1; 244 245 total += IONIC_NUM_LIF_STATS; 246 total += IONIC_NUM_PORT_STATS; 247 248 total += tx_queues * IONIC_NUM_TX_STATS; 249 total += rx_queues * IONIC_NUM_RX_STATS; 250 251 return total; 252 } 253 254 static void ionic_sw_stats_get_tx_strings(struct ionic_lif *lif, u8 **buf, 255 int q_num) 256 { 257 int i; 258 259 for (i = 0; i < IONIC_NUM_TX_STATS; i++) 260 ethtool_sprintf(buf, "tx_%d_%s", q_num, 261 ionic_tx_stats_desc[i].name); 262 } 263 264 static void ionic_sw_stats_get_rx_strings(struct ionic_lif *lif, u8 **buf, 265 int q_num) 266 { 267 int i; 268 269 for (i = 0; i < IONIC_NUM_RX_STATS; i++) 270 ethtool_sprintf(buf, "rx_%d_%s", q_num, 271 ionic_rx_stats_desc[i].name); 272 } 273 274 static void ionic_sw_stats_get_strings(struct ionic_lif *lif, u8 **buf) 275 { 276 int i, q_num; 277 278 for (i = 0; i < IONIC_NUM_LIF_STATS; i++) 279 ethtool_puts(buf, ionic_lif_stats_desc[i].name); 280 281 for (i = 0; i < IONIC_NUM_PORT_STATS; i++) 282 ethtool_puts(buf, ionic_port_stats_desc[i].name); 283 284 for (q_num = 0; q_num < MAX_Q(lif); q_num++) 285 ionic_sw_stats_get_tx_strings(lif, buf, q_num); 286 287 if (lif->hwstamp_txq) 288 ionic_sw_stats_get_tx_strings(lif, buf, lif->hwstamp_txq->q.index); 289 290 for (q_num = 0; q_num < MAX_Q(lif); q_num++) 291 ionic_sw_stats_get_rx_strings(lif, buf, q_num); 292 293 if (lif->hwstamp_rxq) 294 ionic_sw_stats_get_rx_strings(lif, buf, lif->hwstamp_rxq->q.index); 295 } 296 297 static void ionic_sw_stats_get_txq_values(struct ionic_lif *lif, u64 **buf, 298 int q_num) 299 { 300 struct ionic_tx_stats *txstats; 301 int i; 302 303 txstats = &lif->txqstats[q_num]; 304 305 for (i = 0; i < IONIC_NUM_TX_STATS; i++) { 306 **buf = IONIC_READ_STAT64(txstats, &ionic_tx_stats_desc[i]); 307 (*buf)++; 308 } 309 } 310 311 static void ionic_sw_stats_get_rxq_values(struct ionic_lif *lif, u64 **buf, 312 int q_num) 313 { 314 struct ionic_rx_stats *rxstats; 315 int i; 316 317 rxstats = &lif->rxqstats[q_num]; 318 319 for (i = 0; i < IONIC_NUM_RX_STATS; i++) { 320 **buf = IONIC_READ_STAT64(rxstats, &ionic_rx_stats_desc[i]); 321 (*buf)++; 322 } 323 } 324 325 static void ionic_sw_stats_get_values(struct ionic_lif *lif, u64 **buf) 326 { 327 struct ionic_port_stats *port_stats; 328 struct ionic_lif_sw_stats lif_stats; 329 int i, q_num; 330 331 ionic_get_lif_stats(lif, &lif_stats); 332 333 for (i = 0; i < IONIC_NUM_LIF_STATS; i++) { 334 **buf = IONIC_READ_STAT64(&lif_stats, &ionic_lif_stats_desc[i]); 335 (*buf)++; 336 } 337 338 port_stats = &lif->ionic->idev.port_info->stats; 339 for (i = 0; i < IONIC_NUM_PORT_STATS; i++) { 340 **buf = IONIC_READ_STAT_LE64(port_stats, 341 &ionic_port_stats_desc[i]); 342 (*buf)++; 343 } 344 345 for (q_num = 0; q_num < MAX_Q(lif); q_num++) 346 ionic_sw_stats_get_txq_values(lif, buf, q_num); 347 348 if (lif->hwstamp_txq) 349 ionic_sw_stats_get_txq_values(lif, buf, lif->hwstamp_txq->q.index); 350 351 for (q_num = 0; q_num < MAX_Q(lif); q_num++) 352 ionic_sw_stats_get_rxq_values(lif, buf, q_num); 353 354 if (lif->hwstamp_rxq) 355 ionic_sw_stats_get_rxq_values(lif, buf, lif->hwstamp_rxq->q.index); 356 } 357 358 const struct ionic_stats_group_intf ionic_stats_groups[] = { 359 /* SW Stats group */ 360 { 361 .get_strings = ionic_sw_stats_get_strings, 362 .get_values = ionic_sw_stats_get_values, 363 .get_count = ionic_sw_stats_get_count, 364 }, 365 /* Add more stat groups here */ 366 }; 367 368 const int ionic_num_stats_grps = ARRAY_SIZE(ionic_stats_groups); 369