1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright(c) 2017 - 2019 Pensando Systems, Inc */ 3 4 #include <linux/kernel.h> 5 #include <linux/mutex.h> 6 #include <linux/netdevice.h> 7 8 #include "ionic.h" 9 #include "ionic_lif.h" 10 #include "ionic_stats.h" 11 12 static const struct ionic_stat_desc ionic_lif_stats_desc[] = { 13 IONIC_LIF_STAT_DESC(tx_packets), 14 IONIC_LIF_STAT_DESC(tx_bytes), 15 IONIC_LIF_STAT_DESC(rx_packets), 16 IONIC_LIF_STAT_DESC(rx_bytes), 17 IONIC_LIF_STAT_DESC(tx_tso), 18 IONIC_LIF_STAT_DESC(tx_no_csum), 19 IONIC_LIF_STAT_DESC(tx_csum), 20 IONIC_LIF_STAT_DESC(rx_csum_none), 21 IONIC_LIF_STAT_DESC(rx_csum_complete), 22 IONIC_LIF_STAT_DESC(rx_csum_error), 23 }; 24 25 static const struct ionic_stat_desc ionic_tx_stats_desc[] = { 26 IONIC_TX_STAT_DESC(pkts), 27 IONIC_TX_STAT_DESC(bytes), 28 IONIC_TX_STAT_DESC(clean), 29 IONIC_TX_STAT_DESC(dma_map_err), 30 IONIC_TX_STAT_DESC(linearize), 31 IONIC_TX_STAT_DESC(frags), 32 }; 33 34 static const struct ionic_stat_desc ionic_rx_stats_desc[] = { 35 IONIC_RX_STAT_DESC(pkts), 36 IONIC_RX_STAT_DESC(bytes), 37 IONIC_RX_STAT_DESC(dma_map_err), 38 IONIC_RX_STAT_DESC(alloc_err), 39 IONIC_RX_STAT_DESC(csum_none), 40 IONIC_RX_STAT_DESC(csum_complete), 41 IONIC_RX_STAT_DESC(csum_error), 42 }; 43 44 static const struct ionic_stat_desc ionic_txq_stats_desc[] = { 45 IONIC_TX_Q_STAT_DESC(stop), 46 IONIC_TX_Q_STAT_DESC(wake), 47 IONIC_TX_Q_STAT_DESC(drop), 48 IONIC_TX_Q_STAT_DESC(dbell_count), 49 }; 50 51 static const struct ionic_stat_desc ionic_dbg_cq_stats_desc[] = { 52 IONIC_CQ_STAT_DESC(compl_count), 53 }; 54 55 static const struct ionic_stat_desc ionic_dbg_intr_stats_desc[] = { 56 IONIC_INTR_STAT_DESC(rearm_count), 57 }; 58 59 static const struct ionic_stat_desc ionic_dbg_napi_stats_desc[] = { 60 IONIC_NAPI_STAT_DESC(poll_count), 61 }; 62 63 #define IONIC_NUM_LIF_STATS ARRAY_SIZE(ionic_lif_stats_desc) 64 #define IONIC_NUM_TX_STATS ARRAY_SIZE(ionic_tx_stats_desc) 65 #define IONIC_NUM_RX_STATS ARRAY_SIZE(ionic_rx_stats_desc) 66 #define IONIC_NUM_TX_Q_STATS ARRAY_SIZE(ionic_txq_stats_desc) 67 #define IONIC_NUM_DBG_CQ_STATS ARRAY_SIZE(ionic_dbg_cq_stats_desc) 68 #define IONIC_NUM_DBG_INTR_STATS ARRAY_SIZE(ionic_dbg_intr_stats_desc) 69 #define IONIC_NUM_DBG_NAPI_STATS ARRAY_SIZE(ionic_dbg_napi_stats_desc) 70 71 #define MAX_Q(lif) ((lif)->netdev->real_num_tx_queues) 72 73 static void ionic_get_lif_stats(struct ionic_lif *lif, 74 struct ionic_lif_sw_stats *stats) 75 { 76 struct ionic_tx_stats *tstats; 77 struct ionic_rx_stats *rstats; 78 struct ionic_qcq *txqcq; 79 struct ionic_qcq *rxqcq; 80 int q_num; 81 82 memset(stats, 0, sizeof(*stats)); 83 84 for (q_num = 0; q_num < MAX_Q(lif); q_num++) { 85 txqcq = lif_to_txqcq(lif, q_num); 86 if (txqcq && txqcq->stats) { 87 tstats = &txqcq->stats->tx; 88 stats->tx_packets += tstats->pkts; 89 stats->tx_bytes += tstats->bytes; 90 stats->tx_tso += tstats->tso; 91 stats->tx_no_csum += tstats->no_csum; 92 stats->tx_csum += tstats->csum; 93 } 94 95 rxqcq = lif_to_rxqcq(lif, q_num); 96 if (rxqcq && rxqcq->stats) { 97 rstats = &rxqcq->stats->rx; 98 stats->rx_packets += rstats->pkts; 99 stats->rx_bytes += rstats->bytes; 100 stats->rx_csum_none += rstats->csum_none; 101 stats->rx_csum_complete += rstats->csum_complete; 102 stats->rx_csum_error += rstats->csum_error; 103 } 104 } 105 } 106 107 static u64 ionic_sw_stats_get_count(struct ionic_lif *lif) 108 { 109 u64 total = 0; 110 111 /* lif stats */ 112 total += IONIC_NUM_LIF_STATS; 113 114 /* tx stats */ 115 total += MAX_Q(lif) * IONIC_NUM_TX_STATS; 116 117 /* rx stats */ 118 total += MAX_Q(lif) * IONIC_NUM_RX_STATS; 119 120 if (test_bit(IONIC_LIF_UP, lif->state) && 121 test_bit(IONIC_LIF_SW_DEBUG_STATS, lif->state)) { 122 /* tx debug stats */ 123 total += MAX_Q(lif) * (IONIC_NUM_DBG_CQ_STATS + 124 IONIC_NUM_TX_Q_STATS + 125 IONIC_NUM_DBG_INTR_STATS + 126 IONIC_MAX_NUM_SG_CNTR); 127 128 /* rx debug stats */ 129 total += MAX_Q(lif) * (IONIC_NUM_DBG_CQ_STATS + 130 IONIC_NUM_DBG_INTR_STATS + 131 IONIC_NUM_DBG_NAPI_STATS + 132 IONIC_MAX_NUM_NAPI_CNTR); 133 } 134 135 return total; 136 } 137 138 static void ionic_sw_stats_get_strings(struct ionic_lif *lif, u8 **buf) 139 { 140 int i, q_num; 141 142 for (i = 0; i < IONIC_NUM_LIF_STATS; i++) { 143 snprintf(*buf, ETH_GSTRING_LEN, ionic_lif_stats_desc[i].name); 144 *buf += ETH_GSTRING_LEN; 145 } 146 for (q_num = 0; q_num < MAX_Q(lif); q_num++) { 147 for (i = 0; i < IONIC_NUM_TX_STATS; i++) { 148 snprintf(*buf, ETH_GSTRING_LEN, "tx_%d_%s", 149 q_num, ionic_tx_stats_desc[i].name); 150 *buf += ETH_GSTRING_LEN; 151 } 152 153 if (test_bit(IONIC_LIF_UP, lif->state) && 154 test_bit(IONIC_LIF_SW_DEBUG_STATS, lif->state)) { 155 for (i = 0; i < IONIC_NUM_TX_Q_STATS; i++) { 156 snprintf(*buf, ETH_GSTRING_LEN, 157 "txq_%d_%s", 158 q_num, 159 ionic_txq_stats_desc[i].name); 160 *buf += ETH_GSTRING_LEN; 161 } 162 for (i = 0; i < IONIC_NUM_DBG_CQ_STATS; i++) { 163 snprintf(*buf, ETH_GSTRING_LEN, 164 "txq_%d_cq_%s", 165 q_num, 166 ionic_dbg_cq_stats_desc[i].name); 167 *buf += ETH_GSTRING_LEN; 168 } 169 for (i = 0; i < IONIC_NUM_DBG_INTR_STATS; i++) { 170 snprintf(*buf, ETH_GSTRING_LEN, 171 "txq_%d_intr_%s", 172 q_num, 173 ionic_dbg_intr_stats_desc[i].name); 174 *buf += ETH_GSTRING_LEN; 175 } 176 for (i = 0; i < IONIC_MAX_NUM_SG_CNTR; i++) { 177 snprintf(*buf, ETH_GSTRING_LEN, 178 "txq_%d_sg_cntr_%d", 179 q_num, i); 180 *buf += ETH_GSTRING_LEN; 181 } 182 } 183 } 184 for (q_num = 0; q_num < MAX_Q(lif); q_num++) { 185 for (i = 0; i < IONIC_NUM_RX_STATS; i++) { 186 snprintf(*buf, ETH_GSTRING_LEN, 187 "rx_%d_%s", 188 q_num, ionic_rx_stats_desc[i].name); 189 *buf += ETH_GSTRING_LEN; 190 } 191 192 if (test_bit(IONIC_LIF_UP, lif->state) && 193 test_bit(IONIC_LIF_SW_DEBUG_STATS, lif->state)) { 194 for (i = 0; i < IONIC_NUM_DBG_CQ_STATS; i++) { 195 snprintf(*buf, ETH_GSTRING_LEN, 196 "rxq_%d_cq_%s", 197 q_num, 198 ionic_dbg_cq_stats_desc[i].name); 199 *buf += ETH_GSTRING_LEN; 200 } 201 for (i = 0; i < IONIC_NUM_DBG_INTR_STATS; i++) { 202 snprintf(*buf, ETH_GSTRING_LEN, 203 "rxq_%d_intr_%s", 204 q_num, 205 ionic_dbg_intr_stats_desc[i].name); 206 *buf += ETH_GSTRING_LEN; 207 } 208 for (i = 0; i < IONIC_NUM_DBG_NAPI_STATS; i++) { 209 snprintf(*buf, ETH_GSTRING_LEN, 210 "rxq_%d_napi_%s", 211 q_num, 212 ionic_dbg_napi_stats_desc[i].name); 213 *buf += ETH_GSTRING_LEN; 214 } 215 for (i = 0; i < IONIC_MAX_NUM_NAPI_CNTR; i++) { 216 snprintf(*buf, ETH_GSTRING_LEN, 217 "rxq_%d_napi_work_done_%d", 218 q_num, i); 219 *buf += ETH_GSTRING_LEN; 220 } 221 } 222 } 223 } 224 225 static void ionic_sw_stats_get_values(struct ionic_lif *lif, u64 **buf) 226 { 227 struct ionic_lif_sw_stats lif_stats; 228 struct ionic_qcq *txqcq, *rxqcq; 229 struct ionic_tx_stats *txstats; 230 struct ionic_rx_stats *rxstats; 231 int i, q_num; 232 233 ionic_get_lif_stats(lif, &lif_stats); 234 235 for (i = 0; i < IONIC_NUM_LIF_STATS; i++) { 236 **buf = IONIC_READ_STAT64(&lif_stats, &ionic_lif_stats_desc[i]); 237 (*buf)++; 238 } 239 240 for (q_num = 0; q_num < MAX_Q(lif); q_num++) { 241 txstats = &lif_to_txstats(lif, q_num); 242 243 for (i = 0; i < IONIC_NUM_TX_STATS; i++) { 244 **buf = IONIC_READ_STAT64(txstats, 245 &ionic_tx_stats_desc[i]); 246 (*buf)++; 247 } 248 249 if (test_bit(IONIC_LIF_UP, lif->state) && 250 test_bit(IONIC_LIF_SW_DEBUG_STATS, lif->state)) { 251 txqcq = lif_to_txqcq(lif, q_num); 252 for (i = 0; i < IONIC_NUM_TX_Q_STATS; i++) { 253 **buf = IONIC_READ_STAT64(&txqcq->q, 254 &ionic_txq_stats_desc[i]); 255 (*buf)++; 256 } 257 for (i = 0; i < IONIC_NUM_DBG_CQ_STATS; i++) { 258 **buf = IONIC_READ_STAT64(&txqcq->cq, 259 &ionic_dbg_cq_stats_desc[i]); 260 (*buf)++; 261 } 262 for (i = 0; i < IONIC_NUM_DBG_INTR_STATS; i++) { 263 **buf = IONIC_READ_STAT64(&txqcq->intr, 264 &ionic_dbg_intr_stats_desc[i]); 265 (*buf)++; 266 } 267 for (i = 0; i < IONIC_MAX_NUM_SG_CNTR; i++) { 268 **buf = txstats->sg_cntr[i]; 269 (*buf)++; 270 } 271 } 272 } 273 274 for (q_num = 0; q_num < MAX_Q(lif); q_num++) { 275 rxstats = &lif_to_rxstats(lif, q_num); 276 277 for (i = 0; i < IONIC_NUM_RX_STATS; i++) { 278 **buf = IONIC_READ_STAT64(rxstats, 279 &ionic_rx_stats_desc[i]); 280 (*buf)++; 281 } 282 283 if (test_bit(IONIC_LIF_UP, lif->state) && 284 test_bit(IONIC_LIF_SW_DEBUG_STATS, lif->state)) { 285 rxqcq = lif_to_rxqcq(lif, q_num); 286 for (i = 0; i < IONIC_NUM_DBG_CQ_STATS; i++) { 287 **buf = IONIC_READ_STAT64(&rxqcq->cq, 288 &ionic_dbg_cq_stats_desc[i]); 289 (*buf)++; 290 } 291 for (i = 0; i < IONIC_NUM_DBG_INTR_STATS; i++) { 292 **buf = IONIC_READ_STAT64(&rxqcq->intr, 293 &ionic_dbg_intr_stats_desc[i]); 294 (*buf)++; 295 } 296 for (i = 0; i < IONIC_NUM_DBG_NAPI_STATS; i++) { 297 **buf = IONIC_READ_STAT64(&rxqcq->napi_stats, 298 &ionic_dbg_napi_stats_desc[i]); 299 (*buf)++; 300 } 301 for (i = 0; i < IONIC_MAX_NUM_NAPI_CNTR; i++) { 302 **buf = rxqcq->napi_stats.work_done_cntr[i]; 303 (*buf)++; 304 } 305 } 306 } 307 } 308 309 const struct ionic_stats_group_intf ionic_stats_groups[] = { 310 /* SW Stats group */ 311 { 312 .get_strings = ionic_sw_stats_get_strings, 313 .get_values = ionic_sw_stats_get_values, 314 .get_count = ionic_sw_stats_get_count, 315 }, 316 /* Add more stat groups here */ 317 }; 318 319 const int ionic_num_stats_grps = ARRAY_SIZE(ionic_stats_groups); 320