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_SW_DEBUG_STATS, lif->state)) { 121 /* tx debug stats */ 122 total += MAX_Q(lif) * (IONIC_NUM_DBG_CQ_STATS + 123 IONIC_NUM_TX_Q_STATS + 124 IONIC_NUM_DBG_INTR_STATS + 125 IONIC_MAX_NUM_SG_CNTR); 126 127 /* rx debug stats */ 128 total += MAX_Q(lif) * (IONIC_NUM_DBG_CQ_STATS + 129 IONIC_NUM_DBG_INTR_STATS + 130 IONIC_NUM_DBG_NAPI_STATS + 131 IONIC_MAX_NUM_NAPI_CNTR); 132 } 133 134 return total; 135 } 136 137 static void ionic_sw_stats_get_strings(struct ionic_lif *lif, u8 **buf) 138 { 139 int i, q_num; 140 141 for (i = 0; i < IONIC_NUM_LIF_STATS; i++) { 142 snprintf(*buf, ETH_GSTRING_LEN, ionic_lif_stats_desc[i].name); 143 *buf += ETH_GSTRING_LEN; 144 } 145 for (q_num = 0; q_num < MAX_Q(lif); q_num++) { 146 for (i = 0; i < IONIC_NUM_TX_STATS; i++) { 147 snprintf(*buf, ETH_GSTRING_LEN, "tx_%d_%s", 148 q_num, ionic_tx_stats_desc[i].name); 149 *buf += ETH_GSTRING_LEN; 150 } 151 152 if (test_bit(IONIC_LIF_SW_DEBUG_STATS, lif->state)) { 153 for (i = 0; i < IONIC_NUM_TX_Q_STATS; i++) { 154 snprintf(*buf, ETH_GSTRING_LEN, 155 "txq_%d_%s", 156 q_num, 157 ionic_txq_stats_desc[i].name); 158 *buf += ETH_GSTRING_LEN; 159 } 160 for (i = 0; i < IONIC_NUM_DBG_CQ_STATS; i++) { 161 snprintf(*buf, ETH_GSTRING_LEN, 162 "txq_%d_cq_%s", 163 q_num, 164 ionic_dbg_cq_stats_desc[i].name); 165 *buf += ETH_GSTRING_LEN; 166 } 167 for (i = 0; i < IONIC_NUM_DBG_INTR_STATS; i++) { 168 snprintf(*buf, ETH_GSTRING_LEN, 169 "txq_%d_intr_%s", 170 q_num, 171 ionic_dbg_intr_stats_desc[i].name); 172 *buf += ETH_GSTRING_LEN; 173 } 174 for (i = 0; i < IONIC_MAX_NUM_SG_CNTR; i++) { 175 snprintf(*buf, ETH_GSTRING_LEN, 176 "txq_%d_sg_cntr_%d", 177 q_num, i); 178 *buf += ETH_GSTRING_LEN; 179 } 180 } 181 } 182 for (q_num = 0; q_num < MAX_Q(lif); q_num++) { 183 for (i = 0; i < IONIC_NUM_RX_STATS; i++) { 184 snprintf(*buf, ETH_GSTRING_LEN, 185 "rx_%d_%s", 186 q_num, ionic_rx_stats_desc[i].name); 187 *buf += ETH_GSTRING_LEN; 188 } 189 190 if (test_bit(IONIC_LIF_SW_DEBUG_STATS, lif->state)) { 191 for (i = 0; i < IONIC_NUM_DBG_CQ_STATS; i++) { 192 snprintf(*buf, ETH_GSTRING_LEN, 193 "rxq_%d_cq_%s", 194 q_num, 195 ionic_dbg_cq_stats_desc[i].name); 196 *buf += ETH_GSTRING_LEN; 197 } 198 for (i = 0; i < IONIC_NUM_DBG_INTR_STATS; i++) { 199 snprintf(*buf, ETH_GSTRING_LEN, 200 "rxq_%d_intr_%s", 201 q_num, 202 ionic_dbg_intr_stats_desc[i].name); 203 *buf += ETH_GSTRING_LEN; 204 } 205 for (i = 0; i < IONIC_NUM_DBG_NAPI_STATS; i++) { 206 snprintf(*buf, ETH_GSTRING_LEN, 207 "rxq_%d_napi_%s", 208 q_num, 209 ionic_dbg_napi_stats_desc[i].name); 210 *buf += ETH_GSTRING_LEN; 211 } 212 for (i = 0; i < IONIC_MAX_NUM_NAPI_CNTR; i++) { 213 snprintf(*buf, ETH_GSTRING_LEN, 214 "rxq_%d_napi_work_done_%d", 215 q_num, i); 216 *buf += ETH_GSTRING_LEN; 217 } 218 } 219 } 220 } 221 222 static void ionic_sw_stats_get_values(struct ionic_lif *lif, u64 **buf) 223 { 224 struct ionic_lif_sw_stats lif_stats; 225 struct ionic_qcq *txqcq, *rxqcq; 226 int i, q_num; 227 228 ionic_get_lif_stats(lif, &lif_stats); 229 230 for (i = 0; i < IONIC_NUM_LIF_STATS; i++) { 231 **buf = IONIC_READ_STAT64(&lif_stats, &ionic_lif_stats_desc[i]); 232 (*buf)++; 233 } 234 235 for (q_num = 0; q_num < MAX_Q(lif); q_num++) { 236 txqcq = lif_to_txqcq(lif, q_num); 237 238 for (i = 0; i < IONIC_NUM_TX_STATS; i++) { 239 **buf = IONIC_READ_STAT64(&txqcq->stats->tx, 240 &ionic_tx_stats_desc[i]); 241 (*buf)++; 242 } 243 244 if (test_bit(IONIC_LIF_SW_DEBUG_STATS, lif->state)) { 245 for (i = 0; i < IONIC_NUM_TX_Q_STATS; i++) { 246 **buf = IONIC_READ_STAT64(&txqcq->q, 247 &ionic_txq_stats_desc[i]); 248 (*buf)++; 249 } 250 for (i = 0; i < IONIC_NUM_DBG_CQ_STATS; i++) { 251 **buf = IONIC_READ_STAT64(&txqcq->cq, 252 &ionic_dbg_cq_stats_desc[i]); 253 (*buf)++; 254 } 255 for (i = 0; i < IONIC_NUM_DBG_INTR_STATS; i++) { 256 **buf = IONIC_READ_STAT64(&txqcq->intr, 257 &ionic_dbg_intr_stats_desc[i]); 258 (*buf)++; 259 } 260 for (i = 0; i < IONIC_MAX_NUM_SG_CNTR; i++) { 261 **buf = txqcq->stats->tx.sg_cntr[i]; 262 (*buf)++; 263 } 264 } 265 } 266 267 for (q_num = 0; q_num < MAX_Q(lif); q_num++) { 268 rxqcq = lif_to_rxqcq(lif, q_num); 269 270 for (i = 0; i < IONIC_NUM_RX_STATS; i++) { 271 **buf = IONIC_READ_STAT64(&rxqcq->stats->rx, 272 &ionic_rx_stats_desc[i]); 273 (*buf)++; 274 } 275 276 if (test_bit(IONIC_LIF_SW_DEBUG_STATS, lif->state)) { 277 for (i = 0; i < IONIC_NUM_DBG_CQ_STATS; i++) { 278 **buf = IONIC_READ_STAT64(&rxqcq->cq, 279 &ionic_dbg_cq_stats_desc[i]); 280 (*buf)++; 281 } 282 for (i = 0; i < IONIC_NUM_DBG_INTR_STATS; i++) { 283 **buf = IONIC_READ_STAT64(&rxqcq->intr, 284 &ionic_dbg_intr_stats_desc[i]); 285 (*buf)++; 286 } 287 for (i = 0; i < IONIC_NUM_DBG_NAPI_STATS; i++) { 288 **buf = IONIC_READ_STAT64(&rxqcq->napi_stats, 289 &ionic_dbg_napi_stats_desc[i]); 290 (*buf)++; 291 } 292 for (i = 0; i < IONIC_MAX_NUM_NAPI_CNTR; i++) { 293 **buf = rxqcq->napi_stats.work_done_cntr[i]; 294 (*buf)++; 295 } 296 } 297 } 298 } 299 300 const struct ionic_stats_group_intf ionic_stats_groups[] = { 301 /* SW Stats group */ 302 { 303 .get_strings = ionic_sw_stats_get_strings, 304 .get_values = ionic_sw_stats_get_values, 305 .get_count = ionic_sw_stats_get_count, 306 }, 307 /* Add more stat groups here */ 308 }; 309 310 const int ionic_num_stats_grps = ARRAY_SIZE(ionic_stats_groups); 311