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