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