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