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